Создайте собственное окно Windows в JNA и немного GetWindowLong с GWL_WNDPROC

Добрый день,

Некоторое время я использовал 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 другого, но мне было интересно, есть ли способ (конечно, должен быть) обойти это.

Есть указатели? (каламбур предназначен)

1 ответ

Решение

Не используйте GetLastError() после вызова JNA. JNA & JNI могут вызывать другие API, которые могут изменить последнюю ошибку. Объявить SetWindowLong с предложением выдает исключение LastErrorException, например:

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

Обратите внимание на "А" после имени. Это явно использует версию ANSI. Вы также можете использовать SetWindowLongW.

Убедитесь, что ваш обратный вызов реализует как Callback, так и StdCall. Я предпочитаю максимально использовать примитивные типы, потому что это делает отображение быстрым и очевидным для JNA:

public interface WndProcCallbackListener extends Callback, StdCall {

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

}
Другие вопросы по тегам