2

I'm working on an application for taking screenshots on Windows, OSX and Linux in C++/Qt. Now I need to set global hotkeys, so the user can take screenshots when the application is running in the background. I tried with Qxt and UGlobalHotkey, which are both Qt libraries, but neither of them seemed to work.

I tried to implement it for OSX with Carbon (tutorial), but I need to call a class member function, which just doesn't work. Could someone provide me with an example? You can find my code here. The function i need to call is new_screenshot().

Or is there any other way to achieve something like this? I really need my application to take a screenshot from the background, otherwise it's pretty useless (yes, I should probably have implemented it at the very beginning to see if it even works). Would it maybe be better to have a separate client for every platform (Cocoa Swift for OSX, GTK for Linux, C# client for Windows)? I have often thought about this the past few days.

rettetdemdativ
  • 369
  • 5
  • 16

2 Answers2

1

Do I understand correctly that you want to call new_screenshot from the hot key event handler? If so, InstallApplicationEventHandler lets you pass a pointer to user data in 4th argument. Pass a pointer to your MainWindow instance (based on code from the tutorial):

MainWindow *mainWindow = ... // get main window somehow
InstallApplicationEventHandler(&MyHotKeyHandler,1,&eventType,mainWindow,NULL);

Then you can use it in the event handler.

OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent, void *userData)
{
//Do something once the key is pressed
static_cast<MainWindow*>(userData)->new_screenshot();
return noErr;
}
Georgy Pashkov
  • 1,285
  • 7
  • 11
  • Yes, this is what I was looking for. I should really start reading documentation. Unfortunately, it still doesn't work. new_screenshot() never gets called. [This](https://gist.github.com/mkocs/26045dc924391a8e4166) is what I currently have. – rettetdemdativ Feb 24 '16 at 20:50
  • I see that you don't set the `eventKind` member of the `EventTypeSpec`. Should be `kEventHotKeyPressed`. – Georgy Pashkov Feb 24 '16 at 21:00
  • That did the trick! Thank you very much. May I ask where you found about how this works? I'm actually just trying to learn how to do some more complicated stuff and couldn't find any documentation about Carbon at all, since it seems to be deprecated. – rettetdemdativ Feb 24 '16 at 21:07
  • I'm using `JFHotkeyManager` in my app. It's in Objective C, but should not be too hard to understand: https://github.com/jaz303/JFHotkeyManager – Georgy Pashkov Feb 24 '16 at 22:02
1

I did something in the past with MFC and WIN32 API....so it only works on Windows...but pressing ALT+F10 was able to hide/show a window...

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");

    }   
}

Basically this code activates/deactivates the hot key ALT+F10, once it activates you can hide/unhide a running window on the system by setting the mouse pointer over the window and press ALT+F10...

This is from the WindowProc function:

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);
            }
        }
    } 

You can use the code to register your own HOT Key and use it to take a screenshot...

Hope it helps...

James Adkison
  • 9,412
  • 2
  • 29
  • 43
Ram Shmider
  • 55
  • 1
  • 6
  • Thank you for your reply. I think this will be very helpful, since I want to enable this feature on Windows, OSX and Linux. I already read about the RegisterHotkey function in windows API. But how does this->GetSafeHwnd() work? How would I get the HWND to pass? – rettetdemdativ Feb 24 '16 at 21:22
  • this may give you the hwnd: [link]http://stackoverflow.com/questions/14048565/get-hwnd-on-windows-with-qt5-from-wid[/link] – Ram Shmider Feb 24 '16 at 21:36
  • Thanks a lot! Seems to be just what I needed for Windows. – rettetdemdativ Feb 24 '16 at 21:43
  • Great, Good Luck with your project. – Ram Shmider Feb 24 '16 at 21:45
  • Could you point me in the right direction here? You seem to know a lot about this and I think my [code](https://gist.github.com/mkocs/dc0a5a122be4df593210) now works because it prints 0x16171fc0 every time I press my exact key combination, but my window never shows up. I guess this is because of the loop? How would I listen for the key combination without blocking the rest? Running it in a separate thread doesn't seem to work because it doesn't detect the hotkey combination anymore. – rettetdemdativ Feb 25 '16 at 21:20