0
votes

I'm trying to create macro application that will start running certain operations when key is pressed (system wide shortcut). I did created Windows Form Application with Visual Studio 2012. When form is loaded keyboard hook is installed:

HookHandle = SetWindowsHookEx( WH_KEYBOARD_LL, (HOOKPROC)keyboardHookHandler, GetModuleHandle(NULL), NULL);
if( HookHandle == 0){
    MessageBox::Show("Error setting hook!");
}

My hook callback function is:

public: static LRESULT CALLBACK keyboardHookHandler( int code, WPARAM wParam, LPARAM lParam ) {
    if(code>=0 && wParam == WM_KEYDOWN){
        MessageBox::Show("Key Down");
    }
    return CallNextHookEx( HookHandle, code, wParam, lParam); 
}

When I do compile application and run it message box is never shown. More to say I know this call back function is fired but wParam always contains value 45 (I did checked and none of those WM constants that should be returned has value 45). Also after few key events application crashes.

What is the reason why this code doesn't work like it should to?

Update: I did removed cast to HOOKPROC and changed it to delegated procedure:

private: 
    delegate LRESULT CALLBACK HOOKPROC( int code, WPARAM wParam, LPARAM lParam );
    HOOKPROC^ keyboardHookProcedure;

And hook setting to:

keyboardHookProcedure = gcnew HOOKPROC(this, &MyForm::keyboardHookHandler);
HookHandle = SetWindowsHookEx( WH_KEYBOARD_LL, keyboardHookProcedure, GetModuleHandle(NULL), NULL);

But now I have this problem:

error C2664: 'SetWindowsHookExW' : cannot convert parameter 2 from 'WindowsFormTest::MyForm::HOOKPROC ^' to 'HOOKPROC'

1
public: static ... you're coming from Java, right? ;)nijansen
A global hook requires that your hook procedure is implemented in a .dll. Your call to SetWindowsHookEx passes the HINSTANCE of the executable image that started the process (GetModuleHandle(NULL)). While debugging your application VS' debugger can translate a message identifier into humanreadable form. Set up a watch with the respective symbol appending the ,wm format specifier, like wParam,wm.IInspectable
It is a Low Level hook so it shouldn't require DLL. I did it in NetBeans using only Windows Api (simple simple window). What is wrong with STATIC in callback procedure? It is required to pass procedure to hook. Or em I wrong?Artur Stępień
You shouldn't need to cast your callback function. And the first argument to CallNextHookEx should be nullptr. Other than that, perhaps you're missing the main pumping for the hook calls.chris
You are writing C++/CLI code, not C++ code. You will need to get rid of that (HOOKPROC) cast, that only stops the compiler from telling you that you are doing it wrong. The error message you get from the compiler when you remove the cast tells you what the problem is.Hans Passant

1 Answers

0
votes

If you're trying to catch a unique key combination globally, it might be simpler to use RegisterHotKey. It defines a system-wide hot key with no need for hooks or anything special. It is going to override the foreground process handling, so this won't be ideal if you're trying to register a common key combo.