'How can my Delphi 11 FMX project detect that "My Menu Item" in system menu clicked?

I've tried using wndproc to detect "My Menu Item" clicked in System Menu in windows. I used from source code to capture WndProc and add menu item to system menu. Mouse wheel in WndProc can detected but "My Menu Item" click not detected. My code is:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, FMX.Forms,
  FMX.Platform.Win, FMX.Types, FMX.Layouts, FMX.Memo, FMX.Memo.Types,
  FMX.Controls, FMX.Controls.Presentation, FMX.ScrollBox;

const
  SC_MyMenuItem = WM_USER + 1;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FHwnd: HWND;//Save the window handle
    FOldWndProc: LONG;//Save the original message processing function
  public
    function WndProc(HWND: HWND; Msg: UINT; wParam: wParam; lParam: lParam): LRESULT;
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

function WindowProc(HWND: HWND; Msg: UINT; wParam: wParam; lParam: lParam): LRESULT; stdcall;
begin
 //Because during normal development, you need to access the methods or controls inside the window, etc.
 //For convenience, so here is a message forwarding
  Result := Form1.WndProc(HWND, Msg, wParam, lParam);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 //Obtain the handle of the main window. Under the FMX framework, Handle is no longer the handle of this window, you need to convert it
  FHwnd := FmxHandleToHwnd (Handle);

  AppendMenu(GetSystemMenu(FHwnd, FALSE), MF_SEPARATOR, 0, '');
  AppendMenu(GetSystemMenu(FHwnd, FALSE), MF_STRING, SC_MyMenuItem, 'My Menu Item');

 //Save the original WindowProc address
  FOldWndProc := GetWindowLongPtr(FHwnd, GWL_WNDPROC);
 //Get message processing rights
  SetWindowLongPtr(FHwnd, GWL_WNDPROC, NativeInt(@WindowProc));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 //Because the message delivered by Windows cannot be processed after the window is destroyed, a memory access error will occur
 //So before the window is destroyed, the message processing power should be transferred to the original WindowProc
  SetWindowLongPtr(FHwnd, GWL_WNDPROC, FOldWndProc);
end;

function TForm1.WndProc(HWND: HWND; Msg: UINT; wParam: wParam; lParam: lParam): LRESULT;
begin
  Result := 0;

 //Test the mouse wheel message here

  if Msg = WM_MOUSEWHEEL then
  begin
    Memo1.Lines.Add('You used the mouse wheel');
    Exit;
  end;

  if Msg = SC_MyMenuItem then
  begin
    Memo1.Lines.Add('My Menu Item Clicked');
    Exit;
  end;

//  if Msg = 293 then
//  begin
//    Memo1.Lines.Add('My Menu Item Clicked');
//    Exit;
//  end;

  Result := CallWindowProc(Ptr(FOldWndProc), HWND, Msg, wParam, lParam);
end;

end.

In TForm1.WndProc Mouse wheel can detected but "My Menu Item" click not detected. what is the problem?



Solution 1:[1]

Your coding style looks like Visual C++, processing all message by yourself.

But you don't need to do so in Delphi. In your Project, you can edit your Form1 in Design mode visually.

After placing the component you named "My Menu Item" on the Form1, you can double click the "My Menu Item" in Design mode, and the default event handler will create "OnClick" event for you.

And then you can add any codes you wish to have for the event in the method.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dennies Chang