手把手教你實現Java監聽器全域性監控

daditao發表於2014-01-08

http://www.csdn123.com/html/blogs/20130514/12650.htm


1.前段時間,閒來無聊,想做個像QQ截圖一樣的截圖工具,在卻在做的過程中發現java自帶API中的監聽器帶有很大的侷限性,java的滑鼠監聽器只有在滑鼠在程式視窗之上時才會生效,而鍵盤監聽器則更加侷限,只有在當前視窗為焦點視窗時才會生效,這顯然是不符合我們需要效果的,我們所需要的是全域性的鍵盤監聽,不管你在幹什麼,只要觸發我們設定的固定的組合鍵是,就會執行我們需要的功能,所以用java是不太好辦。

2.那麼QQ是怎麼做到的呢?QQ是用C語言寫的,並不是java,而且windows也是C語言寫出來的,所以他能輕易的實現這種全域性監聽。這也就是一個突破口,native,不知道你有沒有注意過這個關鍵字,這是用來呼叫原生程式碼的一個關鍵字。我們可以這樣設想,假如我們將所有的程式碼全部用java實現,卻用C語言去監聽全域性鍵盤,然後返回為我們所用。是不是很有意思。

3.下面我來說明這樣用java程式碼呼叫C語言的方法(函式)。

package test;
public class HelloWorld{
         static{
                 System.loadLibrary("HelloDll");
         }  
         public static void main(String args[]){
                 HelloWorld hw = new HelloWorld();
                 hw.sayHello();
         }
         public native void sayHello();
}

上面這個System.loadLibrary("HelloDll");此句為引入一個叫做HelloDll的本地檔案,而這個必定包含了sayHello();的實現程式碼。java工作我們算是昨晚了,也就是一個簡單的列印HelloWorld的程式碼,重要的是我們怎樣用C語言去實現這個本地方法,怎樣讓其經行工作。

(1).編寫java檔案。上一步已經實現

(2).javac執行原始檔生成class檔案

(3).javah test.HelloWorld 這裡注意不用上帶字尾,我在經行這一步驟時,路徑問題很麻煩。在包這一層執行javah test.HelloWorld就會生成一個叫test_HelloWorld.h的C語言標頭檔案。

因為我們的方法是要用C語言實現的,所以經行到這一步,我們得到了一個C的標頭檔案。如果你開啟這個標頭檔案,你會發現裡面會有一個叫做JNIEXPORT void JNICALL Java_test_HelloWorld_sayHello(JNIEnv *, jobject);的方法,這個方法其實就是我們的java方法在C語言裡邊的對映了(我一般這麼稱呼,不知道對不對),我們只要將這個方法用C語言實現了,然後編譯成一個java能呼叫的DLL本地檔案就OK了。

(4)開啟Microsoft Visual C++,File-->new-->Win32 Dynamic-Link Library,新建一個叫HelloDLL的檔案動態連結工程,點選左下角FileView,點開HelloDll files。然後File-->new-->C/C++ Header File,名字為test_HelloWorld.h,然後點開Header Files裡的test_HelloWorld.h,將我們剛才生成的test_HelloWorld.h檔案內容複製進去,再File-->new-->C++ Source File,名字hello(隨便取),然後點開檔案寫入內容:

#include "test_HelloWorld.h"
#include <iostream.h>
JNIEXPORT void JNICALL Java_test_HelloWorld_sayHello
    (JNIEnv *, jobject){
		cout<<"HelloWorld"<<endl;
}

可以看出,我們生成標頭檔案的目的,無非就是為了用C語言實現,因為我們這裡引入了這個標頭檔案,而這裡邊唯一的一個方法,就是我們生成的標頭檔案,也就是我們的java程式碼未實現的程式碼在C中的對映,然後我在這個方法中列印了HelloWorld這句話。(如果看不懂C程式碼,建議百度一下,就算看不懂,憑我文字描述應該也是能懂一些的,不過應該不會看不懂吧)。

另外就是,這一個段落我寫的比較詳細,甚至比較囉嗦,主要是為了沒用過Microsoft Visual C++或者沒學過C的人,能夠手把手的教他執行這個程式,大神可以略過。

好了,言歸正傳,我們還需引入java的lib環境,Tools-->Options-->Directories在底下的方框欄中加入你C:\PROGRAM FILES\JAVA\JDK1.6.0_04\INCLUDE和C:\PROGRAMFILES\JAVA\JDK1.6.0_04\INCLUDE\WIN32也就是java的JDK的include和include中win32兩個資料夾。然後Build-->Rebuild All。

你會發現,在你C++資料夾HelloDll中Debug中有一個HelloDll.dll檔案。那麼這個檔案就是我們需要的動態連結檔案了。如果你將它開啟,那麼你會發現大部分是亂碼。

(5)將得到的HelloDll.dll複製到你的java工程的包這一層下,然後執行java test.eHelloWorld,就會列印HelloWorld這句話了,如果在沒有這個dll檔案時你就引進執行了,會丟擲一個找不到動態連結檔案的異常。

(6)這樣我們就實現了用java呼叫C語言的方法了。這就是動態連結了,在下一篇我將描述,怎樣用C語言的HHOOK鉤子去獲取windows底層鍵盤和滑鼠的相應。




相關文章