# Global Hotkeys in Java?



## Schusta (2. Mai 2006)

Hi Leute!

Ich arbeite seit einiger Zeit an einem MP3/WAV-Player in Java. Bisher funktioniert alles so wie ich mir das vorstelle, aber jetzt stehe ich ein bisschen ratlos da.

Ich würde gern für meinen Player "Global Hotkeys" verwenden. Manche kennen das vielleicht aus Winamp. Auf jeden Fall soll wenn ich zB meinen Webbrowser offen habe und ich STRG+PFEIL_NACH_RECHTS drücke mein Player anfängt das File abzuspielen. 

Ich denke das zu verwirklichen ist nur unter der Verwendung von Java nicht möglich, aber ich habe gehört, dass es mit einer C++-DLL die mit dem Javaprogramm kommuniziert funktionieren soll. 

Leider hab ich nur spärliche Erfahrung in C++ und weiß nicht wie ich das bewerkstelligen soll. Deshalb wäre meine Frage ob das schonmal jemand gemacht hat oder ob jemand evtl. Tipps hat wie ich das machen soll.

Falls der Thread eher ins C++-Forum passt, wäre es net wenn ihn ein Mod verschieben könnte.

Besten Dank schonmal im Vorraus und fG,

Schusta


----------



## flashray (3. Mai 2006)

Hallo Schusta,

Programmweite Hotkeys sind in Java möglich. D.h. solange die Applikation den Fokus hat wird es jegliche gesetze Shortcuts empfangen.

Siehe hierzu:
http://www.tutorials.de/forum/java/242472-abbruch-mit-escape.html

Weiterhin besteht die Möglichkeit, eine Java Applikation mit Dateitypen zu assoziieren, sodass bei doppelklick auf eine Datei dieser Formate die Javaanwendung startet. Hier beispielsweise mit wav und mp3.

Siehe hierzu:
https://jdic.dev.java.net/
https://jdic.dev.java.net/documentation/Examples.html


Systemweite Hotkeys kann man wie schon von dir erwähnt mit java nicht setzen.
Wenn man bei MSDN nach "hotkey" sucht, findet man zwar viele Artikel und Doku dazu. Allerdings kenne ich mich weder mit c/c++/visualbasic noch JNI aus.
http://msdn1.microsoft.com/en-us/default.aspx


Vg Erdal


----------



## flashray (3. Mai 2006)

Hier noch ein deutschsprachiger Artikel:

Systemweite Hotkeys mit Visual Basic 5/6 erzeugen und verwenden
http://www.microsoft.com/germany/ms...sualBasic56ErzeugenUndVerwenden.mspx?mfr=true

Auch dabei ist ein vollständiger Beispielcode.

Könnte vielleicht jemand hier aus dem Forum eine Java Klasse implementieren welche dieses Visual Basic Script aufrufen kann. Auch sollte die Hotkey Kombination nicht fest im Basic Code sein, sondern möglichst von der Java Klasse aus als Parameter übergeben werden können. Vielleicht liest der Weihnachtsmann auch im Forum mit  , und er postet die Lösung, wenn wir bis zum Ende des Jahres brav bleiben ^^ .


Vg Erdal


----------



## Benain (2. Juli 2006)

Falls das Problem noch besteht, kann ich auch weiterhelfen. Dann bitte nochmal fragen.


----------



## RealHAZZARD (3. Juli 2006)

Betrachte diesen Beitrag als Nachfrage
THX


----------



## Benain (3. Juli 2006)

Wo hakt es denn?  
Im Prinzip ist die Idee mit der C++-Bibliothek richtig. 
Grundlegend ist die Kommunikation Java->C++(JNI)->Java(JNI) nötig. Ich habe mal in ein eigenes Javaprojekt Global Hotkeys eingebaut; allerdings noch rudimentär. Das ist sicherlich noch verbesserungswürdig, da ich die Tasten vorher festgelegt habe und das Ganze somit ohne Parameterübergabe gemacht habe (wollte mich da bei JNI nicht zusätzlich noch damit belasten).


