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

Wskaźnik na niestatyczną metodę obiektu.

Ostatnio zmodyfikowano 2015-02-03 16:20
Autor Wiadomość
Fireho
Temat założony przez niniejszego użytkownika
Wskaźnik na niestatyczną metodę obiektu.
» 2015-01-27 21:05:08
Jak przekazać niestatyczną metodę konkretnego, utworzonego obiektu Windowsowi jako procedurę obsługi zdarzeń? W "tutejszym" kursie WinAPI nie ma nic o łączeniu WinAPI i OOP, zajrzałem do Xion'a(koniec 2.2 zaawansowana obiektowość) i tam pokazywał coś takiego, ale nawet przykładowy kod nie chciał działać. Polegało to na tym, że tworzył specjalną strukturę przechowującą wskaźnik na obiekt i wskaźnik na metodę klasy, następnie używał operatora ->* i to miało działać. Ale nie kompiluje się:
C/C++
#include <iostream>
class CFoo {
public:
    void Metoda( int nParam )
    { std::cout << "Wywolano z " << nParam; }
   
};
struct METHODPOINTER
{
   
    CFoo * pObject;
    void( CFoo::* p2mfnMethod )( int );
   
    METHODPOINTER( CFoo * pObj, void( CFoo::* p2mfn )( int ) )
        : pObject( pObj )
         , p2mfnMethod( p2mfn )
    { }
   
    void operator ()( int nParam )
    {( pObject->* p2mfnMethod( nParam ) ); }
};
int main() {
    CFoo Foo;
    METHODPOINTER p2ofnMetoda( & Foo, & CFoo::Metoda );
    p2ofnMetoda( 69 );
}
main.cpp|69|error: must use '.*' or '->*' to call pointer-to-member function in '((METHODPOINTER*)this)->METHODPOINTER::p2mfnMethod (...)', e.g. '(... ->* ((METHODPOINTER*)this)->METHODPOINTER::p2mfnMethod) (...)'|
Jak to naprawić? Jest jakiś inny sposób?

PS: Wcześniej dałem w złym dziale, przenieście tamten temat do kosza czy coś.
P-125635
maly
» 2015-01-27 21:14:15
Jak przekazać niestatyczną metodę konkretnego, utworzonego obiektu Windowsowi jako procedurę obsługi zdarzeń?
Nie da się.
P-125636
DejaVu
» 2015-01-27 22:30:42
Da się zapisać wskaźnik na metodę:
http://cpp0x.pl/kursy/Kurs-C++​/Poziom-X/Wskaznik-na-metode/264

Inną kwestią jest to co chcesz osiągnąć. Jest to również do zrealizowania pod warunkiem, że masz do dyspozycji jeden argument, któremu możesz przekazać dowolną wartość (wskaźnik) z którym zostanie wywołana Twoja funkcja przez WinAPI.
P-125642
maly
» 2015-01-28 07:03:42
Co do błędu to...
( pObject->* p2mfnMethod )( nParam );

Możesz też spojrzeć na mój temat o delegacie.
http://cpp0x.pl/forum/temat/​?id=14973
P-125646
Fireho
Temat założony przez niniejszego użytkownika
» 2015-01-28 09:09:38
Ostatecznie dałem Windowsowi funkcje ze statycznym wskaźnikiem na mój obiekt. Natrafiłem na problem "jak ustawić wartość wskaźnika" ale ostatecznie kazałem ustawiać wartość jeśli pierwszy parametr(uchwyt do okna) będzie miał wartość 0(Windows raczej nie wyśle komunikatu do nieistniejącego okna?) to rzutuje z drugiego parametru(uint uMsg, czyli kod wiadomości) na wskaźnik do CWindow i kończy działanie. Będę jeszcze musiał rozdzielić okno i jego klasę(tą Windowsową), ale czy w obecnym sposobie nie ma błędów? Kod:
C/C++
#include <iostream>
#include <windows.h>

class CWindow {
    WNDCLASSEX oWndClass;
    HINSTANCE hInstance;
    std::string sWndClass, sWndName;
    HWND hOkno;
public:
    CWindow( HINSTANCE _hInstance, std::string _sWndClass, std::string _sWndName );
   
    LRESULT WndEventProc( HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam );
};
LRESULT CALLBACK WndEvRedirPr( HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    static CWindow * pObj;
    if( hWindow == NULL ) {
        pObj =( CWindow * ) uMsg;
        return 0;
    }
    if( pObj == NULL ) {
        std::cerr << "blad podczas przekierowywania obsługi zdarzen\n";
    }
    return pObj->WndEventProc( hWindow, uMsg, wParam, lParam );
}
CWindow::CWindow( HINSTANCE _hInstance, std::string _sWndClass, std::string _sWndName )
    : hInstance( _hInstance )
     , sWndClass( _sWndClass )
     , sWndName( _sWndName )
{
    WndEvRedirPr( NULL,( unsigned int ) this, 0, 0 );
   
    ZeroMemory( & oWndClass, sizeof( WNDCLASSEX ) );
    oWndClass.cbSize = sizeof( WNDCLASSEX );
    oWndClass.hInstance = hInstance;
    oWndClass.lpfnWndProc = WndEvRedirPr;
    oWndClass.lpszClassName = sWndClass.c_str();
    oWndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
    oWndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    oWndClass.hbrBackground =( HBRUSH ) COLOR_WINDOW;
    if( !RegisterClassEx( & oWndClass ) ) {
        std::cerr << "blad podczas rejestracji klasy\n";
    }
    if( !( hOkno = CreateWindowEx(
    0,
    sWndClass.c_str(),
    sWndName.c_str(),
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    NULL,
    NULL,
    hInstance,
    NULL
    ) ) ) {
        std::cerr << "blad podczas tworzenia okna\n";
    }
   
    ShowWindow( hOkno, 10 );
}
LRESULT CWindow::WndEventProc( HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    switch( uMsg ) {
    case WM_QUIT:
        PostQuitMessage( 0 );
        return 0;
    }
    return DefWindowProc( hWindow, uMsg, wParam, lParam );
}



