5.1 Листинг:
Файл edit.inc:
; константы_SETFOCUS equ 7h
; сообщение приходит при закрытии окна_DESTROY equ 2
; сообщение приходит при содании окна_CREATE equ 1
; сообщение, если что-то происходит с элементами на окне_COMMAND equ 111h
; сообщение, позволяющее послать элементу строку
WM_SETTEXT equ 0Ch_PAINT equ 0FH
; сообщение, позволяющее получить строку_GETTEXT equ 0Dh
; компоненты цветовequ 49equ 106equ 197equ 195 shl 13equ 0; черный
; свойства окна
CS_VREDRAW equ 1h
CS_HREDRAW equ 2h_GLOBALCLASS equ 4000h_OVERLAPPEDWINDOW equ 000CF0000Hequ CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS
; CS_HREDRAW equ 2h_DEFPUSHBUTTON equ 1h_VISIBLE equ 10000000h_CHILD equ 40000000h_BORDER equ 800000h_TABSTOP equ 00010000hequ WS_CHILD + BS_DEFPUSHBUTTON + WS_VISIBLE + WS_TABSTOPequ WS_CHILD + WS_VISIBLE + WS_BORDER + WS_TABSTOP
; идентификатор стандартной иконки_APPLICATION equ 32512
; идентификатор курсора_ARROW equ 32512;
; режим показа окна - нормальный_SHOWNORMAL equ 1
; прототипы внешних процедур
EXTERN SetFocus@4:NEAR
EXTERN SendMessageA@16:NEARMessageBoxA@16:NEARCreateWindowExA@48:NEARDefWindowProcA@16:NEARDispatchMessageA@4:NEARExitProcess@4:NEARGetMessageA@16:NEARGetModuleHandleA@4:NEARLoadCursorA@8:NEARLoadIconA@8:NEARPostQuitMessage@4:NEARRegisterClassA@4:NEARShowWindow@8:NEARTranslateMessage@4:NEARUpdateWindow@4:NEARBeginPaint@8:NEAREndPaint@8:NEARTextOutA@20:NEARGetStockObject@4:NEARCreateSolidBrush@4:NEARSetBkColor@8:NEARSetTextColor@8:NEAR InvalidateRect@12:NEAR
; структуры
; структура сообщения
MSGSTRUCT STRUCDD?DD?DD?DD?DD? DD?
MSGSTRUCT ENDS
;----структура класса окон
WNDCLASS STRUCDD?DD?DD?DD?DD?DD?DD?DD?DD?DD?ENDSSTRUCDWORD 0DWORD 0DWORD 0DWORD 0DWORD 0DWORD 0DWORD 0DWORD 0DB 32 dup(0)ENDS
Файл edit.asm:
P
; плоская модель
.MODEL FLAT, stdcall qq.inc
; подключение библиотек
includelib user32.lib;Модуль для поддержки пользовательского интерфейса
includelib kernel32.lib;Модуль для работы с ядром ОС
includelib gdi32.lib;Модуль для поддержки графического интерфейса
;------------------------------------------------------------
; сегмент данных
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'DD 0;хэндлер окнаMSGSTRUCT <?>WNDCLASS <?>PAINTSTR <?>DD 0; дескриптор приложенияDB 'Macro Assembler',0DB 'CLASS32',0 DB 'Копировать',0
CPBUT1 DB 'Повторить 20 раз с помощью REPT',0DB ' ',0DB 'BUTTON',0DB 'EDIT',0DB 0DWORD 0DWORD 0DWORD 0DWORD 0DWORD 10DWORD 90DB 'Введите текст',0 50 DUP(0); продолжение буфера
TEXTM DB 'Строка выведена 10 раз с помощью макрокоманды REPT',0
DB 50 DUP(0); продолжение буфера
_DATA ENDS
; сегмент кода
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE':
; получить дескриптор приложения
PUSH 0
CALL GetModuleHandleA@4; Возвращает дескриптор модуля, содержащего тип, представленный данным экземпляром
MOV [HINST], EAX
REG_CLASS:;регистрация класса окна
; заполнить структуру окна
; стиль
MOV [WC.CLSSTYLE], STYLE
; процедура обработки сообщений
MOV [WC.CLWNDPROC], OFFSET WNDPROC
MOV [WC.CLSCBCLSEX],0
MOV [WC.CLSCBWNDEX],0
MOV EAX, [HINST][WC.CLSHINST], EAX
;-------- иконка окнаIDI_APPLICATION0LoadIconA@8;загружаем иконку[WC.CLSHICON], EAX
;---------- курсор окнаIDC_ARROW0LoadCursorA@8;загружаем курсор[WC.CLSHCURSOR], EAX
;---------[WC.CLBKGROUND], 28; цвет окнаDWORD PTR [WC.CLMENNAME], 0DWORD PTR [WC.CLNAME], OFFSET CLASSNAME OFFSET WC
CALL RegisterClassA@4;Регистрирует класс, определенный конструктором, с дополнительным базовым типом и типом интерфейса
; создать окно зарегистрированного класса
PUSH 0
PUSH [HINST]00600; DY - высота окна 1200; DX - ширина окна
PUSH 100; Y - координата левого верхнего угла
PUSH 100; X - координата левого верхнего угла
PUSH WS_OVERLAPPEDWINDOWOFFSET TITLENAME; имя окнаOFFSET CLASSNAME; имя класса0 CreateWindowExA@48
; проверка на ошибку
CMP EAX, 0
JZ _ERR
MOV [NEWHWND], EAX; дескриптор окна
PUSH SW_SHOWNORMAL[NEWHWND] ShowWindow@8; показать созданное окно
;------------------------------------------------------------
PUSH [NEWHWND]
CALL UpdateWindow@4; команда перерисовать видимую
; часть окна, сообщение WM_PAINT
; цикл обработки сообщений
MSG_LOOP:000 OFFSET MSG
CALL GetMessageA@16;получаем сообщение из очереди
CMP EAX, 0;если в очередь пришел ноль, значит выходим из программы
JE END_LOOPOFFSET MSGTranslateMessage@4OFFSET MSGDispatchMessageA@4MSG_LOOP_LOOP:
; выход из программы (закрыть процесс)
PUSH [MSG.MSWPARAM]ExitProcess@4
_ERR:
JMP END_LOOP
;----------- функция определения длины строки ------------------------
; длина строки
; [EBP+08H] - указатель на строку
LENSTR PROCEBPEBP, ESPESIESI, DWORD PTR [EBP+8]EBX, EBX:BYTE PTR [ESI], 0LBL2EBXESILBL1:ESIEBP 4
LENSTR ENDP
; процедура окна
; расположение параметров в стеке
; [EBP+014Н]; LPARAM
; [EBP+10H]; WAPARAM
; [EBP+0CH]; MES
; [EBP+8]; HWNDPROCEBPEBP,ESP
; PUSH EBX
; PUSH ESI
; PUSH EDIREG, <EBX,ESI,EDI>; макроповторение IRPREGDWORD PTR [EBP+0CH],WM_DESTROYWMDESTROYDWORD PTR [EBP+0CH],WM_CREATEWMCREATEDWORD PTR [EBP+0CH],WM_PAINTWMPAINTDWORD PTR [EBP+0CH],WM_COMMANDWMCOMMNDDEFWNDPROC:EAX,HWNDBTNDWORD PTR [EBP+14H],EAX; определяем нажата ли кнопка «Событие 1» BUTT1
; получить отредактированную строку
PUSH OFFSET TEXT
PUSH 150WM_GETTEXTHWNDEDT SendMessageA@16; показать эту строку
; записать отредактированную строку текстовое поле HWNDEDT1
PUSH OFFSET TEXT0WM_SETTEXTHWNDEDT1SendMessageA@16NODESTROY:EAX,HWNDBTN1DWORD PTR [EBP+14H],EAX; определяем нажата ли кнопка «Событие 2»NODESTROY[NEWHWND]0 0
CALL InvalidateRect@12; принудительная перерисовка окна
.IF TMP==0; изменение условий перерисовки окна
MOV TMP,1
.ELSETMP,0
.ENDIFNODESTROY:EAX, 0FINISH:OFFSET PNTDWORD PTR [EBP+08H] BeginPaint@8
PUSH EAX; сохранить контекст (дескриптор)
;---------------- цвет фона = цвет окна
PUSH RGBW
PUSH EAXSetBkColor@8
;---------------- контекстEAX EAX
;---------------- цвет текста
PUSH RGBT
PUSH EAXSetTextColor@8EAX
.IF TMP==1; проверка условия прорисовки текста по событию 2
REPT 20; макроповторение REPT
PUSH EAX
;---------------- вывести текст
PUSH OFFSET TEXT
CALL LENSTR; вызов процедуры определения длины сообщения
PUSH EBX; длина строки
PUSH OFFSET TEXT; адрес строки
ADD YT,20YT; YXT; XEAX; контекст окнаTextOutA@20EAX
.ENDIFYT,90OFFSET PNTDWORD PTR [EBP+08H]EndPaint@8EAX, 0FINISH:
; создать окно-кнопку "Событие1"
PUSH 0[HINST]0DWORD PTR [EBP+08H]20; DY300; DX10; Y10; XSTYLBTNOFFSET CPBUT; имя окнаOFFSET CLSBUTN; имя класса0 CreateWindowExA@48
MOV HWNDBTN,EAX; запомнить дескриптор кнопки
; создать окно-кнопку "Событие2"
PUSH 0
PUSH [HINST]0DWORD PTR [EBP+08H]20; DY300; DX85; Y10; XSTYLBTNOFFSET CPBUT1; имя окнаOFFSET CLSBUTN; имя класса0 CreateWindowExA@48
MOV HWNDBTN1,EAX; запомнить дескриптор кнопки
; создать окно редактирования1
PUSH 0
PUSH [HINST]
PUSH 0DWORD PTR [EBP+08H]20; DY300; DX40; Y10; XSTYLEDTOFFSET CPEDT; имя окнаOFFSET CLSEDIT; имя класса0 CreateWindowExA@48
MOV HWNDEDT,EAX
; создать окно редактирования 2
PUSH 0[HINST]0DWORD PTR [EBP+08H]20; DY300; DX60; Y10; XSTYLEDTOFFSET CPEDT; имя окнаOFFSET CLSEDIT; имя класса0 CreateWindowExA@48
MOV HWNDEDT1,EAX
;--------- поместить строку в окно редактирования
PUSH OFFSET TEXT0WM_SETTEXT HWNDEDT
CALL SendMessageA@16
;--------- установить фокус на окне редактирования
PUSH HWNDEDTSetFocus@4
;------------------------------------------------------------EAX, 0FINISH:DWORD PTR [EBP+14H]DWORD PTR [EBP+10H]DWORD PTR [EBP+0CH]DWORD PTR [EBP+08H] DefWindowProcA@16; вызывается оконной процедурой по умолчанию,
;чтобы обеспечить обработку по умолчанию любого сообщения окна,
;которые приложение не обрабатывает
JMP FINISH
WMDESTROY:0PostQuitMessage@4; сообщение WM_QUITEAX, 0:EDIESIEBXEBP16ENDP
_TEXT ENDSSTART