Lazarus

Free Pascal => Windows => Topic started by: linuxbob on July 07, 2022, 03:31:40 am

Title: MessageBox needs an hWnd?
Post by: linuxbob on July 07, 2022, 03:31:40 am
When I try to type in 'MessageBox' into a unit, the code prediction tells me I need to provide an hWnd. If I don't provide an hWnd, I get an error.

The wiki doesn't refer to the hWnd parameter at all, nor does the appropriate Delphi reference. Coming from VB6, I never needed an hWnd there either.

If an hWnd is required, which one should I pass?

TIA.
Title: Re: MessageBox needs an hWnd?
Post by: 440bx on July 07, 2022, 03:34:00 am
If an hWnd is required, which one should I pass?
Pass zero (0) as the hwnd.
Title: Re: MessageBox needs an hWnd?
Post by: linuxbob on July 07, 2022, 03:47:56 am
Cool, I'll give that a try.
Title: Re: MessageBox needs an hWnd?
Post by: MarkMLl on July 07, 2022, 09:24:29 am
What exactly are you trying to do (and on what platform)? There's a risk here that a suggestion from the IDE is leading you towards a low-level API rather than a more general routine to e.g. display a dialog(u)e.

Also note that the- in fact any- wiki should not automatically be considered authoritative documentation. See e.g. https://lazarus-ccr.sourceforge.io/docs/lcl/ hence https://lazarus-ccr.sourceforge.io/docs/lcl/forms/tapplication.messagebox.html

I'd suggest that even if not obvious, it is always prudent to give the compiler and IDE version in a question. For example, it might be that you have am IDE version where there are known to be deficiencies in some areas of the help subsystem.

MarkMLl
Title: Re: MessageBox needs an hWnd?
Post by: Zvoni on July 07, 2022, 09:26:44 am
at a Guess, the hWnd is "representing" the Parent-Form of the Message-Box,
but looking at Mark's link to TApplication.MessageBox i'm wondering where the hWnd is coming from....
Title: Re: MessageBox needs an hWnd?
Post by: MarkMLl on July 07, 2022, 09:36:11 am
at a Guess, the hWnd is "representing" the Parent-Form of the Message-Box,
but looking at Mark's link to TApplication.MessageBox i'm wondering where the hWnd is coming from....

https://lazarus-ccr.sourceforge.io/docs/lcl/lclintf/messagebox.html

...which is also what Google turns up in preference to the TApplication method :-/

MarkMLl
Title: Re: MessageBox needs an hWnd?
Post by: Zvoni on July 07, 2022, 11:23:29 am
at a Guess, the hWnd is "representing" the Parent-Form of the Message-Box,
but looking at Mark's link to TApplication.MessageBox i'm wondering where the hWnd is coming from....

https://lazarus-ccr.sourceforge.io/docs/lcl/lclintf/messagebox.html

...which is also what Google turns up in preference to the TApplication method :-/

MarkMLl

and there it is....
Quote
The MessageBox function displays an modal dialog, with the given text, caption, icon and buttons.
"Modal" implies a Parent
Title: Re: MessageBox needs an hWnd?
Post by: BobDog on July 07, 2022, 04:50:19 pm

It has to be nil, it is a pointer.
Code: Pascal  [Select][+][-]
  1.  
  2. function msgbox(p:pointer;msg:pchar;title:pchar;L1:int32;L2:int32;milliseconds:int32):integer; cdecl external 'user32.dll' name 'MessageBoxTimeoutA';
  3.  
  4. begin
  5. writeln(msgbox(nil,'Wait 3 seconds, or close the messagebox . . .','Hello',0,0,3000));
  6. end.
  7.  
Title: Re: MessageBox needs an hWnd?
Post by: rvk on July 07, 2022, 05:21:01 pm
It has to be nil, it is a pointer.
Luckily a nil pointer is one that has the value 0  :)

http://www.delphibasics.co.uk/RTL.asp?Name=Nil
Title: Re: MessageBox needs an hWnd?
Post by: 440bx on July 07, 2022, 05:44:21 pm
It has to be nil, it is a pointer.
It should _not_ be a pointer.  An HWND is not a pointer, it's a handle and, attempting to de-reference it will, more often than not, cause an access violation.

You should correct that definition.

