Шаблон ассемблерного оконного приложения — Архив WASM.RU

Все статьи

Шаблон ассемблерного оконного приложения — Архив WASM.RU

  Каждый сайт, хоть немного причастный к программированию для Windows, считает своим долгом поместить на своих страницах шаблон оконного приложения. Assembler.ru в этом отношении ничем не хуже остальных. Почему бы и нет? Это настоящее, живое, работающее приложение, чего ж его стыдиться? Многим из нас его хватит, чтобы сказать себе с удовлетворением: "Достаточно, я в себя поверил", и вернуться к любимому третьему видеорежиму. Остальным же, возможно, оно понадобится еще много-много раз для того, чтобы начать с него новый проект, и, потратив полмесяца на его развитие, выяснить, что нужно было начинать с чего-то другого. Итак:

.386
.Model flat,stdcall

;заголовочный файл API;
;////////////////////////////////////////////////////// windows.inc
GetModuleHandleA  PROTO :DWORD               ;прототипы функций API
LoadIconA         PROTO :DWORD,:DWORD
LoadCursorA       PROTO :DWORD,:DWORD
RegisterClassExA  PROTO :DWORD
CreateWindowExA   PROTO :DWORD,:DWORD,:DWORD,:DWORD,\
                        :DWORD,:DWORD,:DWORD,:DWORD,\
                        :DWORD,:DWORD,:DWORD,:DWORD
ShowWindow        PROTO :DWORD,:DWORD
GetMessageA       PROTO :DWORD,:DWORD,:DWORD,:DWORD
TranslateMessage  PROTO :DWORD
DispatchMessageA  PROTO :DWORD
ExitProcess       PROTO :DWORD
PostQuitMessage   PROTO :DWORD
DefWindowProcA    PROTO :DWORD,:DWORD,:DWORD,:DWORD

WNDCLASSEXA STRUCT 8                         ;структура класса окна
  cbSize          dd ?
  style           dd ?
  lpfnWndProc     dd ?
  cbClsExtra      dd ?
  cbWndExtra      dd ?
  hInstance       dd ?
  hIcon           dd ?
  hCursor         dd ?
  hbrBackground   dd ?
  lpszMenuName    dd ?
  lpszClassName   dd ?
  hIconSm         dd ?
WNDCLASSEXA ENDS

POINT STRUCT 8
  x               dd ?
  y               dd ?
POINT ENDS

MSG STRUCT 8                                 ;структура сообщения
  hwnd            dd ?
  message         dd ?
  wParam          dd ?
  lParam          dd ?
  time            dd ?

  pt              POINT{}
MSG ENDS

NULL              =0                         ;разные константы
IDI_APPLICATION   =32512
IDC_ARROW         =32512
COLOR_WINDOWFRAME =6
SW_SHOW           =5
EXIT_ERROR        =0ffffffffh
WM_DESTROY        =2

CS_VREDRAW        =0001h
CS_HREDRAW        =0002h

WS_OVERLAPPED     =00000000h                 ;константы стилей окна
WS_CAPTION        =00C00000h
WS_SYSMENU        =00080000h
WS_THICKFRAME     =00040000h
WS_MINIMIZEBOX    =00020000h
WS_MAXIMIZEBOX    =00010000h

WS_OVERLAPPEDWINDOW=WS_OVERLAPPED OR\
                    WS_CAPTION OR\
                    WS_SYSMENU OR\
                    WS_THICKFRAME OR\
                    WS_MINIMIZEBOX OR\
                    WS_MAXIMIZEBOX

;///////////////////////////////////////////////////////// WinMain
.const
	app_name      db "WinApp Template",0            ;имя приложения
	class_name    db "WinApp Template Class",0      ;имя класса окна
.data?
	win_class     WNDCLASSEXA{}
	win_handle    dd ?
	loop_message  MSG{}
.code
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::
WinMain PROC PUBLIC hinst,prev_hinst,command_line,cmd_show
;................................ регистрация класса окна
  mov win_class.cbSize,sizeof(WNDCLASSEXA)
  mov win_class.style,CS_HREDRAW OR CS_VREDRAW
  mov win_class.lpfnWndProc,offset win_procedure
  mov win_class.cbClsExtra,0
  mov win_class.cbWndExtra,0
  invoke GetModuleHandleA,NULL
  mov win_class.hInstance,eax
  invoke LoadIconA,NULL,IDI_APPLICATION
  mov win_class.hIcon,eax
  mov win_class.hIconSm,eax
  invoke LoadCursorA,NULL,IDC_ARROW
  mov win_class.hCursor,NULL
  mov win_class.hbrBackground,COLOR_WINDOWFRAME
  mov win_class.lpszMenuName,NULL
  mov win_class.lpszClassName,offset class_name
  invoke RegisterClassExA,offset win_class
  .if(!eax)
    jmp abort
  .endif
