具有平台 API 的 C++ 全局热键
Posted
技术标签:
【中文标题】具有平台 API 的 C++ 全局热键【英文标题】:C++ Global Hotkeys with platform APIs 【发布时间】:2016-06-07 07:03:42 【问题描述】:我正在开发一个使用 C++/Qt 在 Windows、OSX 和 Linux 上截屏的应用程序。现在我需要设置全局热键,以便用户可以在应用程序在后台运行时截取屏幕截图。我尝试使用 Qxt 和 UGlobalHotkey,它们都是 Qt 库,但它们似乎都不起作用。
我尝试使用 Carbon (tutorial) 为 OSX 实现它,但我需要调用一个类成员函数,但这不起作用。有人可以给我一个例子吗?你可以找到我的代码here。我需要调用的函数是 new_screenshot()。
或者有没有其他方法可以实现这样的目标?我真的需要我的应用程序从后台截取屏幕截图,否则它非常没用(是的,我可能应该在一开始就实现它,看看它是否有效)。为每个平台(OSX 的 Cocoa Swift、Linux 的 GTK、Windows 的 C# 客户端)拥有一个单独的客户端会更好吗?这几天我经常想到这个。
【问题讨论】:
【参考方案1】:我是否正确理解您想从热键事件处理程序中调用new_screenshot
?如果是这样,InstallApplicationEventHandler
允许您在第 4 个参数中传递指向用户数据的指针。传递指向您的 MainWindow
实例的指针(基于教程中的代码):
MainWindow *mainWindow = ... // get main window somehow
InstallApplicationEventHandler(&MyHotKeyHandler,1,&eventType,mainWindow,NULL);
然后你可以在事件处理程序中使用它。
OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent, void *userData)
//Do something once the key is pressed
static_cast<MainWindow*>(userData)->new_screenshot();
return noErr;
【讨论】:
是的,这就是我要找的。我真的应该开始阅读文档了。不幸的是,它仍然不起作用。 new_screenshot() 永远不会被调用。 This 是我目前拥有的。 我看到你没有设置EventTypeSpec
的eventKind
成员。应该是kEventHotKeyPressed
。
成功了!非常感谢。请问你是从哪里找到它是如何工作的?我实际上只是想学习如何做一些更复杂的事情,根本找不到任何关于 Carbon 的文档,因为它似乎已被弃用。
我在我的应用程序中使用JFHotkeyManager
。它在 Objective C 中,但应该不难理解:github.com/jaz303/JFHotkeyManager【参考方案2】:
我过去用 MFC 和 WIN32 API 做过一些事情……所以它只适用于 Windows……但按 ALT+F10
可以隐藏/显示一个窗口……
void CWinHideDlg::OnButtonActive()
CString tmp;
GetDlgItemText(IDC_BUTTON_ACTIVE,tmp);
if(0 == strcmp(tmp.GetBuffer(tmp.GetLength()),"Activate"))
m_myAtom=GlobalAddAtom("MY_GLOBAL_HOT_HIDE_KEY");
int err=RegisterHotKey(this->GetSafeHwnd(),m_myAtom,MOD_ALT,VK_F10);
SetDlgItemText(IDC_BUTTON_ACTIVE,"Stop");
CButton *pBtn = (CButton *)GetDlgItem(IDC_BUTTON_UNHIDE);
pBtn->EnableWindow(TRUE);
SetDlgItemText(IDC_STATIC_INFO,"Set the mouse over the window \nand press ALT + F10 to hide it...");
else
UnregisterHotKey(this->GetSafeHwnd(),m_myAtom);
GlobalDeleteAtom(m_myAtom);
CButton *pBtn = (CButton *)GetDlgItem(IDC_BUTTON_UNHIDE);
pBtn->EnableWindow(FALSE);
SetDlgItemText(IDC_BUTTON_ACTIVE,"Activate");
基本上此代码激活/停用热键ALT+F10
,一旦激活,您可以通过将鼠标指针设置在窗口上并按ALT+F10
来隐藏/取消隐藏系统上正在运行的窗口...
这是来自WindowProc
函数:
if(message == WM_HOTKEY)
CString tmp;
POINT pc;
GetCursorPos(&pc);
if(GetAsyncKeyState(VK_F10))
HWND hwnd=::WindowFromPoint(pc);
if(hwnd)
tmp.Format("%08Xh",hwnd);
m_HideWins.InsertString(m_HideWins.GetCount(),tmp);
::ShowWindow(hwnd,SW_HIDE);
您可以使用代码注册自己的HOT Key并使用它来截图......
希望对你有帮助……
【讨论】:
感谢您的回复。我认为这将非常有帮助,因为我想在 Windows、OSX 和 Linux 上启用此功能。我已经阅读了 Windows API 中的 RegisterHotkey 函数。但是 this->GetSafeHwnd() 是如何工作的呢?如何让 HWND 通过? 这可能会给你hwnd:[link]***.com/questions/14048565/… 非常感谢!似乎正是我在 Windows 上所需要的。 太好了,祝你的项目好运。 你能给我指出正确的方向吗?您似乎对此了解很多,我认为我的code 现在可以正常工作,因为每次我按下确切的组合键时它都会打印 0x16171fc0,但我的窗口从未出现。我猜这是因为循环?我如何在不阻塞其余部分的情况下收听组合键?在单独的线程中运行它似乎不起作用,因为它不再检测热键组合。以上是关于具有平台 API 的 C++ 全局热键的主要内容,如果未能解决你的问题,请参考以下文章