RazzorFlame Temat założony przez niniejszego użytkownika |
[WinApi] GetWindowLong nie zwraca poprawnej wartości » 2014-09-18 20:31:11 Pisze Wrapper pod WinApi już od dłuższego czasu. Korzystam z wielu tutoriali, i w praktycznie każdym widze kod odpowiedzialny za procedure zdarzeń. Wygląda ona mniej więcej tak: LRESULT CALLBACK AbstractWindow::stDefProcedure( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { AbstractWindow * pWnd; if( uMsg == WM_NCCREATE ) { SetWindowLong( hwnd, GWL_USERDATA,( long )(( LPCREATESTRUCT( lParam ) )->lpCreateParams ) ); } pWnd =( AbstractWindow * ) GetWindowLong( hwnd, GWL_USERDATA ); if( pWnd ) { return pWnd->DefProcedure( hwnd, uMsg, wParam, lParam ); } return DefWindowProc( hwnd, uMsg, wParam, lParam ); }
U mnie jednak pWnd jest niepoprawne, przez co wykonuje się DefWindowProc zamiast mojej funkcji. DefWindowProc nie zamyka procesu aplikacji, głównie dlatego chcę wykonywać swoją funkcję. Gdy wywołuje GetLastError (kiedy !pWnd) dostaje errory: Jakieś 90% to wartość "2" czyli "ERROR_FILE_NOT_FOUND" występuje np. kiedy przesuwam okno. Reszta to "1400" czyli "ERROR_INVALID_WINDOW_HANDLE" i 1410 czyli "ERROR_CLASS_ALREADY_EXISTS". Tutaj AbstractWindow.hpp class AbstractWindow { protected: HWND hWindow; string sName; uVector < int > vWindowSize; UINT uStyle; public: AbstractWindow(); virtual void parseMessage() = 0; virtual void parseMessage( UINT, WPARAM, LPARAM ) = 0; virtual LRESULT CALLBACK DefProcedure( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) = 0; static LRESULT CALLBACK stDefProcedure( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); inline static AbstractWindow * GetObjectFromWindow( HWND hWnd ) { return( AbstractWindow * ) GetWindowLongPtr( hWnd, GWL_USERDATA ); } };
Nie wiem już co zrobić. Jeżeli potrzeba jeszcze jakiegoś kodu to napiszcie. Z góry dzięki. |
|
Monika90 |
» 2014-09-18 21:45:37 Nie pokazałes jak tworzysz okno, tzn. kod wywołujący CreateWindow i czy kompilujesz to jako 32 czy 64 bitowy program? |
|
RazzorFlame Temat założony przez niniejszego użytkownika |
» 2014-09-18 22:01:00 64 bitowy. Oto kod: bool Window::create( string _name, string _classname, UINT _style, uVector < int > _size, bool _windowed ) { LPSTR __name =( char * ) _name.c_str(); LPSTR __classname =( char * ) _classname.c_str(); RECT nRect = { 0, 0, _size.x, _size.y }; AdjustWindowRect( & nRect, _style, !_windowed ); uVector < int > __size; __size.x = nRect.right - nRect.left; __size.y = nRect.bottom - nRect.top; hWindow = CreateWindowEx( WS_EX_CLIENTEDGE, __classname, __name, _style, CW_USEDEFAULT, CW_USEDEFAULT, __size.x, __size.y, NULL, NULL, GetModuleHandle( NULL ), NULL ); reachable = hWindow != NULL; if( !reachable ) errorManager.addError( Error( "e10000", "Cannot create window!" ) ); return reachable; }
Dla klasy AbstractWindow nie mam funkcji create, jedynie dla pochodnej. Edit: Okno się tworzy, jedynie zawsze wywoływane jest DefWindowProc zamiast mojej funkcji. |
|
Monika90 |
» 2014-09-18 22:18:49 Powinieneś przekazać wskaźnik this jako ostatni argument CreateWindowEx i to po zrzutowaniu na AbstractWindow*, czyli tak: hWindow = CreateWindowEx( WS_EX_CLIENTEDGE, __classname, __name, _style, CW_USEDEFAULT, CW_USEDEFAULT, __size.x, __size.y, NULL, NULL, GetModuleHandle( NULL ), static_cast < AbstractWindow *>( this ) );
to raz, a dwa, to w 64 bitowym kodzie wskaźniki są 64 bitowe, a long jest 32 bitowe, więc Set/GetWindowLong obetnie Ci połowę wskaźnika. Dlatego musisz użyć Set/GetWindowLongPtr. Czyli tak: if( uMsg == WM_NCCREATE ) { SetWindowLongPtr( hwnd, GWLP_USERDATA,( LONG_PTR )(( LPCREATESTRUCT( lParam ) )->lpCreateParams ) ); }
pWnd =( AbstractWindow * ) GetWindowLongPtr( hwnd, GWLP_USERDATA );
w funkcji GetObjectFromWindow nawet masz już to zrobione. EDIT zamiast GWL_USERDATA ma być oczywiśćie GWLP_USERDATA |
|
RazzorFlame Temat założony przez niniejszego użytkownika |
» 2014-09-18 22:24:38 Jesteś boska ;) Chciałbym posiadać taką wiedzę jak Ty. Dziękuje Ci za pomoc. Wszystko działa :) Bardzo bardzo dziękuje. |
|
Monika90 |
» 2014-09-18 22:28:21 Bardzo mnie cieszy że działa, tylko zmień jeszcze GWL_USERDATA na GWLP_USERDATA. Nie używaj też nazw które zaczynają sie od dwóch znaków podkreślenia, bo one są zarezerwowane. |
|
RazzorFlame Temat założony przez niniejszego użytkownika |
» 2014-09-18 22:44:15 Okej, jeszcze raz dzięki. |
|
« 1 » |