2012-12-09 69 views
4

我在試圖列出我電腦上正在運行的所有進程。如何調用EnumWindowsProc?

我的短示例代碼中的EnumWindowsProc()調用語句有什麼問題。我的編譯器聲稱,在這一行中:

EnumWindows(@EnumWindowsProc, ListBox1); 

在函數調用中需要有一個變量。我應該如何將@EnumWindowsProc更改爲var?

unit Unit_process_logger; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
    System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, 
    Vcl.ExtCtrls, Vcl.StdCtrls; 

type 
    TForm1 = class(TForm) 
    ListBox1: TListBox; 
    Timer1: TTimer; 
    procedure Timer1Timer(Sender: TObject); 
    private 
    { Private-Deklarationen }  
    public 
    { Public-Deklarationen } 
    end; 

function EnumWindowsProc(wHandle: HWND; lb: TListBox): Boolean; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

function EnumWindowsProc(wHandle: HWND; lb: TListBox): Boolean; 
var 
    Title, ClassName: array[0..255] of Char; 
begin 
    GetWindowText(wHandle, Title, 255); 
    GetClassName(wHandle, ClassName, 255); 
    if IsWindowVisible(wHandle) then 
    lb.Items.Add(string(Title) + '-' + string(ClassName)); 
end; 

procedure TForm1.Timer1Timer(Sender: TObject); 
begin 
    ListBox1.Items.Clear;  
    EnumWindows(@EnumWindowsProc, ListBox1);  
end; 

end. 
+4

,你應該看到的錯誤消息:E2010不兼容的類型:'NativeInt'和'TListBox' –

回答

11

首先聲明是錯誤的。它需要是stdcall,它返回BOOL

function EnumWindowsProc(wHandle: HWND; lb: TListBox): BOOL; stdcall; 

其次,您的實現不設置返回值。返回True繼續枚舉,False停止枚舉。在你的情況下,你需要返回True

最後,當您撥打EnumWindows時,您需要將列表框放置爲LPARAM

EnumWindows(@EnumWindowsProc , LPARAM(ListBox1)); 

查詢documentation的全部細節。

全部放在一起你有這樣的:

function EnumWindowsProc(wHandle: HWND; lb: TListBox): BOOL; stdcall; 
var 
    Title, ClassName: array[0..255] of char; 
begin 
    GetWindowText(wHandle, Title, 255); 
    GetClassName(wHandle, ClassName, 255); 
    if IsWindowVisible(wHandle) then 
    lb.Items.Add(string(Title) + '-' + string(ClassName)); 
    Result := True; 
end; 

procedure TForm1.Timer1Timer(Sender: TObject); 
begin 
    ListBox1.Items.Clear; 
    EnumWindows(@EnumWindowsProc, LPARAM(ListBox1)); 
end; 

還要注意EnumWindows不枚舉所有正在運行的進程。它所做的是枚舉所有頂級窗口。注意完全相同的事情。枚舉所有正在運行的進程有EnumProcesses。但是,由於您正在閱讀窗口標題和窗口類名稱,因此您可能需要使用EnumWindows


正如我已經說過很多次,我不願意說德爾福標題翻譯EnumWindows使用PointerEnumWindowsProc參數的事實。這意味着你不能依靠編譯器來檢查類型安全性。我個人總是使用我自己的EnumWindows版本。

type 
    TFNWndEnumProc = function(hwnd: HWND; lParam: LPARAM): BOOL; stdcall; 

function EnumWindows(lpEnumFunc: TFNWndEnumProc; lParam: LPARAM): BOOL; 
    stdcall; external user32; 

然後當你調用函數你不使用@操作等,讓你的回調函數正確聲明的編譯器檢查:

EnumWindows(EnumWindowsProc, ...); 
+3

只是一個偏好:但我會寫GetWindowText(wHandle,@Title [0],Length(Title));這將確保它也適用於動態數組,並且在數組長度發生更改時不會失敗。 (和你的答案+1) – Remko

+0

EnumWindowsProc應該定義爲「函數EnumWindowsProc(wHandle:HWND; var lb:TListBox):BOOL; stdcall;」否則XE10.2會在函數中發生異常。 –

+1

@Mehmet不,這不可能是正確的。我只能想象你錯誤地通過了'LPARAM(@ListBox1)'。 –