----------



## javaprogger1987 (3. Juli 2006)

Hey das ist interessant - nach dem Thread hatte ich das ganze auch mal versucht, allerdings habe ich es nicht geschafft einen Aufruf einer Java Methode von C++ aus zu machen, da ich kein Handle auf ein JNIEnv habe..
Würde mich echt brennend interessieren wie du das gelöst hast 

Gruß
Tobias

P.S. Wenn du willst kann ich dir auch mal meinen bisherigen Code schicken, hab auch schon so Sachen wie Shift Alt etc. prinzipiell implementiert..


----------



## Benain (3. Juli 2006)

Thema Rückkommunikation:
Ja, das ist ein wenig knifflig. Bei mir ist das gelöst dadurch, dass ich ein und dasselbe Objekt genommen habe. Sprich ein Javaobjekt kommuniziert zu C++ über JNI und aktiviert die Global Hotkeys. Und genau zu diesem Objekt wird später die Rückverbindung wieder über JNI gebaut. 

Dazu ein wenig Codegeschnipsel:

- In meinem C++ - Code gibt es eine native Methode namens OnLoad. Selbige wird automatisch aufgerufen, wenn ich die DLL später in Java einbinde. Dort wird ein Verweis auf die aktuelle Java Virtual Machine gesichert. 

- Es gibt in meiner Javaklasse eine native Methode, die die Global Hotkeys aktiviert. In der entsprechenden C++-Methode wird die Referenz der Klasse, welche die Aktivierung durchführt, also ein Objekt, gesichert, ebenso die Methode, welche der Global Hotkey in dem Javaobjekt aufrufen soll. Es gibt also in diesem Fall eine Methode in meiner Javaklasse namens hotkey_F1().

- In meinem C++ - Code gibt es auch eine Methode, namens hotkey_F1 (hätte sie vermutlich zur Besseren Unterscheidung zu der Methode in der Javaklasse unterschiedlich benennen sollen). Selbige soll aufgerufen werden, wenn der Hotkey gedrückt wird. Das ist dann in C++ zu regeln. 
Diese Methode muss dann dem aktuell laufenden Thread der JVM (die in OnLoad gesichert wurde) zugeordnet werden (mit AttachCurrentThread). Das war es dann im Prinzip. Beim Drücken des Global Hotkeys wird dann hotkey_F1 in C++ ausgeführt und selbige ruft dann in meinem Javaobjekt die Methode auf, die sich hinter hk_F1 verbirgt. 

JavaVM * jvm = NULL;
jobject guiObj;
jmethodID hk_F1;

void hotkey_F1(void *)
{	
   JNIEnv * env;

    if (jvm->AttachCurrentThread((void **)&env, NULL) < 0) {
        printf("Error AttachCurrentThread\n");
        return;
    }
    env->CallVoidMethod(guiObj, hk_F1);
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM * _jvm, void * reserved) {
	jvm = _jvm;
	return JNI_VERSION_1_4;
}

JNIEXPORT void JNICALL Java_gui_Gui_activateGlobalHotkeys
(JNIEnv * env, jobject obj) {
	guiObj = env->NewGlobalRef(obj);
	hk_F1 = env->GetMethodID(env->GetObjectClass(obj), "hotkey_F1", "()V");
        ........
}

Deinen Code würde ich natürlich gerne sehen


----------



## javaprogger1987 (4. Juli 2006)

Ja.. also erstmal vielen Dank für den Tipp 
Allerdings konnte ich ihn noch nicht ganz testen, weil jetzt was anderes nicht mehr klappt 
Ich hatte vorher 2 DLL's, eine JNI Dll und diese hat noch eine Keyhook DLL geladen..
Da deine Version allerdings nicht mit 2 Dll zu klappen scheint, hab ich das einfach mal alles in eine DLL reingestrickt..
Nun hab ich aber das Problem, das nach dem Aufruf 
	
	
	



