Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

TrommlBomml

Community-Fossil

  • »TrommlBomml« ist der Autor dieses Themas

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

1

15.05.2008, 10:06

Einfache Dialogklasse für WinAPI - CALLBACK als Member?

Ich bastel zurzeit ein wenig am Modelkonverter für das MoonEngine-Projekt, was ich über die WinAPI progge. ich wollte eine einfache Dialogklasse machen, die ein bissle arbeit abnimmt und globale variablen vermeidet. Ich hatte mir das wie folgt gedacht:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
class CDialog
{
public:

    CDialog() {}
    ~CDialog() {}

    int DoModal(HINSTANCE hInstance,unsigned int iDlgID);

    INT_PTR CALLBACK WinProc(HWND hWnd,unsigned int uiMsg,WPARAM WParam,LPARAM LParam);
};


wichtig für das Problem ist DoModal(), wo einfach nur DialogBoxA() aufgerufen, wird, um den gewünschten Dialog aufzurufen:

C-/C++-Quelltext

1
2
3
4
int DoModal(HINSTANCE hInstance,unsigned int iDlgID)
{
    return DialogBoxA(hInstance,MAKEINTRESOURCE(iDlgID),0,WinProc);
}


und genau bei WinProc ist das problem. folgender fehler wird dazu generiert:

Zitat von »"VC Debugger"«


d:\programmieren\c++\moonengine_svn\moonconvert\src\maindialog.cpp(68) : error C2276: '&' : illegal operation on bound member function expression


lösen lässt sich das ganze, wenn man die CALLBACK static macht. jedoch gefällt mir das ganze nicht, da dann alles, was innerhalb an funktionen und membervariablen verwendet werden soll (das ist der grund, WARUM ich die CALLBACK als Member haben will :), um auf die member des objektes zugreifen zu können!) auch als static deklariert werden muss. ist eigentlich nciht so schlimm, da ich sowieso nur eine instanz haben werde, aber trotzdem gefällt mir das nicht so ganz.

gibt es eine alternative, womit die CALLBACK als Member bleibt aber ohne static? wichtig ist, dass ich auf Member des Objektes zugreifen kann, da es auch einfach Klassen für Edit-Felder und ListBox geben wird, die auch als Member für einfaches Behandeln der Controls vorhanden sein werden.

CodingCat

1x Contest-Sieger

Beiträge: 420

Beruf: Student (KIT)

  • Private Nachricht senden

2

15.05.2008, 10:17

Das Problem trat bereits etliche Male auf, gibt einige leicht unterschiedliche Wege (je nach gewünschter Allgemeinheit und Komplexität) dies zu lösen. Da ich zu faul bin, in diesem Forum zu suchen, bin ich mal so frei, und verweise hier auf die ZFX FAQ: http://www.zfx.info/FAQ.php?ID=21 ;-)
alphanew.net (last updated 2011-06-26) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

3

15.05.2008, 10:22

Verwende statt dem Macro DialogBox einfach die Funktion DialogBoxParam . Der kannst du als letzten Parameter einen Zeiger auf deine Instanz mitgeben. Deine DlgProc Prozedur muss darf zwar dennoch keine Memberfunktion sein, kann aber, dank der übergebenen Instanz, den Aufruf weiterleiten.
@D13_Dreinig

4

15.05.2008, 15:31

Einfach DialogBoxParam und static Memberproc. .. die dann auf eine virtual Memberproc umleitet ... is doch easy :) Und schon 1000X hier im Forum gelöst.
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

TrommlBomml

Community-Fossil

  • »TrommlBomml« ist der Autor dieses Themas

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

5

16.05.2008, 13:30

Zitat von »"Deviloper"«

Einfach DialogBoxParam und static Memberproc. .. die dann auf eine virtual Memberproc umleitet ... is doch easy :) Und schon 1000X hier im Forum gelöst.


wenn mans weiss ja :)

danke leuts, ich werd das glei ma frickeln^^

TrommlBomml

Community-Fossil

  • »TrommlBomml« ist der Autor dieses Themas

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

6

16.05.2008, 15:15

öhm joa, zu früh gefreut. ich hab jetzt mal versucht devils vorschlag umzusetzen, aber dasselbe problem^^. ich poste nochmal die essentials, hab ich da etwas übersehen/missverstanden?

