delphi – firemonkey和全球热键?

delphi – firemonkey和全球热键?,第1张

概述我正在寻找一种方法来加速firemonkey应用程序中的全局热键(仅限 Windows,至少目前为止). 经过一些挫折和谷歌搜索后,这应该工作: 用winapi电话注册热键 RegisterHotKey(FmxHandleToHWND(form1.Handle), 0 , MOD_CONTROL, $41); 它返回true. 然后在表单的过程中捕获热键 procedure WMHotKey(va 我正在寻找一种方法来加速firemonkey应用程序中的全局热键(仅限 Windows,至少目前为止).
经过一些挫折和谷歌搜索后,这应该工作:
用winAPI电话注册热键

RegisterHotKey(FmxHandletoHWND(form1.Handle),MOD_CONTRol,);

它返回true.
然后在表单的过程中捕获热键

procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;

但这个从未被称为.
我之前习惯在vcl应用程序中这样做,所以我的猜测是firemonkey以不同的方式处理消息.
所以问题是:如何在firemonkey app中捕获全局热键?

编辑:应用该解决方案的一些示例.我创建了一个小班的单元

unit fire_hotkey;interfaceuses windows,messages,allocatehwnd;type  TMsgHandler = procedure (var Msg: TMessage) of object;  THotClass = class(TObject)    fMsgHandlerHWND : HWND;    proc:TMsgHandler;    constructor Create;    procedure init;    destructor Destroy; overrIDe;  end;implementation{ hotClass }constructor THotClass.Create;begin  inherited;end;destructor THotClass.Destroy;begin  ThreadDeallocateHWnd(fMsgHandlerHWND);  inherited;end;procedure THotClass.init;begin   fMsgHandlerHWND := ThreadAllocateHWnd(proc,true);end;end.

然后我的主窗体有一个处理热键事件的过程:

procedure TformEditor.WMHotKey(var Msg: TMessage);begin  if Msg.Msg = WM_HOTKEY then  begin    //call lua function or sth    //...  end  else    Msg.Result := DefWindowProc(hotkeyGrabber.fMsgHandlerHWND,Msg.Msg,Msg.wParam,Msg.lParam);end;

并且有一个全球热键抓取:THotClass;在表单创建时初始化:

hotkeyGrabber:=THotClass.Create;  hotkeyGrabber.proc:=WMHotKey;  hotkeyGrabber.init;

在那之后你应该像通常的vcl应用程序一样注册热键,他们将是cought
http://www.swissdelphicenter.ch/torry/showcode.php?id=147
希望它有意义

解决方法 FMX框架不会将消息路由到您的表单.因此,永远不会调用您的WMHotKey,因为FMX框架从不调用dispatch.您可以通过检查FMX.Platform.Win单元的实现部分中声明的WndProc方法来查看这种情况.

解决此问题的最简单方法是通过调用CreateWindow创建自己的窗口.然后为该窗口实现一个窗口过程来处理WM_HOTKEY消息.

我已经包装了这样的低级API调用:

unit AllocateHWnd;interfaceuses  System.SysUtils,System.Classes,System.SyncObJs,WinAPI.Messages,WinAPI.windows;function ThreadAllocateHWnd(AMethod: TWndMethod; MessageOnly: Boolean): HWND;procedure ThreadDeallocateHWnd(Wnd: HWND);implementationconst  GWL_METHODCODE = SizeOf(Pointer)*0;  GWL_METHODDATA = SizeOf(Pointer)*1;  ThreadAllocateHWndClassname = 'MyCompanyname_ThreadAllocateHWnd';var  ThreadAllocateHWndLock: TCriticalSection;  ThreadAllocateHWndClassRegistered: Boolean;function ThreadAllocateHWndProc(Window: HWND; Message: UINT; wParam: WParaM; lParam: LParaM): LRESulT; stdcall;var  Proc: TMethod;  Msg: TMessage;begin  Proc.Code := Pointer(getwindowlongPtr(Window,GWL_METHODCODE));  Proc.Data := Pointer(getwindowlongPtr(Window,GWL_METHODDATA));  if Assigned(TWndMethod(Proc)) then begin    Msg.Msg := Message;    Msg.wParam := wParam;    Msg.lParam := lParam;    Msg.Result := 0;    TWndMethod(Proc)(Msg);    Result := Msg.Result  end else begin    Result := DefWindowProc(Window,Message,wParam,lParam);  end;end;function ThreadAllocateHWnd(AMethod: TWndMethod; MessageOnly: Boolean): HWND;  procedure RegisterThreadAllocateHWndClass;  var    WndClass: TWndClass;  begin    if ThreadAllocateHWndClassRegistered then begin      exit;    end;    ZeroMemory(@WndClass,SizeOf(WndClass));    WndClass.lpszClassname := ThreadAllocateHWndClassname;    WndClass.hInstance := HInstance;    WndClass.lpfnWndProc := @ThreadAllocateHWndProc;    WndClass.cbWndExtra := SizeOf(TMethod);    WinAPI.windows.RegisterClass(WndClass);    ThreadAllocateHWndClassRegistered := True;  end;begin  ThreadAllocateHWndLock.Acquire;  Try    RegisterThreadAllocateHWndClass;    if MessageOnly then begin      Result := CreateWindow(ThreadAllocateHWndClassname,'',HWND_MESSAGE,HInstance,nil);    end else begin      Result := CreateWindowEx(WS_EX_TOolWINDOW,ThreadAllocateHWndClassname,WS_POPUP,nil);    end;    Win32Check(Result<>0);    SetwindowLongPtr(Result,GWL_METHODDATA,NativeInt(TMethod(AMethod).Data));    SetwindowLongPtr(Result,GWL_METHODCODE,NativeInt(TMethod(AMethod).Code));  Finally    ThreadAllocateHWndLock.Release;  End;end;procedure ThreadDeallocateHWnd(Wnd: HWND);begin  Win32Check(DestroyWindow(Wnd));end;initialization  ThreadAllocateHWndLock := TCriticalSection.Create;finalization  ThreadAllocateHWndLock.Free;end.

这是VCL AllocateHWnd的线程安全版本,它因在主线程外部无法使用而臭名昭着.

你需要做的是创建一个带有窗口过程的类,即实现TWndMethod的东西.它可以是实例方法或类方法.然后只需调用ThreadAllocateHWnd来创建窗口,并将该窗口传递给RegisterHotKey.什么时候解开它,取消注册你的热键,并通过调用ThreadDeallocateHWnd来销毁窗口.

总结

以上是内存溢出为你收集整理的delphi – firemonkey和全球热键?全部内容,希望文章能够帮你解决delphi – firemonkey和全球热键?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1245974.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存