При получении моим окном WM_PAINT я должен перерисовать в своем rect`е изображение. Для этого я должен постояно знать/хранить что и где мне надо нарисовать. Не хачу! Надо чтоб то что я уже нарисовал, не перерисовывалось, а я отрисовывал только изменения. Т.е. есть задача, еложу мышкой где-нибудь давлю кнопарь у меня там рисуется символ. И вот не хочется мне хранить все координаты тыканья этой мыши, чтобы коректно отображать экран. Может кто знает как быть в данном случае? Вопрос второй, как я могу узнать rect вышележашего окна, т.е. того которое закрывает какую-либо мою область окна? Заранее благодарю, и прошу прощения за такие глупые вопросы .
San1 Там - это где? На кнопке? Или в окне? Если на кнопке, то вынеси сообщения для кнопки в отдельную процедуру, и не надо будет рисовать окно, только для кнопки будешь обрабатывать сообщения. Если в окне, пробуй GetUpdateRect по WM_PAINT При WM_PAINT обычно вызывается BeginPaint, она заполняет структуру PAINTSTRUCT, в которой есть такое: rcPaint Specifies a RECT structure that specifies the upper left and lower right corners of the rectangle in which the painting is requested, in device units relative to the upper-left corner of the client area. Если это всё не то, расшифруй вопрос, а то уж больно криво задан
Криво задавать вопросы - это я умею Расшифрую что хочу получить... Обрабатываю сообщения о движении мыши, когда юзерь давит кнопку мыши, то совершается некоторое дейсвие над экраном (пусть для простоты печатается, нет, пусть лучше рисуется какой то символ) После этого вызываю InvalidateRect. В результате получаю WM_PAINT, и конечно структуру с описанием координат области для перерисовки окна. Вот теперь самое интересное, как мне сделать так чтобы сохранить на экране то, что уже там было прорисовано. у меня происходит полное перерисовка области rect. Просто только начинаю копаться в win32 и не знаю за что зацепится.
Написал вот такое... Код (Text): Displ db "DISPLAY",0 Char WPARAM 20h WndProc PROC hWnd: HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM LOCAL hdc :HDC LOCAL hdcD :HDC LOCAL ps :PAINTSTRUCT LOCAL rect :RECT LOCAL hfont :HFONT .IF uMsg==WM_DESTROY invoke DeleteDC, hdc invoke PostQuitMessage, 0 .ELSEIF uMsg==WM_CREATE invoke CreateDC, addr Displ,0,0,0 mov hdcD, eax invoke CreateCompatibleDC, eax mov hdc,eax invoke GetDeviceCaps, hdcD, HORZRES push eax invoke GetDeviceCaps, hdcD, VERTRES pop ebx invoke CreateCompatibleBitmap, hdc, eax, ebx invoke SelectObject, hdc, eax invoke DeleteDC, hdcD .ELSEIF uMsg==WM_CHAR mov eax, wParam mov Char,eax invoke TextOut, hdc, 0, 0,offset Char, 1 invoke InvalidateRect, hWnd, 0,1 .ELSEIF uMsg==WM_RBUTTONDOWN mov eax,lParam call MoveMouse RGB 255, 0, 0 invoke SetTextColor, hdc, eax invoke TextOut, hdc, hitpoint.x, hitpoint.y,addr Char, 1 invoke InvalidateRect,hWnd,0,1 .ELSEIF uMsg==WM_MOUSEMOVE mov eax,lParam call MoveMouse .ELSEIF uMsg==WM_PAINT invoke BeginPaint, hWnd, addr ps mov hdcD, eax invoke GetClientRect, hWnd, addr rect mov eax, rect.bottom sub eax, rect.top mov ebx, rect.right sub ebx, rect.left invoke BitBlt, hdcD, rect.left, rect.top, ebx, eax, hdc, rect.left, rect.top, SRCCOPY call GetLastError invoke EndPaint, hWnd, addr ps .ELSE invoke DefWindowProc, hWnd, uMsg, wParam, lParam ret .ENDIF xor eax,eax ret WndProc ENDP не работает. BitBlt ругается. Помогите глупому, наставте на путь истинный
Если ты нарисовал например при помощи DrawText или DrawIcon что-либо на своём hDC, и затем вызываешь InvalidateRect, провоцируя WM_PAINT, при этом ты потеряешь свой рисунок. Чтобы не терять, ты должен и по WM_PAINT тоже рисовать такой же рисунок. Попробуй сделать обработчик WM_PAINT таким образом, чтобы в нем можно было рисовать, печатать текст и т.д. Щас попытаюсь понятней выразится Пусть есть исходная процедура которую ты вызываешь по WM_PAINT с упрощениями примерно так: Код (Text): .data SomeText db 260 Dup(0) hSomeIcon dd 0 .code PaintProc proc ;-- здесь какие-то действия, выполняемые при каждом WM_PAINT, например залить область mov hDC, FUNC(BeginPaint,hWin,ADDR Ps) invoke GetClientRect,hWin, ADDR Rct invoke FillRect,hDC,ADDR Rct,hBrush ;-- а здесь действия, которые могут и не выполняться, в зависимости от некоторых условий: invoke DrawText,hDC,ADDR SomeText,-1,ADDR Rct,NULL invoke DrawIconEx,hDC,1,1,hSomeIcon,0,0,0,0,DI_NORMAL ;-- и здесь снова выполняемое при каждом WM_PAINT: invoke EndPaint,hWin, ADDR Ps ret PaintProc endp И когда тебе надо напечатать какой-то текст, скопируй его в буфер SomeText и вызывай InvalidateRect, при этом перерисуется окно и напечатается текст, который в буфере, если тебе надо убрать текст, забей первый байт буфера нулём, и снова InvalidateRect, окно перерисуется, но уже без текста. Вернее с текстом пустая строка. Ну и аналогично если надо например иконку нарисовать: в hSomeIcon либо хэндл иконки, либо ноль. Если ноль - не рисуем, если валидный хэндл - отображаем. Это так, схематически написано, можно дополнить и развить эту процедуру, например, указывать RECT для текста или для рисунка, может лучше сначала проверять буфер на ноль, и если ноль, то вообще не вызывать DrawIcon или DrawText, и прочие вещи
San1 Написал вот такое... Мой приятель делал нечто подобное для буржуйского форума. Если есть вопросы спрашывай. _609352800__demoforgallo.rar
Я тут немного опоздал, но ничего: Если тебе по WM_MOUSEMOVE, то примерно так попробуй вызывать: Код (Text): .ELSEIF uMsg==WM_MOUSEMOVE mov eax, lParam ;здесь определяем, где мышь ;- ;- ;и если она в какой-то оговоренной области, ;пишем текст: invoke lstrcpy ADDR SomeText, ADDR Buffer invoke InvalidateRect,hWnd,NULL,TRUE ret ;если мышь за пределами участка, и надо стереть надпись lea eax,SomeText mov byte ptr [eax],0 invoke InvalidateRect,hWnd,NULL,TRUE ret И ещё: заведи переменную - флаг, которая будет показывать нарисован или стерт текст, чтобы при движении мыши постоянно не перерисовывать уже нарисованое, или соответственно, не стирать уже стертое. Нарисовал - забей во флаг 1, стёр - 0, и если мышь движется, проверь флаг, стерта надпись или нет, может и не надо лишний раз вызывать InvalidateRect Чот касается BitBlt, то где у ты получаешь hdc? Если считаешь, что по WM_CREATE получил и достаточно, то наверное это ошибочно, надо при каждом WM_PAINT делать CreateCompatibleDC. имхо.
cresta заведи переменную - флаг ... может и не надо лишний раз вызывать InvalidateRect WM_PAINT приходят по разным причинам, поэтому флаг тут не помощник. надо при каждом WM_PAINT делать CreateCompatibleDC Не уверен, не пиши.
q_q Я не предлагаю WM_PAINT обрабатывать\не обрабатывать по флагу, а именно InvalidateRect вызывать\не вызывать в зависимости от того, надо изменить\не надо изменить Написал же "наверное" и в конце добавил: "имхо"
Блин, как у вас всё сложно. Я предлагаю: 1. Все рисование происходит только в обработчке WM_PAINT 2. Если необходимо изменить часть экрана, то используем InvalidateRect() 3. Используем флаги для обозначения видимости элементов, то есть проверяем их в обработчике WM_PAINT 4. Если происходит событие, могущее показать/спрятать элемент, то при получении такого события необходимо исследовать/изменять флаги и на основании исследования звать или не звать InvalidateRect() Если делать, как я предлагаю, то система сама будет следить, что нарисовано, а что надо перерисовать. Эта информация доступна из PAINTSTRUCT, как заметил cresta.
Если же элементов нет никаких, а надо рисовать мышью везде, где тычут, и чтоб при этом оставалось (как в PANIT), то необходимо после рисования сохранять изображения окна, а перед рисованием выводить сохранённое изображение.
to q_q Огромное спасибо за исходник, очень помог. Разобрался со своими грехами. Я не верно определял размер области в памяти, да еще и hdc блока памяти засунул в локал , поэтому Blt и ругался постояно разными ошибками. to cresta Дело в том что так как ты предлагаешь я делал. Т.е. у меня был массивчик с указанием хитпоинтов, строки символов и флага отрисовки. У этого метода есть очень большие недостатки: алгоритм запутанный, и при необходимости изменения программы в сторону утяжеления её другими отображаемыми элементами надо изрядно код поколбасить. Поэтому подумал что рисовать надо не на экране, а сразу в памяти, а по WM_PAINT отображать из памяти на экран. Вот собствено над чем и бился. Foamplast Проше сразу в памяти рисовать.