Wie bekomme ich Zugriff auf alle geöffneten Fenster?


Den Anzeige-Zustand und die Position eines Fensters ermittelt man mit der API-Funktion GetWindowPlacement. Die folgende Funktion GetWindowState gibt den Anzeigezustand des Fensters mit dem Handle Wnd zurück:

function GetWindowState(Wnd : HWnd) : integer;
var WPlacement : PWINDOWPLACEMENT;
begin
  GetMem(WPlacement,SizeOf(TWINDOWPLACEMENT));
  WPlacement^.Length := SizeOf(TWINDOWPLACEMENT);
  if GetWindowPlacement(Wnd,WPlacement) then
    Result := WPlacement^.showCmd
  else
    Result := -1;
  FreeMem(WPlacement);
end;

mögliche Rückgabewerte: SW_HIDE, SW_MINIMIZE, SW_RESTORE, SW_SHOW, SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, SW_SHOWMINNOACTIVE, SW_SHOWNA, SW_SHOWNOACTIVATE oder SW_SHOWNORMAL (siehe auch in der API-Hilfe zur Funktion GetWindowPlacement).

Das nachfolgende Unit demonstriert die folgenden API-Funktionen:

EnumWindows,
GetWindowText,
GetClassName,
IsWindowVisible,
GetWindowThreadProcessID und
GetProcessVersion.

Mit Hilfe dieser Funktionen wird eine Liste aller aktuell geöffneten Fenster und deren Handles, Prozess-IDs, Klassen, Titel, etc.
erstellt. Auch die Funktion zur Ermittlung des mit dem Fenster verbundenen EXE-Namens wird demonstriert. Die API-Funktionen die Process32First und Process32Next sind nur unter W95 definiert, daher funktioniert die Unit so nicht unter Windows NT.

Bitte bei Benutzung/Weitergabe die Autoren angeben.

{ 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;

{These 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.
Delphi 1 Delphi 2 Delphi 3 Delphi 4
nicht getestet Version nicht betroffen getestet

siehe auch:

Wie kann ich die Programmdatei (*.exe) einer Anwendung über deren Fensterhandle ermittteln?


Delphi FAQ