Страницы

Поиск по вопросам

четверг, 2 мая 2019 г.

Почему у меня SetPixel не отрисовывает пиксель?

Почему у меня 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).

Комментариев нет:

Отправить комментарий