```
System.loadLibrary("jni_keyhook");
```
 die DLLMain der Methode nicht aufgerufen wird - Problem bestand vorher nicht, da der Aufruf in der DLL war..  (Und die hat die DLLMAin der keyhook-DLL aufgerufen)..
Kann das an meinem Linker liegen? (mingw).. Hab mir das mal angeguckt und der übergibt dem Linker (genauer dlltool) immer 
	
	
	



```
--exclude-symbol=DllMainCRTStartup@12
```
.. Ich vermute mal das liegt daran, krieg das aber nicht abgestellt da der das intern irgendwie macht -.-

Aber nun zu meiner Keyhook Methode - die leider im Moment halt nicht klappt:

```
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 
{ 
    CHAR szBuf[128]; 
    size_t cch; 
    size_t * pcch;
    HRESULT hResult;
 
    WORD wLHigh = (WORD) (lParam >> 16);
    BOOL fReleasedKey = wLHigh & KF_UP; //aequivalent zu lParam & 0x80000000
    BOOL fAltDown = wLHigh & KF_ALTDOWN; // lParam & (KF_ALTDOWN << 16)
    BOOL fLCtrlDown = GetKeyState( VK_LCONTROL ) & 0x8000;
    BOOL fRCtrlDown = GetKeyState( VK_RCONTROL ) & 0x8000;
    BOOL fLShiftDown = GetKeyState( VK_LSHIFT ) & 0x8000;
    BOOL fRShiftDown = GetKeyState( VK_RSHIFT ) & 0x8000;    
    BOOL fTabDown = GetKeyState( VK_TAB ) & 0x8000;
    BOOL fLWinDown = GetKeyState( VK_LWIN ) & 0x8000;
    BOOL fRWinDown = GetKeyState( VK_RWIN ) & 0x8000;

    if (nCode < 0)  //Message nicht verarbeiten
        return CallNextHookEx(g_hKeyHook, nCode, wParam, lParam);

    if ( IsModifier( wParam ) ) //Event einer Modifiertaste (Alt, Shift, Ctrl...)
        return CallNextHookEx(g_hKeyHook, nCode, wParam, lParam);
 
    if ( fReleasedKey ) // Taste wurde losgelassen - für Hotkeys uninteressant
    {
        c = 0;
        //MessageBox(NULL, "Taste losgelassen!", "Out", MB_OK);
        return CallNextHookEx(g_hKeyHook, nCode, wParam, lParam);
    }

    hResult = sprintf(szBuf, "%d ", wParam);
    c++;
    if (FAILED(hResult))
    {
       MessageBox(NULL, "FAIL1!", "Out", MB_OK);
    }
    hResult = sizeof(szBuf, 128/sizeof(TCHAR), pcch);
    if (FAILED(hResult))
    {
       MessageBox(NULL, "FAIL2!", "Out", MB_OK);
    }
    if (c == 1) //Nur wenn Taste zum erstenmal gedrueckt wurde reagieren
    {
         //MessageBox(NULL, "ou", "ou", MB_OK);
         
         JavaVMAttachArgs args;
         args.version= JNI_VERSION_1_4;
         args.name="user";
         args.group=NULL;
         
         jint res = javavm->AttachCurrentThread( (void**)&jniEnv, &args );
   
         if ( res <= 0)
           MessageBox(NULL, "Out", "Fehler", MB_OK);

         //res = (*javavm)->GetEnv( javavm, (void**)&jniEnv, JNI_VERSION_1_2 );
         jclass jclazz;
         jmethodID mId;
         jclazz = jniEnv->GetObjectClass( globClass );
         mId = jniEnv->GetMethodID( jclazz, "jniActionPerformed", "(III)V" );
         jniEnv->CallVoidMethod( globClass, mId, (jint) 10, (jint)0, (jint)0 );

         if ( res != JNI_OK)
           MessageBox(NULL, "Out", "Fehler", MB_OK);

//         Call();
         javavm->DetachCurrentThread();
    }
      
    return CallNextHookEx(g_hKeyHook, nCode, wParam, lParam);
}
```

