WM_PAINT моргает

Тема в разделе "WASM.WIN32", создана пользователем murtix, 26 фев 2005.

  1. murtix

    murtix New Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    110
    Адрес:
    Russia
    при обработке WM_PAINT (рисую график на канве окна)

    окно моргает ужасно помню в делфи подобное лечилось DoubleBuffer-ом, а в масм что делать
     
  2. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    CreateCompatibleDC+рисовать в памяти+BitBlt из памяти на hDC окна



    Что за канва? Или канава?
     
  3. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    murtix

    в масм что делать

    Правильно обработать WM_ERASEBKGND.
     
  4. EGOiST

    EGOiST New Member

    Публикаций:
    0
    Регистрация:
    20 мар 2004
    Сообщения:
    7
    на с чет WM_ERASEBKGND по подробней пжалста :)
     
  5. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    EGOiST

    Обработчик WM_ERASEBKGND такой же как WM_PAINT, только не надо BeginPaint/EndPaint, т.к. wParam уже содержит hdc, + В первом надо возвращать не ноль. Примерно так:
    Код (Text):
    1. ...
    2. case WM_PAINT:
    3. case WM_ERASEBKGND:
    4. {
    5.   PAINTSTRUCT ps;
    6.   HDC hdc  = ((WM_ERASEBKGND == uMsg) ? (HDC) wParam : BeginPaint(hwnd, &ps));
    7.  
    8.   ...  /* здесь необходимо полностью обновить
    9.           клиентскую часть окна */
    10.  
    11.   if (WM_ERASEBKGND != uMsg)
    12.     EndPaint(hwnd, &ps);
    13.  
    14.   return (WM_ERASEBKGND == uMsg) ? 1 : 0;
    15. }
    16. ...
     
  6. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    q_q

    Т.е. вы рисуете и в WM_PAINT и в WM_ERASEBKGND. Зачем 2 раза подряд рисовать? От этого моргать будет ещё больше. Проще отключить WM_ERASEBKGND (в обработчике вернуть 1) и рисовать только в WM_PAINT.
     
  7. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Quantum

    От этого моргать будет ещё больше

    Не правда.

    Моргает потому, что стандартный обработчик WM_ERASEBKGND заливает клиентскую область цветом/паттерном указанным в WNDCLASS.hbrBackground, т.е. стирает предыдущую картинку. Именно отсутствие картинки между вызовами WM_ERASEBKGND и WM_PAINT обеспечивает эффект моргания.



    Зачем 2 раза подряд рисовать? ... Проще отключить WM_ERASEBKGND ... рисовать только в WM_PAINT.

    Не факт. Все зависит от конкретного задания.

    Я не знаю, сколько времени пройдет между этими вызовами. Если рисование картинки заключается в тривиальном BitBlt, то это практически не скажется на производительности.
     
  8. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    q_q



    Согласен.





    Я не знаю ни одного задания, где бы возникла необходимость рисовать одно и тоже 2 раза подряд. А пустой обработчик WM_ERASEBKGND - это рекомендация самой MS. Об этом где-то в MSDN написано.
     
  9. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    q_q







    Разве возврат ненулевого значения по WM_ERASEBKGND не предотвращает стирание бэкграунда стандартным обработчиком?
     
  10. flankerx

    flankerx New Member

    Публикаций:
    0
    Регистрация:
    2 июл 2004
    Сообщения:
    423
    Адрес:
    Moscow, Russia
    MSDN:

    An application should return nonzero if it erases the background; otherwise, it should return zero.



    An application should return nonzero in response to WM_ERASEBKGND if it processes the message and erases the background; this indicates that no further erasing is required. If the application returns zero, the window will remain marked for erasing.
     
  11. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    flankerx



    Ничто не мешает не стирать бэкграунд, и при этом вернуть единицу, чтобы и системный обработчик тоже не стер.

    Тогда и перерисовывать по WM_ERASEBKGND без необходимости не надо будет. А когда действительно будет необходимо, тебе пришлют WM_PAINT. Вот тогда и рисуй
     
  12. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Quantum & cresta

    Теоретически вы правы, достаточно вернуть не ноль.

    Однако я не исключаю существование задачи, где обработка WM_ERASEBKGND и WM_PAINT может потребовать как различные, так и общие действия, поэтому использовал фразу "примерно так", т.е. код обработчика зависит от конкретной задачи. Заметьте пояснить про WM_ERASEBKGND попросил не автор темы, т.е. задача не конкретизирована.



    Еще эффект мерцания может наблюдаться если в обработчике WM_PAINT картинка на какой-то момент будет стерта, например, обработчик устроен так, что сначала очищается фон, а потом рисуется рисунок.



    Итого для подавления эффекта мерцания необходимо обеспечить одновременный вывод фона и рисунка, т.е. обрабатывать WM_ERASEBKGND и выводить картинку при помощи, например, BitBlt.
     
  13. murtix

    murtix New Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    110
    Адрес:
    Russia
    В общем вписал пустой обработчик WM_ERASEBKGND перестала в основном моргать. Просто я WM_PAINT обрабатываю в WM_MOUSEMOVE, точнее вызываю

    invoke InvalidateRect,hWin,NULL,TRUE

    и при этом в WM_PAINT делаю еще и вычисления с использованием сопроцессора (привожу вещественный массив к целочисленному и черчу график заливая перед этим задний фон) (извращенство :)? щас исправлюсь !).

    Кстати, q_q именно для этого мне нужны массивы в структуре при этом в структуре я хочу хранить еще и параметры графика цвет, толшина и т.п. и графиков должно быть много.

    И еще я использую гди плюс.
     
  14. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257




    Вот от этого тоже надо избавиться. Рисуй свой график в memoryDC, а когда будет готов, перенесёшь его на hDC. Не стирая предыдущего. Поверх.
     
  15. murtix

    murtix New Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    110
    Адрес:
    Russia
    заливку фона реализовал в WM_ERASEBKGND.

    Так наверно лучше?.
     
  16. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Какая необходимость заливать, тратя на это время и провоцируя мерцание, от которого хочешь избавиться?



    BitBlt скопирует рисунок, подготовленный в памяти, поверх старого рисунка. Перекроет старый полностью. Без необходимости стирания. И соответственно без мерцания.
     
  17. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Код (Text):
    1. ;========== WindowProc =======================
    2.     ;......
    3.     mov eax,uMsg
    4.     .if eax==WM_INITDIALOG
    5.         push hWin
    6.         pop  hWnd
    7.         invoke SetTimer,hWin,1,1000,NULL
    8.     .elseif eax==WM_PAINT    
    9.         mov hDC,FUNC(BeginPaint,hWin,ADDR Ps)
    10.         push hDC
    11.         push hWin
    12.         Call PaintProc
    13.         invoke EndPaint,hWin,ADDR Ps   
    14.         mov eax,TRUE
    15.         ret
    16.     .elseif eax==WM_TIMER
    17.         invoke GetDC,hWin
    18.         mov hDC,eax
    19.         push hDC
    20.         push hWin
    21.         Call PaintProc
    22.         invoke ReleaseDC,hWin,hDC
    23.         ret
    24. ;================================================
    25. PaintProc proc hwnd:DWORD, hdc:DWORD
    26.     LOCAL memDC                 :DWORD
    27.     LOCAL Rct                   :RECT
    28.     LOCAL mRct                  :RECT
    29.     LOCAL hBmp                  :DWORD
    30.     LOCAL hBrush                :DWORD
    31.     LOCAL hFont                 :DWORD
    32.     LOCAL Buffer[16]            :BYTE
    33.  
    34. .data  
    35.     Verdana_48    LOGFONT <-70,0,0,0,700,0,0,0,-52,3,2,1,34,"Verdana]
    36.     dwCounter     dd 0
    37. .code
    38.     mov hFont,FUNC(CreateFontIndirect,ADDR Verdana_48)
    39.     mov memDC, FUNC(CreateCompatibleDC,hdc)
    40.     mov hBmp,FUNC(CreateCompatibleBitmap,hdc,400,400)
    41.     invoke SelectObject,memDC,hBmp
    42.     mov hBrush,FUNC(GetStockObject,WHITE_BRUSH)
    43.     mov mRct.left,0
    44.     mov mRct.top,0
    45.     mov mRct.right,400
    46.     mov mRct.bottom,400
    47.     invoke FillRect,memDC,ADDR mRct,hBrush
    48.     invoke DeleteObject,hBrush
    49.     mov mRct.top,100
    50.     mov mRct.bottom,300
    51.     mov hBrush,FUNC(GetStockObject,LTGRAY_BRUSH)
    52.     invoke FillRect,memDC,ADDR mRct,hBrush
    53.     invoke DeleteObject,hBrush
    54.     invoke SelectObject,memDC,hFont
    55.     invoke SetBkMode,memDC,TRANSPARENT
    56.     invoke wsprintf,ADDR Buffer,SADD("%lu"),dwCounter
    57.     invoke lstrcat,ADDR Buffer,SADD(" MemDC")
    58.     invoke DrawText,memDC,ADDR Buffer,-1,ADDR mRct,65h
    59.     inc dwCounter
    60.     invoke BitBlt,hdc,0,0,400,400,memDC,0,0,SRCCOPY
    61.    
    62.     invoke DeleteObject,hBmp
    63.     invoke DeleteObject,hFont
    64.     invoke DeleteDC,memDC
    65.     ret
    66. PaintProc endp




    Это не график, но тоже довольно толстым шрифтом выводится :) Принцип тот же.

    И при этом два раза происходит FillRect - первый раз белой кистью, на весь кусок, второй раз - серой, на половину куска. И тем не менее не мерцает, т.к. все эти операции производятся в памяти, этого процесса не видно, и только после того, как всё нарисовано, залито, стерто и готово к употреблению, отображается на экране (BitBlt).



    P.S.

    WM_ERASEBKGND не обрабатывается никак. Его вообще нет в WndProc.
     
  18. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    murtix

    именно для этого мне нужны массивы в структуре

    Imho зря ты разорвался на две темы. Давай о структурах там, только дай больше информации о их применении.



    заливку фона реализовал в WM_ERASEBKGND

    Обработчик, используемый по умолчанию, сделает это сам, только укажи правильный цвет/паттерн при регистрации класса окна.



    В общем cresta совершенно справедливо заметил, что необходимо все рисование делать в память, а в WM_PAINT только BitBlt.





    cresta

    WM_ERASEBKGND не обрабатывается никак. Его вообще нет в WndProc

    Твой диалог позволяет менять собственные размеры?
     
  19. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    q_q



    Да, я обращал на этот момент тоже внимание, когда растягиваю/сжимаю окно, тоже не мерцает.



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



    Но запускать и ресайзить вполне можно. Безобидно.



    [​IMG] 2146441885__Test Project.exe
     
  20. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Забыл dll, может без неё не запустится, можно рядом с ехе кинуть

    [​IMG] 93263337__BrowseDLG.dll