Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Рисуем через WinAPI / 8 сообщений из 8, страница 1 из 1
17.12.2003, 12:18
    #32355077
m-j
m-j
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рисуем через WinAPI
Всем привет.
Проблема такая:
рисую на окне общую картинку (About screen и везде через BitBlt);
рисую в нужном месте битмап с текстом;
накладываю на последний маску для плавного затемнения текста сверху и снизу;
делаю SetTimer и двигаю текст;
все перерисовываю (UpdateBMP(...) собств. ф-я).
Короче все работает :-) Вот только текст мерцает.
Проблема в том, что процедура перерисовки вызывается на событие WM_PAINT и из процедуры таймера, а BeginPaint-EndPaint расположены в обработчике WM_PAINT. Если поместить последние в саму UpdateBMP() то текст вообще не перерисовывается (по таймеру).
Может кто понял в чем моя проблема. Если кто готов помочь, могу прислать исходник (здесь вряд ли пометится). Или подскажите пример (только не из MSDN по использованию BitBlt, а конкретно по рисованию на окне, созданном на WinAPI !)
...
Рейтинг: 0 / 0
17.12.2003, 12:54
    #32355136
Tracer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рисуем через WinAPI
Примерно так

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
  case WM_PAINT:
  {
       HDC dc = BeginPaint( hwnd,&paint );

       hMemDC = CreateCompatibleDC( dc );

       HBITMAP hScreen;
       HBITMAP oldBmp;

       hScreen = CreateCompatibleBitmap( dc, cxClient, cyClient );
       oldBmp = (HBITMAP)SelectObject( hMemDC, hScreen );
       PatBlt( hMemDC,  0 ,  0 , cxClient, cyClient, WHITENESS );

       // Устанавливаешь, если нужно
       // SetMapMode( ... );
       // SetWindowOrg( ... );
       // SetWindowExt( ... );

       // Рисуешь, используя hMemDC
       ... Draw code ...

       BitBlt( dc,  0 ,  0 , cxClient, cyClient, hMemDC,  0 ,  0 , SRCCOPY );
       SelectObject( hMemDC, oldBmp );
       DeleteObject( hScreen );
       DeleteDC( hMemDC );

       EndPaint( hwnd, &paint );

       return  0 ;
  }
...
Рейтинг: 0 / 0
17.12.2003, 13:10
    #32355177
m-j
m-j
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рисуем через WinAPI
Это подойдет, если перерисовка происходит только при сообщении WM_PAINT.
А в моем случае нужно перерисовывать еще и при срабатывании таймера :-(
Второй раз BeginPaint-EndPaint не напишешь же.
...
Рейтинг: 0 / 0
17.12.2003, 13:24
    #32355213
Shkurenko Alexander
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рисуем через WinAPI
m-j>Это подойдет, если перерисовка происходит только при сообщении WM_PAINT.
m-j>А в моем случае нужно перерисовывать еще и при срабатывании таймера :-(

при получении WM_TIMER использовать InvalidateRect
...
Рейтинг: 0 / 0
17.12.2003, 18:37
    #32355941
vdimas
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рисуем через WinAPI
1. можно использовать двойную буферизацию
2. убедись , что перехватил WM_ERASEBACKGROUND и ничего не сделал в ответ.
3. InvalidateRect - гиблое дело для real-time эффектов, т.к. WM_PAINT имеет вообще самый низкий приоритет и всегда находится в конце очереди (или постоянно сдвигается туда во время ожидания выборки), поэтому можно использовать RefreshWindow для непосредственной прорисовки.
4. рисуй непосредственно в девайс БЕЗ WM_PAINT и парных BeginPaint-EndPaint, т.е. просто бери GetDC(), "ручками" ограничивай видимую область, и просто рисуй. Не забудь потом удалить полученное таким вот образом DC, в MSDN очень подробно все ньюансы разжеваны.
...
Рейтинг: 0 / 0
18.12.2003, 15:28
    #32356926
m-j
m-j
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рисуем через WinAPI
Тут наверное стоит уточнить.
Мерцает не фон (который тоже перерисовывается на WM_PAINT), а мерцает сам текст.
2 vdimas: а тебя нет ссылок на сайте M$ где все это описано, а то я тут ищу про двойную буферизацию, а мне выдает только по GDI+, OpenGL и DX.
...
Рейтинг: 0 / 0
18.12.2003, 20:40
    #32357327
vdimas
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рисуем через WinAPI
двойная буферизация - это прием, он не реализован на уровне API,
рисуешь в некотором MemDC кусочек картинки/контрола, и по bitblt швыряешь в целевое DC.
Мерцание текста от того, что сначала он стирается (т.е. рисуется фон под ним), а потом снова рисуется, двойная буферизация должна помочь.

Опять же, повторюсь, проверь, что перехвачено WM_ERASEBACKGROUND, ибо по-умолчанию DefWindowProc чистит ВСЕ окно кистью, прописанной в классе окна. (window class, не С++ класс!!!), т.е. перхвати его и верни TRUE.
НО, при этом твоя процедура прорисовки (по WM_PAINT) отныне отвечает за "покраску" ВСЕЙ поверхности окна.

держи простейшую реализацию двойной буферизации:
(c) мой :)

BufferDC.h
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
#pragma once
#include  "afxwin.h" 

class CBufferDC : public CDC{
    HDC     m_hDestDC;
    CRect   m_rect;
public:
    CBufferDC(HDC hDestDC, CRect& rcPaint);
    ~CBufferDC();
};


BufferDC.cpp
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
#include  "StdAfx.h" 
#include  ".\bufferdc.h" 

static HBITMAP bmp, oldbmp;
static CRect rect;
static HDC hDC;

static struct initializer {
    initializer() {
        bmp=oldbmp=NULL;
        rect.SetRect( 0 ,  0 ,  0 ,  0 );
        hDC=NULL;
    }
    
    ~initializer() {
        if(bmp) ::DeleteObject(bmp);
        if(hDC) ::DeleteObject(hDC);
    }
} initializer_object;

CBufferDC::CBufferDC(HDC hDestDC, CRect& rcPaint) : m_hDestDC(hDestDC), _rect(rcPaint) {
    if(hDC==NULL) 
        hDC=::CreateCompatibleDC (m_hDestDC);
    
    m_hDC=hDC;
    
    if(m_rect.Width()>rect.Width() || m_rect.Height()>rect.Height()) {
        if(bmp) ::DeleteObject(bmp);
        bmp=::CreateCompatibleBitmap (hDestDC, m_rect.right, m_rect.bottom);
    }
    
    oldbmp = (HBITMAP)::SelectObject (m_hDC, bmp);
}


CBufferDC::~CBufferDC() {
    ::BitBlt (m_hDestDC, m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), m_hDC, m_rect.left, m_rect.top, SRCCOPY);
    ::SelectObject(hDC, oldbmp);
    m_hDC=NULL;
}


надеюсь, пояснений не требуется :)
обрати внимание, что эта реализация весьма эффективна (экономит время и ресурсы, пересоздает MemDC только если старый не подходит), но предназначена для работы в приложении в котором GUI работает строго в одном треде (вернее, данный класс используется строго в одном треде GUI).

В принципе, почти все мои приложухи многопоточны, но GUI я всегда "кручу" только в одном треде, это типа хорошего тона. :)
...
Рейтинг: 0 / 0
22.12.2003, 10:49
    #32359350
m-j
m-j
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рисуем через WinAPI
Большое спасибо, все работает просто супер.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Рисуем через WinAPI / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]