Перерисовка окна

Discussion in 'WASM.BEGINNERS' started by mc black, May 25, 2007.

  1. mc black

    mc black Member

    Blog Posts:
    0
    Joined:
    Jan 19, 2005
    Messages:
    213
    Location:
    Russia, N.Novgorod
    Как принудительно перерисовать окно своей программы? Я вызываю UpdateWindow или посылаю WM_PAINT, но внешний вид окошка не меняется (а должен). Окно у меня WS_EX_LAYERED с LMA_ALPHA or LMA_COLORKEY, на окошке я рисую через DrawText и т.п., а когда данные изменяются, надо их напечатать по новой. Что-то делаю не так??
     
  2. Perre

    Perre New Member

    Blog Posts:
    0
    Joined:
    Apr 6, 2007
    Messages:
    100
    Текст выведеный через DrawText при перерисовке не перерииисовуется системой, его надо выводить снова , отлавливая сообщения WM_PAINT
     
  3. wasm_test

    wasm_test wasm test user

    Blog Posts:
    0
    Joined:
    Nov 24, 2006
    Messages:
    5,582
    Все, что ты выводишь, нужно перерисовывать в WM_PAINT заново. Оно для этого и посылается программе, чтобы та перерисовала клиентскую часть окна.
    Когда окно затирается другим, А потом снова появляется, то неклиентскую часть винда перерисовывает самостоятельно (хотя это поведение можно изменить). А вот как рисовать клиентскую часть она не знает, поэтому и посылает WM_PAINT, чтобы программа сама занялась обновлением клиентской части окна.
    То есть, если у тебя графический редактор, например, придется гдето запоминать нарисованное дополнительно, чтобы это все заново воспроизводить в окошке при WM_PAINT
     
  4. mc black

    mc black Member

    Blog Posts:
    0
    Joined:
    Jan 19, 2005
    Messages:
    213
    Location:
    Russia, N.Novgorod
    Perre, Great я всё это прекрасно понимаю, поэтому тем более мне непонятно, почему PaintProc, которая выполняется у меня при обработке сообщения WM_PAINT выполняется лишь однажды - при первом построении окна, но затем при вызове UpdateWindow сообщение WM_PAINT больше не приходит окну..

    Сдается мне, что-то я делаю не так! Но что именно?

    У меня календарик на рабочий стол. Есть глобальная переменная типа SYSTEMTIME и ещё пара глобальных переменных, которые я заполняю до создания окна, а потом на основе этих переменных строится вся картинка в PaintProc. Процедура выполняется после сообщения WM_PAINT, следовательно достаточно изменить мои переменные и заставить перерисовать окно. Переменные меняю, но вот как перерисовать, если UpdateWindow у меня почему-то не сработала? не перерисовывается мое окно :dntknw:
     
  5. Quantum

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

    Blog Posts:
    0
    Joined:
    Jan 6, 2003
    Messages:
    3,143
    Location:
    Ukraine
    mc black
    InvalidateRect + UpdateWindow
     
  6. asmfan

    asmfan New Member

    Blog Posts:
    0
    Joined:
    Jul 10, 2006
    Messages:
    1,004
    Location:
    Abaddon
    RedrawWindow
     
  7. wasm_test

    wasm_test wasm test user

    Blog Posts:
    0
    Joined:
    Nov 24, 2006
    Messages:
    5,582
    Сдается мне, что действительно что-то не так. Покажи код.
    точнее, у тебя почему-то не вызывается WndProc с WM_PAINT
    Опять же, код в студию. Полный сорс обработчика сообщений и создания окна
     
  8. cresta

    cresta Active Member

    Blog Posts:
    0
    Joined:
    Jun 13, 2004
    Messages:
    2,257
    Quantum

    А зачем "+UpdateWindow" ?
    Достаточно просто InvalidateRect.
     
  9. Quantum

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

    Blog Posts:
    0
    Joined:
    Jan 6, 2003
    Messages:
    3,143
    Location:
    Ukraine
    cresta
    Чтоб не ждать когда user32 удосужиться отправить сообщение WM_PAINT.
     
  10. cresta

    cresta Active Member

    Blog Posts:
    0
    Joined:
    Jun 13, 2004
    Messages:
    2,257
    Ни разу не видел, чтобы задержка была бы заметна на глаз :)
    К тому же в описании UpdateWindow не указано, что UpdateWindow форсирует WM_PAINT. Посылает - да, но сообщение будет послано, когда винда посчитает нужным. Иначе говоря, не форсирует.
     
  11. Quantum

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

    Blog Posts:
    0
    Joined:
    Jan 6, 2003
    Messages:
    3,143
    Location:
    Ukraine
    cresta
    Примитивная спрайтовая анимация на слабой машине - задержку видно на глаз. Но проблема у человека не в задержке сообщения а в том, что оно не приходит.

    Если не использовать UpdateWindow, то сообщения WM_PAINT могут совмещаться, т.е. вместо нескольких таких сообщений подряд приходит одно.

    А что она тогда делает? :)
     
  12. q_q

    q_q New Member

    Blog Posts:
    0
    Joined:
    Oct 5, 2003
    Messages:
    1,706
    cresta
    описании UpdateWindow не указано
    Imho заблуждаешься.
    Цитата msdn. UpdateWindow: "The UpdateWindow function updates the client area of the specified window by sending a WM_PAINT message to the window if the window's update region is not empty. The function sends a WM_PAINT message directly to the window procedure of the specified window, bypassing the application queue. If the update region is empty, no message is sent."
     
  13. AsmGuru62

    AsmGuru62 Member

    Blog Posts:
    0
    Joined:
    Sep 12, 2002
    Messages:
    689
    Location:
    Toronto
    Code (Text):
    1. ...
    2.  
    3. case WM_PAINT:
    4.   WmPaint ();  // <-- BRK1
    5.   break;
    6.  
    7. ...
    8.  
    9.  
    10. UpdateWindow (...);  // <-- BRK2
    11. NextCall ();  // <-- BRK3
    В отладчике легко видно, что если достигается BRK2, то BRK1 будет перед BRK3, иными словами WM_PAINT вызовется до возврата из UpdateWindow().
     
  14. kero

    kero Модератор SOURCES & 2LZ Staff Member

    Blog Posts:
    0
    Joined:
    Apr 4, 2006
    Messages:
    1,074
    Location:
    Москва
    Забудьте об этой никчемной UpdateWindow :)

    При изменении данных -
    либо InvalidateRect(hWnd,0,1),
    либо RedrawWindow(hWnd,0,0,RDW_INVALIDATE OR RDW_ERASE),
    а далее -
    либо на WM_PAINT:
    BeginPaint(hWnd,addr ps)
    Func(eax)
    EndPaint(hWnd,addr ps)

    либо на WM_ERASEBKGND:
    DefWindowProc(hWnd,uMsg,wParam,lParam)
    Func(wParam)

    где Func, например, -
    SetBkMode(TRANSPARENT)
    DrawText
     
  15. mc black

    mc black Member

    Blog Posts:
    0
    Joined:
    Jan 19, 2005
    Messages:
    213
    Location:
    Russia, N.Novgorod
    Всем спасибо, решил эту проблемму вчера вечером, додумался точно до того же: GetClientRect - InvalidateRect - UpdateWindow У меня не работало потому, что UpdateWindow не будет посылать никакого сообщения WN_PAINT, если нет областей указанны для перерисовки. Спасибо большое за участие всем ещё раз!
     
  16. kero

    kero Модератор SOURCES & 2LZ Staff Member

    Blog Posts:
    0
    Joined:
    Apr 4, 2006
    Messages:
    1,074
    Location:
    Москва
    mc black

    >GetClientRect - InvalidateRect - UpdateWindow

    Решили - это хорошо, но уверены, что код у вас не избыточен ?
    В ваших же интересах было бы его все-таки показать.
     
  17. AsmGuru62

    AsmGuru62 Member

    Blog Posts:
    0
    Joined:
    Sep 12, 2002
    Messages:
    689
    Location:
    Toronto
    Только не надо вызывать самому ни WM_PAINT, ни WM_ERASEBKGND. Это делает Windows.

    Не так давно, я сопровождал большой C++ проект, где такая "техника" постоянно использовалась. После такого невозможно отловить те места, где не происходит правильная перерисовка - всегда оставались не перерисованные места.

    Правильный подход к рисованию это пара InvalidateRect()/UpdateWindow() или единственный RedrawWindow(). Причём "InvalidateRect (hWnd, 0, 1);" может вызвать мелькание. Лучше всего в InvalidateRect () указывать инвалидный прямоугольник, тогда Windows отсечёт всё не нужное и прорисовка произойдёт быстрее.
     
  18. mc black

    mc black Member

    Blog Posts:
    0
    Joined:
    Jan 19, 2005
    Messages:
    213
    Location:
    Russia, N.Novgorod
    Не вопрос с исходниками, код открытый целиком и стопудово не на 100% оптимальный, возможно где-то и избыточный. Скачать можно на http://mc-black.narod.ru/src/dzp.src.zip По всему проекту интересны ваши отклики.

    AsmGuru62, UpdateWindow блокирует все сообщения до тех пор, пока окошко не перерисуется, поэтому и могут возникать корявости, когда пытаются отправлять WM_PAINT.
     
  19. kero

    kero Модератор SOURCES & 2LZ Staff Member

    Blog Posts:
    0
    Joined:
    Apr 4, 2006
    Messages:
    1,074
    Location:
    Москва
    mc black

    >UpdateWindow блокирует все сообщения до тех пор, пока окошко не перерисуется, поэтому и могут возникать корявости, когда пытаются отправлять WM_PAINT.

    ???
     
  20. AsmGuru62

    AsmGuru62 Member

    Blog Posts:
    0
    Joined:
    Sep 12, 2002
    Messages:
    689
    Location:
    Toronto
    kero
    Всё верно - блокирует. Потому что напрямую вызывается процедура окна:
    Что-то в таком вот виде (реализация UpdateWindow()):
    Code (Text):
    1. BOOL UpdateWindow (HWND hWnd)
    2. {
    3.     ...
    4.     WNDPROC pfnWndProc = GetWindowLong (hWnd, GWL_WNDPROC);
    5.     CallWindowProc (pfnWndProc, hWnd, WM_PAINT, ... , ... );
    6.     ...
    7. }
    Ну и естественно, пока процедура окна не вернётся - других сообщений не получим. Хотя процедура окна реентерабельна... в принципе.