【问题标题】:C++ Global Hotkeys with platform APIs具有平台 API 的 C++ 全局热键
【发布时间】: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# 客户端)拥有一个单独的客户端会更好吗?这几天我经常想到这个。

【问题讨论】:

    标签: c++ qt hotkeys global-hotkey


    【解决方案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]stackoverflow.com/questions/14048565/…
    • 非常感谢!似乎正是我在 Windows 上所需要的。
    • 太好了,祝你的项目好运。
    • 你能给我指出正确的方向吗?您似乎对此了解很多,我认为我的code 现在可以正常工作,因为每次我按下确切的组合键时它都会打印 0x16171fc0,但我的窗口从未出现。我猜这是因为循环?我如何在不阻塞其余部分的情况下收听组合键?在单独的线程中运行它似乎不起作用,因为它不再检测热键组合。
    猜你喜欢
    • 1970-01-01
    • 2010-12-21
    • 2012-08-02
    • 2017-12-20
    • 2011-03-29
    • 2016-06-04
    • 2012-02-05
    • 2018-12-21
    相关资源
    最近更新 更多