Отправляет email-рассылки с помощью сервиса Sendsay

Assembler - Просто и Эффективно.

  Все выпуски  

Assembler - Просто и Эффективно. Глава #7: Окна


Assembler

Глава #7 - Окна

  Окна в Windows.
Пользовательская программа может создавать окна (windows) для комуникации с пользователем, получения сообщений от системы или от другой программы.
Окна имеют древовидную структуру т.е каждое окно может содержать "дочерние" (child) окна.
Свойства окна зависят от многих параметров: Класса, стиля и т.д.
Для просмотра дерева созданых окон, можно использовать программу Windows Explorer
Для создания окна обычно используется функция CreateWindowExA, имеющая следующие параметры:

#Описание
1Дополнительный стиль (константы WS_EX_)
2Имя или номер класса (см.ниже)
3Текст окна
4Стиль (константы WS_)
5X - позиция
6Y - позиция
7Размер по X
8Размер по Y
9Хэндл "parent'а"
10Хэндл меню, или ID
11Хэндл модуля, создающего окно
12Параметр, передаваемый сообщению WM_CREATE
Координаты X и Y отсчитываютя от левого верхнего угла parent'а.
Хэндл окна действителен во всех запущенных процессах.
   -------------------------------

  Класс (Class)
Класс обычно создается функцией RegisterClassExA. Единственный параметр - указатель на структуру WNDCLASSEX. При создании окна нужно указать класс, к которому оно будет принадлежать. От класса зависит большая часть свойств окна.
Структура WNDCLASSEX определена следующим образом:

nameoffsetОписание
cbSize0размер структуры (в байтах) - 30h
style4Стиль класса (константы CS_)
lpfnWndProc8Адрес процедуры обработки сообщений
cbClsExtra0СhКоличество дополнительной памяти, выделяемое классу
cbWndExtra10hКоличество дополнительной памяти, выделяемое каждому окну класса
hInstance14hХэндл модуля, создающего класс
hIcon18hХэндл иконки класса
hCursor1ChХэндл курсора класса
hbrBackground20hХэндл кисти фона класса (может быть константы COLOR_)
lpszMenuName24hИмя/номер меню класса
lpszClassName28hИмя/номер класса
hIconSm2ChХэндл маленькой иконки класса

   -------------------------------

  Сообщения (Message)
Каждому потоку (thread - у нас пока один - основной) программы, Windows посылает сообщения. Большая часть из них посылается когда пользователь совершает какие-либо действия над окнами потока. Некоторые сообщения посылаютя при событиях системы (например, завершение Windows).
Основная часть сообщений обозначается константами WM_
Сообщения выстраиваются в очередь (message queue). Для реагирования на сообщения программа должна организовать цикл - (Message Loop) - считывающий сообщение из очереди, и передающий его процедурам обработки сообщений окон.
Стандартный цикл обработки сообщений выглядит следующим образом:
MsgLoop:
 call GetMessageA,offset MsgS,0,0,0
 inc eax
 jz EndMsgLoop
 dec eax
 jz EndMsgLoop
 call TranslateMessage,offset MsgS
 call DispatchMessageA,offset MsgS
 jmp MsgLoop
EndMsgLoop:
 call ExitProcess,0

   -------------------------------

  Процедура обработки сообщений окна (WindowProc)
Процедура обработки сообщений дает возможность реагировать на сообщения, посылаемые окну. Указывается при регистрации класса.
Так выглядит "пустая" процедура :
WindowProc proc hwnd:dword,uMsg:dword,wParam:dword,lParam:dword
 cmp [uMsg],WM_DESTROY
 jnz NotWmDestroy
 call PostQuitMessage,0
 xor eax,eax
 ret
NotWmDestroy:
 call DefWindowProcA,[hwnd],[uMsg],[wParam],[lParam]
 ret
WindowProc endp
Данная процедура обрабатывает сообщение WM_DESTROY, возвращая 0
Все остальные сообщения передаются стандартному обработчику, возвращая значение, которое он установит.

WindowProc - процедура соглашения stdcall, имеет 4 входных параметра:
hwnd - хэндл окна, которому адресовано сообщение
uMsg - Код сообщения
wParam и lParam - дополнительная информация о сообщении (специфична для каждого кода)
Значение (зависит от кода сообщения) возвращает через регистр eax.
   -------------------------------

  Пример
Ниже приведен пример программы, создающей окно. В процедуру обработки сообщений добавлена обработка WM_CLOSE в качестве примера.
Внимание! Файл windows.inc в пакете с компилятором нужно использовать осторожно, т.к он для Win16.
Константы, используемые в данном примере включены в исходный код.
Для дальнейшего написания программ под Windows, вам понадобится файл c описанием консатнт под Win32, его легко можно найти в сети.
 .386
 .model flat,stdcall

