Методические рекомендации по выполнению лабораторной работы

Задания.

  1. Изучить процедуру главного окна
  2. Изучить цикл обработки сообщений
  3. Изучить используемые в программе API-функции
  4. Изменить параметры функции GetMessageA
  5. Изменить параметры функции CreateWindowExA

6. Изменить главную процедуру окна WNDPROC

Методические рекомендации по выполнению лабораторной работы

Рассмотрим простую программу графического приложения. Разберите ее внимательно – она будет фундаментом, на котором мы будем строить дальнейшее рассмотрение.

Прежде всего обратите внимание на директиву INCLUDELIB. В пакете TASM32 довольно много разных библиотек. Для данного примера необходима: import32.lib. При наборе текста программы нужно изменить путь к библиотеке.

Сначала определяются константы и внешние библиотечные процедуры. В действительности все эти определения можно найти в include-файлах, прилагаемых к пакету TASM32. Мы не будем использовать стандартные include-файлы, т.к. так удобнее понять технологию программирования.

Необходимо четко понимать способ функционирования процедуры окна, так как именно это определяет суть программирования под Windows. Задача данной процедуры – правильная реакция на все приходящие сообщения. Нужно детально разобратся в работе нашего приложения. Сначала обратите внимание на то, что необработанные сообщения должны возвращаться в систему при помощи функции DefWindowProcA.

Программа отслеживает четыре сообщения: WM_CREATE, WM_DESTROY, WM_LBUTTONDOWN, WM_RBUTTONDOWN. Сообщения WM_CREATE и WM_DESTROY в терминах объектного программирования играют роль конструктора и деструктора: они приходят в функцию окна при создании окна и при уничтожении окна. Если щелкнуть по крестику в правом углу окна, то в функцию окна придет сообщение WM_DESTROY. Далее будет выполнена функция PostQuitMessage и приложению будет послано сообщение WM_QUIT, которое вызовет выход из цикла ожидания и выполнение функции ExitProcess, что, в свою очередь, приведет к удалению приложения из памяти.

Обратите внимание на метку _ERR – переход на нее происходит при возникновении ошибки, и здесь можно поместить соответствующее сообщение.

Выполните набор программы в блокноте или в любом другом простом текстовом редакторе. Чтобы получить загружаемый модуль, выполните следующие команды:

TASM32 /ml prog.asm

TLINK32 –aa prog.obj

Текст программы:

.386P

.MODEL FLAT, stdcall

; константы

; сообщение приходит при закрытии окна

WM_DESTROY equ 2

; сообщение приходит при создании окна

WM_CREATE equ 1

; сообщение при щелчке левой кнопкой мыши в области окна

WM_LBUTTONDOWN equ 201h

; сообщение при щелчке праввой кнопкой мыши в области окна

WM_RBUTTONDOWN equ 204h

; свойства окна

CS_VREDRAW equ 1h

CS_HREDRAW equ 2h

CS_GLOBALCLASS equ 4000h

WS_OVERLAPPEDWINDOW equ 000CF0000H

style equ CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS

; идентификатор стандартной иконки

IDI_APPLICATION equ 32512

; идентификатор курсора

IDC_CROSS equ 32515

; режим показа окна - нормальный

SW_SHOWNORMAL equ 1

; прототипы внешних процедур

EXTERN MessageBoxA: NEAR

EXTERN CreateWindowExA: NEAR

EXTERN DefWindowProcA: NEAR

EXTERN DispatchMessageA: NEAR

EXTERN ExitProcess: NEAR

EXTERN GetMessageA: NEAR

EXTERN GetModuleHandleA: NEAR

EXTERN LoadCursorA: NEAR

EXTERN LoadIconA: NEAR

EXTERN PostQuitMessage: NEAR

EXTERN RegisterClassA: NEAR

EXTERN ShowWindow: NEAR

EXTERN TranslateMessage: NEAR

EXTERN UpdateWindow: NEAR

; директивы компоновщику для подключения библиотек

includelib c:\win32\tasm32\lib\import32.lib

;-------------------------------------------------------------------------

; структуры

; структура сообщения

MSGSTRUCT STRUC

MSHWND DD?; идентификатор сообщения

MSWPARAM DD?; доп. информация о сообщении

MSLPARAM DD?; доп. информация о сообщении

MSTIME DD?; время посылки сообщения

MSPT DD?; положение курсора во время посылки сообщения

MSGSTRUCT ENDS

;---------------------------

WNDCLASS STRUC

CLSSTYLE DD?; стиль окна

CLWNDPROC DD?; указатель на процедуру окна

CLSCEXTRA DD?; информация о доп. байтах для данной структуры

CLWNDEXTRA DD?; информация о доп. байтах для окна

CLSHINSTANCE DD?; дискриптор приложения

CLSHICON DD?; идентификатор иконы окна

CLSHCURSOR DD?; идентификатор курсора окна

CLBKGROUND DD?; идентификатор кисти окна

CLMENUNAME DD?; имя-идентификатор меню

CLNAME DD?; специфицирует имя класса окна

WNDCLASS ENDS

; сенмент данных

_DATA SEGMENT DWORD PUBLIC USE32 'DATA'

NEWHWND DD 0