Title: Re: MessageBox needs an hWnd?
Post by: Remy Lebeau on July 07, 2022, 06:11:17 pm
It should _not_ be a pointer.  An HWND is not a pointer, it's a handle

Indeed, though technically a HANDLE/HWND is actually a pointer in the POV of the Win32 API.  But FPC (and Delphi) has the THandle type to represent OS handles.  But I agree, the declaration needs to be fixed, the parameter should be a HWND/THandle instead of a Pointer.

Also, just about everything else about the declaration is wrong and should be fixed:


So, a more appropriate example would look more like this:

Code: Pascal  [Select][+][-]
  1. function MessageBoxTimeout(hWnd: HWND; const lpText, lpCaption: PAnsiChar; uType: UINT; wLanguageId: WORD; dwMilliseconds: DWORD): Integer; stdcall external 'user32.dll' name 'MessageBoxTimeoutA';
  2.  
  3. begin
  4.   WriteLn(MessageBoxTimeout(0{or an actual HWND}, 'Wait 3 seconds, or close the messagebox . . .', 'Hello', 0{MB_OK}, 0, 3000));
  5. end.
  6.  
Title: Re: MessageBox needs an hWnd?
Post by: BobDog on July 07, 2022, 08:50:33 pm

Win32 datatypes are not needed, no need for uses windows.
C suggests
int MessageBoxTimeoutA(IN HWND hWnd, IN LPCSTR lpText,
    IN LPCSTR lpCaption, IN UINT uType,
    IN WORD wLanguageId, IN DWORD dwMilliseconds);

But the function works fine as is in a simple format.
Code: Pascal  [Select][+][-]
  1. {$macro on}
  2. {$define plus:=or}
  3.  
  4. function msgbox(p:pointer;msg:pchar;title:pchar;L1:int32;L2:int32;milliseconds:int32):integer; cdecl external 'user32.dll' name 'MessageBoxTimeoutA';
  5. const
  6. RETRYCANCEL    =$00000005;
  7. ICONINFORMATION=$00000040;
  8. var
  9. i:integer=0;
  10. j:integer=1;
  11. s,g:string;
  12.  
  13. begin
  14. while i<>2 do
  15. begin
  16. j:=j+1;
  17. Str(j,s);
  18. g:=concat('Wait ',s,' seconds or choose something . . .');
  19. i:=msgbox(nil,@g[1],'Messagebox Timed out',RETRYCANCEL plus ICONINFORMATION,0,1000*j);
  20. end;
  21. end.
  22.  



Title: Re: MessageBox needs an hWnd?
Post by: Remy Lebeau on July 08, 2022, 02:30:40 am
Win32 datatypes are not needed, no need for uses windows.

They are not required, no.  But they do make things easier and consistent.

But, you DO need to match the correct data type sizes at least (ie sizeof(WORD) <> sizeof(Int32)!), and especially the correct calling convention (very important!), or else bad things will happen, whether you notice them right away or not.

But the function works fine as is in a simple format.

It doesn't work correctly if you use the wrong calling convention, for instance (as this example is doing).

If you compile for 32bit, then all Win32 APIs (except for wsprintf(A/W)) use the stdcall calling convention, NOT cdecl, despite what MS's documentation suggests (since MS doesn't usually display the calling convention used, it is implied instead). So, don't mismatch them!  In the example provided, stack corruption WILL occur when the program tries to clean up the call stack a second time AFTER MessageBoxTimeoutA() has already cleaned up the call stack upon its exit.

If you compile for 64bit, then this issue is moot since there is only 1 calling convention defined by the Windows 64bit ABI, which the compiler handles for you, so the cdecl/stdcall keywords are ignored in code.
Title: Re: MessageBox needs an hWnd?
Post by: PascalDragon on July 12, 2022, 01:47:15 pm
If you compile for 64bit, then this issue is moot since there is only 1 calling convention defined by the Windows 64bit ABI, which the compiler handles for you, so the cdecl/stdcall keywords are ignored in code.

They are not ignored, they are mapped to the default calling convention for - in this case - Windows. For non-Windows they would be mapped to the SysV ABI calling convention. And then there's also vectorcall as well as sysv_abi_default and ms_abi_default. ;)
TinyPortal © 2005-2018