6

我正在尝试列出我计算机上所有正在运行的进程。

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

1 回答 1

16

首先声明是错误的。它需要stdcall,它会返回BOOL

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

其次,您的实现没有设置返回值。返回True继续枚举,False停止枚举。在您的情况下,您需要返回True

最后,您需要在LPARAM调用时将列表框转换为EnumWindows.

EnumWindows(@EnumWindowsProc , LPARAM(ListBox1));

有关完整的详细信息,请参阅文档

把它们放在一起你有这个:

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.


正如我之前多次说过的,我讨厌 Delphi 标头转换用于EnumWindows参数的Pointer事实。EnumWindowsProc这意味着您不能依赖编译器来检查类型安全。我个人总是使用我自己的EnumWindows.

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

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

然后,当您调用该函数时,您不使用@运算符,因此让编译器检查您的回调函数是否已正确声明:

EnumWindows(EnumWindowsProc, ...);
于 2012-12-09T10:36:42.653 回答