Une boite de dialogue personnalisée
Page 1 sur 1
Une boite de dialogue personnalisée
Il existe d'autres boites de dialogue spécialisées (mais que je n'ai pas encore utilisées ) comme une boite de recherche dans du texte, mais maintenant nous allons voir la boite de dialogue où c'est vous qui définissez toutes les zones necessaires et gerez les évenements qui peuvent les toucher. Dans la terminologie windows, les zones sont appelées contrôles et dans l'API windows, vous trouverez des fonctions pour créer ces contrôles à partir d'un fichier des ressources. Comme avec nasm, nous n'utilisons pas de fichiers ressources, nous allons utiliser une fonction qui crée la boite de dialogue à partir de la description en mémoire.
Dans le programme ci dessous, nous commençons par décrire tous les textes qui seront affichés dans la boite : libelles statiques, titre de la boite et de chaque bouton avec une instruction pour calculer leur longueur. Ceci est necessaire car curieusement tous les textes de la boite doivent lui être passés en caractères UNICODE (sauf les textes des zones de saisies). Il nous faut donc convertir ces textes d'ANSI en UNICODE.
Ensuite nous trouvons la description de l'entete de la boite de dialogue. C'est une structure de type DLGTEMPLATE plus quelques données complémentaires. Nous y trouvons les constantes definissant le style de la fenêtre : visible avec bordure, modale avec la barre système standard.
Puis nous avons le nombre de controles que va contenir la boite : cad les zones textes, les boutons, les zones de saisies et les listbox. Ici nous avons 5 controles.
Puis nous trouvons les données qui positionnent la boite sur l'écran et sa taille.Dans les données complémentaires, nous trouvons une zone pour indiquer la présence de menu et une identification de la classe (utilisation à approfondir un jour !!) puis le titre de la boite de dialogue en caractères unicode. C'est pourquoi sa longueur est le double de la longueur du texte proprement dit.
Après cela nous allons trouver la description des 5 contrôles qui doivent être alignés sur une frontière de double mots.
La description commence par une structure de type DLGITEMTEMPLATE qui donne le style du contrôle : enfant, visible, accessible par la touche <TAB> ou bouton par défaut etc. puis son positionnement à l’intérieur de la boite et enfin l'identification du contôle : cette zone est importante car elle sera véhiculée à l’intérieur des messages et nous servira à determiner quelle action entreprendre sur ce contrôle.
Ensuite nous trouvons une zone qui sera toujours à FFFF et une zone qui donne le type du controle (80 pour un bouton,81 pour une zone de saisie, 82 pour du texte statique 83 pour une list box) puis le libellè du contrôle pour celle qui en ont un. Il y a aussi une zone finale et quelquefois des caractères d'ajout pour assurer l'alignement des structures. En effet comme tenu de la longueur de la zone titre qui peut être variable, il n'est pas facile de déterminer exactement la longueur de chaque définition d'un contrôle et si l'alignement n'est pas réalisé, nous avons un crash du programme. Donc par expérience, lors de la mise au point, je commence par mettre 0 contrôle dans la boite puis 1 puis 2 et en ajustant ce nombre de caractères complémentaire. Il y a peut être mieux à faire
Au niveau du code, nous commençons par récupérer le handle de notre programme par la fonction GetModuleHandleA puis nous convertissons chaque libellé d'ANSI en UNICODE par la fonction MultiByteToWideChar. Nous passons en paramètre la zone d'entree, la zone de sortie la longueur et les paramètres de conversion. Comme il y a plus de 4 paramètres, il faut gérer l'alignement et la réservation sur la pile.
Maintenant nous allons creer notre boite de dialogue par la fonction CreateDialogIndirectParamA. Nous commençons par lui passer en paramètre un texte qui servira lors de l'initialisation, le handle du programme, l'adresse du début de la structure d'entête de la boite et l'adresse de la procèdure qui va gérer les évènements.Ici elle s’appelle Proc_dialogue et il faudra la créer dans la suite du programme.
Remarque : nous ne passons à cette fonction que l'adresse de l'entête et donc c'est la fonction qui à partir du nombre de contrôles spécifiés dans cette entête, va retrouver les informations de chacun. Vous comprenez pourquoi les structures doivent être alignées correctement.
Après la création de la boite, nous devons l'afficher par la fonction ShowWindow (remarque la documentation précise que cette fonction est inutile si on a indiqué VISIBLE dans le style de la boite, mais dans mon cas, cela ne fonctionne pas).
Puis nous trouvons une boucle de traitement des messages. Nous retrouverons ce mécanisme pour la création des fenêtres. En fait, chaque controle et la boite de dialogue vont à une action de l'utilisateur envoyer un message. Tous ces messages vont être analysés et transmis à la procédure gestionnaire. Lorsque le message PostQuitMessage sera envoyé à la fermeture de la boite, le registre rax sera à zero et la boucle se terminera. Ici nous avons la fonction GetMessageA pour la récupèration et la fonction IsDialogMessageA pour l'analyse et l'envoi à la procédure.
Voyons le contenu de la fonction Proc_dialogue. Contrairement aux autres fonctions de l'API que nous avons vu jusqu'à maintenant, celle -ci sera écrite par nos soins et appelée par windows pour traiter les messages qui nous sont destinés. Et windows passera les paramètres nécessaires dans les 4 registres rcx,rdx,r8 et r9.
Pour assurer la compatiblité, nous recopions ces 4 paramètres dans les zones réservées de la pile (à creuser un peu plus pour voir l'utilité).
Ensuite nous testons la zone uMsg qui contient le type de message reçu. Ici nous allons traiter les messages WM_INITDIALOG WM_DESTROY,WM_CLOSE et WM_COMMAND.
Le message WM_INITDIALOG est envoyé lors de la création de la boite de dialogue et permet d'initialiser certaines zones. Comme exemple, nous récuperons l'adresse du texte passé en premier paramètre de la fonction CreateDialogIndirectParamA. Celle ci est contenu dans le paramètre lParam. Et nous envoyons le texte dans la zone de saisie de la boite par la fonction SendDlgItemMessageA gràce à son identifiant ID_EDIT1.
Les messages WM_DESTROY et WM_CLOSE ne feront que fermer la boite de dialogue par la fonction EndDialog et d'envoyer le message de fin par PostQuitMessage.
Le message WM_COMMAND necessite d'abord de connaitre quel bouton a été appuyé. Nous testons d'abord l'identifiant IDOK pour le 1er bouton puis IDCLOSEpour le 2ième et IDCANCEL au cas où l'utilisateur aurait utiliser la touche <ESC>.
Dans le cas du bouton OK, nous récuperons dans un buffer le texte de la zone de saisie par la fonction GetDlgItemTextA, nous le convertissons en majuscule par CharUpperA et nous l'ajoutons à une ligne du contrôle LISTBOX par la fonction SendDlgItemMessageA mais avec le paramètre LB_ADDSTRING. Ainsi à chaque saisie d'un texte dans la zone de saisie, et appuie sur le bouton OK, le texte sera mis en majuscule et ajouté aux lignes de la listBox. Vous remarquerez que au delà de la taille de la listbox, un ascenseur apparait automatiquement : c'est pas beau ça !!!!
Remarque : les premières mises au point d'une boite de dialogue peuvent être laborieuses. En effet il faut que les définitions des contrôles soient bonnes mais aussi que la procédure de traitement soit correcte (rax doit toujours retourner ou FALSE ou TRUE). En cas de doute, ne mettre qu'un seul controle dans la définition de la BAL puis augmenter quand le précedent est OK. Mettre aussi une procèdure de vidage en début de la procèdure de gestion pour voir quel type de message arrive et le suivre.
Nous verrons que la création de fenêtres repose aussi sur le même mécanisme de gestion de message et de procèdure de réception.
Dans le programme ci dessous, nous commençons par décrire tous les textes qui seront affichés dans la boite : libelles statiques, titre de la boite et de chaque bouton avec une instruction pour calculer leur longueur. Ceci est necessaire car curieusement tous les textes de la boite doivent lui être passés en caractères UNICODE (sauf les textes des zones de saisies). Il nous faut donc convertir ces textes d'ANSI en UNICODE.
Ensuite nous trouvons la description de l'entete de la boite de dialogue. C'est une structure de type DLGTEMPLATE plus quelques données complémentaires. Nous y trouvons les constantes definissant le style de la fenêtre : visible avec bordure, modale avec la barre système standard.
Puis nous avons le nombre de controles que va contenir la boite : cad les zones textes, les boutons, les zones de saisies et les listbox. Ici nous avons 5 controles.
Puis nous trouvons les données qui positionnent la boite sur l'écran et sa taille.Dans les données complémentaires, nous trouvons une zone pour indiquer la présence de menu et une identification de la classe (utilisation à approfondir un jour !!) puis le titre de la boite de dialogue en caractères unicode. C'est pourquoi sa longueur est le double de la longueur du texte proprement dit.
Après cela nous allons trouver la description des 5 contrôles qui doivent être alignés sur une frontière de double mots.
La description commence par une structure de type DLGITEMTEMPLATE qui donne le style du contrôle : enfant, visible, accessible par la touche <TAB> ou bouton par défaut etc. puis son positionnement à l’intérieur de la boite et enfin l'identification du contôle : cette zone est importante car elle sera véhiculée à l’intérieur des messages et nous servira à determiner quelle action entreprendre sur ce contrôle.
Ensuite nous trouvons une zone qui sera toujours à FFFF et une zone qui donne le type du controle (80 pour un bouton,81 pour une zone de saisie, 82 pour du texte statique 83 pour une list box) puis le libellè du contrôle pour celle qui en ont un. Il y a aussi une zone finale et quelquefois des caractères d'ajout pour assurer l'alignement des structures. En effet comme tenu de la longueur de la zone titre qui peut être variable, il n'est pas facile de déterminer exactement la longueur de chaque définition d'un contrôle et si l'alignement n'est pas réalisé, nous avons un crash du programme. Donc par expérience, lors de la mise au point, je commence par mettre 0 contrôle dans la boite puis 1 puis 2 et en ajustant ce nombre de caractères complémentaire. Il y a peut être mieux à faire
Au niveau du code, nous commençons par récupérer le handle de notre programme par la fonction GetModuleHandleA puis nous convertissons chaque libellé d'ANSI en UNICODE par la fonction MultiByteToWideChar. Nous passons en paramètre la zone d'entree, la zone de sortie la longueur et les paramètres de conversion. Comme il y a plus de 4 paramètres, il faut gérer l'alignement et la réservation sur la pile.
Maintenant nous allons creer notre boite de dialogue par la fonction CreateDialogIndirectParamA. Nous commençons par lui passer en paramètre un texte qui servira lors de l'initialisation, le handle du programme, l'adresse du début de la structure d'entête de la boite et l'adresse de la procèdure qui va gérer les évènements.Ici elle s’appelle Proc_dialogue et il faudra la créer dans la suite du programme.
Remarque : nous ne passons à cette fonction que l'adresse de l'entête et donc c'est la fonction qui à partir du nombre de contrôles spécifiés dans cette entête, va retrouver les informations de chacun. Vous comprenez pourquoi les structures doivent être alignées correctement.
Après la création de la boite, nous devons l'afficher par la fonction ShowWindow (remarque la documentation précise que cette fonction est inutile si on a indiqué VISIBLE dans le style de la boite, mais dans mon cas, cela ne fonctionne pas).
Puis nous trouvons une boucle de traitement des messages. Nous retrouverons ce mécanisme pour la création des fenêtres. En fait, chaque controle et la boite de dialogue vont à une action de l'utilisateur envoyer un message. Tous ces messages vont être analysés et transmis à la procédure gestionnaire. Lorsque le message PostQuitMessage sera envoyé à la fermeture de la boite, le registre rax sera à zero et la boucle se terminera. Ici nous avons la fonction GetMessageA pour la récupèration et la fonction IsDialogMessageA pour l'analyse et l'envoi à la procédure.
Voyons le contenu de la fonction Proc_dialogue. Contrairement aux autres fonctions de l'API que nous avons vu jusqu'à maintenant, celle -ci sera écrite par nos soins et appelée par windows pour traiter les messages qui nous sont destinés. Et windows passera les paramètres nécessaires dans les 4 registres rcx,rdx,r8 et r9.
Pour assurer la compatiblité, nous recopions ces 4 paramètres dans les zones réservées de la pile (à creuser un peu plus pour voir l'utilité).
Ensuite nous testons la zone uMsg qui contient le type de message reçu. Ici nous allons traiter les messages WM_INITDIALOG WM_DESTROY,WM_CLOSE et WM_COMMAND.
Le message WM_INITDIALOG est envoyé lors de la création de la boite de dialogue et permet d'initialiser certaines zones. Comme exemple, nous récuperons l'adresse du texte passé en premier paramètre de la fonction CreateDialogIndirectParamA. Celle ci est contenu dans le paramètre lParam. Et nous envoyons le texte dans la zone de saisie de la boite par la fonction SendDlgItemMessageA gràce à son identifiant ID_EDIT1.
Les messages WM_DESTROY et WM_CLOSE ne feront que fermer la boite de dialogue par la fonction EndDialog et d'envoyer le message de fin par PostQuitMessage.
Le message WM_COMMAND necessite d'abord de connaitre quel bouton a été appuyé. Nous testons d'abord l'identifiant IDOK pour le 1er bouton puis IDCLOSEpour le 2ième et IDCANCEL au cas où l'utilisateur aurait utiliser la touche <ESC>.
Dans le cas du bouton OK, nous récuperons dans un buffer le texte de la zone de saisie par la fonction GetDlgItemTextA, nous le convertissons en majuscule par CharUpperA et nous l'ajoutons à une ligne du contrôle LISTBOX par la fonction SendDlgItemMessageA mais avec le paramètre LB_ADDSTRING. Ainsi à chaque saisie d'un texte dans la zone de saisie, et appuie sur le bouton OK, le texte sera mis en majuscule et ajouté aux lignes de la listBox. Vous remarquerez que au delà de la taille de la listbox, un ascenseur apparait automatiquement : c'est pas beau ça !!!!
- Code:
;---programme d'utilisation d'une boite de dialogue 64 bits
;BoiteDialogue1
; les routines de vidage et d'affichage sont déportées dans le fichier routineswin.obj
%include "../windowsinc64.inc"
;=======================================
; segment des données initialisées
;=======================================
segment .data
szMessFin db "Fin programme",0
szRetourLigne db 10,13,0
szTexteBD db "abcde",0 ; pour initialiser la zone de saisie
;************************************************************
;identification des controles de la boite
ID_EDIT1 equ 200 ; zone de saisie
IDD_LB1 EQU 201 ; list box
ID_TXT1 EQU 202 ; texte simple
;************************************************************
;libellés des textes à afficher dans la Boite de Dialogue
szTitreDialog db "DIALOGUE1",0
ILGTD equ $ - szTitreDialog ;et leur longueur
szTitreBouton db "OK",0
ILGTB1 equ $ - szTitreBouton
szTitreBouton2 db "FIN",0
ILGTB2 equ $ - szTitreBouton2
szTitreTexte db "Saississez un texte :",0
ILGTT1 equ $ - szTitreTexte
;************************************************************
;Description de la boite de dialogue
;entête des données générales
lpdta: align 4 ; Important
lpdt: istruc DLGTEMPLATE
at DLGTEMPLATE.style, dd WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION | DS_MODALFRAME | WS_VISIBLE
at DLGTEMPLATE.cdit, dw 5 ; nombre de controles
at DLGTEMPLATE.x, dw 10 ; position du coin à gauche de la boite de dialogue
at DLGTEMPLATE.y, dw 10 ; et en haut
at DLGTEMPLATE.cx, dw 300 ; largeur de la boite
at DLGTEMPLATE.cy, dw 200 ; hauteur de la boite
iend
lpdtmenu dw 0 ; pas de menu
lpdtclass dw 0
szTitreD Times (ILGTD * 2) db 0 ; titre de la fenêtre mais hélas en caractères Unicode
;description du premier controle (attention ce n'est peut être pas le premier de l'écran)
lpditC1a: align 4 ; Important
lpditC1: istruc DLGITEMTEMPLATE
at DLGITEMTEMPLATE.style, dd WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP
at DLGITEMTEMPLATE.dwExtendedStyle, dd WS_EX_NOPARENTNOTIFY
at DLGITEMTEMPLATE.x, dw 10 ;position à gauche du controle dans la boite
at DLGITEMTEMPLATE.y, dw 100 ; position en haut du controle dans la boite
at DLGITEMTEMPLATE.cx, dw 80 ; largeur du controle
at DLGITEMTEMPLATE.cy, dw 15 ; hauteur du controle
at DLGITEMTEMPLATE.id, dw IDOK ; identification
iend
sysClassC1 dw 0xFFFF ; toujours cette valeur
idClassC1 dw 0x0080 ; c'est un bouton
szTitreC1 Times (ILGTB1 * 2) db 0 ; libellé en caractères unicode
cbCreationDataC1 dw 0 ; à voir
;description du 2ième controle
lpditC2a: align 4
lpditC2: istruc DLGITEMTEMPLATE
at DLGITEMTEMPLATE.style, dd ES_LEFT | WS_BORDER | WS_CHILD |WS_TABSTOP| WS_VISIBLE
at DLGITEMTEMPLATE.x, dw 10
at DLGITEMTEMPLATE.y, dw 50
at DLGITEMTEMPLATE.cx, dw 80
at DLGITEMTEMPLATE.cy, dw 15
at DLGITEMTEMPLATE.id, dw ID_EDIT1 ; identification
iend
sysClassC2 dw 0xFFFF
idClassC2 dw 0x0081 ; c'est une zone de saisie
db 0 ; pas de libellé
cbCreationDataC2 dw 0
szfinC2 db 0
;description du 3ieme controle
lpditC3a: align 4
lpditC3: istruc DLGITEMTEMPLATE
at DLGITEMTEMPLATE.style, dd LBS_NOTIFY | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_TABSTOP
at DLGITEMTEMPLATE.x, dw 10
at DLGITEMTEMPLATE.y, dw 120
at DLGITEMTEMPLATE.cx, dw 63
at DLGITEMTEMPLATE.cy, dw 42
at DLGITEMTEMPLATE.id, dw IDD_LB1 ; identification
iend
sysClassC3 dw 0xFFFF
idClassC3 dw 0x0083 ; c'est une list box
szTitreC3 dw 0 ; pas de libellé
cbCreationDataC3 dw 0
;description du 4ième controle
lpditC4a: align 4
lpditC4: istruc DLGITEMTEMPLATE
at DLGITEMTEMPLATE.style, dd WS_VISIBLE ; on peut ajouter WS_BORDER si on veut l'entourer
at DLGITEMTEMPLATE.x, dw 10 ; d'une bordure
at DLGITEMTEMPLATE.y, dw 10
at DLGITEMTEMPLATE.cx, dw 100
at DLGITEMTEMPLATE.cy, dw 20
at DLGITEMTEMPLATE.id, dw ID_TXT1 ; identification
iend
sysClassC4 dw 0xFFFF
idClassC4 dw 0x0082 ; c'est du texte statique
szTitreC4 Times (ILGTT1 * 2) db 0
cbCreationDataC4 dw 0
lpditC5a: align 4
lpditC5: istruc DLGITEMTEMPLATE
at DLGITEMTEMPLATE.style, dd WS_CHILD | WS_VISIBLE | WS_TABSTOP
at DLGITEMTEMPLATE.dwExtendedStyle, dd WS_EX_NOPARENTNOTIFY
at DLGITEMTEMPLATE.x, dw 10
at DLGITEMTEMPLATE.y, dw 170
at DLGITEMTEMPLATE.cx, dw 80
at DLGITEMTEMPLATE.cy, dw 15
at DLGITEMTEMPLATE.id, dw IDCLOSE ; identification
iend
sysClassC5 dw 0xFFFF ; toujours cette valeur
idClassC5 dw 0x0080 ; c'est un bouton
szTitreC5 Times (ILGTB2 * 2) db 0 ; libellé en caractères unicode
cbCreationDataC5 dw 0 ; à voir
;
szfinb db 0,0,0,0,0,0 ; zone de sécurité si pb de longueur
;instance message
msg: istruc MSG
at MSG.fin, db "<<< "
iend
;=======================================
; segment des données non initialisées
;=======================================
segment .bss
hInst resq 1 ; handle du programme
hDlg resq 1 ; handle de la boite de dialogue
ILGBUFFER equ 100
szBuffer resb ILGBUFFER
;=======================================
; segment de code
;=======================================
segment .text
global Main
; les fonctions de l'API sont dans le fichier des includes
; ces fonctions sont mes routines utilitaires du fichier routines64.obj
extern afferreur,affmessageP,affconsoleP,afftoutregistreP,afftoutreg8a15P,affmemoireP,affmessage,saisieClavier
Main:
sub rsp, 8h
sub rsp, 20h
;recup handle de l'instance du programme
mov rcx, NULL
call GetModuleHandleA
cmp rax,NULL
je .gestionerreurs
mov [hInst],rax
;tous les textes sont en caractères unicode.
;il faut donc les convertir d'ANSI en UNICODE
;et donc leur taille est multiplié par deux
add rsp,20h ; 2 push donc pas d'alignement
push ILGTD * 2 ; taille de la zone de reception (voir s'il ne faut pas ajouter un pour la fin)
push szTitreD ; zone de reception
sub rsp, 20h
mov rcx,CP_ACP ; code page ANSI par défaut
mov rdx,0 ; flags qui indiquent les types de conversion (voir la doc )
mov r8,szTitreDialog ; zone à convertir
mov r9,-1 ; taille de la zone à convertir, si -1 la chaine est terminée par zero
; et c'est la fonction qui determinara la taille
call MultiByteToWideChar ;fonction de conversion ANSI ==> UNICODE
add rsp,10h ; pour les 2 push
mov r9,__LINE__
cmp eax,NULL
je .gestionerreurs
add rsp,20h
push ILGTB1 * 2
push szTitreC1
sub rsp, 20h
mov rcx,CP_ACP
mov rdx,0
mov r8, szTitreBouton
mov r9,-1
call MultiByteToWideChar
add rsp,10h ; pour les 2 push
mov r9,__LINE__
cmp eax,NULL
je .gestionerreurs
add rsp,20h
push ILGTT1 *2
push szTitreC4
sub rsp, 20h
mov rcx,CP_ACP
mov rdx,0
mov r8, szTitreTexte
mov r9,-1
call MultiByteToWideChar
add rsp,10h ; pour les 2 push
mov r9,__LINE__
cmp eax,NULL
je .gestionerreurs
add rsp,20h
push ILGTB2 *2
push szTitreC5
sub rsp, 20h
mov rcx,CP_ACP
mov rdx,0
mov r8, szTitreBouton2
mov r9,-1
call MultiByteToWideChar
add rsp,10h ; pour les 2 push
mov r9,__LINE__
cmp eax,NULL
je .gestionerreurs
;************************************
push __LINE__ ; routine personnelle de vidage d'une zone mémoire
push lpdt ; instructions à supprimer
push 20 ; ou à remplacer par votre propre routine de vidage
call affmemoireP
;***********************************
; création boite de dialogue
add rsp,20h
sub rsp,8h
push szTexteBD ; passage de l'adresse du texte comme parametre à la procédure
sub rsp,20h
mov rcx,[hInst] ; instance du programme à laquelle sera attachée la boite
mov rdx,lpdt ; adresse de début de la structure d'entête de la boite de dialogue
mov r8,NULL
mov r9,Proc_Dialogue ; procédure de gestion des évenements de la boite
call CreateDialogIndirectParamA ; création de la boite
add rsp,10h
mov r9,__LINE__
cmp rax,NULL
je .gestionerreurs
mov [hDlg],rax ; conservation du handle de la boite attribuée par windows
;affichage de la boite
mov rcx,rax
mov rdx,SW_SHOWDEFAULT
call ShowWindow
.boucle_commande: ; boucle standard de l'API windows
mov rcx,msg ; pour traiter les évenements qui arrivent à une fenêtre
mov rdx,NULL ; Chaque evenement envoie un message qui est analysé ici et renvoyé
mov r8,0 ; vers la procèdure qui les traitera
mov r9,0
call GetMessageA ;récuperation des messages
cmp rax,0 ; fin de boucle : l'utilisateur a fermé la fenetre
jz .main_fin
mov rcx,[hDlg]
mov rdx,msg
call IsDialogMessageA ; messages pour la boite de dialogue
jmp .boucle_commande
.gestionerreurs:
call afferreur
mov rax,1
.main_fin: ; fin du prograame , ici on ne fait rien
;push szMessFin
;call affconsoleP
;call saisieClavier
mov rax,0
.fin:
mov rcx,rax ; code retour
call ExitProcess ; fin du programme
;===================================================
;procedure boite de dialogue ; même paramètre que fenetre
;===================================================
; va traiter les évenements de la boite dialogue ( clic, appui sur bouton, fermeture etc).
; windows appelle cette fonction en lui passant 4 parametres dans les registres rcx,rdx,r8,r9
Proc_Dialogue:
%define hWnd rbp+16 ; pour simplifier l'ecriture dans les instructions suivantes
%define uMsg rbp+24
%define wParam rbp+32
%define lParam rbp+40
mov [rsp+8],rcx ; handle fenêtre voir l'utilité est-ce bien necessaire
mov [rsp+16],rdx ; type de message
mov [rsp+24],r8 ; wparam
mov [rsp+32],r9 ; lparam
enter 0,0 ; pour récuperer les valeurs definies plus haut
sub rsp,20h ; reservation standard
mov rax,[uMsg] ; umsg contient le type de message lié à l'evenement de la boite
cmp rax,WM_INITDIALOG ; initialisation de la boite
je .init
cmp eax,WM_DESTROY ; fermeture de la fenêtre
je .close
cmp rax,WM_CLOSE ; fermeture de la fenetre
je .close
cmp rax,WM_COMMAND ; appui sur les boutons
je .bouton
add rsp,20h
leave
mov rax,FALSE ; IMPORTANT pour tous les autres messages non traités
ret
;******************************Appui sur les boutons
.bouton:
mov rax,[wParam] ; wparam
cmp rax,IDOK ; c'est lequel ?
jne .autrebouton
;traitement du bouton OK
mov rcx,[hWnd] ; handle de la boite
mov rdx,ID_EDIT1 ; identification de la zone de saisie
mov r8,szBuffer ; buffer de reception
mov r9,ILGBUFFER ; longueur maxi du buffer
call GetDlgItemTextA; recuperation du texte de la zone saisie
mov r9,__LINE__ - 1
cmp rax,0
je .erreur
;pour exemple on convertit le texte saisi en majuscule
mov rcx, szBuffer ;buffer à convertir
call CharUpperA ; appel de la conversion en place
mov r9,__LINE__ - 1
cmp rax,0
je .erreur
add rsp,20h
sub rsp,8h ; 1 seul push donc alignement pile à faire
push szBuffer ; zone à afficher
sub rsp,20h
mov rcx,[hWnd] ; handle de la BdD
mov rdx,IDD_LB1 ; identifiant de la list box
mov r8,LB_ADDSTRING ; parametre pour ajouter la ligne dans la listbox
mov r9,0
call SendDlgItemMessageA ; pour maj de la listbox avec le texte modifié
add rsp,10h ; 1 push et 1 alignement
jmp .fin
.autrebouton:
cmp rax,IDCLOSE ; c'est le bouton fin donc on ferme la boutique
je .close
cmp rax,IDCANCEL ;fermeture par <ESC>
je .close
jmp .fin
;==========================
.init: ; initialisation de la BdD
add rsp,20h
sub rsp,8h ; 1 seul push donc alignement pile à faire
push qword [lParam] ; récupération du paramétre passé à la procèdure
sub rsp,20h
mov rcx,[hWnd] ; handle de la BdD
mov rdx,ID_EDIT1 ; identifiant de la zone d'edition
mov r8,WM_SETTEXT ; c'est du texte
mov r9,0
call SendDlgItemMessageA ; pour maj de la zone d'edition avec le texte
add rsp,10h ; 1 push et 1 alignement
jmp .fin
;==================================================
.close:
mov rcx,[hWnd] ; handle de la boite
mov rdx,IDCANCEL
call EndDialog ; fermeture de la boite de dialogue
mov rcx,0 ; valeur de retour
call PostQuitMessage ; envoie du message de fin (WM_QUIT)
jmp .fin ; attention, il ne faut pas l'envoyer systématiquement
.erreur:
call afferreur
.fin:
add rsp,20h ; libération place
leave ; pendant du enter
mov rax,TRUE ; IMPORTANT pour le bon fonctionnement
ret ;
Remarque : les premières mises au point d'une boite de dialogue peuvent être laborieuses. En effet il faut que les définitions des contrôles soient bonnes mais aussi que la procédure de traitement soit correcte (rax doit toujours retourner ou FALSE ou TRUE). En cas de doute, ne mettre qu'un seul controle dans la définition de la BAL puis augmenter quand le précedent est OK. Mettre aussi une procèdure de vidage en début de la procèdure de gestion pour voir quel type de message arrive et le suivre.
Nous verrons que la création de fenêtres repose aussi sur le même mécanisme de gestion de message et de procèdure de réception.
Sujets similaires
» La boite message
» La boite selection de polices
» La boite selection de fichier
» La boite selection de couleurs
» La boite selection de polices
» La boite selection de fichier
» La boite selection de couleurs
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum
|
|