Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скляров И. Изучаем Assembler за 7 дней (2010).pdf
Скачиваний:
1335
Добавлен:
23.02.2015
Размер:
2.11 Mб
Скачать

http://www.sklyaroff.ru

162

Чтобы использовать поля этой структуры в программе нужно с помощью директивы INCLUDE подключить файл WINDOWS.INC и в сегменте данных сделать следующее определение:

wc WNDCLASSEX <?>

Доступ к отдельным полям осуществляется с помощью точки:

mov wc.lpszMenuName,NULL ; запись нулевого значения в поле lpszMenuName mov wc.lpszClassName,OFFSET ClassName ; запись адреса строки с именем

; создаваемого класса окна

; в поле lpszClassName

7.4.2. Создание окна

После регистрации класса окна можно создать окно вызовом API-функции CreateWindow. После успешного выполнения эта функция возвращает дескриптор созданного окна, в противном случае – NULL.

HWND CreateWindow( LPCTSTR lpClassName,

LPCTSTR lpWindowName, DWORD dwStyle,

int x, int y,

int nWidth, int nHeight,

HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam

);

Параметры функции:

lpClassName — указатель на строку с именем класса. В большинстве случаев значение этого параметра совпадает со значением последнего поля структуры

WNDCLASS, передаваемой RegisterClass;

lpWindowName — указатель на строку содержащую строку заголовка окна;

dwStyle — стиль окна, который определяет, будет ли окно иметь заголовок, иконку системного меню, кнопки минимизации, максимизации, рамка окна и т. д. Идентификаторы стиля начинаются с приставки WS_;

x — отступ левого верхнего угла окна от левого края экрана в пикселах;

y — отступ левого верхнего угла окна от верхней границы экрана в пикселах;

nWidth ширина окна в пикселах;

nHeight высота окна в пикселах;

hWndParent дескриптор родительского окна;

hMenu дескриптор меню;

hInstance дескриптор экземпляра приложения;

lpParam — дополнительные значения. Если окну не передаются никакие дополнительные значения, этот параметр должен быть равен NULL.

7.4.3. Цикл обработки очереди сообщений

На языке Си цикл обработки очереди сообщений выглядит следующим образом: while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

http://www.sklyaroff.ru

163

DispatchMessage(&msg);

}

Как видно в цикле используется три API-функции: GetMessage, TranslateMessage, DispatchMessage.

Функция GetMessage выбирает из очереди очередное сообщение и записывает его в структуру msg. Второй параметр этой функции — дескриптор окна, созданного программой. Если этот параметр равен NULL, то обрабатываться будут сообщения для всех созданных программой окон.

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

Цикл обработки сообщений останавливается, а, следовательно, прекращается работа программы, только после получения единственного сообщения WM_QUIT.

Функция TranslateMessage преобразует сообщения о нажатии виртуальных клавиш в символьные сообщения. Например, сообщения WM_KEYDOWN и WM_KEYUP в WM_CHAR и WM_DEADCHAR, а также WM_SYSKEYDOWN и WM_SYSKEYUP в WM_SYSCHAR и WM_SYSDEADCHAR. Эта функция необходима только тем приложениям, которые обрабатывают ввод с клавиатуры. Например, она позволяет пользователям выбирать команды меню нажатием клавиш, а не только щелчками мыши.

Функция DispatchMessage передает сообщение на обработку соответствующей оконной процедуре, автоматически определяя окно, которому адресовано сообщение.

На ассемблере цикл обработки сообщений может выглядеть следующим образом:

MSG_LOOP:

invoke GetMessage, ADDR msg,NULL,0,0

cmp eax,0 je END_LOOP

invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg jmp MSG_LOOP

END_LOOP:

mov eax,msg.wParam invoke ExitProcess,eax

или более короткий вариант:

.WHILE TRUE

invoke GetMessage, ADDR msg,NULL,0,0

.BREAK .IF (!eax)

invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg

.ENDW

mov eax,msg.wParam ; сохранение возвращаемого значения в eax invoke ExitProcess,eax

7.4.4. Процедура главного окна

Прототип оконной процедуры на языке Си выглядит следующим образом:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

http://www.sklyaroff.ru

164

Параметры, передаваемые в оконную функцию: hWnd — дескриптор окна, которому посылается сообщение, message — идентификатор сообщения, wParam и lParam — дополнительная информация, зависящая от конкретного сообщения.

Все четыре параметра в ассемблере имеют тип DWORD. Компиляция:

ml /c /coff /Cp gdiwin.asm

link.exe /SUBSYSTEM:WINDOWS /LIBPATH:d:\masm32\lib gdiwin.obj

Листинг 7.4. Простейшая графическая программа под Windows (gdiwin.asm)

.386

.model flat,stdcall option casemap:none

include\masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib

.data

 

ClassName

db "SimpleWinClass",0

AppName

db "Our First Window",0

; Для функции MessageBox

hello_mess1

db "Нажата левая клавиша мыши",0

hello_mess2

db "Нажата правая клавиша мыши",0

hello_title

db "Ура!",0

.data?

 

hInstance

HINSTANCE ?

hInst

HINSTANCE ?

CommandLine

LPSTR ?

wc

WNDCLASSEX <?>

msg

MSG <?>

hwnd

HWND ?

.code

 

start:

 

invoke

GetModuleHandle,NULL

mov

hInstance,eax

mov

wc.cbSize,SIZEOF WNDCLASSEX

mov

wc.style,CS_HREDRAW or CS_VREDRAW

mov

wc.lpfnWndProc,OFFSET WndProc

mov

wc.cbClsExtra,NULL

mov

wc.cbWndExtra,NULL

push

hInstance

pop

wc.hInstance

mov

wc.hbrBackground,COLOR_WINDOW+1

mov

wc.lpszMenuName,NULL

http://www.sklyaroff.ru

165

mov

wc.lpszClassName,OFFSET ClassName

invoke

LoadIcon,NULL,IDI_APPLICATION

mov

wc.hIcon,eax

mov

wc.hIconSm,eax

invoke

LoadCursor,NULL,IDC_ARROW

mov

wc.hCursor,eax

invoke

RegisterClassEx,addr wc

INVOKE

CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\

WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\

CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\

hInst,NULL

 

mov

hwnd,eax

invoke

ShowWindow,hwnd,SW_SHOWNORMAL

invoke

UpdateWindow,hwnd

MSG_LOOP:

 

 

invoke

GetMessage,ADDR msg,NULL,0,0

 

cmp

eax,0

 

je

END_LOOP

 

invoke

TranslateMessage,ADDR msg

 

invoke

DispatchMessage,ADDR msg

 

jmp

MSG_LOOP

END_LOOP:

 

 

mov

eax,msg.wParam

 

invoke

ExitProcess,eax

WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

cmp

uMsg,WM_DESTROY

je

WMDESTROY

cmp

uMsg,WM_LBUTTONDOWN

je

LBUTTON

 

cmp

uMsg,WM_RBUTTONDOWN

je

RBUTTON

 

JMP

DEFWNDPROC

WMDESTROY:

 

 

invoke

PostQuitMessage,NULL

xor

eax,eax

 

jmp

FINISH

 

LBUTTON:

 

 

invoke

MessageBoxA,0,addr hello_mess1,addr hello_title,MB_OK

jmp

FINISH

 

RBUTTON:

 

 

invoke

MessageBoxA,0,addr hello_mess2,addr hello_title,MB_OK

jmp

FINISH

 

DEFWNDPROC:

 

 

invoke

DefWindowProc,hWnd,uMsg,wParam,lParam

FINISH:

 

 

ret

WndProc endp