CMainDialog.h:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class CMainDialog
{
private:
    
    HINSTANCE m_hInstance; //App-ID


private:

    //Nachrichtenverarbeitung

    virtual INT_PTR CALLBACK WinProc(HWND hWnd,unsigned int iMsg,WPARAM WParam,LPARAM LParam);

    //Einfachen Konstruktor verbieten

    CMainDialog();

public:

    //erzeugen/freigeben

    CMainDialog(HINSTANCE hInstance): m_hInstance(hInstance),m_pD3D(0),m_pVDList(0),m_pModel(0){}
    ~CMainDialog();

    //Modal laufen lassen

    int DoModal(unsigned int IDialogID);

    //Nachrichtenverarbeitungs-CALLBACK, ruft virtuelle Funktion auf

    static INT_PTR CALLBACK MainProc(HWND hWnd,unsigned int uiMsg,WPARAM WParam,LPARAM LParam);
};


entsprechende cpp-datei:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int CMainDialog::DoModal(unsigned int IDialogID)
{
    //Dalogbox starten

    return DialogBoxParam(m_hInstance,MAKEINTRESOURCE(IDialogID),0,&CMainDialog::MainProc,0);
}

INT_PTR CALLBACK CMainDialog::WinProc(HWND hWnd,unsigned int iMsg,WPARAM WParam,LPARAM LParam)
{
    switch(iMsg)
    {
    /*...*/
    }
}

INT_PTR CALLBACK CMainDialog::MainProc(HWND hWnd,unsigned int uiMsg,WPARAM WParam,LPARAM LParam)
{
    return WinProc(hWnd,uiMsg,WParam,LParam);
}

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

7

16.05.2008, 15:26

Ja hast du. Hättest du meinen Beitrag mal gelesen dann wüsstest du auch was.
@D13_Dreinig

CodingCat

1x Contest-Sieger

Beiträge: 420

Beruf: Student (KIT)

  • Private Nachricht senden

8

16.05.2008, 15:37

Nuja, das Grundproblem hattest du schon richtig erkannt. Ohne this Zeiger gehts nunmal nicht. :-p David_pb und Deviloper sprachen die Möglichkeit von DialogBoxParam an, einen beliebigen Zusatzparameter zu übergeben. Wenn du als Zusatz jetzt 0 übergibst, hast du nicht allzu viel davon. ;-) Übergibst du anstatt dessen reinterpret_cast<LPARAM>(this), ist das schonmal ein Anfang. :)

Der Zusatzparameter taucht nämlich in WM_INITDIALOG wieder auf als LParam, was äußerst praktisch sein kann:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
INT_PTR CALLBACK CMainDialog::MainProc(HWND hWnd,unsigned int uiMsg,WPARAM WParam,LPARAM LParam) 
{ 
    CMainDialog *pThis = NULL;

    if(uiMsg == WM_INITDIALOG )
    {
        // In WM_INITDIALOG findest du deinen Parameter wieder

        pThis = reinterpret_cast<CMainDialog*>(LParam);
        // Deshalb speicherst du ihn dir am besten gleich für weitere Nachrichten direkt beim Fenster ab

        SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pThis));
    }
    else
        // Und holst ihn dir dann immer wenn du ihn brauchst

        pThis = reinterpret_cast<CMainDialog*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

    // Auf diese Weise hast du deinen this Pointer

    if(pThis) return pThis->WinProc(hWnd,uiMsg,WParam,LParam); 
    // Für den Fall, dass am Anfang oder am Ende noch Nachrichten kommen, wenn deine Klasse nicht mehr existiert

    else return DefWindowProc(hWnd,uiMsg,WParam,LParam);
}


Virtual brauchst du die Methode nur, wenn du weitere Klassen von deiner Dialog-Klasse ableitest, die auch Nachrichten verarbeiten sollen und somit die WindowProc Methode überschreiben können müssen.
alphanew.net (last updated 2011-06-26) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite

TrommlBomml

Community-Fossil

  • »TrommlBomml« ist der Autor dieses Themas

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

9

16.05.2008, 15:44

ah, jetz hats klick gemacht, wenn man zu blöd zum lesen is :D. klappt suppa^^

und wenn das wirklich schon sooft beantwortet wurde, warum steht das dann net in den faq?^^

so hab ichs nu gemacht:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
int CMainDialog::DoModal(unsigned int IDialogID)
{
    //Dalogbox starten

    return DialogBoxParam(m_hInstance,MAKEINTRESOURCE(IDialogID),0,MainProc,reinterpret_cast<LPARAM>(this));
}

INT_PTR CALLBACK MainProc(HWND hWnd,unsigned int iMsg,WPARAM WParam,LPARAM LParam)
{
    return reinterpret_cast<CMainDialog*>(LParam)->WinProc(hWnd,iMsg,WParam,LParam);
}


EDIT: thx, codingcat, habs na nu selbst hinbekommen, warst nur schneller im tipseln :)

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

10

16.05.2008, 16:03

Aber deine Variante ist nicht ganz richtig. Den Zeiger bekommst du nur bei WM_INITDIALOG, das solltest du also noch explizit abfragen.
@D13_Dreinig

Werbeanzeige