How do I call EnumWindowsProc?

delphi, delphi-xe2

Solution

First of all the declaration is wrong. It needs to be `stdcall`, and it returns `BOOL`.

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

Secondly, your implementation doesn't set the return value. Return `True` to continue enumeration, `False` to stop enumeration. In your case you need to return `True`.

Finally, you'll need to cast the list box to be `LPARAM` when you call `EnumWindows`.

EnumWindows(@EnumWindowsProc , LPARAM(ListBox1));

Consult the documentation for the full details.

Putting it all together you have this:

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;

Note also that `EnumWindows` does not enumerate all running processes. What it does is enumerate all top level windows. Note quite the same thing. To enumerate all running processes there is `EnumProcesses`. However, since you are reading out window titles and window class names, you probably do want to use `EnumWindows`.

As I've said many times before, I loath the fact that the Delphi header translation for `EnumWindows` uses `Pointer` for the `EnumWindowsProc` parameter. Which means that you can't rely on the compiler to check type safety. I personally always use my own version of `EnumWindows`.

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

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

And then when you call the function you don't use the `@` operator and so let the compiler check that your callback function is declared correctly:

EnumWindows(EnumWindowsProc, ...);

Problem

I'm, trying to list all running processes on my computer. What is wrong with my `EnumWindowsProc()` calling statement in my short example code. My compiler claims that, in this line: ``` EnumWindows(@EnumWindowsProc, ListBox1); ``` that there needs to be a variable inside the function call. How should I change `@EnumWindowsProc` to a 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. ```

Original source