Overview
I am trying to enumerate a list of all visible window names and then populate a list passed as a parameter.
In Delphi I was able to get this to work with the following:
function EnumWindowNamesProc(wHandle: HWND; List: TStrings): BOOL; stdcall;
var
Title: array[0..255] of Char;
begin
Result := False;
GetWindowText(wHandle, Title, 255);
if IsWindowVisible(wHandle) then
begin
if Title <> '' then
begin
List.Add(string(Title));
end;
end;
Result := True;
end;
Then I could call the above like so:
EnumWindows(@EnumWindowNamesProc, LPARAM(FWindowNames));
Note: FWindowNames
is a stringlist created inside a custom class.
Problem
I am also trying to make the function compatible with Lazarus/FPC but it wont accept the List: TStrings
parameter.
The compiler error in Lazarus complains about a type mismatch (I have highlighted the important parts):
Error: Incompatible type for arg no. 1: Got " (address of function(LongWord;TStrings):LongBool;StdCall) ", expected " (procedure variable type of function(LongWord;LongInt):LongBool;StdCall) "
I can stop the compiler complaining by changing the function declaration like so:
{$IFDEF FPC}
function EnumWindowNamesProc(wHandle: HWND; Param: LPARAM): BOOL; stdcall;
{$ELSE}
function EnumWindowNamesProc(wHandle: HWND; List: TStrings): BOOL; stdcall;
{$ENDIF}
var
Title: array[0..255] of Char;
begin
Result := False;
GetWindowText(wHandle, Title, 255);
if IsWindowVisible(wHandle) then
begin
if Title <> '' then
begin
{$IFDEF FPC}
// List no longer available
{$ELSE}
List.Add(string(Title));
{$ENDIF}
end;
end;
Result := True;
end;
But then I lose my List
parameter.
I know I could modify the code and use a Listbox1 for example directly inside the function but I was hoping to create a reusable function that does not need to know about VCL/LCL controls, instead I was hoping for a more elegant solution and simply pass a TStrings
based parameter and add to this instead.
Question:
So my question is, in Delphi I am able to pass a TStrings
based parameter to my EnumWindowNamesProc
but in Lazarus it wont accept it. Is it possible, and if so, how can I modify the code so Lazarus accepts the List: TStrings
parameter?
You can. You don't have to lose your List
.
Just use correct parameters and typecast
function EnumWindowNamesProc(wHandle: HWND; List: LPARAM): BOOL; stdcall;
var
Title: array[0..255] of Char;
begin
Result := False;
GetWindowText(wHandle, Title, 255);
if IsWindowVisible(wHandle) then
begin
if Title <> '' then
begin
TStringList(List).Add(string(Title));
end;
end;
Result := True;
end;
EnumWindows(@EnumWindowNamesProc, LPARAM(list));
To complete my answer. There is one more option - define the function by yourself with pointer (like in Delphi). Then you can use it the same way.
function EnumWindows(lpEnumFunc:Pointer; lParam:LPARAM):WINBOOL; external 'user32' name 'EnumWindows';