Шаг 12.
Пример простой программы для Windows

    На этом шаге мы приведем пример простой программы для Windows.

    Приступим теперь к разбору конкретных примеров. В листинге этого шага представлена простая программа. Разберите ее внимательно - она будет фундаментом, на котором мы будем строить дальнейшее рассмотрение.

    Прежде всего обратите внимание на директивы INCLUDELIB. В пакете MASM32 довольно много разных библиотек. Для данного примера нам понадобились две: user32.1ib и kernel32.lib.

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

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

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


    Пример простой программы для Windows (MASM32).
.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@16:NEAR
EXTERN    CreateWindowExA@48: NEAR
EXTERN    DefWindowProcA@16:NEAR
EXTERN    DispatchMessageA@4:NEAR
EXTERN    ExitProcess@4:NEAR
EXTERN    GetMessageA@16:NEAR
EXTERN    GetModuleHandleA@4:NEAR
EXTERN    LoadCursorA@8:NEAR
EXTERN    LoadIconA@8:NEAR
EXTERN    PostQuitMessage@4:NEAR
EXTERN    RegisterClassA@4:NEAR
EXTERN    ShowWindow@8:NEAR
EXTERN    TranslateMessage@4:NEAR
EXTERN    UpdateWindow@4:NEAR
;Директивы компоновщику для подключения библиотек.
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
 
;Структуры.
;Структура сообщения.
MSGSTRUCT  STRUC	
           MSHWND     DD ? ;Идентификатор окна, получающего сообщение.
           MSMESSAGE  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@4
     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@8
    MOV    [WC.CLSHICON], EAX
;------------ курсор окна
    PUSH   IDC_CROSS
    PUSH   0
    CALL   LoadCursorA@8
    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@4
;Создать окно зарегистрированного класса.
    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@48
;Проверка на ошибку.
    CMP        EAX,0
    JZ    _ERR
    MOV   [NEWHWND], EAX  ;Дескриптор окна.
;------------------------------------
    PUSH  SW_SHOWNORMAL
    PUSH  [NEWHWND]
    CALL  ShowWindow@8    ;Показать созданное окно.
;------------------------------------
    PUSH  [NEWHWND]
    CALL UpdateWindow@4   ;Команда перерисовать видимую
                          ;часть окна, сообщение WM_PAINT.
;Цикл обработки сообщений 
MSG_LOOP:
    PUSH 0
    PUSH 0
    PUSH 0
    PUSH OFFSET MSG
    CALL GetMessageA@16
    CMP  EAX, 0
    JE   END_LOOP
    PUSH  OFFSET MSG
    CALL TranslateMessage@4
    PUSH OFFSET MSG
    CALL DispatchMessageA@4
    JMP  MSG_LOOP 
END_LOOP: 
;Выход из программы (закрыть процесс).
    PUSH  [MSG.MSWPARAM]
    CALL ExitProcess@4 
_ERR:
    JMP  END_LOOP
;-----------------------------------------
;Процедура окна.
;Расположение параметров в стеке: 
;[ЕВР+014Н] LPARAM 
;[ЕВР+10Н] WAPARAM 
;[ЕВР+0СН] MES 
;[ЕВР+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 ;МВ_ОК
        PUSH OFFSET CAP
        PUSH OFFSET MES1
        PUSH DWORD PTR [EBP+08H]
        CALL MessageBoxA@16
        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@16
        JMP  FINISH
WMDESTROY:	
        PUSH 0  ;MB_OK
        PUSH OFFSET CAP
        PUSH OFFSET MES2
        PUSH DWORD PTR [EBP+08H]   ;Дескриптор окна.
        CALL MessageBoxA@16
        PUSH 0
        CALL PostQuitMessage@4   ;Сообщение WM_QUIT.
        MOV  EAX, 0
FINISH:	
        POP  EDI
        POP  ESI
        POP  EBX
        POP  EBP
        RET  16
WNDPROC ENDP
_TEXT   ENDS	
        END START	
Текст этой программы можно взять здесь.

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


Рис.1. Результат нажатия левой кнопки мыши

   

    На следующем шаге мы приведем ввариант этой же программы для TASM32.




Предыдущий шаг Содержание Следующий шаг