Downloadez le premier exemple ici, le second Là.
SendDlgItemMessage proto hwndDlg:DWORD,\Cet appel d'API est super utile pour l'action réciproque avec les 'child window control'. Par exemple, si vous voulez récupérer le texte d'un contrôle d'édition, vous pouvez faire ceci :
idControl:DWORD,\
uMsg:DWORD,\
wParam:DWORD,\
lParam:DWORD
call SendDlgItemMessage, hDlg, ID_EDITBOX, WM_GETTEXT, 256, ADDR text_bufferPour savoir quel message (quelle commande) vous devez utiliser, vous devez consulter votre référence Win32 API.
DlgProc proto hDlg:DWORD ,\La 'procédure de boîte de dialogue' est très semblable à une 'procédure de fenêtre' à part le type de valeur de retour qui est TRUE / FAULSE au lieu de LRESULT. L'administrateur de boîte de dialogue interne à Windows EST la vraie procédure de fenêtre pour la boîte de dialogue. Il appelle notre procédure de boîte de dialogue avec les messages qu'il a reçu. Donc la règle générale en vigueur consiste en ce que : si notre procédure de boîte de dialogue traite un message, il DOIT retourner la valeur TRUE (VRAIE) dans eax et s'il ne traite pas le message, il doit retourner FAULSE (FAUX) dans eax. Remarquez qu'une procédure de boîte de dialogue ne transmet pas les messages et elle ne traite pas l'appel de DefWindowProc puisque ce n'est pas une procédure de fenêtre réelle (normale).
iMsg:DWORD ,\
wParam:DWORD ,\
lParam:DWORD
.data
ClassName
db "DLGCLASS",0
MenuName
db "MyMenu",0
DlgName
db "MyDialog",0
AppName
db "Our First Dialog Box",0
TestString
db "Wow! Je suis dans une boîte d'édition maintenant",0
.data?
hInstance
HINSTANCE ?
CommandLine
LPSTR ?
buffer
db 512 dup(?)
.const
IDC_EDIT
equ 3000
IDC_BUTTON
equ 3001
IDC_EXIT
equ 3002
IDM_GETTEXT
equ 32000
IDM_CLEAR
equ 32001
IDM_EXIT
equ 32002
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain
proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hDlg:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,DLGWINDOWEXTRA
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,OFFSET MenuName
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateDialogParam,hInstance,ADDR DlgName,NULL,NULL,NULL
mov hDlg,eax
invoke ShowWindow, hDlg,SW_SHOWNORMAL
invoke UpdateWindow, hDlg
invoke GetDlgItem,hDlg,IDC_EDIT
invoke SetFocus,eax
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke IsDialogMessage, hDlg, ADDR msg
.IF eax ==FALSE
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDIF
.ENDW
mov eax,msg.wParam
ret
WinMain
endp
WndProc
proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF lParam==0
.IF ax==IDM_GETTEXT
invoke GetDlgItemText,hWnd,IDC_EDIT,ADDR buffer,512
invoke MessageBox,NULL,ADDR buffer,ADDR AppName,MB_OK
.ELSEIF ax==IDM_CLEAR
invoke SetDlgItemText,hWnd,IDC_EDIT,NULL
.ELSE
invoke DestroyWindow,hWnd
.ENDIF
.ELSE
mov edx,wParam
shr edx,16
.IF dx==BN_CLICKED
.IF ax==IDC_BUTTON
invoke SetDlgItemText,hWnd,IDC_EDIT,ADDR TestString
.ELSEIF ax==IDC_EXIT
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
.ENDIF
.ENDIF
.ENDIF
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc
endp
end
start
#define
IDC_EDIT
3000
#define
IDC_BUTTON
3001
#define
IDC_EXIT
3002
#define
IDM_GETTEXT
32000
#define
IDM_CLEAR
32001
#define
IDM_EXIT
32003
MyDialog
DIALOG 10, 10, 205, 60
STYLE
0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU
| WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION
"Our First Dialog Box"
CLASS
"DLGCLASS"
BEGIN
EDITTEXT IDC_EDIT,
15,17,111,13, ES_AUTOHSCROLL | ES_LEFT
DEFPUSHBUTTON "Dis Bonjour", IDC_BUTTON, 141,10,52,13
PUSHBUTTON "E&xit", IDC_EXIT, 141,26,52,13,
WS_GROUP
END
MyMenu
MENU
BEGIN
POPUP "Test Controls"
BEGIN
MENUITEM "Get Text", IDM_GETTEXT
MENUITEM "Clear Text", IDM_CLEAR
MENUITEM "", , 0x0800 /*MFT_SEPARATOR*/
MENUITEM "E&xit", IDM_EXIT
END
END
MyDialog DIALOG 10, 10, 205, 60
On déclare le nom d'un dialogue, dans ce cas, "MyDialog" suivi du mot-clé "DIALOG". Les quatre nombres suivants sont : x, y, largeur et hauteur de la boîte de dialogue, ce sont des unités propres aux DialogBox (C'est pas des pixels).
STYLE
0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU
| WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
Déclare les styles de la boîte de dialogue.
CAPTION "Our First Dialog Box"
C'est le texte qui apparaîtra dans la barre de titre de la boîte de dialogue.
CLASS "DLGCLASS"
Cette ligne est cruciale. C'est ce mot-clé CLASS qui nous permet d'employer le calibre de boîte de dialogue comme une 'Window Class' (classe de fenêtre). Puis, suivant le mot-clé on trouve le nom de la "Window Class"
BEGIN
EDITTEXT IDC_EDIT,
15,17,111,13, ES_AUTOHSCROLL | ES_LEFT
DEFPUSHBUTTON "Dis Bonjour", IDC_BUTTON, 141,10,52,13
PUSHBUTTON "E&xit", IDC_EXIT, 141,26,52,13
END
Le susdit bloc définit les 'child window controls' de la boîte de dialogue. Ils sont définis entre les mots-clés BEGIN et END. Généralement la syntaxe est la suivante :
invoke IsDialogMessage, hDlg, ADDR msg
.IF eax ==FALSE
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDIF
Le programme entre dans la boucle de message et avant que nous traduisions et expédiions des messages, nous appelons la fonction IsDialogMessage pour que l'administrateur de boîte de dialogue puisse s'occuper de la logique du clavier à notre place. Si ces retours de fonction sont TRUES(VRAIS), alors ça signifie que le message est destiné à la boîte de dialogue et est traité par l'administrateur de la boîte de dialogue. Remarquez une autre différence par rapport Tutorial précédent. Quand la procédure de fenêtre veut récupérer le texte qui est inscrit dans la zone d'édition, elle appelle la fonction GetDlgItemText au lieu de GetWindowText. GetDlgItemText accepte un contrôle ID au lieu d'un 'Window Handle'. Ceci rend l'appel plus facile dans le cas vous employez une boîte de dialogue.
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
include
\masm32\include\windows.inc
include
\masm32\include\user32.inc
include
\masm32\include\kernel32.inc
includelib
\masm32\lib\user32.lib
includelib
\masm32\lib\kernel32.lib
.data
DlgName
db "MyDialog",0
AppName
db "Our Second Dialog Box",0
TestString
db "Wow! Je suis dans une zone d'édition",0
.data?
hInstance
HINSTANCE ?
CommandLine
LPSTR ?
buffer
db 512 dup(?)
.const
IDC_EDIT
equ 3000
IDC_BUTTON
equ 3001
IDC_EXIT
equ 3002
IDM_GETTEXT
equ 32000
IDM_CLEAR
equ 32001
IDM_EXIT
equ 32002
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
invoke ExitProcess,eax
DlgProc
proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_INITDIALOG
invoke GetDlgItem, hWnd,IDC_EDIT
invoke SetFocus,eax
.ELSEIF uMsg==WM_CLOSE
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF lParam==0
.IF ax==IDM_GETTEXT
invoke GetDlgItemText,hWnd,IDC_EDIT,ADDR buffer,512
invoke MessageBox,NULL,ADDR buffer,ADDR AppName,MB_OK
.ELSEIF ax==IDM_CLEAR
invoke SetDlgItemText,hWnd,IDC_EDIT,NULL
.ELSEIF ax==IDM_EXIT
invoke EndDialog, hWnd,NULL
.ENDIF
.ELSE
mov edx,wParam
shr edx,16
.if dx==BN_CLICKED
.IF ax==IDC_BUTTON
invoke SetDlgItemText,hWnd,IDC_EDIT,ADDR TestString
.ELSEIF ax==IDC_EXIT
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
.ENDIF
.ENDIF
.ENDIF
.ELSE
mov eax,FALSE
ret
.ENDIF
mov eax,TRUE
ret
DlgProc
endp
end
start
#define
IDC_EDIT
3000
#define
IDC_BUTTON
3001
#define
IDC_EXIT
3002
#define IDR_MENU1 3003
#define
IDM_GETTEXT
32000
#define
IDM_CLEAR
32001
#define
IDM_EXIT
32003
MyDialog
DIALOG 10, 10, 205, 60
STYLE
0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU
| WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION
"Our Second Dialog Box"
MENU
IDR_MENU1
BEGIN
EDITTEXT IDC_EDIT,
15,17,111,13, ES_AUTOHSCROLL | ES_LEFT
DEFPUSHBUTTON "Dis Bonjour", IDC_BUTTON, 141,10,52,13
PUSHBUTTON "E&xit", IDC_EXIT, 141,26,52,13
END
IDR_MENU1
MENU
BEGIN
POPUP "Test Controls"
BEGIN
MENUITEM "Get Text", IDM_GETTEXT
MENUITEM "Clear Text", IDM_CLEAR
MENUITEM "", , 0x0800 /*MFT_SEPARATOR*/
MENUITEM "E&xit", IDM_EXIT
END
END
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
Nous déclarons le prototype de fonction de DlgProc ,ainsi nous pouvons lui attribuer l'opérateur addr à la ligne ci-dessous :
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
la susdite ligne appelle la fonction DialogBoxParam qui prend 5 paramètres : l'Instance handle', le 'nom du calibre de boîte de dialogue', l'handle de la fenêtre parente', l'adresse de la procédure de la de boîte de dialogue et des données dialogue-spécifiques. DialogBoxParam crée une boîte de dialogue modale. Rien ne sera retourné tant que la boîte de dialogue ne sera pas détruite.
.IF uMsg==WM_INITDIALOG
invoke GetDlgItem, hWnd,IDC_EDIT
invoke SetFocus,eax
.ELSEIF uMsg==WM_CLOSE
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
La procédure de boîte de dialogue ressemble à une procédure de fenêtre sauf qu'elle ne reçoit pas le message WM_CREATE. Le premier message qu'elle reçoit est WM_INITDIALOG. Normalement vous pouvez mettre le code d'initialisation ici. Remarquez que vous devez renvoier la valeur TRUE (VRAIE) dans eax si vous traitez le message.
L'administrateur interne de boîte de dialogue n'envoie pas à notre procédure de boîte de dialogue par défaut le message WM_DESTROY quand WM_CLOSE est envoyé à notre boîte de dialogue. Ainsi si nous voulons réagir quand l'utilisateur presse le bouton proche sur notre boîte de dialogue, nous devons traiter le message WM_CLOSE. Dans notre exemple, nous envoyons le message WM_COMMAND avec la valeur IDM_EXIT dans wParam. Ça a le même effet que lorsque l'utilisateur choisit l'article de menu de Sortie (le sous-menu : EXIT). EndDialog est appelé dans la réponse à IDM_EXIT.
Le traitement du messages WM_COMMAND reste le même.
Quand vous voulez détruire la boîte de dialogue, il faut appeler la fonction EndDialog. N'essayez pas DestroyWindow! EndDialog ne détruit pas la boîte de dialogue immédiatement. Il met seulement un drapeau(Flag) pour l'administrateur de la boîte de dialogue et continue à exécuter les instructions suivantes.
Maintenant on va examiner le fichier de ressources. Un changement notable est qu'au lieu de l'utilisation d'une chaîne de texte pour le nom de menu nous employons une valeur, IDR_MENU1. C'est nécessaire si vous voulez attacher un menu à une boîte de dialogue créée avec DialogBoxParam. Notez que dans le calibre de boîte de dialogue, vous devez ajouter le mot-clé MENU suivi de la ressource du menu ID.
La différence entre les deux exemples de ce Tutorial est le manque d'une icône dans le dernier exemple. Cependant, vous pouvez mettre l'icône en envoyant le message WM_SETICON à la boîte de dialogue pendant WM_INITDIALOG.