Ist halt geplant an jniActionPerformed Keycode und Shiftstate etc zu übergeben, aber kann das leider nicht testen, da der den Keyhook nicht richtig macht..
(Da ich halt kein hModule Handle hab - da DLLMain nicht aufgerufen wird - mahc ich das so, klappt aber nicht - er macht keinen Fehler aber die Callback Methode wird nie aufgerufen)

```
g_hKeyHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle(NULL), 0);
```

Gruß
Tobias


----------



## Benain (6. Juli 2006)

Hmm, so ganz verstehe ich glaube ich das Problem noch nicht. Wieso geht das denn nicht, wenn Du alles in einer DLL hast. Du müsstest doch alles aufrufen können, was Du willst. 

Meine Lösung integrierte übrigens eine Klasse, die ich irgendwo mal gefunden hatte, die mir in C++ ein Fenster generierte und dort die Hotkeys registrierte. Ich hab sieh einfach dann adaptiert und für mich so in meine dll eingebaut, dass alles funktionierte. Wenn Interesse an den Klassen besteht, lasse ich sie auch gerne mal zukommen. Falls Du Visual Studio nutzt auch gerne als komplettes Projekt.


----------



## javaprogger1987 (6. Juli 2006)

Also ich weiß selber nicht genau wo das Problem liegt..
Die Registrierung des Hooks klappt halt ohne Fehler, allerdings wird die Callback Methode nicht aufgerufen...

Ich vermute nun, dass es an der Art liegt, wie ich den Hook registriere 
	
	
	



```
#include "dll.h"
#include "keyhook_HotKeyManager.h"

//HINSTANCE hDll = NULL;
HHOOK g_hKeyHook SHARED = NULL;    // Handle unseres Hooks (als "shared" Deklariert)
HINSTANCE g_hInst SHARED = NULL;     // Handle der DLL selbst
JavaVM *javavm = NULL;
JNIEnv *jniEnv = NULL;
int hotkeyCount = 0;
jobject globClass;
jmethodID action;

BOOL APIENTRY DllMain( HINSTANCE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved)
{
    switch (ul_reason_for_call)
            {
                case DLL_PROCESS_ATTACH:
                    g_hInst = hModule;
                     break;
                case DLL_THREAD_ATTACH:
                    break;
                case DLL_THREAD_DETACH:
                    break;
                case DLL_PROCESS_DETACH:
                    break;
            }
    return TRUE;
}

BOOL InstallHook( int nrOfHotkeys, JavaVM *vm, jobject clazz )
{
    //Werte sichern
    hotkeyCount = nrOfHotkeys;

    //MessageBox(NULL, "Install!", "Out", MB_OK);
    if(g_hKeyHook != NULL)
        return TRUE;

    g_hKeyHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle(NULL), 0);
    
    if(g_hKeyHook == NULL)
        return FALSE;
        
    return TRUE;
}

BOOL UninstallHook()
{
    if(g_hKeyHook != NULL)
    {
        UnhookWindowsHookEx(g_hKeyHook);
        g_hKeyHook = NULL;
    }
    return TRUE;
}

BOOL IsModifier ( WPARAM wParam )
{
     switch ( (WORD) wParam )
     {
            case VK_RETURN: return TRUE;
            case VK_CONTROL: return TRUE;
            case VK_SHIFT: return TRUE;
            case VK_MENU: return TRUE;
            case VK_LCONTROL: return TRUE;
            case VK_RCONTROL: return TRUE;
            case VK_LSHIFT: return TRUE;
            case VK_RSHIFT: return TRUE;
            case VK_TAB: return TRUE;
            case VK_LWIN: return TRUE;
            case VK_RWIN: return TRUE;
     }
     return FALSE;
}

JNIEXPORT jboolean JNICALL Java_keyhook_HotKeyManager_installHook
  (JNIEnv *env, jobject clazz, jint nrOfHooks)
  {
          globClass = env->NewGlobalRef( clazz );
          action = env->GetMethodID( env->GetObjectClass( clazz ), "jniActionPerformed", "(III)V" );
          return (jboolean) InstallHook( (int)nrOfHooks, javavm, globClass );
  }


JNIEXPORT jboolean JNICALL Java_keyhook_HotKeyManager_uninstallHook
  (JNIEnv *env, jobject clazz)
  {      
         bool ret = UninstallHook();
         return (jboolean) ret;
  }

jint JNI_OnLoad
  (JavaVM *vm, void *reserved)
  {
         javavm = vm;
         return JNI_VERSION_1_4;
  }
```

