2011-01-13 22 views
7

私は、USBデバイスと通信するJavaで簡単なアプリケーションを作成しようとしています。 USBデバイスは、マイクロチップマイクロコントローラを使用して私によって作られています。 USBデバイスはHIDクラスのものであるため、通信はかなり簡単です。コンピュータとデバイスの間で64バイトの配列が交換されます。 私のプログラムは、製品IDとベンダーIDに基づいてデバイスを検出し、64バイトの書き込みと読み取りが可能ですが、デバイスがコンピュータに接続または切断されたときに検出したいと考えています。JAVA JNA WindowProcの実装

サンプルアプリケーションとしてマイクロチップが提供するC#プログラムで見たように、WndProcメソッドはオーバーライドされ、WM_DEVICECHANGEメッセージが処理されます。私の質問は、JNAを使ってJavaでこれをどうやって行うことができるのか、どうすればWindowProcメソッドをオーバーライドしてメッセージを処理することができるのでしょうか?:) D

お返事ありがとう。

ガボール。

+0

あなたが使用したコードを投稿してください。ありがとう。 –

+0

私は1つの質問があります、あなたはRegisterDeviceNotificationのようなものを使用する必要はありませんか、WindowsがWM_DEVICECHANGEを自動的にブロードキャストするポートデバイスを探していますか? –

答えて

1

C#プログラムのCOM DLLまたはOCXを作成し、それをJavaコードで使用することができます。アプリケーションを作成する場合。

使用JACOB OR JCOM

これは、JavaとCOMオブジェクトの間のブリッジになります。他のオプションはJNIを使​​用してDLLとOCXと通信できることです。

+0

私はWM_DEVICECHANGEについてのアイデアを得ていないので、C#コードを実際に使用したくないので、答えをありがとうが、別のオプションはありません。例えば、JNAのKernel32クラスを通して、私はUSBデバイスへの読み書きのためのReadFileとWriteFileメソッドにアクセスしました。ありがとう。 – Gabor

8

私は最終的に問題を解決するために管理:)そして、私は、次の解決策が見つかりました:

最初に次に、WindowsメッセージコードをWinUserインターフェイスを拡張し、次のよう

public interface MyUser32 extends User32 { 

    public static final MyUser32 MYINSTANCE = (MyUser32) Native.loadLibrary("user32", MyUser32.class, W32APIOptions.UNICODE_OPTIONS); 

    /** 
    * Sets a new address for the window procedure (value to be set). 
    */ 
    public static final int GWLP_WNDPROC = -4; 

    /** 
    * Changes an attribute of the specified window 
    * @param hWnd  A handle to the window 
    * @param nIndex  The zero-based offset to the value to be set. 
    * @param callback The callback function for the value to be set. 
    */ 
    public int SetWindowLong(WinDef.HWND hWnd, int nIndex, Callback callback); 
} 

でのUSER32インターフェースを拡張しますあなたが必要とする、私の場合、これはWM_DEVICECHANGEです。なぜなら私はUSBデバイスがコンピュータに接続されているか、コンピュータから切り離されているかをチェックしたいからです。

public interface MyWinUser extends WinUser { 
    /** 
    * Notifies an application of a change to the hardware configuration of a device or the computer. 
    */ 
    public static final int WM_DEVICECHANGE = 0x0219; 
} 

次に、実際には私のWndProc関数であるコールバック関数を使用してインターフェイスを作成します。

//Create the callback interface 
public interface MyListener extends StdCallCallback { 

    public LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam); 
} 

public MyListener listener = new MyListener() 
{ 
    public LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam) 
    { 
     if (uMsg == MyWinUser.WM_DEVICECHANGE) 
     { 
      // TODO Check If my device was attached or detached 
      return new LRESULT(1); 
     } 
     return new LRESULT(0); 
    } 
}; 

そしてどこかにあなたは物事がのSetWindowLong関数でウィンドウプロシージャのための新しいアドレスを追加する初期化したJFrameのコードで:

