如何在 Delphi FMX Windows 窗体中检测鼠标的后退和前进按钮?

4

有人发现了在Delphi FMX表单中检测Windows(仅限Windows)鼠标前进和后退按钮的方法吗?

我知道在VCL应用程序中使用以下代码可以正常工作:

procedure WMAppCommand(var Msg: Winapi.Messages.TMessage); message WM_APPCOMMAND;

但这在FMX应用程序中没有任何效果。
如果有人已经解决了这个问题,非常感谢给一个提示(或者当然也可以提供他们使用的代码)。

你确定你的鼠标产生的是WM_AppComand而不是像“VK_BROWSER_BACK”和“VK_BROWSER_FORWARD”一样模拟键盘命令吗?如果它正在模拟键命令,那么你只需要使用"OnKeyDown"或"OnKeyUp"事件即可。你会惊讶地发现,这些额外的鼠标按钮仅仅向计算机发送特定的键盘命令。 - SilverWarior
@SilverWarior 是的,我是。OnKeyDown和OnKeyUp事件是我检查的第一件事情之一。但它们并没有被触发。 - Domus
1个回答

5

FMX严格过滤窗口消息,仅会分发它实际使用的少量消息。 WM_APPCOMMAND 不在其中,这就是为什么像VCL中那样简单的 message 处理程序在FMX中无法工作。

因此,您需要手动子类化TForm的Win32 HWND,通过SetWindowLongPtr(GWLP_WNDPROC)SetWindowSubclass(),以在FMX看到它们之前拦截窗口消息。请参见子类化控件

理想的子类化位置是重写TForm.CreateHandle()方法。您可以使用FMX的FormToHWND()函数,在TForm创建后获取其HWND

protected
  procedure CreateHandle; override;

...

uses
  FMX.Platform.Win, Winapi.Windows, Winapi.CommCtrl;

function MySubclassProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM;
  uIdSubclass: UINT_PTR; dwRefData: DWORD_PTR): LRESULT; stdcall;
begin
  case uMsg of
    WM_APPCOMMAND: begin
     // use TMyForm(dwRefData) as needed...
    end;
    WM_NCDESTROY:
      RemoveWindowSubclass(hWnd, @MySubclassProc, uIdSubclass);
  end;
  Result := DefSubclassProc(hWnd, uMsg, wParam, lParam);
end;

procedure TMyForm.CreateHandle;
begin
  inherited;
  SetWindowSubclass(FormToHWND(Self), @MySubclassProc, 1, DWORD_PTR(Self));
end;

procedure InitStandardClasses;
var 
  ICC: TInitCommonControlsEx;
begin
  ICC.dwSize := SizeOf(TInitCommonControlsEx);
  ICC.dwICC := ICC_STANDARD_CLASSES;
  InitCommonControlsEx(ICC);
end;

initialization
  InitStandardClasses;

修改了你的答案,希望你不介意。经过这些更改,它现在完美地运行了。谢谢! - Domus
@Domus能分享一下你改了什么吗? - Remy Lebeau
它说需要由可信的社区成员批准。那肯定是你吧?我把“procedure”改成了“function”,在函数末尾添加了“Result := DefSubclassProc(hWnd, uMsg, wParam, lParam)”,并在最后添加了“var ICC: TInitCommonControlsEx;initialization ICC.dwSize := SizeOf(TInitCommonControlsEx); ICC.dwICC := ICC_STANDARD_CLASSES; InitCommonControlsEx(ICC);”。 - Domus
谢谢。我忘记添加 Winapi.CommCtrl 到 uses 子句中了。奇怪,我在编辑中已经添加了所有内容。 - Domus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接