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

Код: 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
Рисуем через WinAPI
    #32355177
m-j
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
m-j
Гость
Это подойдет, если перерисовка происходит только при сообщении WM_PAINT.
А в моем случае нужно перерисовывать еще и при срабатывании таймера :-(
Второй раз BeginPaint-EndPaint не напишешь же.
...
Рейтинг: 0 / 0
Рисуем через WinAPI
    #32355213
Shkurenko Alexander
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m-j>Это подойдет, если перерисовка происходит только при сообщении WM_PAINT.
m-j>А в моем случае нужно перерисовывать еще и при срабатывании таймера :-(

при получении WM_TIMER использовать InvalidateRect
...
Рейтинг: 0 / 0
Рисуем через WinAPI
    #32355941
Фотография vdimas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. можно использовать двойную буферизацию
2. убедись , что перехватил WM_ERASEBACKGROUND и ничего не сделал в ответ.
3. InvalidateRect - гиблое дело для real-time эффектов, т.к. WM_PAINT имеет вообще самый низкий приоритет и всегда находится в конце очереди (или постоянно сдвигается туда во время ожидания выборки), поэтому можно использовать RefreshWindow для непосредственной прорисовки.
4. рисуй непосредственно в девайс БЕЗ WM_PAINT и парных BeginPaint-EndPaint, т.е. просто бери GetDC(), "ручками" ограничивай видимую область, и просто рисуй. Не забудь потом удалить полученное таким вот образом DC, в MSDN очень подробно все ньюансы разжеваны.
...
Рейтинг: 0 / 0
Рисуем через WinAPI
    #32356926
m-j
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
m-j
Гость
Тут наверное стоит уточнить.
Мерцает не фон (который тоже перерисовывается на WM_PAINT), а мерцает сам текст.
2 vdimas: а тебя нет ссылок на сайте M$ где все это описано, а то я тут ищу про двойную буферизацию, а мне выдает только по GDI+, OpenGL и DX.
...
Рейтинг: 0 / 0
Рисуем через WinAPI
    #32357327
Фотография vdimas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
двойная буферизация - это прием, он не реализован на уровне 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
Рисуем через WinAPI
    #32359350
m-j
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
m-j
Гость
Большое спасибо, все работает просто супер.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Рисуем через WinAPI
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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