Disclosure Statement: This site contains affiliate links, which means that I may receive a commission if you make a purchase using these links. As an eBay Partner, I earn from qualifying purchases.
If you find these projects useful please consider becoming a sponsor with Patreon, GitHub or Liberapay.

Lazarus and WM_* messages

Post Reply
wolf
Posts: 22
Joined: Thu Jan 31, 2019 6:36 pm

Lazarus and WM_* messages

Post by wolf »

In Lazarus / Windows, these messages are never fired:

* WM_MOVING
* WM_ENTERMENULOOP
* WM_EXITMENULOOP

(WM_MOVE works).

What are the side effects when these three messages are not triggered?
User avatar
salvadordf
Posts: 4580
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Lazarus and WM_* messages

Post by salvadordf »

Hi,

WM_MOVE and WM_MOVING call TChromiumCore.NotifyMoveOrResizeStarted which has these code comments :

Code: Select all

  ///
  // Notify the browser that the window hosting it is about to be moved or
  // resized. This function is only used on Windows and Linux.
  ///
If we search for more comments in the code we can read this :

Code: Select all

// Call the parent method to dismiss any existing popups.

Code: Select all

// Notify DesktopWindowTreeHostWin of move events so that screen rectangle
  // information is communicated to the renderer process and popups are
  // displayed in the correct location.
https://bitbucket.org/chromiumembedded/cef/src/21d714ab6e09eff6a6c103387efa32f54f68b1d1/libcef/browser/native/browser_platform_delegate_native_win.cc?at=master#lines-404

The Lazarus demos resize the browser correctly and the contents are in the right location when the user moves the form. In this case, I think the term "popups" means the options of a SELECT element. The demos must close the options automatically when the browser is moving or resizing and the Lazarus demos do that.

WM_ENTERMENULOOP and WM_EXITMENULOOP are used by the official CEF sample application here :
https://bitbucket.org/chromiumembedded/cef/src/21d714ab6e09eff6a6c103387efa32f54f68b1d1/tests/cefclient/browser/root_window_win.cc?at=master#lines-570

cefclient calls cef_set_osmodal_loop when it receives those messages and it has these code comments :

Code: Select all

///
// Set to true (1) before calling Windows APIs like TrackPopupMenu that enter a
// modal message loop. Set to false (0) after exiting the modal message loop.
///
Delphi handles WM_ENTERMENULOOP in TCustomForm and I assumed that Lazarus forms can also receive that message.

I just did a quick search and Lazarus handles WM_EXITMENULOOP in TWindowProcHelper.DoWindowProc which is called by WindowProc but I haven't investigated long enough to know if WM_ENTERMENULOOP and WM_EXITMENULOOP are intercepted before reaching the forms.
wolf
Posts: 22
Joined: Thu Jan 31, 2019 6:36 pm

Re: Lazarus and WM_* messages

Post by wolf »

Thanks for the info.

In Lazarus, you can process these messages as described here:
https://wiki.freepascal.org/Win32/64_Interface#Processing_non-user_messages_in_your_window

I just tried it with this code. Maybe there are better solutions, but it seems to work:

Code: Select all

WM_MyMoving = WM_USER + 145;
WM_MyEnterMenuLoop = WM_USER + 146;
WM_MyExitMenuLoop = WM_USER + 147;

...

procedure WMMove(var aMessage: TWMMove); message WM_MOVE; 
procedure WMMoving(var aMessage: TMessage); message WM_MyMoving; 
procedure WMEnterMenuLoop(var aMessage: TMessage); message WM_MyEnterMenuLoop; 
procedure WMExitMenuLoop(var aMessage: TMessage); message WM_MyExitMenuLoop;

...

var
   PrevWndProc: WNDPROC;

...

function MyWndProc(Ahwnd: HWND; uMsg: UINT; wParam: WParam; lParam: LParam): LRESULT; stdcall;
begin
   if uMsg = WM_ENTERMENULOOP then
   begin
      SendMessage(Ahwnd, WM_MyEnterMenuLoop, WParam, lParam);
   end
   else if uMsg = WM_EXITMENULOOP then
   begin
      SendMessage(Ahwnd, WM_MyExitMenuLoop, WParam, lParam);
   end
   else if uMsg = WM_MOVING then
   begin
      SendMessage(Ahwnd, WM_MyMoving, WParam, lParam);
   end
   else
   begin
      //prev wndproc
      Result := CallWindowProc(PrevWndProc, Ahwnd, uMsg, WParam, LParam);
   end;
end;

procedure TMainForm.FormCreate(Sender: TObject); 
begin
   PrevWndProc := Windows.WNDPROC(SetWindowLongPtr(Self.Handle, GWL_WNDPROC, PtrUInt(@MyWndProc)));
Post Reply