Почему у меня SetPixel не отрисовывает пиксель на форме?
WndProc proc uses ebx edi esi, hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
switch wmsg
case WM_INITDIALOG
invoke SendMessage, hwnd, WM_SETICON, 1, FUNC(LoadIcon, NULL, IDI_ASTERISK)
case WM_PAINT
invoke SetPixel, hwnd, 15, 20, 65285
case WM_CLOSE
exit_program:
invoke EndDialog, hwnd, 0
endsw
xor eax,eax
ret
WndProc endp
Ответ
В качестве первого параметра SetPixel принимает не идентификатор окна, а идентификатор контекста устройства (в данном случае, идентификатор контекста окна). Контекст устройства упрощенно можно сравнить с холстом, на котором происходит рисование.
В вашем случае нужно получить этот идентификатор с помощью функции BeginPaint, нарисовать пиксель, потом освободить контекст при помощи EndPaint
Код для обработки сообщения WM_PAINT будет примерно такой:
invoke BeginPaint, hwnd, addr ps
invoke SetPixel, eax, 15, 20, 65285
invoke EndPaint, hwnd, addr ps
Также необходимо объявить переменную ps, которая является структурой PAINTSTRUCT. Скорее всего определение этой структуры уже есть в каком-то из подключаемых файлов пакета MASM. addr - ключевое слово для подстановки адреса переменной.
Для нескольких вызовов SetPixel можно сделать например так:
invoke BeginPaint, hwnd, addr ps
push ebx
mov ebx, eax
invoke SetPixel, ebx, 15, 20, 65285
invoke SetPixel, ebx, 30, 20, 65285
invoke SetPixel, ebx, 45, 20, 65285
pop ebx
invoke EndPaint, hwnd, addr ps
Это вариант без использования дополнительной переменной. По соглашениям stdcall и cdecl, вызываемые процедуры не должны модифицировать регистры ebx, edi, esi (но могут модифицировать eax, ecx, edx), поэтому ebx, например, можно использовать для временного хранения значений, которые не должны затираться вызовами процедур. Но так как процедура WndProc тоже должна соответствовать соглашению stdcall, то перед модификацией ebx его значение нужно сохранить, а потом восстановить. Это можно сделать либо локально, вокруг места, где происходит модификция ebx (как показано в этом примере), либо сохранить в начале процедуры, а в конце (перед ret) - восстановить.
Еще одно замечание - код цвета лучше писать в шестнацатеричном виде, в данном случае это будет 00FF05h, тогда будет сразу понятно, что этот цвет ближе к зеленому (порядок цветов - 0x00bbggrr, согласно описанию типа COLORREF).
Комментариев нет:
Отправить комментарий