Toon posts:

[WIN32] Het maken van meerdere windows *

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo,

Ik moest als opdracht voor een Game Engine een "window manager" maken waarin een gebruiker meerdere windows kan open maken. Het probleem is dat ik niet bepaald heb kunnen begrijpen waarom het mij niet lukt.

Ik had eerst Besloten om in de Window Manager de "globale" Message Queue te geven, helaas om een of andere rede werkt de HWND pointer niet goed en geeft hij in de debugger aan dat het niet goed wordt gevuld. De leraar die ons begeleid kon het probleem zelf ook niet vinden, hij wou ook niet de oplossing tot het probleem geven omdat we het zelf moeten leren. Mijn groep zit momenteel ook vast ermee, en andere mensen hebben dit onderdeel geskippen en zijn verder gegaan met de object manager zelf.

Basically is het programma als volgt opgezet, eerst wordt de Windowsmanager opgestart met Winmain, daarin is een WNDCLASS die een keer wordt aangemaakt, met een Hinstance die dan in een Linked list moest worden gezet, als een test hebben we een for loop gemaakt waarin de meerdere windows worden aangemaakt, in de Window.cpp zelf wordt er dan uiteindelijk de window gecreate. Maar om een of andere rede komt die HWND niet goed uit de debugger. Ik heb op google gezocht, maar ik kon helaas niks vinden over hoe je een multiple Window scherm moest maken, alleen was er een artikel op Gamedev,maar die leek heel erg incompleet te zijn. Ik hoop dat iemand weet wat ik fundamenteel fout aan het doen ben, ik weet dat de code waarschijnlijk erg brak is, maar dat boek van petzold helpt ook niet helaas :( Ik hoef geen code die werkt, maar het zou fijn zijn als ik een beetje in de goede richting wordt geholpen want ik ben nu al 12 uur bezig met deze opdracht :)

Alvast bedankt !

Wijnand


Window_Manager.h
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <windows.h>
#include "window.h"


class Window_Manager
{ 
public: 
    // de Message Queue van Windhoos
    void addWindow();

    Window_Manager(); // c'tor
    virtual ~Window_Manager(void); // d'tor

private:
    void* listStart;    

};


Window Manager.cpp

C++:
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "Window_Manager.h"


HINSTANCE hInst = 0;

struct WindowList
{
    Window* wnd;
    WindowList* lNext;
};

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch( msg ) 
    { 
        // Handle left mouse button click message. 
        case WM_LBUTTONDOWN: 
             MessageBox(0, TEXT("WM_LBUTTONDOWN message."), TEXT("Msg"), MB_OK); 
        return 0; 
        // Handle destroy window message. 
        case WM_DESTROY: 
            PostQuitMessage(0); 
    return 0; 
    } 
    // Forward any other messages we didn't handle to the 
    // default window procedure. 
    return DefWindowProc(hWnd, msg, wParam, lParam); 
}

Window_Manager::Window_Manager()
{
    this->listStart = NULL;
}

void Window_Manager::addWindow()
{
    WNDCLASSEX wc;

    wc.style         = CS_HREDRAW | CS_VREDRAW; 
    wc.lpfnWndProc   = WndProc; 
    wc.cbClsExtra    = 0; 
    wc.cbWndExtra    = 0; 
    wc.hInstance     = hInst; 
    wc.hIcon         = NULL; 
    wc.hCursor       = NULL; 
    wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); 
    wc.lpszMenuName  = 0; 
    wc.lpszClassName = TEXT("Vyper"); 

    RegisterClassEx(&wc);


    WindowList* nWnd = new WindowList;
    WindowList* sWnd = reinterpret_cast<WindowList*> (this->listStart);

    nWnd->wnd = new Window(wc, 100, 100, 300, 300);
    nWnd->lNext = NULL;

    if (this->listStart == NULL)
        this->listStart = nWnd;
    else if (sWnd->lNext == NULL)
        sWnd->lNext = nWnd;
    else
    {
        while (sWnd->lNext != NULL)
            sWnd = sWnd->lNext;

        sWnd->lNext = nWnd;
    }
}

Window_Manager::~Window_Manager()
{

}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    hInst = hInstance;
    Window_Manager* wm = new Window_Manager();
    for (int i = 0; i < 3; i++)
    {
        wm->addWindow();
    }
}


Window.h
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <windows.h>

class Window 
{
public: 
    Window(); // default c'tor 
    Window(WNDCLASSEX wc, int x, int y, int width, int height); // specific c'tor
    virtual ~Window(); // d'tor
    //bool getFocus();
    //void setFocus(bool hasFocus);

    
private:
    HWND hWnd; 
    WNDCLASSEX wc;
    //bool hasFocus;
    
};


Window.cpp
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "Window_Manager.h"


Window::Window(WNDCLASSEX wc, int x, int y, int width, int height)
{
    
    this->wc = wc;
    this->hWnd = CreateWindow(TEXT("test"), TEXT("Vyper"), WS_OVERLAPPEDWINDOW, 
                            x, y, width, height, NULL, NULL, wc.hInstance, NULL);

    ShowWindow(this->hWnd, SW_SHOWDEFAULT);
    UpdateWindow(this->hWnd);


}
Window::~Window()
{

}

[ Voor 1% gewijzigd door RobIII op 27-11-2006 21:47 . Reden: Code=C++ van gemaakt. Syntax-highlighting FTW \O/ ]


  • DroogKloot
  • Registratie: Februari 2001
  • Niet online

DroogKloot

depenisvanjezus

Ten eerste: waarom is listStart een void*? Als je die WindowList (voor de duidelijkheid zou ik daar overigens WindowListNode van maken) struct in Window_Manager.h definieert, kun je die reinterpret_cast in addWindow() zo wegmieteren. :)

