2012-04-06 79 views
0

我一直試圖使用JNI實現簡單的低級別keyhook,一切都很順利我想我無法在DLL在無限循環(消息循環)時調用方法。所以我決定創建新的線程,但不知何故,我做了它之後,消息循環運行在它自己的循環中,低級別keyhook停止響應,意味着它不再調用keyproc,我不知道這是爲什麼?有沒有其他的解決方法呢?我需要能夠在鍵盤掛鉤仍在運行時調用DLL的方法。WINAPI的消息循環驅使我瘋狂

我當前的代碼很簡單,只要

寄存器鍵盤鉤子:

keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardProc, hInstance, 0); 

啓動線程

HANDLE threadHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, &threadId); 

我的鍵盤proc和ThreadProc的有以下幾種:

DWORD WINAPI ThreadProc(LPVOID lpVoid) { 
    MSG msg; 
    while(GetMessage(&msg, NULL, 0, 0)) { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
    return 0; 
} 

LRESULT CALLBACK keyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { 
    KBDLLHOOKSTRUCT keyEvent = *((KBDLLHOOKSTRUCT*)lParam); 
    jint vkCode = keyEvent.vkCode; 
    jint flags = keyEvent.flags; 
    jint action = wParam; 
    (*globalEnv).CallVoidMethod(globalObj, keyboardMethodId, vkCode, flags, action); 
    return CallNextHookEx(NULL, nCode, wParam, lParam); 
} 

我該在哪裏出錯? 即使我爲從未調用的keyproc添加簡單日誌記錄,我也確信它不是java。但是,如果我停止使用線程並在主線程上運行消息循環,它將正常工作,但DLL不會響應之後的方法調用。

+0

http://stackoverflow.com/questions/617248/can-the-hwnd-from-createwindow-createdialog-be-getmessaged-from-another-thread – JosephH 2012-04-06 15:05:59

回答

2

您需要在調用SetWindowsHookEx()的同一個線程上抽取消息循環。所以把這個調用移動到你的ThreadProc()。當然,要注意你的CallVoidMethod()回調函數在同一個線程上運行,所以要小心你在那個函數中做了什麼。您訪問的任何共享狀態都需要使用鎖來保護。

+0

你在那裏提出了一些有效的觀點。我會在那裏打電話試試看!鎖只是爲了確保兩個線程沒有併發訪問來搞亂一些數據? – Ruuhkis 2012-04-06 15:25:01

+0

謝謝,你解決了我的問題! :) – Ruuhkis 2012-04-06 15:34:35

1

您正在嘗試安裝跨桌面所有進程的桌面範圍掛鉤。也就是說,您的DLL被映射到幾個具有特定進程集的全局變量的進程。您在其他進程中沒有有效的globalEnv,並且您可能會遇到訪問衝突或類似錯誤(全局變量可以使用共享數據段創建,請參閱this article for details)。

要安裝線程特定的鉤子,您需要一個不同類型的鉤子(WH_KEYBOARD_LL是全局唯一的!)和SetWindowsHookEx中的非零最後一個參數。

+0

這正是我想要的,我需要dektop寬掛鉤附加快捷鍵等,它運作良好,直到我試圖運行外部線程上的消息循環,它甚至有可能嗎?我只需要在掛鉤後能夠響應我的方法調用。 – Ruuhkis 2012-04-06 15:10:45

+0

那麼你的'globalEnv'是什麼? – 2012-04-06 15:14:55

+0

Java環境對象:P – Ruuhkis 2012-04-06 15:24:01