Страницы

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

понедельник, 24 февраля 2020 г.

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

#winapi #ассемблер #masm32 #gdi


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

    


Ответы

Ответ 1



В качестве первого параметра 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).

Ответ 2



Потому что SetPixel ожидает первым параметром hdc, а не hwnd. Вам нужно вызвать BeginPaint для получения hdc, а после отрисовки вызвать EndPaint.

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

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