Search code examples
windowsdelphifiremonkeymessageboxdelphi-10.1-berlin

Create FMX window with MessageBox style


I have a question: how I can create FMX window to make it looks like ShowMessage window?

ShowMessage (contain Move and Close items):

enter image description here

FMX window:

BorderIcons := [TBorderIcon.biSystemMenu];
BorderStyle := TFmxFormBorderStyle.Single;

enter image description here

What I need: remove Icon and delete disabled menu items


Solution

  • On Windows, ShowMessage() displays a system dialog using the Win32 API MessageBoxIndirect() function.

    To customize the default system menu of a standard FMX form, you have to drop down to the Win32 API layer and manipulate the system menu directly. That means getting the HWND of the Form (you can use the FormToHWND() function in the FMX.Platform.Win unit) and then use the Win32 API GetMenu() and DeleteMenu() functions.

    To remove the Form's icon, use the Win32 API SendMessage() function to send the HWND a WM_SETICON message with the lParam set to 0. Or use SetWindowLongPtr() to enable the WS_EX_DLGMODALFRAME window style.

    Override the Form's virtual CreateHandle() method to perform these operations, eg:

    interface
    
    ...
    
    type
      TForm1 = class(TForm)
        ...
      {$IFDEF MSWINDOWS}
      protected
        procedure CreateHandle; override;
      {$ENDIF}
        ...
      end;
    
    implementation
    
    {$IFDEF MSWINDOWS}
    uses
      Windows;
    {$ENDIF}
    
    ...
    
    {$IFDEF MSWINDOWS}
    procedure TForm1.CreateHandle;
    var
      Wnd: HWND;     
      Menu: HMENU;
      ExStyle: LONG_PTR;
    begin
      inherited;
      Wnd := FormToHWND(Self);
    
      Menu := GetMenu(Wnd);
      DeleteMenu(Menu, SC_TASKLIST, MF_BYCOMMAND);
      DeleteMenu(Menu, 7, MF_BYPOSITION);
      DeleteMenu(Menu, 5, MF_BYPOSITION);
      DeleteMenu(Menu, SC_MAXIMIZE, MF_BYCOMMAND);
      DeleteMenu(Menu, SC_MINIMIZE, MF_BYCOMMAND);
      DeleteMenu(Menu, SC_SIZE, MF_BYCOMMAND);
      DeleteMenu(Menu, SC_RESTORE, MF_BYCOMMAND);
    
      SendMessage(Wnd, WM_SETICON, ICON_SMALL, 0);
      SendMessage(Wnd, WM_SETICON, ICON_BIG, 0);
    
      ExStyle := GetWindowLongPtr(Wnd, GWL_EXSTYLE);
      SetWindowLong(Wnd, GWL_EXSTYLE, ExStyle or WS_EX_DLGMODALFRAME);
      SetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_FRAMECHANGED);
    end;
    {$ENDIF}
    
    ...
    
    end.