2012-12-09 26 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)'。 –