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 可能会调用其他 API 来更改最后一个错误。使用子句声明 SetWindowLong 会抛出 LastErrorException,如下所示:

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 回答