Ich glaube halt das 
	
	
	



```
g_hKeyHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle(NULL), 0);
```
 nicht richtig funktioniert, ich würde auch als 3.ten Parameter den Habdle nehmen der der DLLMain übergeben wird, die wird aber gar nicht erst aufgerufen..
Was hast du denn als 3.ten Parameter?

Wäre echt gut wenn du mir mal deine Klassen zeigen könntest..
Wenn du das nicht posten möchtest: tobias.viehweger@gmx.de

Gruß
Tobias


----------



## Thomas Darimont (6. Juli 2006)

Hallo!

Also ich würde das so machen:

```
/**
 * 
 */
package de.tutorials;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * @author Tom
 * 
 */
public class GlobalHotKeyExample {

    static {
        System.loadLibrary("globalHotKeySupport");
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        registerGlobalHotKeyListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                EventQueue.invokeLater(new Runnable() {
                    public void run() {
                        System.out.println("Global hotkey was pressed: " + e);
                        // hier die Swing UI Manipulieren...
                    }
                });
            }
        });
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    private static native void registerGlobalHotKeyListener(
            ActionListener listener);
}
```

und meine globalHotKeySupport.dll schaut so aus:

```
// globalHotKeySupport.cpp : Definiert den Einstiegspunkt für die DLL-Anwendung.
//

#include "stdafx.h"
#include <iostream>
#include "de_tutorials_GlobalHotKeyExample.h"

using namespace std;


jobject hotKeyListener;
JNIEnv *jniEnv;

/*
 * Class:     de_tutorials_GlobalHotKeyExample
 * Method:    registerGlobalHotKeyListener
 * Signature: (Ljava/awt/event/ActionListener;)V
 */
JNIEXPORT void JNICALL Java_de_tutorials_GlobalHotKeyExample_registerGlobalHotKeyListener
(JNIEnv *env, jclass clazz, jobject listener){
	cout << "test" << endl;
	hotKeyListener = listener;
	jniEnv = env;
	//Das hier in losfeuern, wenn der Hotkey betätigt wurde... -> in andere Funktion verschieben.
	/*
	jclass actionListenerClass = jniEnv->FindClass("java/awt/event/ActionListener");
	jmethodID actionPerformedMethodId = jniEnv->GetMethodID(actionListenerClass ,"actionPerformed","(Ljava/awt/event/ActionEvent;)V");
	jniEnv->CallObjectMethod(listener,actionPerformedMethodId,NULL); // hier entsprechendes java.awt.event.ActionEvent bauen und dies dann statt NULL übergeben...
	*/
}

  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved){
    cout << "JNI_OnLoad" << endl;
//hier Global Hot Key registrieren, beispielsweise über einen Systemweiten Hook
      return JNI_VERSION_1_4;
  }
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}
```

Gruß Tom


----------



## d3x (25. Juni 2007)