extrn GetModuleHandleA:proc
extrn LoadIconA:proc
extrn LoadCursorA:proc
extrn RegisterClassExA:proc
extrn CreateWindowExA:proc
extrn GetMessageA:proc
extrn TranslateMessage:proc
extrn DispatchMessageA:proc
extrn ExitProcess:proc
extrn MessageBoxA:proc
extrn PostQuitMessage:proc
extrn DefWindowProcA:proc

;Константы, используемые в программе:
CS_VREDRAW equ 1h
CS_HREDRAW equ 2h
IDI_APPLICATION equ 32512
IDC_ARROW  equ 32512
COLOR_WINDOW  equ 5
CW_USEDEFAULT equ 80000000h
WS_THICKFRAME equ 40000h
WS_VISIBLE   equ 10000000h
WS_MINIMIZEBOX equ 20000h
WS_MAXIMIZEBOX equ 10000h
WS_SYSMENU  equ 80000h
WM_CLOSE   equ 10h
MB_YESNO   equ 4h
MB_ICONQUESTION equ 20h
IDNO    equ 7
WM_DESTROY  equ 2h

WNDCLASSEX STRUCT
 cbSize  DWORD ?
 style  DWORD ?
 lpfnWndProc DWORD ?
 cbClsExtra DWORD ?
 cbWndExtra DWORD ?
 hInstance DWORD ?
 hIcon  DWORD ?
 hCursor  DWORD ?
 hbrBackground DWORD ?
 lpszMenuName DWORD ?
 lpszClassName DWORD ?
 hIconSm   DWORD ?
WNDCLASSEX ENDS

 .data
ProgramClassName db 'AnyClassName',0  ;имя класса
WindowText db 'Заголовок окна',0   ;текст заголовка окна
CloseTitle db 'Сообщение',0
CloseText db 'Закрыть окно?',0
WClass WNDCLASSEX <>
MsgS dd 7 dup (?) ;MSG <>
 .code
start:
;заполняем структуру WNDCLASSEX
 mov WClass.cbSize,size WNDCLASSEX  ;размер структуры (30h)
 mov WClass.style,CS_HREDRAW or CS_VREDRAW
 mov WClass.lpfnWndProc,offset MainWindowProc
 mov WClass.cbClsExtra,0
 mov WClass.cbWndExtra,0
 call GetModuleHandleA,0
 mov WClass.hInstance,eax
 call LoadIconA,0,IDI_APPLICATION
 mov WClass.hIcon,eax
 mov WClass.hIconSm,eax
 call LoadCursorA,0,IDC_ARROW
 mov WClass.hCursor,eax
 mov WClass.hbrBackground,COLOR_WINDOW
 mov WClass.lpszMenuName,0
 mov WClass.lpszClassName,offset ProgramClassName
 call RegisterClassExA,offset WClass  ;зарегистрируем класс

;создадим окно
 call CreateWindowExA,0,offset ProgramClassName,offset WindowText,\
  WS_THICKFRAME or WS_VISIBLE or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU,\
  CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,\
  0,0,[WClass.hInstance],0

;цикл чтения сообщений из очереди
MsgLoop:
 call GetMessageA,offset MsgS,0,0,0
 inc eax
 jz EndMsgLoop
 dec eax
 jz EndMsgLoop
 call TranslateMessage,offset MsgS
 call DispatchMessageA,offset MsgS
 jmp MsgLoop
EndMsgLoop:
 call ExitProcess,0

;процедура обработки сообщений
MainWindowProc proc hwnd:dword,uMsg:dword,wParam:dword,lParam:dword
 cmp [uMsg],WM_CLOSE
 jnz NotWmClose
 call MessageBoxA,[hwnd],offset CloseText,\
  offset CloseTitle,MB_YESNO or MB_ICONQUESTION
 cmp eax,IDNO
 jnz CallDefProc
 xor eax,eax
 ret
NotWmClose:
 cmp [uMsg],WM_DESTROY
 jnz NotWmDestroy
 call PostQuitMessage,0
 xor eax,eax
 ret
NotWmDestroy:

CallDefProc:
 call DefWindowProcA,[hwnd],[uMsg],[wParam],[lParam]
 ret
MainWindowProc endp
end start
   -------------------------------

 Содержание дальнейших выпусков зависит от вас. Будут разъясняться те темы, которые непонятны большинству читателей. Сайт рассылки: asm32.nm.ru. Присылайте свои вопросы и предложения по адресу: asm32@nm.ru .
   -------------------------------


Автор рассылки Владимир Пронин. Любое коммерческое использование материалов рассылки без ведома и прямого согласия автора запрещено.
Письма присланные автору рассылки могут быть опубликованы целиком или частично без предварительного уведомления. Если вы не хотите, чтобы ваше письмо было опубликовано укажите это в начале письма.
Перепечатка материалов разрешена только с непосредственной ссылкой на asm32.nm.ru


В избранное