代码之家  ›  专栏  ›  技术社区  ›  Nikola Yovchev

在JNA中创建本机Windows窗口,并使用gwl_wndproc创建一些getwindowlong

  •  4
  • Nikola Yovchev  · 技术社区  · 14 年前

    很好的一天,

    我已经使用JNA与WindowsAPI进行了一段时间的交互,现在我在创建窗口时陷入了困境。就我所做的而言: 1。已创建现有窗口的子窗口,并获取了该窗口的有效处理程序。 2。了解到Windows中的每个窗口都有一个不间断的消息调度循环。 三。了解将窗口包含在消息调度循环中的最佳方法是使用如下代码(不是我的,但我也会这样做):

    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的地址,但我想知道是否有任何方法(当然应该有)可以绕过这一点。

    有什么指针吗?(双关语)

    1 回复  |  直到 14 年前
        1
  •  2
  •   fernacolo    14 年前

    不要在JNA调用后使用getLastError()。JNA&JNI可以调用可能更改上一个错误的其他API。使用子句来声明setWindowLong引发lastErrorException,如下所示:

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

    注意名字后面的“A”。它明确使用了ANSI版本。也可以使用setwindowlongw。

    确保回调同时实现回调和stdcall。我更喜欢尽可能多地使用原始类型,因为这使得映射对JNA来说很快和明显:

    public interface WndProcCallbackListener extends Callback, StdCall {
    
        int callback(int hWnd, int Msg, int wParam, int lParam);
    
    }