問題來源: 
http://www.cnblogs.com/del/archive/2009/10/16/1584488.html#1727205 
// EnumWindows 的功能是遍歷所有頂層窗口
function EnumWindows(
  lpEnumFunc: TFNWndEnumProc; {回調(diào)函數(shù)指針}
  lParam: LPARAM              {給回調(diào)函數(shù)的參數(shù), 它對應(yīng)回調(diào)函數(shù)的第二個參數(shù)}
): BOOL; stdcall; //成功與否, 其實(shí)是返回了回調(diào)函數(shù)的返回值
// EnumWindows 專用的回調(diào)函數(shù)的格式:
function EnumWindowsProc(
  hwnd: HWND;        {找到的窗口句柄}
  lParam: LPARAM     {EnumWindows 傳給的參數(shù); 因?yàn)樗侵羔? 可傳入, 但一般用作傳出數(shù)據(jù)}
): Boolean; stdcall; {函數(shù)返回 False 時, 調(diào)用它的 EnumWindows 將停止遍歷并返回 False}
例一: 獲取所有頂層窗口的句柄 
//需要個 TListBox 顯示數(shù)據(jù)
function EnumWindowsProc_1(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
begin
  Form1.ListBox1.Items.Add(IntToStr(hwnd));
  Result := True;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
  EnumWindows(@EnumWindowsProc_1, 0);
end;
例二: 獲取所有頂層窗口的標(biāo)題(排除無標(biāo)題窗口) 
function EnumWindowsProc_2(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
begin
  GetWindowText(hwnd, buf, SizeOf(buf));
  if buf <> '' then Form1.ListBox1.Items.Add(buf);
  Result := True;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
  EnumWindows(@EnumWindowsProc_2, 0);
end;
例三: 查找第一個記事本的句柄 
function EnumWindowsProc_3(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
begin
  GetClassName(hwnd, buf, SizeOf(buf));
  if buf = 'Notepad' then
  begin
    Form1.ListBox1.Items.Add(Format('記事本句柄: %d', [hwnd]));
    Result := False; //如果不需要繼續(xù)找, 找到第一個就結(jié)束
  end
  else
  begin
    Result := True;
  end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
  EnumWindows(@EnumWindowsProc_3, 0);
end;
例四: 獲取所有頂層窗口的句柄與類名數(shù)組: 
type
  TMyStruct = record
    hwnd: HWND;
    ClassName: string;
  end;
  TMyStructArray = array of TMyStruct;
  PMyStructArray = ^TMyStructArray;
function EnumWindowsProc_4(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
  p: PMyStructArray;
begin
  GetClassName(hwnd, buf, SizeOf(buf));
  p := PMyStructArray(lParam);
  SetLength(p^, Length(p^) + 1);
  p^[High(p^)].hwnd := hwnd;
  p^[High(p^)].ClassName := buf;
  Result := True;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
  Arr: TMyStructArray;
begin
  EnumWindows(@EnumWindowsProc_4, Integer(@Arr));
  ShowMessage(IntToStr(Length(Arr)));                         //總數(shù)
  ShowMessageFmt('%d - %s', [Arr[0].hwnd, Arr[0].ClassName]); //第一個元素
end;
例五: 重復(fù)上一個例子, 如果數(shù)組是全局遍歷并不靠參數(shù)傳遞, 代碼會簡單些 
type
  TMyStruct = record
    hwnd: HWND;
    ClassName: string;
  end;
var
  Arr: array of TMyStruct;
function EnumWindowsProc_5(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
begin
  GetClassName(hwnd, buf, SizeOf(buf));
  SetLength(Arr, Length(Arr) + 1);
  Arr[High(Arr)].hwnd := hwnd;
  Arr[High(Arr)].ClassName := buf;
  Result := True;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
  SetLength(Arr, 0);
  EnumWindows(@EnumWindowsProc_5, Integer(Arr));
  ShowMessage(IntToStr(Length(Arr)));                         //總數(shù)
  ShowMessageFmt('%d - %s', [Arr[0].hwnd, Arr[0].ClassName]); //第一個元素
end;
SplendourChiang 的目的是獲取進(jìn)程 ID 和窗口句柄的數(shù)組, 按 "例四" 的方法給修改如下: 
type
  MyProcessInfo = record
    PID, WinHWND : DWORD;
  end;
  TMyProcessInfoArray = array of MyProcessInfo;
  PMyProcessInfoArray = ^TMyProcessInfoArray;
function MyEnumWindowsProc(Wnd: DWORD; lParam: LPARAM): Bool; stdcall;
var
  PID : DWORD;
  p: PMyProcessInfoArray;
begin
  GetWindowThreadProcessID(Wnd, @PID);
  p := PMyProcessInfoArray(lParam);
  SetLength(p^, Length(p^) + 1);
  p^[High(p^)].PID := PID;
  p^[High(p^)].WinHWND := Wnd;
  Result := True;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
  CC: TMyProcessInfoArray;
begin
  SetLength(CC, 0);
  EnumWindows(@MyEnumWindowsProc, Integer(@CC));
  ShowMessage(IntToStr(Length(CC)));                     //總數(shù)
  ShowMessageFmt('%d - %d', [CC[0].PID, CC[0].WinHWND]); //第一個元素
end;