Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[WinApi] GetWindowLong nie zwraca poprawnej wartości

Ostatnio zmodyfikowano 2014-09-18 22:44
Autor Wiadomość
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:
C/C++
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
C/C++
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.
P-117161
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?
P-117164
RazzorFlame
Temat założony przez niniejszego użytkownika
» 2014-09-18 22:01:00
64 bitowy.
Oto kod:
C/C++
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.
P-117166
Monika90
» 2014-09-18 22:18:49
Powinieneś przekazać wskaźnik this jako ostatni argument CreateWindowEx i to po zrzutowaniu na AbstractWindow*, czyli tak:
C/C++
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:
C/C++
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
P-117167
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.
P-117168
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.
P-117169
RazzorFlame
Temat założony przez niniejszego użytkownika
» 2014-09-18 22:44:15
Okej, jeszcze raz dzięki.
P-117170
« 1 »
  Strona 1 z 1