据我所知,Windows没有提供API函数来告诉应用程序注册了一个全局热键(通过RegisterHotkey)。我只能发现如果RegisterHotkey返回false,则注册了热键,但不是“拥有”热键的人。
在没有直接API的情况下,是否会有迂回的方式? Windows维护与每个注册热键关联的句柄 - 这有点令人抓狂,因此无法获取此信息。
可能不起作用的示例:发送(模拟)已注册的热键,然后拦截Windows将发送给注册它的进程的热键消息。首先,我不认为拦截消息会显示目标窗口句柄。其次,即使有可能,这也是一件坏事,因为发送热键会触发各种程序中各种可能不需要的活动。
这并不重要,但我已经看到频繁请求此类功能,并且我自己一直是注册热键的应用程序的受害者,甚至没有在UI或文档中的任何地方公开它。
(在Delphi工作,只不过是WinAPI的学徒,请善待。)
答案 0 :(得分:25)
一种可能的方法是使用Visual Studio tool Spy++。
尝试一下:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\spyxx_amd64.exe
)WM_HOTKEY
,或在消息组中查看键盘(如果您的确有更多潜在噪音)WM_HOTKEY
行,右键单击,然后在上下文菜单中选择属性... EXPLORER
)答案 1 :(得分:19)
你的问题引起了我的兴趣,所以我做了一些挖掘,但不幸的是,我没有给你一个正确的答案,我想我会分享我所拥有的。
我发现这个example of creating keyboard hook (in Delphi)写于1998年,但在Delphi 2007中可以通过几个调整进行编译。
这是一个调用SetWindowsHookEx
的DLL,它通过一个回调函数,然后可以拦截键击:在这种情况下,它是为了好玩而修改它们,将左光标向右移动等等。一个简单的app然后调用DLL并根据TTimer事件报告其结果。如果您有兴趣,我可以发布基于Delphi 2007的代码。
它有详细记录和评论,您可能会将其用作确定按键操作的基础。如果您可以获得发送击键的应用程序的句柄,您可以以这种方式跟踪它。有了这个句柄,您就可以轻松获得所需的信息。
其他应用尝试通过快捷方式确定热键,因为它们可以包含快捷键,这只是热键的另一个术语。但是,大多数应用程序不倾向于设置此属性,因此它可能不会返回太多。如果您对该路由感兴趣,Delphi可以访问IShellLink
COM接口,您可以使用该接口加载快捷方式并获取其热键:
uses ShlObj, ComObj, ShellAPI, ActiveX, CommCtrl;
procedure GetShellLinkHotKey;
var
LinkFile : WideString;
SL: IShellLink;
PF: IPersistFile;
HotKey : Word;
HotKeyMod: Byte;
HotKeyText : string;
begin
LinkFile := 'C:\Temp\Temp.lnk';
OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, SL));
// The IShellLink implementer must also support the IPersistFile
// interface. Get an interface pointer to it.
PF := SL as IPersistFile;
// Load file into IPersistFile object
OleCheck(PF.Load(PWideChar(LinkFile), STGM_READ));
// Resolve the link by calling the Resolve interface function.
OleCheck(SL.Resolve(0, SLR_ANY_MATCH or SLR_NO_UI));
// Get hotkey info
OleCheck(SL.GetHotKey(HotKey));
// Extract the HotKey and Modifier properties.
HotKeyText := '';
HotKeyMod := Hi(HotKey);
if (HotKeyMod and HOTKEYF_ALT) = HOTKEYF_ALT then
HotKeyText := 'ALT+';
if (HotKeyMod and HOTKEYF_CONTROL) = HOTKEYF_CONTROL then
HotKeyText := HotKeyText + 'CTRL+';
if (HotKeyMod and HOTKEYF_SHIFT) = HOTKEYF_SHIFT then
HotKeyText := HotKeyText + 'SHIFT+';
if (HotKeyMod and HOTKEYF_EXT) = HOTKEYF_EXT then
HotKeyText := HotKeyText + 'Extended+';
HotKeyText := HotKeyText + Char(Lo(HotKey));
if (HotKeyText = '') or (HotKeyText = #0) then
HotKeyText := 'None';
ShowMessage('Shortcut Key - ' + HotKeyText);
end;
如果您有权访问Safari Books Online,则Steve Teixeira和Xavier Pacheco的Borland Delphi 6开发人员指南中有good section about working with shortcuts / shell links。我上面的例子是那里的屠宰版本和this site。
希望有所帮助!
答案 2 :(得分:9)
经过一些研究,您似乎需要访问MS用于存储热键的内部结构。 ReactOS有一个干净的房间实现,通过迭代内部列表并提取与调用参数匹配的热键来实现GetHotKey
调用。
根据ReactOS的实现与MS实现的接近程度,您可以在内存中查找结构,但这已经超出了我的想法......
BOOL FASTCALL
GetHotKey (UINT fsModifiers,
UINT vk,
struct _ETHREAD **Thread,
HWND *hWnd,
int *id)
{
PHOT_KEY_ITEM HotKeyItem;
LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
{
if (HotKeyItem->fsModifiers == fsModifiers &&
HotKeyItem->vk == vk)
{
if (Thread != NULL)
*Thread = HotKeyItem->Thread;
if (hWnd != NULL)
*hWnd = HotKeyItem->hWnd;
if (id != NULL)
*id = HotKeyItem->id;
return TRUE;
}
}
return FALSE;
}
我认为this thread on sysinternals是由与此问题相关的人提出的,但我认为无论如何我都要将它们联系起来以保持两者在一起。该线程看起来非常有趣,但我怀疑在没有访问MS内部构件的情况下需要进行一些深潜探测。
答案 3 :(得分:3)
在我的脑海中,您可以尝试使用EnumWindows枚举所有窗口,然后在回调中,将WM_GETHOTKEY发送到每个窗口。
编辑:显然我错了。 MSDN有更多信息:
WM_HOTKEY与WM_GETHOTKEY和WM_SETHOTKEY热键无关。 WM_HOTKEY消息是为通用热键发送的,而WM_SETHOTKEY和WM_GETHOTKEY消息与窗口激活热键有关。
注意:Here是一个程序,声称具有您正在寻找的功能。你可以尝试反编译它。
答案 4 :(得分:2)
这似乎告诉了你很多: http://hkcmdr.anymania.com/help.html
答案 5 :(得分:1)
另一个线程提到全局NT级键盘钩子:
Re-assign/override hotkey (Win + L) to lock windows
也许你可以获得以这种方式调用钩子的进程句柄,然后你可以将其解析为进程名称
(免责声明:我在我的书签中有这个,没有真正尝试/测试过)
答案 6 :(得分:0)
我知道您可以在自己的进程中的任何窗口中拦截消息流 - 我们以前在VB6中调用子类。 (虽然我不记得这个函数,也许是SetWindowLong?)我不确定你是否可以在自己的进程之外的窗口中执行此操作。但是为了这个帖子,我们假设您找到了一种方法。然后,您可以简单地拦截所有顶级窗口的消息,监视WM_HOTKEY消息。您无法立即知道所有键,但是当它们被按下时,您可以轻松找出使用它们的应用程序。如果将结果保存到磁盘并在每次运行监视器应用程序时重新加载,则可以随着时间的推移提高应用程序的性能。
答案 7 :(得分:-1)
这并不能完全回答有关Windows API的问题部分,但它回答了有关全局热键列表和“拥有”它们的应用程序的部分问题。
http://hkcmdr.anymania.com/处的免费热键资源管理器显示了所有全局热键以及拥有它们的应用程序的列表。这只是帮助我弄清楚为什么特定于应用程序的快捷键停止工作以及如何修复它(通过在已注册的应用程序中重新配置注册的全局热键),在几秒钟内。