上個星期在Sourceforge的Feeling項目下新增加了一個org.eclipse.swt.extension子項目,意在增強SWT的本機功能。我一向是SWT的Fans,不過卻很抵觸大型的RCP項目,喜歡only dependent SWT。經過一個星期的努力,現在已經整合了在Win32平臺下獲取系統、磁盤、內存、CPU相關信息,注冊表,以及系統鉤子等功能,喜歡SWT的朋友可以試用。目前還沒有放出一個版本,請通過sf的CVS下載代碼:
cvs -d:pserver:anonymous@feeling.cvs.sourceforge.net:/cvsroot/feeling login
由于一直使用的都是Java,對Win32編程并不是非常熟悉。但局限于Java的功能,對我們有相當大的限制,IBM就屢屢向突破這個限制,因此產生了SWT。這里我重點想說的是怎么使用Win32的系統鉤子。SWT里已經包含了大量的Win32函數,不過那都是局限于Eclipse的需要,如果Eclipse不需要,SWT是不予以優先考慮的。通過SWT我們很容易使用線程鉤子監控自己程序的鍵盤鼠標事件,而且封裝的很好。但是想使用系統鉤子確是一件不可能的事情,先看看鉤子的函數原型:
?HHOOK?SetWindowsHookEx(?int??idHook,?HOOKPROC?lpfn,?HINSTANCE?hMod,?DWORD?dwThreadId);?
idHook -- 系統鉤子類型,實際上是一個int值,具體的定義請看MSDN
lpfn -- 鉤子回調函數指針,當收到鉤子消息時就執行這個回調函數,回調函數有3個參數,不同類型的鉤子這3個參數有不同的含義,具體請看MSDN。
hMod -- DLL實例句柄(我猜是這樣,我不熟悉Win32API編程),當鉤子為系統鉤子時這個參數是必須的,如果是單個程序或者線程使用的鉤子那么可以不用這個值。
dwThreadId -- 線程ID,如果是單個程序或者線程使用的鉤子這個參數是必須的。
在SWT生成的DLL中,并沒有系統鉤子必須用到的hMod,并不像一般的DLL有DllMain入口可以接受到DLL實例句柄。因此我們只要在JNI下的C代碼里添加這個DLL實例句柄就可以完成系統鉤子的功能了:
#define?Dll_Export?__declspec(dllexport)

HINSTANCE?instance?=?NULL;

BOOL?APIENTRY?DllMain(HINSTANCE?hInstance,?DWORD??ul_reason_for_call,?LPVOID?lpReserved)


{
????instance?=?hInstance;
????return?TRUE;
}

Dll_Export?HHOOK?SetHook(int?hookType,HOOKPROC?hookproc)


{
????return?SetWindowsHookEx(hookType,?hookproc,?instance,?NULL);
}

Dll_Export?BOOL?UnHook(HHOOK?hook)


{
????if(hook?!=?NULL)
????????return?UnhookWindowsHookEx(hook);
????else
????????return?0;
}

#ifndef?NO_SetSystemHook
JNIEXPORT?jint?JNICALL?Swt_extension_NATIVE(SetSystemHook)
????(JNIEnv?*env,?jclass?that,?jint?arg0,?jint?arg1)


{
????jint?rc?=?0;
????rc?=?(jint)SetHook(arg0,?(HOOKPROC)arg1);
????return?rc;
}
#endif

#ifndef?NO_UnSystemHook
JNIEXPORT?jboolean?JNICALL?Swt_extension_NATIVE(UnSystemHook)
????(JNIEnv?*env,?jclass?that,?jint?arg0)


{
????jboolean?rc?=?0;
????rc?=?(jboolean)UnHook((HHOOK)arg0);
????return?rc;
}
#endif那么通過SWT來實現系統鉤子有多大難度呢?各位看看代碼就知道了:
Callback?callback?=?new?Callback?(this,?"keyHook",?3);?//$NON-NLS-1$
int?proc?=?callback.getAddress?();
hook?=?Extension.SetSystemHook(13,?proc);

………………………………

int?keyHook(int?nCode,int?wParam,int?lParam)


{
????int?Result=OS.CallNextHookEx(hook,nCode,wParam,lParam);
????………………
????return?Result;
}
很簡單吧^_^