Hallo zusammen,
ich suche auch schon eine Weile nach einer Lösung für dieses Problem, leider hab ich von C++ keine Ahnung und weiß nicht wie ich mir aus dem Code eine DLL bauen könnte?! :-/
Kann mir jemand vielleicht die DLL schicken, oder einen Link posten, wo ich sie runterladen kann?

Danke im Vorraus
Gruss
d3x


----------



## tobias_petry (25. Juni 2007)

interessant wäre, ob gloable hotkeys auch in linux oder mac möglich sind
weiß das zufällig einer?
weil man findet nur ansätze für windows, aber linux oder mac nie


----------



## d3x (25. Juni 2007)

Ich habe jetzt mal versucht, den obigen Code mit Visual C++ 2005 Express Edition selber zu  compilen, aber ic bekomme folgenden Fehler, irgendwas fehlt wohl noch. Aber ich weiß nicht was oder woher ich es nehmen sollte:
1>..\..\..\..\..\workspace\DLLTest\GlobalHotKeySupport.cpp(3) : fatal error C1083: Datei (Include) kann nicht geöffnet werden: "de_tutorials_GlobalHotKeyExample.h": No such file or directory

Kann mir da jemand weiterhelfen?

Gruss
d3x


----------



## HansWernerM (25. Juni 2007)

Habe da gestern (Internet FH München) was von  "Keymap" gelesen.
Dies betrifft aber glaube ich nur die zentrale Definiton für Tastaturkürzel in Menüs.


----------



## d3x (29. Juni 2007)

Scheint wohl keiner mehr dieses DLL zu haben, oder?


----------



## Flo<H> (29. Juni 2007)

@d3x:
Was dir fehlt ist die Header-Datei von der C++ Datei. Die sollte man aber relativ einfach selber schreiben können, dadarin meines Wissens nur die Signaturen der Methoden stehen. Bin mir da aber nicht 100% sicher, da ich mit C++ bisher eher weniger gemacht hab.
mfg flo

Edit:
Ok, ganz so einfach scheints dann doch nicht zu sein. Hab grad gelesen, dass die Header-Datei mit dem Tool javah erstellt werden muss. In Zukunft informier ich mich lieber vorher, bevor ich irgendwelche Vermutungen anstelle


----------



## d3x (30. Juni 2007)

=)

Mir gehts ähnlich, ich hab von C++ überhaupt keine Ahnung... Aber da wohl keiner mehr diese DLL hat, oder die header Datei werde ich wohl auf die globalen Shortcuts verzichten müssen.
Vielleicht kommt das ja irgendwann für JAVA ^^

Danke und Grüsse
d3x


----------



## tobias_petry (30. Juni 2007)

d3x hat gesagt.:


> Vielleicht kommt das ja irgendwann für JAVA ^^



hmm, da ein neues Java nur alle 18 Monate kommt und Java 6 erst kam, wirst du wohl noch ewig warten müssen, wenn man mal Dokus über globale Shortcuts für Linux und Mac finden würde, könnte man ja mal nen Jar bauen, was weitestgehend "platformunabhängig" läuft, aber auf den Platformen ist das scheinbar nicht möglich :-(


----------



## Billie (23. April 2008)

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?


```
// 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;
}
```


----------



## zeja (23. April 2008)

Auf der ersten Seite finden sich doch Beispiele wie man eine Java-Methode aufruft.

AttachCurrentThread und CallxxxMethod


----------



## JUsername (23. April 2008)

Du könnest Dir ja mal JIntellitype (http://melloware.com/products/jintellitype/index.html) anschauen.


----------



## Billie (24. April 2008)

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:


```
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


----------



## Billie (24. April 2008)

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

An dieser Stelle:

```
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:

```
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?!


----------



## Billie (24. April 2008)

Ok, JVM ist nicht mehr NULL durch folgende Definitionen:


```
#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


```
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.


----------

