7

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

サンプル アプリケーションとして Microchip が提供する C# プログラムで見たように、WndProc メソッドはオーバーライドされ、WM_DEVICECHANGE メッセージが処理されます。私の質問は、JNAを使用してJavaでこれを行う方法です.WindowProcメソッドをオーバーライドしてメッセージを処理するにはどうすればよいですか.

回答ありがとうございます。

ガボール。

4

4 に答える 4

8

私はついに問題を解決することができました:)そして、次の解決策を見つけました:

最初に、次の方法で User32 インターフェイスを拡張します

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);
}

次に、必要な Windows メッセージ コードを使用して WinUser インターフェイスを拡張します。私の場合、これは 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);
    }
};

次に、JFrame のコードの初期化を行う場所に、SetWindowLong 関数を使用してウィンドウ プロシージャの新しいアドレスを追加します。

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

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

このコードは問題なく動作しますが、1 つの点について疑問があります。コールバック関数の戻り値が正しいかどうかわかりません。WM_DEVICECHANGE メッセージを処理した後、コールバック関数は true を返す必要があることを MSDN で読みましたが、現在返されている値がシステムによって期待される値であるかどうかわからないため、提案は大歓迎です。

HID通信用に私が書いたコード全体に興味がある人がいれば、喜んでお手伝いします:)

乾杯、ガボール。

于 2011-01-14T12:58:52.623 に答える
1

残念ながら、以前に投稿したソリューションにはいくつかの問題があります:(

ウィンドウの WndProc をオーバーライドするため、Frame に追加したコントロールが機能しませんでした (当然のことながら、ペイント、再ペイントなどのメッセージは処理されませんでした)。次に、戻る代わりにデフォルトのウィンドウ プロシージャを呼び出す必要があることに気付きましたLRESULT(1)(Win32 C++ プログラムで使用されているため)、それでも問題は解決しませんでした。ラベルを更新できる...だから、この解決策も放棄しなければなりませんでした。

インターネットでさらに検索した後、ここ で素晴らしい記事を見つけました(編集: リンクは無効です。元の記事はここにあります)。ここでは、Windows メッセージを処理するために静的な非表示ウィンドウが作成されます。私は自分のアプリケーション用にコーディングすることができましたが、うまく機能します。(いくつかの関数が含まれていなかったため、JNA からクラスをさらに拡張する必要がありました。誰かが興味を持っている場合は、コードを投稿できます。)

お役に立てれば。

于 2011-01-25T07:39:50.983 に答える
1

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

JACOB またはJCOMを使用する

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

于 2011-01-13T09:10:16.480 に答える