;........................................... создание окна
  invoke CreateWindowExA,NULL,\
                         offset class_name,\
                         offset app_name,\
                         WS_OVERLAPPEDWINDOW,\
                         100,100,300,200,\
                         NULL,\
                         NULL,\
                         win_class.hInstance,\
                         NULL
  .if(!eax)
    jmp abort
  .endif
  mov win_handle,eax           ;он еще пригодится, только не сегодня
;............................................ вывод окна на экран
  invoke ShowWindow,eax,SW_SHOW
;............................................ инициализация
;здесь можно вставить все необходимые действия для первичной инициализации
;приложения (например, загрузку и разбор файла настроек)
;............................................ цикл опроса очереди сообщений
msg_loop:
  invoke GetMessageA,offset loop_message,NULL,0,0
  .if(!eax)
    invoke ExitProcess,loop_message.wParam   ;успешное завершение приложения
  .endif
  invoke TranslateMessage,offset loop_message
  invoke DispatchMessageA,offset loop_message
  jmp msg_loop
;............................................. аварийное завершение
abort:
  invoke ExitProcess,EXIT_ERROR
WinMain ENDP

;///////////////////////////////////////////// Оконная процедура
win_procedure PROC window_from,message,w_param,l_param
  .if(message==WM_DESTROY)
    invoke PostQuitMessage,0
; .elseif(message==...)      ;обработка остальных необходимых сообщений
;   ...
; .elseif(message==...)
;   ...
; .elseif(message==...)
;   ...
  .else                      ;сообщение не обработано
    invoke DefWindowProcA,window_from,message,w_param,l_param
    ret
  .endif
  xor eax,eax                ;сообщение обработано
  ret
win_procedure ENDP

;#############################################################
end


  Вот, собственно, и все приложение. В нем реализованы фундаментальные концепции общего прикладного програмирования для Windows:

  • работа начинается с вынужденного объектно-ориентированного действия - громоздкой регистрации класса окна с помощью функции RegisterClassExA. Вы должны сделать это, даже если собираетесь создать всего одно окно с такими свойствами, потому что так повелел когда-то Уильям Гейтс Второй, известный в народе как просто Билл. Впрочем, вы можете избежать этой неприятной процедуры, если воспользуетесь при создании окна одним из предопределенных классов - BUTTON, COMBOBOX , EDIT , LISTBOX , MDICLIENT , SCROLLBAR , STATIC. С помощью, например, класса BUTTON вы можете сделать большую-пребольшую кнопку и нажимать ее день и ночь до умопомрачения, ожидая, пока из floppy-дисковода выскочит банан. А класс STATIC очень удобен для эмуляции забора: написанное на таком окне емкое трехбуквенное слово всегда напомнит вам о необходимости вернуться к повседневным заботам.
  • если регистрация класса окна прошла успешно, можно создать само окно с помощью функции CreateWindowExA. Полученный при ее возврате в регистре eax дескриптор окна следует сохранить до лучших времен. Он потребуется очень часто для выполнения манипуляций с окном.
  • созданное окно полностью функционально за исключением одной мелочи: его не видно. Может, и в самом деле его не стоит показывать, чтобы не позориться. А иногда это действительно не нужно, например, если использовать главное окно для общей диспетчеризации приложения, а для общения с пользователем создавать другие окна. Но если вам действительно нужно показать окно, то это делает функция ShowWindow
  • следующий этап - ваш. Делайте что хотите. Можете пойти попить кофейку, а можете чего-нибудь попрограммировать. Но помните: пока еще в приложении обработка сообщений не идет, поэтому оно мертво. Свежесозданное окно торчит недвижимо на экране как символ стабильности внутриполитических процессов, и ничто не оставляет на нем следов, как на зубах Кристины Пугачевой/Орбакайте/Пресняковой/Орбакайте.
  • и только цикл опроса очереди сообщений оживит ваше окно, и кнопочки в его заголовке начнут нажиматься, вызывая разные полезные эффекты, и границы его станут послушны движениям придавленной слева мыши, и много еще чего разного можно будет сделать с этим окном.
  • потому что в вашем распоряжении теперь - оконная процедура win_procedure. Она принимает все и всяческие сообщения, адресуемые вашему окну всеми, кому не лень, и делает в ответ на них все, что вы пожелаете. В данном случае вы пожелали отправлять все эти сообщения обратно в систему, чтобы она сама делала с окном то, что повелел когда-то Билл. Единственное сообщение, на которое реагирует ваша оконная процедура - это WM_DESTROY, которое означает, что вам надоело любоваться окном, и вы нажали Alt+F4, или щелкнули по кнопочке с крестиком, или выбрали Close в системном меню. Да и поделом ему.
Если вы соберетесь откомпилировать приложение, вы можете сделать это с помощью MS Developer Studio, воспользовавшись нашими рекомендациями.

2002-2013 (c) wasm.ru