Global Hotkeys in Java?

Ok, ich konnte das Beispiel jetzt so weit ausarbeiten, dass von Java aus die DLL geladen wird und der Systemweite-Hook gesetzt wird.

Jetzt stehe ich aber vor folgendem Problem: Die Callback-Funktion sollte ja die native Methode von Java anstoßen. Dazu benötigte ich aber vor allem einen Pointer auf ein JNIEnv-Objekt. Woher nehmen wenn nicht stehlen?!

Wenn die JVM die DLL lädt und JNI_OnLoad aufruft übergibt sie ja einen Pointer auf ein JavaVM-Objekt. Bekomm ich daraus irgendwie einen gültigen Pointer auf ein JNIEnv-Objekt, den ich mir merken kann und welchen dann die Callback-Funktion zum Aufruf der nativen Methode verwenden kann?

C:
// dllmain.cpp : Definiert den Einstiegspunkt für die DLL-Anwendung.
#include "stdafx.h"

HMODULE hmodDLL = NULL;
HHOOK hKeyboardHook = NULL;
JNIEnv *jniEnv;

LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
	// TODO: call addGlobalKeyListener(JNIEnv *env, jclass clazz, jobject listener)
	return CallNextHookEx(hKeyboardHook, code, wParam, lParam);
}

JNIEXPORT void JNICALL Java_at_co_arz_test_hook_HookExample_addGlobalKeyListener(JNIEnv *env, jclass clazz, jobject listener)
{
	// From where I get a valid pointer to JNIEnv?
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
	hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) KeyboardProc, hmodDLL, 0);
	return JNI_VERSION_1_4;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	hmodDLL = hModule;
	return TRUE;
}
 
Auf der ersten Seite finden sich doch Beispiele wie man eine Java-Methode aufruft.

AttachCurrentThread und CallxxxMethod
 
Hellas,

also grundsätzlich geht es mir gar nicht um globale Hotkeys... Aber um die Tastaturereignisse. Ich bin jetzt auch auf einen sehr interessanten Link gestoßen http://www.jotschi.de/?p=90.

Ich persönlich habe aber gerade das Problem, bei folgender Anweisung irgendetwas schief läuft:

C:
jvm->AttachCurrentThread((void **)&env, NULL);

Nach dieser Anweisung ist irgendwie einfach schluss. Ich bekomme keinen Rückgabewert und der try-catch-Zweig wird nie erreicht.

Bin jetzt aber noch dran, aber für nützliche Hinweise immer offen.

lg Billie
 
Ok, die vorher genannte Anweisung ist fehlgeschlagen, weil der JavaVM Pointer NULL ist... Nur warum?!

An dieser Stelle:
C:
JNIEXPORT void JNICALL Java_at_co_arz_test_hook_HookExample_addGlobalKeyListener(JNIEnv *env, jclass clazz, jobject obj)
{
	if(hKeyboardHook == NULL) {
		hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) KeyboardProc, hModule, 0);
	}
	env->GetJavaVM(&jvm);

Wird der Pointer gesetzt und ist != NULL. Dann, in der Callback-Funktion von Windows:
C:
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	JNIEnv *env;		

	if(jvm == NULL) {
		MessageBoxA(NULL, (LPCSTR) "Don't have a JVM reference.", "Test", MB_ICONERROR);
	}

Ist der Verweis auf einmal NULL... Jemand eine Ahnung, warum?!
 
Ok, JVM ist nicht mehr NULL durch folgende Definitionen:

C:
#pragma data_seg("HOOKDATA") 
HMODULE hModule = NULL;
HHOOK hKeyboardHook = NULL;
JavaVM *jvm = NULL;
#pragma data_seg()  
#pragma comment(linker, "/SECTION:HOOKDATA,RWS"

Was muss alles als DataSegment definiert werden? Es besteht aber trotzdem das Problem, dass mir das ganze beim Aufruf von

C:
jvm->AttachCurrentThread((void **)&env, NULL);

abschmiert. Ich bekomme auf einmal ein DLL_PROCESS_DETACH. Die Java-Anwendung läuft weiter bis ich sie auch beende und dann kommt nocheinmal DLL_PROCESS_DETACH.
 
Zurück