MSG MSGSTRUCT <?>

WC WNDCLASS <?>

HINST DD 0; здесь хранится дескриптор приложения

TITLENAME DB 'Простой пример 32-битного приложения',0

CLASSNAME DB 'CLASS32',0

CAP DB 'Сообщение',0

MES1 DB 'Вы нажали левую кнопку мыши',0

MES2 DB 'Выход из программы. Пока!',0

_DATA ENDS

; сегмент кода

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'

START:

; получить дескриптор приложения

PUSH 0

CALL GetModuleHandleA

MOV [HINST],EAX

REG_CLASS:

; заполнить структуру окна

MOV [WC.CLSSTYLE], style

; процедура обработки сообщений

MOV [WC.CLWNDPROC], OFFSET WNDPROC

MOV [WC.CLSCEXTRA], 0

MOV [WC.CLWNDEXTRA], 0

MOV EAX, [HINST]

MOV [WC.CLSHINSTANCE],EAX

;------------------иконка окна

PUSH IDI_APPLICATION

PUSH 0

CALL LoadIconA

MOV [WC.CLSHICON], EAX

;------------------курсор окна

PUSH IDC_CROSS

PUSH 0

CALL LoadCursorA

MOV [WC.CLSHCURSOR], EAX

;-------------------

MOV [WC.CLBKGROUND],17; цвет окна

MOV DWORD PTR [WC.CLMENUNAME], 0

MOV DWORD PTR [WC.CLNAME], OFFSET CLASSNAME

PUSH OFFSET WC

CALL RegisterClassA

; создать окно зарегистрированного класса

PUSH 0

PUSH [HINST]

PUSH 0

PUSH 0

PUSH 400; DY - высота окна

PUSH 400; DX - ширина окна

PUSH 100; Y - координата левого верхнего угла

PUSH 100; X - координата левого верхнего угла

PUSH WS_OVERLAPPEDWINDOW

PUSH OFFSET TITLENAME; имя окна

PUSH OFFSET CLASSNAME; имя класса

PUSH 0

CALL CreateWindowExA

; проверка на ошибку

CMP EAX, 0

JZ _ERR

MOV [NEWHWND], EAX

PUSH SW_SHOWNORMAL

PUSH [NEWHWND]

CALL ShowWindow; показать созданное окно

PUSH [NEWHWND]

CALL UpdateWindow; команда перерисовать видимую часть окна, сообщение WM_PAINT

; цикл обработки сообщений

MSG_LOOP:

PUSH 0

PUSH 0

PUSH 0

PUSH OFFSET MSG

CALL GetMessageA

CMP EAX, 0

JE END_LOOP

PUSH OFFSET MSG

CALL TranslateMessage

PUSH OFFSET MSG

CALL DispatchMessageA

JMP MSG_LOOP

END_LOOP:

; выход из программы (закрыть процесс)

PUSH [MSG.MSWPARAM]

CALL ExitProcess

_ERR:

JMP END_LOOP

;----------------------------------------------------------------------------

; процедура окна

; расположение параметров в стеке

; [EBP+14H] LPARAM

; [EBP+10H] WPARAM

; [EBP+0CH] MES

; [EBP+8] HWND

WNDPROC PROC

PUSH EBP

MOV EBP, ESP

PUSH EBX

PUSH ESI

PUSH EDI

CMP DWORD PTR [EBP+0CH], WM_DESTROY

JE WMDESTROY

CMP DWORD PTR [EBP+0CH], WM_CREATE

JE WMCREATE

CMP DWORD PTR [EBP+0CH], WM_LBUTTONDOWN; левая кнопка

JE LBUTTON

CMP DWORD PTR [EBP+0CH], WM_RBUTTONDOWN; правая кнопка

JE RBUTTON

JMP DEFWNDPROC

; нажатие правой кнопки приводит к закрытию окна

RBUTTON:

JMP WMDESTROY

; нажатие левой кнопки мыши

LBUTTON:

; выводим сообщение

PUSH 0; MB_OK

PUSH OFFSET CAP

PUSH OFFSET MES1

PUSH DWORD PTR [EBP+08H]

CALL MessageBoxA

MOV EAX, 0

JMP FINISH

WMCREATE:

MOV EAX, 0

JMP FINISH

DEFWNDPROC:

PUSH DWORD PTR [EBP+14H]

PUSH DWORD PTR [EBP+10H]

PUSH DWORD PTR [EBP+0CH]

PUSH DWORD PTR [EBP+08H]

CALL DefWindowProcA

JMP FINISH

WMDESTROY:

PUSH 0; MB_OK

PUSH OFFSET CAP

PUSH OFFSET MES2

PUSH DWORD PTR [EBP+08H]; дескриптор окна

CALL MessageBoxA

PUSH 0

CALL PostQuitMessage; сообщение WM_QUIT

MOV EAX, 0

FINISH:

POP EDI

POP ESI

POP EBX

POP EBP

RET 16

WNDPROC ENDP

_TEXT ENDS

END START

Основная литература – 5[27-68]

Контрольные вопросы.

  1. Какие API-функции используются в программе?
  2. Какие структуры используются в программе?
  3. Структура графического приложения.
  4. Какие API-функции включает цикл обработки сообщений?

Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: