Appel de paramètre var (fonction d'énumation) dans fonction callback [EnumWindow

Résolu
Bacterius Messages postés 3792 Date d'inscription samedi 22 décembre 2007 Statut Membre Dernière intervention 3 juin 2016 - 20 janv. 2009 à 21:32
Bacterius Messages postés 3792 Date d'inscription samedi 22 décembre 2007 Statut Membre Dernière intervention 3 juin 2016 - 21 janv. 2009 à 17:32
Bonsoir, j'ai un problème. Vous avez probablement vu ma source (Alpha Utils), et vous n'aurez donc aucun mal pour savoir que la fonction que je vais montrer ici vient de l'unité AlphaUtils.pas.
Alors voilà mon problème : j'ai décidé de remplacer l'utilisation dans une boucle, de la fonction GetNextWindow (instable et peut faire planter l'appli), par la fonction EnumWindows.
Voilà ma fonction :


<hr />

function SearchHWnds(var HwndList: TList; BaseHwnd: HWND): Longword;



function GenericEnumWindowsCallback(Handle: HWND; Param: LPARAM): BOOL; stdcall;
begin
 HwndList.Add(Pointer(Handle)); // Ajoute l'élément dans la liste (VIOLATION D'ACCES)
 Result := True; // On continue l'énumération ...
end ;



begin

 Result : = 0;  // Par défaut, aucun élément copié


 ifnot Assigned(HwndList) then Exit; // Si la liste pointe sur nil, on s'en va


 EnumWindows(@GenericEnumWindowsCallback, 0);


 HwndList.Delete(HwndList.Count - 1); // On supprime le dernier élément, en trop
// Je ne suis pas sûr, c'était nécessaire pour GetNextWindow, je verrai une fois que ça marche ...


 Result := HWndList.Count; // Résultat : nombre d'éléments dans la liste
end;





<hr />



Vous avez vu ? Une violation d'accès pan dans les dents dès le premier appel à HwndList depuis la fonction interne ! (je tiens à signaler que des handles sont bien renvoyés par WriteLn, c'est donc bien un problème au niveau de la liste ...).
A mon avis, le problème vient que le paramètre de la fonction principale d'énumération HwndList, passé en paramètre var, n'est plus considéré comme paramètre var par la fonction interne et donc, V.A. ... y-a-t-il une manipulation spéciale à faire dans ce cas-là ? (je voudrais éviter de passer par une variable TList temporaire globale ...).

Merci à tous de votre aide

Cordialement, Bacterius !

3 réponses

Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
21 janv. 2009 à 13:40
le LParam est justement la pour ca : mettre ce que tu veux dedans. C'est un peu comme le Tag des TControl.
Donc pour moi, ta fonction me semble tout a fait propre. A toi apres de manipuler ta TList comme une liste de Handle et non de pointeurs (peut etre faire une THandleList qui heriterait de TList serait plus propre).
3
Bacterius Messages postés 3792 Date d'inscription samedi 22 décembre 2007 Statut Membre Dernière intervention 3 juin 2016 10
20 janv. 2009 à 21:42
Bon, en essayant de trouver une solution à mon problème, j'ai regardé le paramètre lParam, et je me suis dit "chuis c*n ou quoi ?".
Alors, (bon vous me direz c'est crade, mais j'ai rien trouvé de mieux), je voulais vous demander à présent si cette solution était envisageable (du point de vue de la qualité du code, et des nombreux transtypages hasardeux ...). Voici le code (qui fonctionne) :


<hr />



function SearchHWnds(var HwndList: TList; BaseHwnd: HWND): Longword; // Renvoie une liste de tous les handles des fenêtres visibles, et le nombre de fenêtres trouvées (hors 0)




function
GenericEnumWindowsCallback(Handle: HWND; var Param: LParam): BOOL; stdcall; // Fonction interne callback générique
begin
 TList(Param).Add(Pointer(Handle)); // En fait, on passe en paramètre var le pointeur vers la liste HWndList
 Result := True;
end ;



begin

 Result : = 0;  // Par défaut, aucun élément copié


 ifnot Assigned(HwndList) then Exit; // Si la liste pointe sur nil, on s'en va


 // On transtype le pointeur vers HWndList en Longword, puis on le passe en paramètre au callback ...
 if EnumWindows(@GenericEnumWindowsCallback, Longword(@HWndList)) = False then Exit;
 // Si erreur d'énumération, on s'en va !


 HwndList.Delete(HwndList.Count - 1); // On supprime le dernier élément (dans la boucle repeat, on ne savait pas que ce serait le dernier, on a donc fait un doublon ...)


 Result : = HWndList.Count; // Résultat : nombre d'éléments dans la liste
end;


<hr />



Je sens que ce code est vraiment très sale, et risque de planter à n'importe-quel moment. M'enfin bon on nous file un paramètre perso, pourquoi s'en priver ?

Merci de votre réponse

Cordialement, Bacterius !
0
Bacterius Messages postés 3792 Date d'inscription samedi 22 décembre 2007 Statut Membre Dernière intervention 3 juin 2016 10
21 janv. 2009 à 17:32
Je sais pas ... pas mal de monde utilise l'astuce des entiers à la place des pointeurs (un pointeur est un entier), et faire un THandleList serait peut-être lourd ... et puis contraignant pour l'utilisateur (<< c'est quoi un THandleList ? >>) - on aime pas trop déclarer des types qu'on ne connaît pas ? Mais sinon merci de m'avoir répondu, donc ma fonction est correcte.
Merci Guillemouze de ta réponse

Cordialement, Bacterius !
0
Rejoignez-nous