при обработке WM_PAINT (рисую график на канве окна) окно моргает ужасно помню в делфи подобное лечилось DoubleBuffer-ом, а в масм что делать
EGOiST Обработчик WM_ERASEBKGND такой же как WM_PAINT, только не надо BeginPaint/EndPaint, т.к. wParam уже содержит hdc, + В первом надо возвращать не ноль. Примерно так: Код (Text): ... case WM_PAINT: case WM_ERASEBKGND: { PAINTSTRUCT ps; HDC hdc = ((WM_ERASEBKGND == uMsg) ? (HDC) wParam : BeginPaint(hwnd, &ps)); ... /* здесь необходимо полностью обновить клиентскую часть окна */ if (WM_ERASEBKGND != uMsg) EndPaint(hwnd, &ps); return (WM_ERASEBKGND == uMsg) ? 1 : 0; } ...
q_q Т.е. вы рисуете и в WM_PAINT и в WM_ERASEBKGND. Зачем 2 раза подряд рисовать? От этого моргать будет ещё больше. Проще отключить WM_ERASEBKGND (в обработчике вернуть 1) и рисовать только в WM_PAINT.
Quantum От этого моргать будет ещё больше Не правда. Моргает потому, что стандартный обработчик WM_ERASEBKGND заливает клиентскую область цветом/паттерном указанным в WNDCLASS.hbrBackground, т.е. стирает предыдущую картинку. Именно отсутствие картинки между вызовами WM_ERASEBKGND и WM_PAINT обеспечивает эффект моргания. Зачем 2 раза подряд рисовать? ... Проще отключить WM_ERASEBKGND ... рисовать только в WM_PAINT. Не факт. Все зависит от конкретного задания. Я не знаю, сколько времени пройдет между этими вызовами. Если рисование картинки заключается в тривиальном BitBlt, то это практически не скажется на производительности.
q_q Согласен. Я не знаю ни одного задания, где бы возникла необходимость рисовать одно и тоже 2 раза подряд. А пустой обработчик WM_ERASEBKGND - это рекомендация самой MS. Об этом где-то в MSDN написано.
q_q Разве возврат ненулевого значения по WM_ERASEBKGND не предотвращает стирание бэкграунда стандартным обработчиком?
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.
flankerx Ничто не мешает не стирать бэкграунд, и при этом вернуть единицу, чтобы и системный обработчик тоже не стер. Тогда и перерисовывать по WM_ERASEBKGND без необходимости не надо будет. А когда действительно будет необходимо, тебе пришлют WM_PAINT. Вот тогда и рисуй
Quantum & cresta Теоретически вы правы, достаточно вернуть не ноль. Однако я не исключаю существование задачи, где обработка WM_ERASEBKGND и WM_PAINT может потребовать как различные, так и общие действия, поэтому использовал фразу "примерно так", т.е. код обработчика зависит от конкретной задачи. Заметьте пояснить про WM_ERASEBKGND попросил не автор темы, т.е. задача не конкретизирована. Еще эффект мерцания может наблюдаться если в обработчике WM_PAINT картинка на какой-то момент будет стерта, например, обработчик устроен так, что сначала очищается фон, а потом рисуется рисунок. Итого для подавления эффекта мерцания необходимо обеспечить одновременный вывод фона и рисунка, т.е. обрабатывать WM_ERASEBKGND и выводить картинку при помощи, например, BitBlt.
В общем вписал пустой обработчик WM_ERASEBKGND перестала в основном моргать. Просто я WM_PAINT обрабатываю в WM_MOUSEMOVE, точнее вызываю invoke InvalidateRect,hWin,NULL,TRUE и при этом в WM_PAINT делаю еще и вычисления с использованием сопроцессора (привожу вещественный массив к целочисленному и черчу график заливая перед этим задний фон) (извращенство ? щас исправлюсь !). Кстати, q_q именно для этого мне нужны массивы в структуре при этом в структуре я хочу хранить еще и параметры графика цвет, толшина и т.п. и графиков должно быть много. И еще я использую гди плюс.
Вот от этого тоже надо избавиться. Рисуй свой график в memoryDC, а когда будет готов, перенесёшь его на hDC. Не стирая предыдущего. Поверх.
Какая необходимость заливать, тратя на это время и провоцируя мерцание, от которого хочешь избавиться? BitBlt скопирует рисунок, подготовленный в памяти, поверх старого рисунка. Перекроет старый полностью. Без необходимости стирания. И соответственно без мерцания.
Код (Text): ;========== WindowProc ======================= ;...... mov eax,uMsg .if eax==WM_INITDIALOG push hWin pop hWnd invoke SetTimer,hWin,1,1000,NULL .elseif eax==WM_PAINT mov hDC,FUNC(BeginPaint,hWin,ADDR Ps) push hDC push hWin Call PaintProc invoke EndPaint,hWin,ADDR Ps mov eax,TRUE ret .elseif eax==WM_TIMER invoke GetDC,hWin mov hDC,eax push hDC push hWin Call PaintProc invoke ReleaseDC,hWin,hDC ret ;================================================ PaintProc proc hwnd:DWORD, hdc:DWORD LOCAL memDC :DWORD LOCAL Rct :RECT LOCAL mRct :RECT LOCAL hBmp :DWORD LOCAL hBrush :DWORD LOCAL hFont :DWORD LOCAL Buffer[16] :BYTE .data Verdana_48 LOGFONT <-70,0,0,0,700,0,0,0,-52,3,2,1,34,"Verdana] dwCounter dd 0 .code mov hFont,FUNC(CreateFontIndirect,ADDR Verdana_48) mov memDC, FUNC(CreateCompatibleDC,hdc) mov hBmp,FUNC(CreateCompatibleBitmap,hdc,400,400) invoke SelectObject,memDC,hBmp mov hBrush,FUNC(GetStockObject,WHITE_BRUSH) mov mRct.left,0 mov mRct.top,0 mov mRct.right,400 mov mRct.bottom,400 invoke FillRect,memDC,ADDR mRct,hBrush invoke DeleteObject,hBrush mov mRct.top,100 mov mRct.bottom,300 mov hBrush,FUNC(GetStockObject,LTGRAY_BRUSH) invoke FillRect,memDC,ADDR mRct,hBrush invoke DeleteObject,hBrush invoke SelectObject,memDC,hFont invoke SetBkMode,memDC,TRANSPARENT invoke wsprintf,ADDR Buffer,SADD("%lu"),dwCounter invoke lstrcat,ADDR Buffer,SADD(" MemDC") invoke DrawText,memDC,ADDR Buffer,-1,ADDR mRct,65h inc dwCounter invoke BitBlt,hdc,0,0,400,400,memDC,0,0,SRCCOPY invoke DeleteObject,hBmp invoke DeleteObject,hFont invoke DeleteDC,memDC ret PaintProc endp Это не график, но тоже довольно толстым шрифтом выводится Принцип тот же. И при этом два раза происходит FillRect - первый раз белой кистью, на весь кусок, второй раз - серой, на половину куска. И тем не менее не мерцает, т.к. все эти операции производятся в памяти, этого процесса не видно, и только после того, как всё нарисовано, залито, стерто и готово к употреблению, отображается на экране (BitBlt). P.S. WM_ERASEBKGND не обрабатывается никак. Его вообще нет в WndProc.
murtix именно для этого мне нужны массивы в структуре Imho зря ты разорвался на две темы. Давай о структурах там, только дай больше информации о их применении. заливку фона реализовал в WM_ERASEBKGND Обработчик, используемый по умолчанию, сделает это сам, только укажи правильный цвет/паттерн при регистрации класса окна. В общем cresta совершенно справедливо заметил, что необходимо все рисование делать в память, а в WM_PAINT только BitBlt. cresta WM_ERASEBKGND не обрабатывается никак. Его вообще нет в WndProc Твой диалог позволяет менять собственные размеры?
q_q Да, я обращал на этот момент тоже внимание, когда растягиваю/сжимаю окно, тоже не мерцает. Тут в аттаче ехе, кнопки желательно не нажимать, это тестовый проект, всяку гадость на нем испытываю, не помню всего, что по кнопкам делается... )) (если что, я не виноват, а то я помню, как ты ругался ) Но запускать и ресайзить вполне можно. Безобидно. 2146441885__Test Project.exe