【问题标题】:Create FMX window with MessageBox style使用 MessageBox 样式创建 FMX 窗口
【发布时间】:2017-03-28 13:16:41
【问题描述】:

我有一个问题:如何创建 FMX 窗口以使其看起来像 ShowMessage 窗口?

ShowMessage(包含MoveClose项):

FMX 窗口:

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

我需要什么:删除图标并删除禁用的菜单项

【问题讨论】:

    标签: windows delphi firemonkey messagebox delphi-10.1-berlin


    【解决方案1】:

    在 Windows 上,ShowMessage() 使用 Win32 API MessageBoxIndirect() 函数显示一个系统对话框。

    要自定义标准 FMX 表单的默认系统菜单,您必须下拉到 Win32 API 层并直接操作系统菜单。这意味着获取Form的HWND(可以使用FMX.Platform.Win单元中的FormToHWND()函数),然后使用Win32 API GetMenu()DeleteMenu()函数。

    要删除窗体的图标,请使用 Win32 API SendMessage() 函数发送 HWND WM_SETICON 消息,并将 lParam 设置为 0。或者使用 SetWindowLongPtr() 启用 WS_EX_DLGMODALFRAME 窗口样式.

    重写Form的虚拟CreateHandle()方法来执行这些操作,例如:

    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.
    

    【讨论】:

    • 感谢您的回答。我知道这可以通过 WinApi 函数实现。在 FMX 表单标题上也显示了系统菜单,这不是自定义的 Delphi 菜单。问题是关于使用 delphi 级函数而不是低级 WinApi 函数更改 FMX 窗口样式。您认为仅使用 API 就可以做到这一点吗?例如,我可以分配BorderStyle := TFmxFormBorderStyle.Single; - 窗口将没有图标,但关闭按钮较小,始终为红色
    • FMX 表单包装标准 Win32 HWND。您看到的菜单是标准的 Win32 系统菜单。 .biSystemMenu 标志仅在HWND 上启用WS_SYSMENU 样式,其余由操作系统本身处理。 BorderStyle 只是根据需要设置启用/禁用HWND 上的其他窗口样式(WS_POPUPWS_BORDERWS_EX_TOOLWINDOW 等)。您必须直接使用 Win32 API 来操作系统菜单的内容。您所要求的不能仅在 FMX 中完成。
    • 谢谢你,你是完全正确的,在 VCL 上我们有 bsDialog 值,对于这个值,Delphi 使用函数 TCustomForm.WMNCCreate 在内部完成所有这些工作 ModifySystemMenu 并且使用 FMX 我们应该手动执行此操作
    • FMX 表单的哪个事件处理程序是使用此代码的正确位置,OnPaint?在 OnPaint 现在删除菜单项工作正常,但图标没有被删除:SendMessage(hWindow, WM_SETICON, 0, 0); where hWindow := FormToHWND(Self);
    • 您需要在表单创建其HWND 后立即执行此操作。重写Form的虚拟CreateHandle()方法,先调用inherited,再调用FormToHWND(),根据需要对HWND进行操作。
    猜你喜欢
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 2014-07-11
    • 2012-07-17
    • 2022-01-18
    相关资源
    最近更新 更多