7.3.4. Диалоги

Графические программы для Windows почти никогда не ограничиваются од­ним меню, потому что оно не позволяет ввести реальную информацию - только выбрать какой-либо пункт из предложенных. Конечно, в цикле после GetMessage

или PeekMessage можно обрабатывать события передвижения мыши и нажатия

клавиш, и так делают в интерактивных программах, например в играх, но если

требуется ввести текст и в дальнейшем его редактировать, выбрать файл на диске

и т. п., то основным средством ввода информации в программах для Windows ока­зываются диалоги.

Диалог описывается, так же как и меню, в файле ресурсов, но если меню легко написать вручную, то ради диалогов, скорее всего, придется пользоваться каким-нибудь редактором, идущим в комплекте с вашим любимым компилятором, при условии, конечно, что вы не знаете в точности, по каким координатам располага­ется каждый контрол (активный элемент диалога).

// windlg.ro

// Файл ресурсов, описывающий диалог, который исполвзуется в программе windlg.asm. // Все следующие определения можно заменить на Kinclude <winuser.h>,   если он есть.

Программирование для Windows

95/NT

// Стили для диалогов, ffdefine DS_CENTER #define DSJ10DAIFRAME ffdefine DS_3DLOOK // Стили для окон, ffdefine WSJIINIMIZEBOX ffdefine WS_SYSMENU ffdefine WSJ/ISIBLE ffdefine WS_OVERLAPPED ffdefine WS^CAPTION

// Стили для

ffdefine ES_AUTOHSCROLL ffdefine ES_LEFT 0x08001 0x80L

Ox0004L

0x000200001 Ox00080000L OxIOOOOOOOL

OxOOOOOOOOL OxCOOOOOL

Ox80L 0 '

ffdefine ZDLG_MENu7

// Идентификаторы контролов диалога. ffdefine IDC.EDIT 0 ffdefine IDCJUHON 1 ffdefine IDC_EXIT 2 // Идентификаторы пунктов меню. ffdefine IDM_GETTEXT 10 ffdefine IDM_CLEAR11 ffdefine IDM_EXIT _ 12

ZZZ^Dialog DIALOG 10,10,205,30 STYLE BS_CENTER I  DSJIOQALFRAME I 0S_3DL00K WS.SYSMENU I WS_VISIBLE I WS^OVERLAPPED

CAPTION "Win32 assembly dialog example" '      ' // Заголовок.

MEND ZDLG_MENU // Меню.

BEGIN // Начало списка контролов.

EDITTEXT IDC_EDIT, 15,7,111,13,ESJUJT0HSCR0LL   I ES_LEFT

PUSHBUTTON "E&xit",IDC_EXIT,141,8,52,13

END

// x, WS_CAPTION

у, ширина, высота. I WS MINIMIZEBOX I

ZDLG_MENU MENU

BEGIN

POPUP

BEGIN

// Меню.

"Test"

MENUITEM

MENUITEM "Get

"Clear Text",IDM CLEAR

MENUITEM SEPARATOR

MENDITEM "E&xit",I0M EXIT

END

END

На простом примере покажем, как можно применять диалог, даже не регист­рируя нового класса. Для этого надо создать диалог командой CгeateDialog или одним из ее вариантов, не конфигурируя никакого окна-предка. Все сообщения от диалога и окон, которые он создает, будут посылаться в процедуру-обработчик типа DialogPгoc, аналогичную \Утс1олуРгос.

; windlg.asm

;  Графическое м<1п32-приложение,  демонстрирующее работу ; Идентификаторы   контролов   (элементов диалога). IDC_EDIT equ О

IDC_BuTTON equ 1

IDC_EXIT equ 2

; Идентификаторы элементов меню.

IOM_GETTEXT equ 10

IDM_CLEAR equ 11

IDM_EXIT equ 12

include def32.inc include kernel32.inc

include user32.inc

с диалогом.

.386 .model

. data

dialog_name

.data?

buffer

. code

_start:

xor

flat

db

db

"ZZZ_Dialog"

512 dup(?)

Имя диалога в ресурсах.

Буфер для введенного текста.

ebx,ebx

;   В ЕВХ будет О для команд push О ;   (короче в 2 раза).

; Определить идентификатор нашей программы. ■ push ebx call GetModuleHandle •; Запустить диалог.

ebx        ;   Значение,   которое перейдет как параметр WMJMTDIALOG. offset dialog_proc ; Адрес процедуры типа DialogProc. ebx        ;   Идентификатор окна-предка  (0 - ничей диалог).

push push

push push push

offset dialog_name ;  Адрес имени диалога в ресурсах. eax        ;  Идентификатор программы,   в ресурсах которой ;   находится диалог  (наш идентификатор в ЕАХ). DialogBoxParam

call

;  Выход из программы.  . - , •

push ebx

call ExitProcess

Процедура dialog_proc.

