{ Unit to demonstrate the usage of EnumWindows and some according API-functions Christoph Handel, Simon Reinhardt and Christian Kästner in October 1998 Uses Messages to transport the Wnd-Handle. This way you do not need to directly use the Form variable } unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Controls, Forms, StdCtrls, ComCtrls, ExtCtrls, TLHelp32, ShellApi; type TMainForm = class(TForm) PanelTop: TPanel; btnEnumerate: TButton; PanelMain: TPanel; ListView: TListView; LblAnzahl: TLabel; procedure btnEnumerateClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ListViewColumnClick(Sender: TObject; Column: TListColumn); private { Private-Deklarationen } WM_ENUMERATE_ID: integer; public { Public-Deklarationen } procedure WriteText(Wnd: HWnd); procedure WndProc(var Message: TMessage); override; end; var MainForm : TMainForm; SortColumn : integer; function RegisterMessage: integer; // get a messageID from Windows function EnumWinProc(Wnd: HWnd; param: lParam): boolean; stdcall; // this is the callbackfunction. Don't miss stdcall // can't be part of the form. implementation {$R *.DFM} function RegisterMessage: integer; begin Result:= RegisterWindowMessage('Enumerate this Window'); end; function EnumWinProc(Wnd: HWnd; param: lParam): boolean; stdcall; var iMsgID: integer; begin iMsgID:= RegisterMessage; SendMessage(param, iMsgID, 0, Wnd); // give data to main form Result:=true; end; procedure TMainForm.WndProc(var Message: TMessage); begin if Message.Msg=WM_ENUMERATE_ID then // oh! Enumerate Window found a window, lets do something WriteText(Message.lParam) else inherited WndProc(Message); end; {This procedures by Simon Reinhardt:} //Sort the listitems alphabetically function MySortProc(Item1, Item2: TListItem; ParamSort: integer): integer; stdcall; var T1,T2 : string; begin case SortColumn of 0 : begin T1:=Item1.Caption; T2:=Item2.Caption; end else begin T1:=Item1.SubItems[SortColumn-1]; T2:=Item2.SubItems[SortColumn-1]; end end; Result := lstrcmp(PChar(T1),PChar(T2)); end; //fill in the listview with all the information procedure TMainForm.WriteText(Wnd: HWnd); var pcWinText : PChar; NewItem : TListItem; aProcessEntry32 : TProcessEntry32; aSnapshotHandle : THandle; WinVersion : DWord; ProcessID : longint; ContinueLoop : boolean; begin NewItem:=ListView.Items.Add; {Is Window Visible?} NewItem.Checked:=IsWindowVisible(wnd); {WindowCaption} pcWinText:= StrAlloc(102); GetWindowText(Wnd, pcWinText, 100); NewItem.Caption:=StrPas(pcWinText); StrDispose(pcWinText); {WindowClassName} pcWinText:= StrAlloc(102); GetClassName(Wnd, pcWinText, 100); NewItem.SubItems.Add(StrPas(pcWinText)); StrDispose(pcWinText); {WindowHandle} NewItem.SubItems.Add(IntToHex(wnd, 8)); {WindowThreadProcessID} GetWindowThreadProcessID(wnd,@ProcessID); NewItem.SubItems.Add(IntToHex(ProcessID, 8)); {WindowsVersion} WinVersion:=GetProcessVersion(ProcessID); NewItem.SubItems.Add(IntToStr(WinVersion shr 16)+'.'+IntToStr(WinVersion mod $1000)); {CommandLine} {According to Christian Kästner:} aSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); aProcessEntry32.dwSize := Sizeof(aProcessEntry32); ContinueLoop := Process32First(aSnapshotHandle, aProcessEntry32); while integer(ContinueLoop) <> 0 do begin if aProcessEntry32.th32ProcessID = ProcessID then NewItem.SubItems.Add(ExtractFileName(aProcessEntry32.szExeFile)); ContinueLoop := Process32Next(aSnapshotHandle,aProcessEntry32); end; CloseHandle(aSnapshotHandle); {end of Chrstian's stuff} end; //sort the listview on columnclick procedure TMainForm.ListViewColumnClick(Sender: TObject; Column: TListColumn); begin SortColumn:=Column.Index; ListView.CustomSort(@MySortProc, 0); end; {end of Simons part} procedure TMainForm.btnEnumerateClick(Sender: TObject); begin ListView.Items.Clear; EnumWindows(@EnumWinProc, self.Handle); // start EnumerateWindows, send the Handle of the Form // so function nows where to send the info LblAnzahl.Caption:='Anzahl : '+IntToStr(ListView.Items.Count); end; procedure TMainForm.FormCreate(Sender: TObject); begin WM_ENUMERATE_ID:= RegisterMessage; // get our msgID end; end.