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

Techie

Alter Hase

  • »Techie« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

1

01.06.2013, 21:49

[GELÖST: Programmierer war zu Dumm] WinAPI wrapper problem...

Hallöchen ich bin's mal wieder.
Ich habe ein Problem was die WinAPI betrifft.

Ich schreibe gerade eine Klasse die ein Fenster erstellt.
Leider gibt's da ein Problem, alle die sich damit befasst haben wissen dass man WndProc als static deklarieren muss.
Danach habe ich im Web gesucht um eine Lösung für das Problem zu schaffen.
Als Lösung habe ich so etwas gefunden:

C-/C++-Quelltext

1
2
Window* pWindow = NULL;
pWindow = (pWindow* ) GetWindowLong( hWnd );


Nun steht da es muss ein änderbarer lvalue sein. Sprich so etwas:

C-/C++-Quelltext

1
pWindow.m_lLong ....


Jedoch geht es mir darum die Klasseninstanz bzw, die Zeigeradresse der Klasseninstanz zu bekommen.
Ich verstehe nicht warum es bei mir nicht geht.

Gruß Techie

P.S.: Um die Lösung zu finden, habe ich diesen Artikell gelesen

EDIT: Ich habe gemerkt das ich irgendwie keinen Klassenpointer auf ein Objelt anwenden kann. F*ck IntelliSense.
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »Techie« (02.06.2013, 01:03)


Techie

Alter Hase

  • »Techie« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

2

02.06.2013, 00:54

Ok, ich habe mich weiter mit dem Problem befasst und wortwörtlich auf IntelliSense gesch**ssen.
Plötzlich akzeptiert er es. Außerdem lässt es sich Problemlos kompilieren. Leider nur noch ein Problem.
Das Programm startet. Der Debugger im Debugmode zeigt nichts an und mein Fenster kommt auch nicht.
Was habe ich da falsch gemacht?
Mein Code:

Main.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
#ifdef _MSC_VER
#    pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
#include "CWindow.h"

int main(){
    CWindow Win( L"Test Window" );
    return Win.Run();
}


CWindow.h:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
#pragma once
#include <Windows.h>

class CWindow{
protected:
    HWND m_hWnd;
    static LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
public:
    CWindow( const LPCWSTR pcTitle );
    int Run();
};


CWindow.cpp:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#pragma once
#include "CWindow.h"

CWindow::CWindow( const LPCWSTR pcTitle ){
    WNDCLASSEX wc;
    ZeroMemory( &wc, sizeof(WNDCLASSEX) );

    wc.cbSize       = sizeof( WNDCLASSEX );
    wc.style        = CS_HREDRAW | CS_VREDRAW ;
    wc.lpfnWndProc  = WndProc;
    wc.cbClsExtra   = NULL;
    wc.cbWndExtra   = NULL;
    wc.hInstance    = GetModuleHandle( NULL );
    wc.lpszMenuName = NULL;

    if(!(RegisterClassEx( &wc ))){
        MessageBox( NULL, L"Failed to register Class! : RegisterClassEx ", L"ERROR!", MB_OK );
    }
    
    //RegisterClassEx( &wc );

    m_hWnd = CreateWindowEx( NULL,
                              pcTitle,
                              pcTitle,
                             WS_OVERLAPPEDWINDOW,
                             0,
                             0,
                             600,
                             400,
                             NULL,
                             NULL,
                             GetModuleHandle( NULL ),
                             NULL );
    ShowWindow( m_hWnd, SW_SHOWDEFAULT );
    UpdateWindow( m_hWnd );
}

int CWindow::Run(){
    MSG msg;
    while( GetMessage( &msg, NULL, NULL, NULL )){
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
    return msg.wParam;
}

LRESULT CALLBACK CWindow::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){
    CWindow* pWin;
    
    if( msg == WM_NCCREATE ){
        SetWindowLong( hWnd, GWL_USERDATA, (long)(LPCREATESTRUCT(lParam)->lpCreateParams) );
    } 

    pWin = (CWindow* ) GetWindowLong( hWnd, GWL_USERDATA );

    switch( msg ){
    case WM_DESTROY: {
        PostQuitMessage( 0 );
        return 0;
                     } break;
    }
    
    return DefWindowProc( hWnd, msg, wParam, lParam );
}


Wie gesagt, der Debugger sagt nichts. Ich habe dann deswegen mal eine Bedingung eingefügt die mir hilft das Problem zu finden.
Nun, es heißt das RegisterClassEx failt.
Leider habe ich da auch keine Ahnung was da jetzt wieder falsch ist.

Hatte jemand das Problem schonmal und kann mir helfen?

Gruß Techie
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Techie

Alter Hase

  • »Techie« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

3

02.06.2013, 00:57

Ok, nach langem versuchen habe ich gemerkt, dass der Mangel an Koffein mich dazu gebracht einen DUMMEN DUMMEN Fehler zumachen.
Nun habe ich es geschafft.
Die Lösung war, dass ich wc.lpszClassName zu initialisieren vergessen habe.

Ich glaube ich bin dem Forum ein Tutorial schuldig wie man nun so eine Klasse erstellt ^^.

EDIT: Nebenbei ist mir noch aufgefallen das ich den Konstruktor aufgerufen habe. Diese verdammten Klammern.... habenden ganze ärger verursacht.
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Techie« (02.06.2013, 03:44)


Tobiking

1x Rätselkönig

  • Private Nachricht senden

4

02.06.2013, 13:12

Bei deinem letzten Code fehlt aber immer noch etwas. SetWindowLong wird mit dem Wert aufgerufen, der dem Fenster beim Erstellen mit übergeben wird. Du übergibst dem Fenster dabei aber NULL (letzter Parameter von CreateWindowEx). Da sollte in dem Fall this stehen, damit die Verbindung zu dem jeweiligen Objekt der Fensterklasse gegeben ist.

Und eine weitere Anmerkung, wenn du GetWindowLongPtr benutzt läuft das ganze auch unter 64 Bit.

Techie

Alter Hase

  • »Techie« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

5

11.06.2013, 19:17

Vielen Dank für deine Anmerkung. Ich werde dies gleich mal so übernehmen ^^

Auch wenn im Titel schon "Gelöst" steht habe ich noch eine Frage:
Muss die Game Logic vor GetMessage ..... stehen? Denn ich arbeite gerade an einem Projekt und neben bei kristallisiert sich eine Engine ( ClockGear ^^ ) heraus. Mein Ziel für die Fensterklasse war es, dass ich es wie in SFML aufrufen kann.

Nochmals vielen Dank für deine Anmerkung, Gruß Techie.
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Tobiking

1x Rätselkönig

  • Private Nachricht senden

6

12.06.2013, 01:50

Die Reihenfolge ist in der Regel ziemlich egal. Immerhin wird eh immer beides abwechselnd aufgerufen.

Allerdings eignet sich GetMessage nicht besonders gut, da die Funktion blockierend ist. Liegt gerade keine Fensternachricht vor, pausiert das Programm. Stattdessen kann man die Funktion PeekMessage nutzen, die direkt zurückkehrt und per Rückgabewert angibt ob eine Nachricht vorlag oder nicht.

Bei mir sieht das folgendermaßen aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
void Win32Window::ProcessEvents()
{
    MSG msg;
    while(PeekMessage(&msg, handle, 0, 0, PM_REMOVE)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}


Und mein Gameloop ist einfach ProcessEvents -> Update -> Render.

Werbeanzeige