Ten tweede is het (tenzij ik me vergis, tijdje geleden dat ik met de Windows API te maken had) zo dat een programma dat uit meerdere windows bestaat altijd 1 parent window moet hebben en 0 of meer child windows, dus bv:

C:
1
2
3
4
5
6
7
8
parentHWnd = CreateWindowEx(0, ClassName, "Parent", WindowStyle 0, 0, 640, 480, NULL, NULL, hInstance, NULL);

...

childHWnd1 = CreateWindowEx(0, ClassName, "Child1", WindowStyle,   0,   0, 320, 240, parentHWnd, NULL, hInstance, NULL);
childHWnd2 = CreateWindowEx(0, ClassName, "Child2", WindowStyle, 320,   0, 320, 240, parentHWnd, NULL, hInstance, NULL);
childHWnd3 = CreateWindowEx(0, ClassName, "Child3", WindowStyle, 240,   0, 320, 240, parentHWnd, NULL, hInstance, NULL);
childHWnd4 = CreateWindowEx(0, ClassName, "Child4", WindowStyle, 320, 240, 320, 240, parentHWnd, NULL, hInstance, NULL);


Wat jij zo te zien doet is allemaal parents aanmaken en die 1 voor 1 registreren waardoor je hWnd's ongeldig worden, maar pin me hier niet op vast. :)

Verwijderd

Topicstarter
ik heb het probleem gevonden denk ik, de WNDPROC was niet goed gedefineerd, en had ik de aanroep van CreateWindow fout gedaan. Maar kan ik in een ChildWindow well Verschillende 3D API's gebruiken? de docent was nogal strict in het zeggen dat hij oneindig veel Windows moest kunnen openen en ook nog eens allemaal een andere scene, en andere Rendering techniek kan gebruiken :(

Ik heb al commentaar gehad dat de code die ik heb geschreven niet goed is aangezien ze nu allemaal een WNDPROC gebruiken, wat niet goed is, maar ik ga morgen een console eronder bouwen, en dan hopelijk lukt het me om de code een beetje af te splitsen zodat elke window ook echt zijn eigen is. misschien kan childwindow wel hopelijk wel ;)

Hartsikke bedankt voor je feedback!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:52

.oisyn

Moderator Devschuur®

Demotivational Speaker

DroogKloot schreef op maandag 27 november 2006 @ 23:37:
Ten tweede is het (tenzij ik me vergis, tijdje geleden dat ik met de Windows API te maken had) zo dat een programma dat uit meerdere windows bestaat altijd 1 parent window moet hebben en 0 of meer child windows
Onzin, een app kan best meerdere top-level windows spawnen :)

Blitz455: Ik zou wel even je code aanpassen zodat hij maar 1 WNDCLASSEX aanmaakt, want alle andere calls failen toch, dus het is niet echt netjes zo. Of je moet maken dat je elke window een andere classname geeft.

[ Voor 22% gewijzigd door .oisyn op 28-11-2006 10:49 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
wat ik waarschijnlijk doe is dat je in de console newWindow jan moet intikken en dat hij dan een window genaamd jan opent. het enige waar ik nog mee zit is dat als ik een window sluit dat hij gelijk ook de hele meuk sluit :( Ik ga denk ik de linked list weg halen, aangezien Windows de HWND's bijhoudt en het dan een beetje overkill is als ik het zelf ook nog ga bijhouden (denk ik zelf).

Volgens mij komt dat door de Hwnd maar ik ga in ieder geval die WNDPROC aanpassen zodat ze wel unieke namen krijgen. Moet nog wel kijken waar ik de message queue wil gaan proppen, of centraal in de Window_Manager , of dat elke Window zijn eigen Message queue mag doorlezen, het is nogal vaag allemaal.


Ik heb een aantal Window_Wrapper tutorials gevonden, maar die zijn nogal complex voor mij :(. Misschien maak ik het allemaal te moeilijk voor mijzelf dat kan natuurlijk ook :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:52

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op dinsdag 28 november 2006 @ 12:13:
het enige waar ik nog mee zit is dat als ik een window sluit dat hij gelijk ook de hele meuk sluit :(
Duh, je doet een PostQuitMessage() zodra je een WM_DESTROY krijgt :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
Verwijderd schreef op dinsdag 28 november 2006 @ 12:13:
Moet nog wel kijken waar ik de message queue wil gaan proppen, of centraal in de Window_Manager , of dat elke Window zijn eigen Message queue mag doorlezen, het is nogal vaag allemaal.
Aangezien die Manager weet welke windows hij onder beheer heeft weet hij direct welk message voor welk window is.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:52

.oisyn

Moderator Devschuur®

Demotivational Speaker

farlane schreef op dinsdag 28 november 2006 @ 14:27:

Aangezien die Manager weet welke windows hij onder beheer heeft weet hij direct welk message voor welk window is.
Het vervelende is echter dat de windowproc wordt gecalled voor CreateWindow returned, dus op dat moment weet je de window handle nog niet :). Dit is een nadeel dat vrijwel alle manieren om een HWND aan een object instance te koppelen treft. Of je nou een std::map<HWND, Window*> gebruikt, of Get/SetProp, of Get/SetWindowLong, je bent altijd 'te laat' met de koppeling. Je zou een (thread local) globale variabele kunnen zetten voor de Window instance en de koppeling maken in de WindowProc als de koppeling nog niet bestaat.

Ik creëer zelf gewoon stukjes assembly code die de Window instance op de stack pusht voordat hij de algemene WindowProc aanroept, die naast de standaard 4 windproc parameters ook nog eens een Window instance verwacht. En die reroute de call dan weer naar een virtual functie op de Window instance. Op die manier kan elke subclass van Window z'n eigen windowproc implementeren.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1