// Get Handle to current window 
    HWND hWnd = new HWND(); 
    hWnd.setPointer(Native.getWindowPointer(this)); 

    MyUser32.MYINSTANCE.SetWindowLong(hWnd, MyUser32.GWLP_WNDPROC, listener); 

このコードはうまく動作しますが、私はいくつかの疑問を持っています一つの事に関して。コールバック関数の戻り値が正しいかどうかはわかりません。私は、WM_DEVICECHANGEメッセージを処理した後、コールバック関数がtrueを返す必要があり、私が現在返す値がシステムによって予期されている値であるとは確信していないので、提案はすべて歓迎されています。

誰もが全体のコードに興味があるなら、私はちょうど私が:)

乾杯、 ガボールを支援するよりも幸せだろう、頼むHID通信のために書かれました。私は以前に掲載

+2

結果を共有していただきありがとうございます – mtraut

+0

MyListenerがもう存在しないので、カスタムコールバックインターフェイスを作成する必要はありません。 JNAはWinUser.WindowProcインターフェイスを提供します。 – Sundae

1

解決策は、残念ながら、いくつかの問題を持っている:(

それは、ウィンドウのWndProcメソッドをオーバーライドするので、何の塗料は、再描画しないので、私は私のフレームに追加したコントロールは、驚くことではない(働いていませんでしたメッセージが処理されました)。それから、私はLRESULT(1)の代わりに、デフォルトのウィンドウproc(Win32 C++プログラムで使用されている)を呼び出す必要があることに気がつきましたが、問題はまだ解決しませんでした。フレームはペイントされましたが、ラベルを更新することができました...だから私はこの解決策も放棄しなければなりませんでした。、静的隠されたウィンドウはウィンドウメッセージを処理するために作成されています。私は素晴らしい記事here(リンクが死んでいる、original article can be found here編集)を見つけたインターネット上でいくつかのより多く検索した後

。私は自分のアプリケーションのためにそれをコード化することができました。 (私は、JNAのクラスをさらに拡張する必要がありました。なぜなら、いくつかの関数は含まれていなかったからです。誰かが興味を持っていればコードを投稿することができます)。

+6

追加情報を回答として投稿しないで、代わりに質問を編集してください。 –

+0

私はあなたのコードで面白いです。あなたはそれを提供できますか?ありがとう! – Maxbester

+0

私はあなたのコードにも興味があります。あなたはそれを提供することができますか? Tnx! – Martijn

2

既存のウィンドウハンドルがない場合は、最初に独自のウィンドウを作成する必要があります。新しいウィンドウを作成するときには、メッセージポンプも管理する必要があります。これを行う方法の例を次に示します。 JNA's own example codeも非常に便利です。

Thread thread; 
HWND hWnd; 
static final int WM_NCCREATE = 0x0081; 

void start() { 
    thread = new Thread(this::myThread); 
    thread.start(); 
} 

void stop() { 
    User32.INSTANCE.PostMessage(hWnd, User32.WM_QUIT, null, null); 
} 

WindowProc callback = new WindowProc() { 
    @Override 
    public LRESULT callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam) { 
     switch (uMsg) { 
     case WM_NCCREATE: 
      return new LRESULT(1); 

     case User32.WM_DEVICECHANGE: 
      return new LRESULT(1); 

     default: 
      return new LRESULT(0); 
     } 
    } 
}; 

void myThread() { 
    WString className = new WString("myclass"); 

    WNDCLASSEX wx = new WNDCLASSEX(); 
    wx.clear(); 
    wx.lpszClassName = className; 
    wx.lpfnWndProc = callback; 

    if (User32.INSTANCE.RegisterClassEx(wx).intValue() != 0) { 
     hWnd = User32.INSTANCE.CreateWindowEx(0, className, null, 0, 0, 0, 0, 0, null, null, null, null); 

     WinUser.MSG msg = new WinUser.MSG(); 
     msg.clear(); 

     while (User32.INSTANCE.GetMessage(msg, hWnd, 0, 0) > 0) { 
      User32.INSTANCE.TranslateMessage(msg); 
      User32.INSTANCE.DispatchMessage(msg); 
     } 
    } 
}