;
       
; шаблонное приложение (взято из fasm'овсих examp'ов)
format PE GUI 4.0         ; формат PE версия gui 4.0
entry start         ; точка входа
include '%include%\win32a.inc'
        ; подключаем наш стандартный инклуд
;*********************** Секция данных********************;
section '.data' data readable writeable
ourTitle db 'Шаблон',0         ; название окна
ourClass db 'ourclass',0         ; название класса окна - нам надо зарегистрировать свой класс
                ; если мы не используем стандартные - типа MessageBox и т.п.
mainhwnd dd ?         ; ///хендл окна - после успешного завершения CreateWindowEx
                ; // он находится в eax - мы должны его сохранить - он нам пригодится для обращения к окну
hinstance dd ?         ; \\ хендл нашей программы - чёт типа идентификатора программы - его
; \\\надо передовать некоторым API
msg MSG ; системные сообщения - которые система посылает нашей программе
;;
;; struc MSG ;- структура MSG (см.\INCLUDE\EQUATES\USER32.INC)
;; {
;; .hwnd dd ? ;\\ msg - это структура, передоваемая окну
;; .message dd ? ;\\ Что-то вроде связи с внешним миром.
;; .wParam dd ? ;\\ Система посылает окну сообщения
;; .lParam dd ? ;\\ и окно их обрабатывает
;; .time dd ? ;\\
;; .pt POINT ;\\
;; }
;; struct MSG ;- struct - это макрос, автоатичеки определяющий размер структуры
;; (см. \INCLUDE\MACRO\STRUCT.INC)
;; macro struct name
;; { virtual at 0
;; name name
;; sizeof.#name = $ - name
;; name equ sizeof.#name
;; end virtual }
wc WNDCLASS ; \ заполняемая нами структура - мы потом передаём её функции RegisterClass
; \\ регестрирующей наш класс окна.
;; struc WNDCLASS ;- структура WNDCLASS
;; {
;; .style dd ? ;- стиль окна, можно комбинировать несколько стилей
; используя 'OR'
;; .lpfnWndProc dd ? ;- указатель на функцию ответственную за окна,
; создаваемые из класса
;; .cbClsExtra dd ? ;- кол-во байтов, кот. нужно зарезервировать. Эти байты будут следовать
; за самой структурой (по умолчанию 0). Цитата: "Если пpиложение
; использует WNDCLASSEX стpуктуpу, чтобы заpегистpиpовать
; диалоговое окно, созданное диpективой CLASS в файле pесуpсов,
; оно должно пpиpавнять этому члену значение DLGWINDOWEXTRA. "
; WASM.RU - Уроки Iczeleona: API - простое окно.
;; .cbWndExtra dd ? ;- тож самое, что и cbClsExtra, только
; касательно окна (не класа, а окна)
;; .hInstance dd ? ;- Хендл программы
;; .hIcon dd ? ;- иконка (указатель на неё - его можно получить функцией LoadIcon)
;; .hCursor dd ? ;- курсор (аналогично hIcon)
;; .hbrBackground dd ? ;- бэкграунд (фон)
;; .lpszMenuName dd ? ;- Указатель на главное меню окна (у нас NALL - нет меню)
;; .lpszClassName dd ? ;- Указатель на имя класса
;; }
;; struct WNDCLASS ;- аналогично MSG
;********************** секция код************************;
section '.code' code readable executable
; входим в исполнимую часть программы (метка start)
start:
invoke GetModuleHandle,0 ; берём хендл программы
mov [hinstance],eax ; хендл возвращается в eax - помещаем его в переменную hinstace
invoke LoadIcon,0,IDI_APPLICATION ;Здесь идёт заполнение структуры wc
mov [wc.hIcon],eax ;|
invoke LoadCursor,0,IDC_ARROW ;|
mov [wc.hCursor],eax ;|
mov [wc.style],0 ;|
mov [wc.lpfnWndProc],WindowProc ;|
;|
mov [wc.cbClsExtra],0 ;|
mov [wc.cbWndExtra],0 ;|
mov eax,[hinstance] ;|
mov [wc.hInstance],eax ;|
mov [wc.hbrBackground],COLOR_BTNFACE+1 ;|
mov [wc.lpszMenuName],0 ;|
mov [wc.lpszClassName],ourClass ;|
invoke RegisterClass,wc ; Вызываем функцию регестрирующую наш класс окна
invoke CreateWindowEx,0,ourClass,ourTitle,WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU,128,128,192,192,NULL,NULL,[hinstance],NULL
;; Вызов функции создающей наше окно. Параметры (1,2,3,4...12 по очереди):
;; 1 - дополнительные стили окна (такие как topmost - всегда наверху). У нас NULL
;; вот они (см. \INCLUDE\EQUATES\USER32.INC):
;; WS_EX_DLGMODALFRAME = 00001h
;; WS_EX_DRAGOBJECT = 00002h
;; WS_EX_NOPARENTNOTIFY = 00004h
;; WS_EX_TOPMOST = 00008h
;; WS_EX_ACCEPTFILES = 00010h
;; WS_EX_TRANSPARENT = 00020h
;; WS_EX_MDICHILD = 00040h
;; WS_EX_TOOLWINDOW = 00080h
;; WS_EX_WINDOWEDGE = 00100h
;; WS_EX_CLIENTEDGE = 00200h
;; WS_EX_CONTEXTHELP = 00400h
;; WS_EX_RIGHT = 01000h
;; WS_EX_LEFT = 00000h
;; WS_EX_RTLREADING = 02000h
;; WS_EX_LTRREADING = 00000h
;; WS_EX_LEFTSCROLLBAR = 04000h
;; WS_EX_RIGHTSCROLLBAR = 00000h
;; WS_EX_CONTROLPARENT = 10000h
;; WS_EX_STATICEDGE = 20000h
;; WS_EX_APPWINDOW = 40000h
;; WS_EX_LAYERED = 80000h
;; WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE
;; WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE or WS_EX_TOOLWINDOW or WS_EX_TOPMOST
;; 2 - имя класса (указатель на него) в формате ACSIIZ (ACSII строка, кончающаяся нулём)
;; 3 - имя окна (указатель), тож ACSIIZ
;; 4 - стили окна. Можно комбинировать их используя OR.
;; Вот они (см. \INCLUDE\EQUATES\USER32.INC):
;; WS_OVERLAPPED = 000000000h
;; WS_ICONICPOPUP = 0C0000000h
;; WS_POPUP = 080000000h
;; WS_CHILD = 040000000h
;; WS_MINIMIZE = 020000000h
;; WS_VISIBLE = 010000000h
;; WS_DISABLED = 008000000h
;; WS_CLIPSIBLINGS = 004000000h
;; WS_CLIPCHILDREN = 002000000h
;; WS_MAXIMIZE = 001000000h
;; WS_CAPTION = 000C00000h
;; WS_BORDER = 000800000h
;; WS_DLGFRAME = 000400000h
;; WS_VSCROLL = 000200000h
;; WS_HSCROLL = 000100000h
;; WS_SYSMENU = 000080000h
;; WS_THICKFRAME = 000040000h
;; WS_HREDRAW = 000020000h
;; WS_VREDRAW = 000010000h
;; WS_GROUP = 000020000h
;; WS_TABSTOP = 000010000h
;; WS_MINIMIZEBOX = 000020000h
;; WS_MAXIMIZEBOX = 000010000h
;; ;
;;WS_OVERLAPPEDWINDOW = WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_THICKFRAME or WS_MINIMIZEBOX or WS_MAXIMIZEBOX
;; WS_POPUPWINDOW = WS_POPUP or WS_BORDER or WS_SYSMENU
;; WS_CHILDWINDOW = WS_CHILD
;; WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW
;; WS_TILED = WS_OVERLAPPED
;; WS_ICONIC = WS_MINIMIZE
;; WS_SIZEBOX = WS_THICKFRAME
;; 5,6 - координаты верхнего левого угла окна. В пикселях.
;; 7,8 - ширина и высота окна в пикселях.
;; 9 - хендл родительского окна (если наше окно дочернее). В даном случае NULL
;; 10 - хендл меню окна (если оно есть) - у нас его нет - NULL
;; 11 - хендл программы, создающей окно
;; 12 - указатель на структуру данных передоваемых окну.
;
mov [mainhwnd],eax ;;;; Функция возвращает в eax хендл окна - сохраним его, он нам пригодится
msg_loop: ;; цикл, читающий сообщения от системы - в принципе это и есть средство
;; связи с внешним миром
invoke GetMessage,msg,NULL,0,0 ; Получает сообщение от системы. Не возвращается, пока не получит сообщение.
; Возвращает 0, если пришло сообщение WM_QUIT - выход из проги.
or eax,eax ; просто выполняем логическую операцию, чтобы заполнить регисть флагов,
; не изменяя содержимое eax. Если в eax содержится 0, то ...
jz end_loop ; ...конец обработки цикла - выход нпа метку end_loop
invoke TranslateMessage,msg ; Вспомогательная функция, обрабатывающая ввод с клавы - генерирует сообщение
; WM_CHAR - сообщение содержит ASCII-код нажатой
; клавиши (вместо скан-кода). Нужна ели обрабатываем ввод с клавы.
invoke DispatchMessage,msg ; Пересылает сообщение процедуре соответствующего окна.
jmp msg_loop ; окончание цикла - возврат на начало - msg_loop
end_loop:
invoke ExitProcess,[msg.wParam] ; выход из программы. При выходе, код выхода сохраняется в msg.wParam
; его надо передать системе при выходе.
;; ;;
;; ---== вот она. функция окна ==--- ;;
;; ;;
; передаём: хэндл пpогpаммы, сообщение (не структура MSG), + дополнительные параметры, передоваемые некоторыми сообщениями
proc WindowProc, hwnd,wmsg,wparam,lparam
enter
push ebx esi edi
cmp [wmsg],WM_DESTROY ; проверим наше сообщение - если WM_DESTROY, то идём до метки wmdestroy
je wmdestroy
;
;; наш код - которого сейчас нет, следует помещать здесь - всё остальное ШАБЛОН
;; если мы не обробатываем сообщение - то надо сделать переход на defwndproc,
;; если обрабатываем - то, после обработки, переход на finish - всё просто
;
defwndproc:
invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] ; дефолтная функция - обрабатывает сообщения, которыми
; наша программа не интересуется
jmp finish ; прыгаем на finish - выход из функции
wmdestroy:
invoke PostQuitMessage,0 ; обрабатывает сообщение WM_DESTROY. Обязательно!
; посылает сообщение WM_QUIT, что вынуждает GetMessage вернуть 0 в eax
; что в сою очередь приводит к предотвращению цикла и выходу из программы
xor eax,eax
finish:
pop edi esi ebx
return
; импортные данные
section '.idata' import data readable writeable
library kernel,'KERNEL32.DLL',\
user,'USER32.DLL'
import kernel,\
GetModuleHandle,'GetModuleHandleA',\
ExitProcess,'ExitProcess'
import user,\
RegisterClass,'RegisterClassA',\
CreateWindowEx,'CreateWindowExA',\
DefWindowProc,'DefWindowProcA',\
GetMessage,'GetMessageA',\
TranslateMessage,'TranslateMessage',\
DispatchMessage,'DispatchMessageA',\
LoadCursor,'LoadCursorA',\
LoadIcon,'LoadIconA',\
PostQuitMessage,'PostQuitMessage'
;;;
;;;
;;; Весь используемый материал взят с WASM.RU
;;;
;;; 25/IV/2009 г.
;;;
С уважением Костик.
Непосредственно вводимый код выделен фиолетовым цветом , все остальное(зеленым) - комментарии.
Примечание Pauk_pv.
Скачать исходный код и исполняемый файл этого примера в zip-архиве
|