int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow )
{
    CWindow okno( hInstance, "CPP_TEST", "C++ CWindow Class Test" );
    MSG msgKomunikat;
    while( GetMessage( & msgKomunikat, NULL, 0, 0 ) )
    {
        TranslateMessage( & msgKomunikat );
        DispatchMessage( & msgKomunikat );
    }
    return static_cast < int >( msgKomunikat.wParam );
}
 
P-125650
Monika90
» 2015-01-28 09:40:44
Statyczny wskażnik to nie jest dobry pomysł, bo będzie można utworzyć tylko jedno okno. Należy skojarzyć wsaźnik this z uchwytem okna, np. przy użyciu funkcji SetWindowLongPtr i GetWindowLongPtr, lub w jakiś inny sposób.
P-125654
Fireho
Temat założony przez niniejszego użytkownika
» 2015-01-28 09:54:02
Zmieniłem wskaźnik do okna na wskaźnik do klasy okna i da się zrobić wiele okien, ale rozumiem że to też źle bo nie będzie można utworzyć wielu klas okna? Dałoby się to rozwiązać poprzez stworzenie klasy służącej czysto przekierowaniom, ale domyślam się że nie ma sensu tak komplikować? Spróbuję użyć tych set i get, a jak zrobię to napisze kolejnego posta.
P-125655
Fireho
Temat założony przez niniejszego użytkownika
» 2015-01-28 10:05:22
Zrobiłem zgodnie z zaleceniami. Oczywiście jeszcze zostały takie drobiazgi jak ustalanie własnej wielkości okna, ale to się zrobi łatwo. Coś jeszcze jest źle? Kod:
C/C++
#include <iostream>
#include <windows.h>

class CWindowClass {
    WNDCLASSEX oWndClass;
    HINSTANCE hInstance;
    std::string sWndClass;
public:
    CWindowClass( HINSTANCE _hInstance, std::string _sWndClass );
    LRESULT WndEventProc( HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam );
    std::string GetName() const { return sWndClass; }
    HINSTANCE GetHInstance() const { return hInstance; }
};

class CWindow {
    CWindowClass * pWndClass;
    HINSTANCE hInstance;
    std::string sWndName;
    HWND hOkno;
public:
    CWindow( CWindowClass * _pWndClass, std::string _sWndName );
    LRESULT WndEventProc( UINT uMsg, WPARAM wParam, LPARAM lParam );
   
};
LRESULT CALLBACK WndEvRedirPr( HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    CWindow * pWindow =( CWindow * ) GetWindowLongPtr( hWindow, GWLP_USERDATA );
    if( pWindow == NULL ) return DefWindowProc( hWindow, uMsg, wParam, lParam );
   
    return pWindow->WndEventProc( uMsg, wParam, lParam );
}
CWindowClass::CWindowClass( HINSTANCE _hInstance, std::string _sWndClass )
    : hInstance( _hInstance )
     , sWndClass( _sWndClass )
{
    ZeroMemory( & oWndClass, sizeof( WNDCLASSEX ) );
    oWndClass.cbSize = sizeof( WNDCLASSEX );
    oWndClass.hInstance = hInstance;
    oWndClass.lpfnWndProc = WndEvRedirPr;
    oWndClass.lpszClassName = sWndClass.c_str();
    oWndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
    oWndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    oWndClass.hbrBackground =( HBRUSH ) COLOR_WINDOW;
    if( !RegisterClassEx( & oWndClass ) ) {
        std::cerr << "ERROR: Class registration failed\n";
    }
}
CWindow::CWindow( CWindowClass * _pWndClass, std::string _sWndName )
    : pWndClass( _pWndClass )
     , hInstance( pWndClass->GetHInstance() )
     , sWndName( _sWndName )
{
    if( !( hOkno = CreateWindowEx(
    0,
    pWndClass->GetName().c_str(),
    sWndName.c_str(),
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    NULL,
    NULL,
    hInstance,
    NULL
    ) ) ) {
        std::cerr << "ERROR: Window creating failed\n";
    }
    SetWindowLongPtr( hOkno, GWLP_USERDATA,( long ) this );
    ShowWindow( hOkno, 10 );
}
LRESULT CWindow::WndEventProc( UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    switch( uMsg ) {
    case WM_QUIT:
        PostQuitMessage( 0 );
        return 0;
    }
    return DefWindowProc( hOkno, uMsg, wParam, lParam );
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow )
{
    CWindowClass wcOkno( hInstance, "CPP_TEMPLATE_CLASS_NAME" );
    CWindow wOkno1( & wcOkno, "C++ WinAPI Template" );
    CWindow wOkno2( & wcOkno, "C++ WinAPI Template" );
    MSG msgKomunikat;
    while( GetMessage( & msgKomunikat, NULL, 0, 0 ) )
    {
        TranslateMessage( & msgKomunikat );
        DispatchMessage( & msgKomunikat );
    }
    return static_cast < int >( msgKomunikat.wParam );
}
P-125656
« 1 » 2
  Strona 1 z 2 Następna strona