具有平台 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 是我目前拥有的。 我看到你没有设置EventTypeSpeceventKind 成员。应该是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++ 全局热键的主要内容,如果未能解决你的问题,请参考以下文章

Google+ 与 Google 身份平台 API

C++ 热键运行功能

具有 OpenGL 和 C++ 的 2D 平台游戏相机

Android 平台上的原生 C/C++ 代码

仅触发一次热键/快捷方式事件

Xmake v2.7.7 发布,支持 Haiku 平台,改进 API 检测和 C++ Modules 支持