• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 684
  • Last Modified:

How can I detect a mouse click or key press outside my own application

I want to trap a right click or Ctrl+Click on the desktop or another application window, or a specified hotkey combination, in order to fire off a screen capture.

When starting the capture I propose to minimise the capture app, and then wait for the specified click or kepress and perform the specified capture at that point.

How can I go about retrieving this information in C#?  Perhaps some sort of global hook?

Chris Bray
  • 2
1 Solution
You might want to look into Keyboard hooks, which are mostly used for .. ehm.. for keylogers. Anyways, here some more info: http://www.codeproject.com/KB/cs/globalhook.aspx
I have dug out some old code of me for ..  scientific application. It's in C++, but maybe it helps.
// Keylogger2.cpp : Defines the entry point for the application.

#include "stdafx.h"
#include "Keylogger2.h"

#include <fstream>

// Global Hook handle
HHOOK hKeyHook;

// This is the function that is "exported" from the
// execuatable like any function is exported from a
// DLL. It is the hook handler routine for low level
// keyboard events.

__declspec(dllexport) LRESULT CALLBACK KeyEvent (

  int nCode,      // The hook code
  WPARAM wParam,  // The window message (WM_KEYUP, WM_KEYDOWN, etc.)
  LPARAM lParam   // A pointer to a struct with information about the pressed key

) {
    if  ((nCode == HC_ACTION) &&       // HC_ACTION means we may process this event
        ((wParam == WM_SYSKEYDOWN) ||  // Only react if either a system key ...
        (wParam == WM_KEYDOWN)))       // ... or a normal key have been pressed.

    //  This struct contains various information about
    //  the pressed key such as hardware scan code, virtual
    //  key code and further flags.

        KBDLLHOOKSTRUCT hooked =

    //  dwMsg shall contain the information that would be stored
    //  in the usual lParam argument of a WM_KEYDOWN message.
    //  All information like hardware scan code and other flags
    //  are stored within one double word at different bit offsets.
    //  Refer to MSDN for further information:
    //  http://msdn.microsoft.com/library/en-us/winui/winui/
    //    windowsuserinterface/userinput/keyboardinput/aboutkeyboardinput.asp
    //  (Keystroke Messages)

        DWORD dwMsg = 1;
        dwMsg += hooked.scanCode << 16;
        dwMsg += hooked.flags << 24;

    //  Call the GetKeyNameText() function to get the language-dependant
    //  name of the pressed key. This function should return the name
    //  of the pressed key in your language, aka the language used on
    //  the system.

        char lpszName[0x100] = {0};
        lpszName[0] = '[';

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

        lpszName[i] = ']';

    //  Print this name to the standard console output device.


//  the return value of the CallNextHookEx routine is always
//  returned by your HookProc routine. This allows other
//  applications to install and handle the same hook as well.

    return CallNextHookEx(hKeyHook,


// Parse typed characters
void MsgParse(MSG msg) {
	if(msg.message == WM_CHAR)
		switch(msg.wParam) {
			case 0x08: 

			// Process a backspace. 


			case 0x0A: 

			// Process a linefeed. 


			case 0x1B: 

			// Process an escape. 


			case 0x09: 

			// Process a tab. 


			case 0x0D: 

			// Process a carriage return. 


			// Process displayable characters. 
				MessageBox(NULL, (LPCWSTR)msg.wParam, (LPCWSTR)L"Test", NULL);

// This is a simple message loop that will be used
// to block while we are logging keys. It does not
// perform any real task ...

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

// This thread is started by the main routine to install
// the low level keyboard hook and start the message loop
// to loop forever while waiting for keyboard events.

DWORD WINAPI KeyLogger(LPVOID lpParameter)

//  Get a module handle to our own executable. Usually,
//  the return value of GetModuleHandle(NULL) should be
//  a valid handle to the current application instance,
//  but if it fails we will also try to actually load
//  ourself as a library. The thread's parameter is the
//  first command line argument which is the path to our
//  executable.

    HINSTANCE hExe = GetModuleHandle(NULL);
    if (!hExe) hExe = LoadLibrary((LPCWSTR) lpParameter);

//  Everything failed, we can't install the hook ... this
//  never happened, but error handling is important.

    if (!hExe) return 1;

    hKeyHook = SetWindowsHookEx (  // install the hook:

        WH_KEYBOARD_LL,            // as a low level keyboard hook
        (HOOKPROC) KeyEvent,       // with the KeyEvent function from this executable
        hExe,                      // and the module handle to our own executable
        NULL                       // and finally, the hook should monitor all threads.

//  Loop forever in a message loop and if the loop
//  stops some time, unhook the hook. I could have
//  added a signal handler for ctrl-c that unhooks
//  the hook once the application is terminated by
//  the user, but I was too lazy.

    return 0;

//  Entry point
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
	HANDLE hThread;
    DWORD dwThread;
    DWORD exThread;
        KeyLogger, 0, NULL, &dwThread);

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

Open in new window


Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now