4

良い一日、

私はしばらく JNA を使用して Windows API とやり取りしていましたが、ウィンドウを作成するときに行き詰まりました。1. 既存のウィンドウの子ウィンドウを作成し、有効なハンドラーを取得しました。2. Windows のすべてのウィンドウには、ノンストップのメッセージ ディスパッチ ループがあることを理解しました。3. 自分のウィンドウをメッセージ ディスパッチ ループに含める最善の方法は、次のコードのようなものを使用することであることがわかりました (私のコードではありませんが、私もそうします)。

final LONG_PTR prevWndProc = new LONG_PTR(User32.INSTANCE.GetWindowLong(hwnd, User32.GWL_WNDPROC));       //this is to obtain a pointer to the WNDPROC of the parent window, which we are going to need later
  wndProcCallbackListener = new WndProcCallbackListener()
   {
      public LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam)
      {
         if (uMsg == WTSAPI.WM_POWERBROADCAST)
         {
           System.out.println("WM_POWERBROADCAST Event: hWnd="+hwnd+", uMsg="+uMsg+", uParam="+uParam+", lParam="+lParam);
         }
         else if (uMsg == WTSAPI.WTS_SESSION_CHANGE)
         {
           System.out.println("WTS_SESSION_CHANGE Event: hWnd="+hwnd+", uMsg="+uMsg+", uParam="+uParam+", lParam="+lParam);
         }

        //Call the window's actual WndProc so the events get processed.
        return User32.INSTANCE.CallWindowProc(prevWndProc, hWnd, uMsg, uParam, lParam);
      }
   };
      //Set the WndProc function to use our callback listener instead of the window's one. 
   int result = User32.INSTANCE.SetWindowLong(hwnd, User32.GWL_WNDPROC, wndProcCallbackListener);

ただし、私の問題は、親ウィンドウ(コードの最初の行) に対して GetWindowLong() を呼び出すと、関数が正常に完了しなかったことを示すポインターに対して 0 を取得することです。その後、GetLastError() を呼び出し、エラー コードをすばやく確認すると、「アクセスが拒否されました」というエラーが表示されます。もちろん、これは論理的です。自分のスレッドから別のスレッドの WNDPROC のアドレスにアクセスしようとしているからです。

ポインタはありますか?(しゃれた意図)

4

1 に答える 1

2

JNA 呼び出しの後に GetLastError() を使用しないでください。JNA と JNI は、最後のエラーを変更する可能性のある他の A​​PI を呼び出す場合があります。次のように、LastErrorException をスローする句で SetWindowLong を宣言します。

int SetWindowLongA(int hWnd, int nIndex, WndProcCallbackListener dwNewLong)
    throws LastErrorException;

名前の後の「A」に注目してください。ANSI バージョンを明示的に使用します。SetWindowLongW も使用できます。

コールバックが Callback と StdCall の両方を実装していることを確認してください。可能な限りプリミティブ型を使用することを好みます。これにより、マッピングが高速になり、JNA にとって明白になるからです。

public interface WndProcCallbackListener extends Callback, StdCall {

    int callback(int hWnd, int Msg, int wParam, int lParam);

}
于 2011-03-20T15:11:07.513 に答える