2010-10-28 11 views
4

Добрый день,Создать собственное окно Windows, в ЮНА и некоторые GetWindowLong с GWL_WNDPROC

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

Любые указатели? (каламбур)

ответ

2

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

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

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

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

public interface WndProcCallbackListener extends Callback, StdCall { 

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

} 
+1

Обновления: если вы используете примитивы, ваше приложение не будет переносимым между 32-битной и 64-битной JVM. Не большая проблема. Я делаю свои приложения JNA только для 32-разрядной JVM, потому что они могут быть установлены на любую версию Windows (32-разрядную и 64-разрядную), а 32-разрядная JVM всегда будет обращаться к 32-разрядной версии библиотек Windows, даже если работающий на 64-битной Windows. – fernacolo