Bonjour à tous et toutes !
Dans une boîte de dialogue Windows, je suis amené à implémenter un petit accessoire de recherche dans une boîte liste qui contient (notamment) des noms de personnes.
Le principe est le suivant : lorsque l'on tape le début du nom d'une personne, la boîte liste sélectionne celle-ci automatiquement.
Toute lettre tapée s'ajoute à une chaîne de recherche et toute autre touche réinitialise la chaîne de recherche.
Tout fonctionne bien sauf que, après que mon programme ait sélectionné la bonne personne, Windows ramène la sélection immédiatement au 1er nom de la liste.
Malgré l'usage intensif du debugger, je ne trouve pas ce qui provoque cette réaction de Windows.
Plus fort encore : lorsque, dans un but de test, j'affiche une petite boîte à messages pour faire apparaître la chaîne de recherche dans son état actuel, Windows ne déplace plus la sélection ! J'y perds mon latin.
Quelques informations sur la boîte liste : elle a les attributs lbs_OwnerDrawFixed (éléments dessinés par le programme et non par Windows), lbs_Sorted (routine de tri fournie par le programme), lbs_WantKeyboardInput (renvoi des caractères tapés au programme) mais pas lbs_HasStrings (la boîte liste ne possède que des pointeurs vers des données de mon programme).
Déclaration du dialogue :
Voici la méthode qui répond à la frappe des touches :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 Type pDlgListePersonnes = ^tDlgListePersonnes; tDlgListePersonnes = Object(tDialog) hListe : hWnd; (* HANDLE DE LA BOITE LISTE *) OptionTri : Integer; (* METHODE DE TRI *) pTeteAjout : pPersonne; (* TETE LISTE NOUVEAUX ELEMENTS *) pQueueAjout : pPersonne; (* QUEUE LISTE NOUVEAUX ELEMENTS *) Recherche : Array [0..20] of Char; (* CHAINE A RECHERCHER *) Constructor INIT (FenetreParent : pWindowsObject); (* CONSTRUCTION DU DIALOGUE INITIALISATION DES CHAMPS *) Procedure SETUPWINDOW; virtual; (* CENTRAGE DU DIALOGUE INITIALISATION BOITE LISTE DES PERSONNES *) Procedure WMMEASUREITEM (var Msg : tMessage); virtual wm_First + wm_MeasureItem; (* DETERMINATION HAUTEUR D'UNE LIGNE BOITE LISTE *) Procedure WMDRAWITEM (var Msg : tMessage); virtual wm_First + wm_DrawItem; (* DESSIN D'UN ELEMENT DE LA BOITE LISTE *) Procedure WMCOMPAREITEM (var Msg : tMessage); virtual wm_First + wm_CompareItem; (* COMPARAISON DE 2 ELEMENTS BOITE LISTE *) Procedure WMCOMMAND (var Msg : tMessage); virtual wm_First + wm_Command; (* DOUBLE CLIC SUR UN ELEMENT DE LA BOITE LISTE CHANGEMENT D'OPTION DE TRI *) Procedure WMVKEYTOITEM (var Msg : tMessage); virtual wm_First + wm_VKeyToItem; (* TOUCHE FRAPPEE AU CLAVIER *) Procedure IDAJOUTER (var Msg : tMessage); virtual id_First + id_Ajouter; (* AJOUT D'UN NOUVEL ELEMENT *) Procedure IDMODIFIER (var Msg : tMessage); virtual id_First + id_Modifier; (* MODIFICATION DE L'ELEMENT COURANT *) Procedure IDSUPPRIMER (var Msg : tMessage); virtual id_First + id_Supprimer; (* SUPPRESSION DES ELEMENTS SELECTIONNES *) Procedure OK (var Msg : tMessage); virtual id_First + id_OK; (* MISE A JOUR DE LA LISTE CHAINEE DES PERSONNES *) Procedure CANCEL (var Msg : tMessage); virtual id_First + id_Cancel; (* MESSAGE DE CONFIRMATION DESALLOCATION LISTE NOUVEAUX ELEMENTS *) end;
Merci de m'aider à mettre le doigt sur le "bug" !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 Procedure tDlgListePersonnes.WMVKEYTOITEM (var Msg : tMessage); (* TOUCHE FRAPPEE AU CLAVIER *) Var p : pPersonne; (* ELEMENT LISTE CHAINEE PERSONNES *) Trouve : Boolean; (* INTERRUPTEUR BOUCLE DE RECHERCHE *) Index : Word; (* INDEX DANS LA BOITE LISTE *) Nb : Word; (* NOMBRE D'ELEMENTS BOITE LISTE *) Begin case Msg.wParam of vk_Insert : begin IDAJOUTER(Msg); (* PAS DE TRAITEMENT ULTERIEUR PAR WINDOWS *) Msg.Result:=-2; (* REINITIALISATION DE LA CHAINE DE RECHERCHE *) FillChar(Recherche,SizeOf(Recherche),0); end; vk_Return : begin IDMODIFIER(Msg); (* PAS DE TRAITEMENT ULTERIEUR PAR WINDOWS *) Msg.Result:=-2; (* REINITIALISATION DE LA CHAINE DE RECHERCHE *) FillChar(Recherche,SizeOf(Recherche),0); end; vk_Delete : begin IDSUPPRIMER(Msg); (* PAS DE TRAITEMENT ULTERIEUR PAR WINDOWS *) Msg.Result:=-2; (* REINITIALISATION DE LA CHAINE DE RECHERCHE *) FillChar(Recherche,SizeOf(Recherche),0); end; Ord('A')..Ord('Z') : begin if StrLen(Recherche) < (SizeOf(Recherche) - 1) then begin (* AJOUT DANS LA CHAINE DE RECHERCHE *) Recherche[StrLen(Recherche)]:=Chr(Msg.wParam); (* RECHERCHE DANS LA BOITE LISTE *) Nb:=SendDlgItemMessage(hWindow,id_Liste,lb_GetCount,0,0); if (Nb <> Word(lb_Err)) and (Nb > 0) then begin Index:=0; Trouve:=False; while (Index <= Nb) and not Trouve do begin SendDlgItemMessage(hWindow,id_Liste,lb_GetText,Index,LongInt(@p)); if StrLComp(p^.CopieDonnees.NomPersonne,Recherche,StrLen(Recherche)) = 0 then Trouve:=True else Inc(Index); end; if Trouve then (* SELECTION DE L'ELEMENT *) SendDlgItemMessage(hWindow,id_Liste,lb_SetCurSel,Index,0); end; end; (* PAS DE TRAITEMENT ULTERIEUR PAR WINDOWS *) Msg.Result:=-2; end; else (* LES AUTRES COMMANDES PEUVENT ETRE TRAITEES PAR WINDOWS *) Msg.Result:=-1; (* REINITIALISATION DE LA CHAINE DE RECHERCHE *) FillChar(Recherche,SizeOf(Recherche),0); end; End;
Partager