Récupérer tous les handles d'une application choisie dans une liste

Résolu
cs_nitrique Messages postés 344 Date d'inscription jeudi 1 mai 2003 Statut Membre Dernière intervention 4 avril 2011 - 13 avril 2006 à 09:53
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 - 18 avril 2006 à 15:00
Bonjour à tous,

Je liste tous les processus actifs dans une liste (de la même manière que le gestionnaire des taches).

Ensuite, à partir du ProcessID de l'application choisie, j'aimerais récuperer tous les handles de ce processus (un handle correspond à un composant de l'application choisie, je me trompe ?),
pour me permettre de sélectionner un champs texte de cette application.
Je le fait de cette manière:
tabHandles: array [0..100] of integer; // Un HWND est un integer...
procedure TfrmMain.ListerHandles(pid: Cardinal);
var
handles: TList;
i: Integer;
findWindowsStruct: TFindWindowsStruct;
begin
handles:= TList.Create;
Try
findWindowsStruct.ProcessID:= pid; // GetCurrentProcessID
findWindowsStruct.HandleList:= handles;
EnumWindows(@EnumWindowsProc, Integer(@findWindowsStruct));
cbThreads.Clear;
for i:= 0 to handles.Count - 1 do begin
cbThreads.Items.Add('Handle: '+IntToStr(Integer(handles[i])));
tabHandles[i] := Integer(handles[i]);
end;
cbThreads.ItemIndex := 0;
Finally
handles.Free;
end;
end;
Mais quand je teste les handles reçus avec un
PostMessage(tabHandles[cbThreads.ItemIndex]),WM_CHAR,sCar,0); // Simulation du copier
Rien ne se passe.

Par exemple, Si je fait:
myHandle := GetTopwindow(GetforegroundWindow); // Ca marche mais que pour notePad
PostMessage(myHandle,WM_CHAR,sCar,0);
Et que le focus est sur le notepad par exemple, handle est égal à 263014.

Mais si j'utilise la méthode de listage pour le notepad, il ne me retourne qu'un enregistrement qui est différent de celui de la solution ci-dessus (459614).

Comment faire ?

[;)] David, à VERSAILLES

12 réponses

Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
14 avril 2006 à 00:22
Bon alors regarde j'ai fait un bout de code, cette approche un peut différente mais c'est la seule qui me permet de faire l'inventaire des composants (plus où moins, ne fonctionne pas avec toutes les applications) et d'en selectionner un pour lui envoyer du texte :

Unit USendText;


Interface


Uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;


Type
TFrmMain = Class (TForm)
cbProcessus: TComboBox;
cbThreads: TComboBox;
Edit1: TEdit;
btn_Refresh: TButton;
Procedure btn_RefreshClick(Sender: TObject);
Procedure FormShow(Sender: TObject);
Procedure FormClose(Sender: TObject; Var Action: TCloseAction);
Procedure cbProcessusChange(Sender: TObject);
Procedure cbThreadsClick(Sender: TObject);
Procedure FormCreate(Sender: TObject);
Private
Procedure ListerChilds(pid: Cardinal);
{ Déclarations privées }
Public
{ Déclarations publiques }
End;


Function EnumWindowsProc(hWnd: HWND; lParam: lParam): Bool; stdcall;


Const
aStr = '%s %d';


Var
FrmMain : TFrmMain;
HandleList : TStringList;


Implementation


{$R *.DFM}
Uses TlHelp32;


Var
tabProcessus : Array[0..100] Of Cardinal;
// Contient le ProcessId de la première comboBox
tabHandles : Array[0..100] Of integer;
// Contient les handles de la deuxième comboBox


Function EnumWindowsProc(hWnd: HWND; lParam: lParam): Bool;
Var
processID : DWORD;
aName : Array[0..255] Of Char;
Begin
GetWindowThreadProcessID(hwnd, @processID);
If (hWnd <> FindWindow('Shell_TrayWnd', Nil)) And
(hWnd <> FindWindow('Progman', Nil)) Then
If IsWindowVisible(hwnd) Then
Begin
GetWindowText(hwnd, aName, SizeOf(aName));
HandleList.Add(Format(aStr, [aName, HWnd]));
TabProcessus[HandleList.Count - 1] := hwnd;
Result := True;
End ;
End;


Procedure GetProcessList;
Begin
HandleList.Clear;
EnumWindows(@EnumWindowsProc, 0);
End;



Procedure TFrmMain.ListerChilds(pid: Cardinal);
Var aHandle : THandle;
aName : Array[0..255] Of Char;
Begin
cbThreads.Clear;
aHandle : = 0;
Repeat
aHandle := FindWindowEx(pid, aHandle, Nil , Nil);
If aHandle <> 0 Then
Begin
GetClassName(aHandle, aName, SizeOf(aName));
cbThreads.Items.Add(Format(aStr, [aName, aHandle]));
tabHandles[cbThreads.Items.Count - 1] : = aHandle;
End;
Until aHandle = 0;
End ;


Procedure TfrmMain.cbProcessusChange(Sender: TObject);
Begin
ListerChilds(TabProcessus[cbProcessus.ItemIndex]);
End;


Procedure TFrmMain.cbThreadsClick(Sender: TObject);
Var S : String;
Begin
S : = '1234567890';
SendMessage(tabHandles[cbThreads.ItemIndex], WM_SETTEXT, 0, Longint(s));
//On Change le Texte
End;


Procedure TFrmMain.FormCreate(Sender: TObject);
Begin
HandleList := TStringList.Create;
End;


Procedure TFrmMain.FormClose(Sender: TObject; Var Action: TCloseAction);
Begin
HandleList.Free;
End;


Procedure TFrmMain.FormShow(Sender: TObject);
Begin
btn_Refresh.Click;
End;


Procedure TFrmMain.btn_RefreshClick(Sender: TObject);
Begin
GetProcessList;
cbProcessus.Items.Clear;
cbProcessus.Items.AddStrings(HandleList);
End;


End.

Le TEdit n'est la que pour tester et pour avoir FrmMain dans la liste il faut cliquer sur Refresh

Tester ok sur : NotePad, Calculatrice et sur lui même.

il faut bien sur affiner mais je pense que c'est la marche à suivre

Tiens moi au courant

@+
Cirec
3
Rejoignez-nous