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

Тема в разделе "WASM.BEGINNERS", создана пользователем mc black, 25 май 2007.

  1. mc black

    mc black Member

    Публикаций:
    0
    Как принудительно перерисовать окно своей программы? Я вызываю UpdateWindow или посылаю WM_PAINT, но внешний вид окошка не меняется (а должен). Окно у меня WS_EX_LAYERED с LMA_ALPHA or LMA_COLORKEY, на окошке я рисую через DrawText и т.п., а когда данные изменяются, надо их напечатать по новой. Что-то делаю не так??
     
  2. Perre

    Perre New Member

    Публикаций:
    0
    Текст выведеный через DrawText при перерисовке не перерииисовуется системой, его надо выводить снова , отлавливая сообщения WM_PAINT
     
  3. wasm_test

    wasm_test wasm test user

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

    mc black Member

    Публикаций:
    0
    Perre, Great я всё это прекрасно понимаю, поэтому тем более мне непонятно, почему PaintProc, которая выполняется у меня при обработке сообщения WM_PAINT выполняется лишь однажды - при первом построении окна, но затем при вызове UpdateWindow сообщение WM_PAINT больше не приходит окну..

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

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

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

    Публикаций:
    0
    mc black
    InvalidateRect + UpdateWindow
     
  6. asmfan

    asmfan New Member

    Публикаций:
    0
    RedrawWindow
     
  7. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Сдается мне, что действительно что-то не так. Покажи код.
    точнее, у тебя почему-то не вызывается WndProc с WM_PAINT
    Опять же, код в студию. Полный сорс обработчика сообщений и создания окна
     
  8. cresta

    cresta Active Member

    Публикаций:
    0
    Quantum

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

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

    Публикаций:
    0
    cresta
    Чтоб не ждать когда user32 удосужиться отправить сообщение WM_PAINT.
     
  10. cresta

    cresta Active Member

    Публикаций:
    0
    Ни разу не видел, чтобы задержка была бы заметна на глаз :)
    К тому же в описании UpdateWindow не указано, что UpdateWindow форсирует WM_PAINT. Посылает - да, но сообщение будет послано, когда винда посчитает нужным. Иначе говоря, не форсирует.
     
  11. Quantum

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

    Публикаций:
    0
    cresta
    Примитивная спрайтовая анимация на слабой машине - задержку видно на глаз. Но проблема у человека не в задержке сообщения а в том, что оно не приходит.

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

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

    q_q New Member

    Публикаций:
    0
    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

    Публикаций:
    0
    Код (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 Команда форума

    Публикаций:
    0
    Забудьте об этой никчемной 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

    Публикаций:
    0
    Всем спасибо, решил эту проблемму вчера вечером, додумался точно до того же: GetClientRect - InvalidateRect - UpdateWindow У меня не работало потому, что UpdateWindow не будет посылать никакого сообщения WN_PAINT, если нет областей указанны для перерисовки. Спасибо большое за участие всем ещё раз!
     
  16. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    mc black

    >GetClientRect - InvalidateRect - UpdateWindow

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

    AsmGuru62 Member

    Публикаций:
    0
    Только не надо вызывать самому ни WM_PAINT, ни WM_ERASEBKGND. Это делает Windows.

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

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

    mc black Member

    Публикаций:
    0
    Не вопрос с исходниками, код открытый целиком и стопудово не на 100% оптимальный, возможно где-то и избыточный. Скачать можно на http://mc-black.narod.ru/src/dzp.src.zip По всему проекту интересны ваши отклики.

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

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    mc black

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

    ???
     
  20. AsmGuru62

    AsmGuru62 Member

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