диалогом каждый раз,   когда в нем что-нибудь происходит. Именно здесь будет происходить вся работа программы.

Процедура не должна изменять регистры и ЕВХ!

dialog_proc        proc near

; Так как мы получаем параметры

push ' ebp

mov ebp.esp в стеке, кадр.

; Процедура типа DialogProc вызывается со следующими параметрами:

dp„hWnd equ dword ptr [ebp+08h]   ; идентификатор диалога,

dp_uMsg equ dword ptr [ebp+OCh] ; номер сообщения, dp.wParam ecru dword ptr [ebp+10h]; первый параметр,

dpIlParam equ dword ptr  [ebp+14h] ;  второй параметр.

mov ecx,dp_hWnd ; ECX будет хранитв идентификатор диалога,

mov eax,dp_uMsg ; а ЕАХ - номер сообщения.

cmp eax,WM_INITDIALOG ; Если мы получили WM_INITDIAL0G,

jne notjnitdialog

push" ■IOCLEOIT

push dp^hWnd

call GetDlgltem ; определить идентифжатор

push eax ; окна редактирования текста

call SetFocus ; и передать ему фокус.

not_initdialog:

cmp eax.WM CLOSE     . ; Если мы получили WM_CL0SE,

jne not_close

push 0

push ecx

call EndOialog ; закрыть диалог.

not_close:

cmp eax,WM_COMMAND ;  Если мы получили WM COMMAND,

jne not_command

mov eax,dp_wParam ; EAX = wParam (номер сообщения).

cmp dp_lParam,0 ; Если lparam ноль - сообщение от меню,

jne lParam_not_0

cmp ax, IDM_GETTEXT ; Если это пункт, меню Get Text,

jne not_gettext

push 512 ' ; Размер буфера.

push. offset  buffer ; Адрес буфера.

push IOC_EDIT ; Номер контроле редактирования.

push ecx

call GetDlgltemText ; Считать текст в буфер

push МВ_0К

push offset dialog_name

push offset buffer

push dpjiwnd

call MessageBox ;  и показатв его в MessageBox.

not_gettext:

cmp     ■ eax, IDM_CLEAR ;   Если это пункт меню Clear:

jne not_clear

push 0 ■; NULL.

push IDO.EDIT ;  Номер контрола.

push ecx

call SetDlgltemText ; установить новый текст.

not_clear:

cmp eax,IDM.EXIT ;   Если это пункт меню Exit:

jne not_exit

push 0 ;   код возврата.

push

ecx

; Идентификатор диалога.

call

EndDialog

; Закрыть диалог.

lParam_not_0:

 

; lParam не ноль - сообщение от контрола.

cmp

eax,IDC EXIT

; Если сообщение от кнопки Exit.

jne

not_exit

 

shr

eax,16

 

cmp

eax.BN CLICKED

; Если ее нажали:

push

0

; код возврата.

push

ecx

Идентификатор диалога.

call

EndDialog

; Закрыть диалог.

not_exit:

 

 

xor

eax,eax

; После обработки команды

inc

eax

; OialogProc должен возвращать TRUE (eax = 1).

leave

 

 

ret

16

; Конец процедуры.

not_command:

 

; Сюда передается управление, если мы получили какое-то незнакомое сообщение.

xor

eax,eax

;  Код возврата FALSE  (eax = 0).

leave

 

 

ret

16

Конец процедуры.

dialog_proc

end'p

 

end

start

 

Добавления в наш user32.inc.

Между ifdef _TASM_ и else:

 

extrn

DialogBoxParamA:near

 

extrn

GetDlgltem:near

 

extrn

SetFocus:near

 

extrn

GetDlgItemTextA:near

 

extrn

SetDlgltemTextA:nea r

 

extrn

EndDialog:near

DialogBoxParam

equ

DialogBoxParamA

GetDlgltemText

equ

GetDlgltemTextA

SetDlgltemText

equ

SetDlgltemTextA

Между else и endif:

 

 

extrn

imp DialogBoxParamA@20:dword

 

extrn

imp GetDlgItem@8:dword

 

extrn

imp SetFocus@4:dword

 

extrn

imp GetDlgItemTextA@16:dword

 

extrn

imp SetDlgItemTextA@12:dword

 

extrn

imp EndDialog@8:dword

DialogBoxParam

equ

_imp_DialogBoxParamA@20

GetDlgltem

equ

__imp__GetDlgItem@8

SetFocus

equ

__imp__SetFocus@4

GetDlgltemText

equ

imp GetDlgItemTextA@16

SetDlgltemText

equ

_imp_SetDlgItemTextA@12

EndDialog

equ

__imp__EndDialog@8

Добавления

к файлу def32.inc:

; Mawinuser.h.

 

 

WM_INITDIALOG

equ

110h

WM_CL0SE

BN_CLICKED equ equ 10h 0