简体   繁体   中英

Simulate global hotkey

Hi I am using visual c++ I have a working program EXCEPT for one thing I want it be able to use separate screenshot program. I have separate screenshot program installed it program have a registered hotkey to take a screenshot, I want my program to do it.

I tried keybd_event and SendInput with FindWindow and it works fine with notepad but it screenshot program runs minimized or hidden and I know about problem with SetForegroundWindow.

Is there a way to make it like to windows system I just pressed on keyboard for all windows like real hotkey? It screenshot program works fine with real hotkey.

Maybe keyboard hook will solve the problem?

Not perfect but they are pretty global

在此处输入图片说明

Here is a source code for a global hotkey . It has been set to listen for a CTRL + y key combination. Once CTRL + y is triggered it grabs a screenshot.

To close the global hotkey, simply press CTRL + q .

To hide the console window and keep the hotkey running in the background press CTRL + w .

#define _WIN32_WINNT 0x0400
#pragma comment( lib, "user32.lib" )

#include <iostream>
#include <windows.h>
#include <stdio.h>

HHOOK hKeyboardHook;
__declspec(dllexport) LRESULT CALLBACK KeyboardEvent (int nCode, WPARAM wParam, LPARAM lParam);
void MessageLoop();
DWORD WINAPI my_HotKey(LPVOID lpParm);
int toggleVisibility = 1;

int screenResolutionX = GetSystemMetrics(SM_CXSCREEN);
int screenResolutionY = GetSystemMetrics(SM_CYSCREEN);
POINT startCoord,endCoord;
void grabScreenshot(POINT a, POINT b);

/*********************************************
***                                        ***
***                                        ***
**********************************************/


int main(int argc, char** argv){

    /* uncomment to hide console window */
    //ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);

    HANDLE hThread;
    DWORD dwThread;

    printf("\n  s c r e e n s h o t   H O T K E Y    \n\n");
    printf("press  CTRL-y  for  screenshot \n");
    printf("press  CTRL-w  to hide or make console window visible  \n");
    printf("press  CTRL-q  to quit  \n");
    printf("\n\n");

    hThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)   my_HotKey, (LPVOID) argv[0], NULL, &dwThread);

    if (hThread) return WaitForSingleObject(hThread,INFINITE);
    else return 1;

}

/*********************************************
***                                        ***
***                                        ***
**********************************************/


__declspec(dllexport) LRESULT CALLBACK KeyboardEvent (int nCode, WPARAM wParam, LPARAM lParam){
    DWORD SHIFT_key=0;
    DWORD CTRL_key=0;
    DWORD ALT_key=0;


    if  ( (nCode == HC_ACTION) &&   ((wParam == WM_SYSKEYDOWN) ||  (wParam == WM_KEYDOWN) ) ) {
        KBDLLHOOKSTRUCT hooked_key =    *((KBDLLHOOKSTRUCT*)lParam);
        DWORD dwMsg = 1;
        dwMsg += hooked_key.scanCode << 16;
        dwMsg += hooked_key.flags << 24;
        char lpszKeyName[1024] = {0};

        int i = GetKeyNameText(dwMsg,   (lpszKeyName+1),0xFF) + 1;

        int key = hooked_key.vkCode;

        SHIFT_key = GetAsyncKeyState(VK_SHIFT);
        CTRL_key  = GetAsyncKeyState(VK_CONTROL);
        ALT_key   = GetAsyncKeyState(VK_MENU);

        //printf("%c",key);

        if ( (key >= 'A') && (key <= 'Z') || (key >= 'a') && (key <= 'z') || (key >= '0') && (key <= '9') ) {

            if  (GetAsyncKeyState(VK_SHIFT)>= 0) key +=32;

            /*********************************************
            ***   Hotkey scope                         ***
            ***   do stuff here                        ***
            **********************************************/

            if ( (CTRL_key !=0) && (key == 'y') || (key == 'Y') ) {

               CTRL_key=0;

               // grab a screenshot

                startCoord.x=0;
                startCoord.y=0;

                endCoord.x=screenResolutionX;
                endCoord.y=screenResolutionY;

                ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);
                Sleep(1000);
                grabScreenshot(startCoord,endCoord);

                ShowWindow(FindWindowA("ConsoleWindowClass", NULL), true);

                printf("\nThe Screenshot is in the Clipboard  \n\n");
            }

            //******************************************************

            if ( (CTRL_key !=0) && (key == 'q') ||  (key == 'Q') ) {
                MessageBox(NULL, "\n\n\n\nShutting down\n\nPress  OK   to close\n\n", "                                     H O T K E Y                                            ", MB_OK);
               PostQuitMessage(0);
            }

            //******************************************************

            if ( (CTRL_key !=0) && (key == 'w') ||  (key == 'W') ) {

                toggleVisibility = - toggleVisibility;

                if (toggleVisibility >0 ) {
                    ShowWindow(FindWindowA("ConsoleWindowClass", NULL), true);
                }
                else{
                    ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);
                }
            }

            SHIFT_key = 0;CTRL_key = 0; ALT_key = 0;
        }
    }
    return CallNextHookEx(hKeyboardHook,    nCode,wParam,lParam);
}


/*********************************************
***                                        ***
***                                        ***
**********************************************/

void MessageLoop(){

    MSG message;
    while (GetMessage(&message,NULL,0,0)){
        TranslateMessage( &message );
        DispatchMessage( &message );
    }
}

/*********************************************
***                                        ***
***                                        ***
**********************************************/


DWORD WINAPI my_HotKey(LPVOID lpParm){
    HINSTANCE hInstance = GetModuleHandle(NULL);
    if (!hInstance) hInstance = LoadLibrary((LPCSTR) lpParm);
    if (!hInstance) return 1;

    hKeyboardHook = SetWindowsHookEx (  WH_KEYBOARD_LL, (HOOKPROC) KeyboardEvent,   hInstance,  NULL    );
    MessageLoop();
    UnhookWindowsHookEx(hKeyboardHook);
    return 0;
}


/*********************************************
***                                        ***
***                                        ***
**********************************************/


void grabScreenshot(POINT a, POINT b){

    // copy screen to bitmap
    HDC     hScreen = GetDC(NULL);
    HDC     hDC     = CreateCompatibleDC(hScreen);
    HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, abs(b.x-a.x), abs(b.y-a.y));
    HGDIOBJ old_obj = SelectObject(hDC, hBitmap);
    BOOL    bRet    = BitBlt(hDC, 0, 0, abs(b.x-a.x), abs(b.y-a.y), hScreen, a.x, a.y, SRCCOPY);

    // save bitmap to clipboard
    OpenClipboard(NULL);
    EmptyClipboard();
    SetClipboardData(CF_BITMAP, hBitmap);
    CloseClipboard();

    // clean up
    SelectObject(hDC, old_obj);
    DeleteDC(hDC);
    ReleaseDC(NULL, hScreen);
    DeleteObject(hBitmap);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM