Re: SetWindowsHookEx not notifing me on key pressed, using JNI and C++ dll
Knitter wrote:
Some points I don't understand...
Why can't I use JNIEnv as global? It's in some of the examples I have.
Why do I need to attach the dll to the VM?
I was under the impression that when a javaVM loads a dll the dll is
already attached to the VM, I'm I wrong?
I'm using DevC++ and Eclipse, and I have my classes and my dll in the
same folder, <project folder>\bin, and I run the app from a DOS command
shell like this:
java -Djava.library.path=bin -classpath bin bkey.Main
The output is:
Testing: Dll main method called.
hook successful at process attach
Testing: Registering dll owner.
Testing: JavaVM not null: True.
Then when I press a key the cursor just stops blinking for 2 or 3
seconds and nothing else happens, if I press any other keys nothing
happens.
Is there any where I can see some correct documentation? I find alot of
contradictory info over the net, and I can't decide what is usefull
and is just old or garbage.
Thanks.
Sorry I forgot to put in the C++ code. Here it is:
#include "winlib.h"
#include "bkey_keyParser.h"
#include "resource.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
LRESULT CALLBACK LowLevelKeyboardProc(int, WPARAM, LPARAM);
jobject parser;
JavaVM *javaVM = NULL;
HHOOK hhkLowLevelKybd = NULL;
/*'Params'
HINSTANCE hInst - Library instance handle.
DWORD reason - Reason this function is being called.
LPVOID reserved - Not used.
*/
extern "C" BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID
reserved)
{
printf("Testing: Dll main method called.\n");
switch (reason)
{
case DLL_PROCESS_ATTACH:
//start hook!
hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL,
LowLevelKeyboardProc, hInst, 0);
if(hhkLowLevelKybd == NULL)
printf("hook at process attach failed!\n");
else
printf("hook successful at process attach\n");
break;
case DLL_PROCESS_DETACH:
//break hook!
UnhookWindowsHookEx(hhkLowLevelKybd);
printf("Final: Unhook successful at process detach\n");
break;
/*Are process and thread called allways or is only one of them
called?*/
case DLL_THREAD_ATTACH:
//ignore
printf("DLL_THREAD_ATTACH ignored\n");
break;
case DLL_THREAD_DETACH:
//ignore
printf("DLL_THREAD_DETACH ignored\n");
break;
}
/* Returns TRUE on success, FALSE on failure */
return TRUE;
}
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam)
{
JNIEnv *java;
KBDLLHOOKSTRUCT *p = (KBDLLHOOKSTRUCT *) lParam;
printf("Testin: Low Level Proc calld.\n");
if(javaVM->AttachCurrentThread((void **)&java, NULL) >= 0)
{
switch (wParam)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
{
printf("Testing: Key pressed\n");
jclass cls = (java)->GetObjectClass(parser);
jmethodID mid = (java)->GetMethodID(cls, "processKey", "(I)V");
(java)->CallVoidMethod(parser, mid, p->vkCode);
}
break;
case WM_KEYUP:
case WM_SYSKEYUP:
printf("Testing: Key released\n");
break;
}
}
else
printf("Error: Error on the attach current thread thing!\n");
//return the control to the sytem!
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
/*
Function called by the Java part in order to return the processed key.
*/
JNIEXPORT void JNICALL Java_bkey_KeyParser_parsedKey (JNIEnv *env,
jobject object, jint key)
{
printf("Testing: Java successfuly sent key code to the dll.\n");
}
/*
Function called by the Java part to register itself as the owner and
caller of this library.
This is used to make the library able to call java methods and send the
intercepted keys to be processed.
*/
JNIEXPORT void JNICALL Java_bkey_KeyParser_registerOwner (JNIEnv *env,
jobject object)
{
printf("Testing: Registering dll owner.\n");
parser = env->NewGlobalRef(object);
env->GetJavaVM(&javaVM);
printf("Testing: JavaVM not null: %s\n", (javaVM ? "True" : "False"
));
}