This declaration is incorrect:
function FindMyWindow(hWnd: HWND; lParam: LPARAM): boolean; stdcall;
It should be:
function FindMyWindow(hWnd: HWND; lParam: LPARAM): BOOL; stdcall;
You must be careful not to confuse Boolean
and BOOL
, as they are not the same. The first is one byte, the last is 4 bytes. This is a mismatch between the expected EnumWindows
and what the callback function provides to cause the observed behavior.
In addition, Rob Kennedy made a wonderful comment:
The compiler can help find this error if you break the habit of using the @
operator before the function name when calling EnumWindows
. If the function signature is compatible, the compiler will allow you to use it without @
. Using @
turns it into a generic pointer and is compatible with everything, so the error is masked by unnecessary syntax. In short, using @
to create function pointers should be considered a code smell.
Discussion
Unfortunately, translating the Windows.pas
header defines EnumWindows
most useless way:
function EnumWindows(lpEnumFunc: TFNWndEnumProc; lParam: LPARAM): BOOL; stdcall;
Now the problem is defining TFNWndEnumProc
. It is defined as:
TFarProc = Pointer; TFNWndEnumProc = TFarProc;
This means that you must use the @
operator to create a shared pointer, because functions require a shared pointer. If TFNWndEnumProc
were declared as follows:
TFNWndEnumProc = function(hWnd: HWND; lParam: LPARAM): BOOL; stdcall;
then the compiler could find the error.
type TFNWndEnumProc = function(hWnd: HWND; lParam: LPARAM): BOOL; stdcall; function EnumWindows(lpEnumFunc: TFNWndEnumProc; lParam: LPARAM): BOOL; stdcall; external 'user32'; function FindMyWindow(hWnd: HWND; lParam: LPARAM): Boolean; stdcall; begin Result := False; end; .... EnumWindows(FindMyWindow, 0);
The compiler rejects the EnumWindows
call with the following error:
[DCC error] Unit1.pas (38): E2010 Incompatible types: "LongBool" and "Boolean"
I think I will be QC this problem and try my luck convincing Embarcadero to stop using TFarProc
.