· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.WIN32 —› Как перерисовать только изменения окна?

Посл.отвђт Сообщенiе


Дата: Ноя 3, 2004 10:55:53

При получении моим окном WM_PAINT я должен перерисовать в своем rect`е изображение. Для этого я должен постояно знать/хранить что и где мне надо нарисовать. Не хачу!
Надо чтоб то что я уже нарисовал, не перерисовывалось, а я отрисовывал только изменения. Т.е. есть задача, еложу мышкой где-нибудь давлю кнопарь у меня там рисуется символ. И вот не хочется мне хранить все координаты тыканья этой мыши, чтобы коректно отображать экран. Может кто знает как быть в данном случае?
Вопрос второй, как я могу узнать rect вышележашего окна, т.е. того которое закрывает какую-либо мою область окна?
Заранее благодарю, и прошу прощения за такие глупые вопросы :).


Дата: Ноя 3, 2004 11:26:56

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.

Если это всё не то, расшифруй вопрос, а то уж больно криво задан :)


Дата: Ноя 3, 2004 11:58:35

Криво задавать вопросы - это я умею :)
Расшифрую что хочу получить...
Обрабатываю сообщения о движении мыши, когда юзерь давит кнопку мыши, то совершается некоторое дейсвие над экраном (пусть для простоты печатается, нет, пусть лучше рисуется какой то символ) После этого вызываю InvalidateRect.
В результате получаю WM_PAINT, и конечно структуру с описанием координат области для перерисовки окна. Вот теперь самое интересное, как мне сделать так чтобы сохранить на экране то, что уже там было прорисовано. у меня происходит полное перерисовка области rect.
Просто только начинаю копаться в win32 и не знаю за что зацепится.


Дата: Ноя 3, 2004 16:41:03

Написал вот такое...
[code][/code]
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 ругается.

Помогите глупому, наставте на путь истинный


Дата: Ноя 3, 2004 17:12:20

Если ты нарисовал например при помощи DrawText или DrawIcon что-либо на своём hDC, и затем вызываешь InvalidateRect, провоцируя WM_PAINT, при этом ты потеряешь свой рисунок. Чтобы не терять, ты должен и по WM_PAINT тоже рисовать такой же рисунок. Попробуй сделать обработчик WM_PAINT таким образом, чтобы в нем можно было рисовать, печатать текст и т.д. Щас попытаюсь понятней выразится :)

Пусть есть исходная процедура которую ты вызываешь по WM_PAINT с упрощениями примерно так:
.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, и прочие вещи


Дата: Ноя 3, 2004 17:33:36

San1
Написал вот такое...
Мой приятель делал нечто подобное для буржуйского форума. Если есть вопросы спрашывай.


_609352800__demoforgallo.rar


Дата: Ноя 3, 2004 17:34:19

Я тут немного опоздал, но ничего:

Если тебе по WM_MOUSEMOVE, то примерно так попробуй вызывать:
    .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. имхо.


Дата: Ноя 3, 2004 17:41:44

cresta
заведи переменную - флаг ... может и не надо лишний раз вызывать InvalidateRect
WM_PAINT приходят по разным причинам, поэтому флаг тут не помощник.

надо при каждом WM_PAINT делать CreateCompatibleDC
Не уверен, не пиши.


Дата: Ноя 3, 2004 18:21:53

q_q

„WM_PAINT приходят по разным причинам, поэтому флаг тут не помощник“

Я не предлагаю WM_PAINT обрабатывать\не обрабатывать по флагу, а именно InvalidateRect вызывать\не вызывать в зависимости от того, надо изменить\не надо изменить

„Не уверен, не пиши“

Написал же "наверное" и в конце добавил: "имхо"


Дата: Ноя 4, 2004 02:36:19

Блин, как у вас всё сложно.

Я предлагаю:

1. Все рисование происходит только в обработчке WM_PAINT
2. Если необходимо изменить часть экрана, то используем InvalidateRect()
3. Используем флаги для обозначения видимости элементов,
то есть проверяем их в обработчике WM_PAINT
4. Если происходит событие, могущее показать/спрятать элемент, то при получении такого события необходимо исследовать/изменять флаги и на основании исследования звать или не звать InvalidateRect()

Если делать, как я предлагаю, то система сама будет следить, что нарисовано, а что надо перерисовать. Эта информация доступна из PAINTSTRUCT, как заметил cresta.


Дата: Ноя 4, 2004 02:38:41

Если же элементов нет никаких, а надо рисовать мышью везде, где тычут, и чтоб при этом оставалось (как в PANIT), то необходимо после рисования сохранять изображения окна, а перед рисованием выводить сохранённое изображение.


Дата: Ноя 4, 2004 08:47:22

to q_q
Огромное спасибо за исходник, очень помог. Разобрался со своими грехами. Я не верно определял размер области в памяти, да еще и hdc блока памяти засунул в локал :), поэтому Blt и ругался постояно разными ошибками.

to cresta

Дело в том что так как ты предлагаешь я делал. Т.е. у меня был массивчик с указанием хитпоинтов, строки символов и флага отрисовки. У этого метода есть очень большие недостатки: алгоритм запутанный, и при необходимости изменения программы в сторону утяжеления её другими отображаемыми элементами надо изрядно код поколбасить. Поэтому подумал что рисовать надо не на экране, а сразу в памяти, а по WM_PAINT отображать из памяти на экран. Вот собствено над чем и бился.

Foamplast
„Если же элементов нет никаких, а надо рисовать мышью везде, где тычут, и чтоб при этом оставалось (как в PANIT), то необходимо после рисования сохранять изображения окна, а перед рисованием выводить сохранённое изображение.“
Проше сразу в памяти рисовать.


Дата: Ноя 5, 2004 00:55:09

Ну да, так и есть.


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.053