Toon posts:

C++ Window Class

Pagina: 1
Acties:

Verwijderd

Topicstarter
HoI!

Ik ben bezig met het schrijven van een class om makkelijk windows mee aan te vragen in C++.
Ik krijg wat fouten en heb geeeen idee hoe ze op te lossen zijn.

Dit zijn de fouten:
--------------------Configuration: Windows Classer - Win32 Debug--------------------
Compiling...
class_window.cpp
Skipping... (no relevant changes detected)
main.cpp
Linking...
main.obj : error LNK2005: "public: bool __thiscall cWindowClass::Build(char *,unsigned long,int,int,int,int,char *)" (?Build@cWindowClass@@QAE_NPADKHHHH0@Z) already defined in class_window.obj
main.obj : error LNK2005: "public: virtual long __stdcall cWindowClass::Win_Proc(struct HWND__ *,unsigned int,unsigned int,long)" (?Win_Proc@cWindowClass@@UAGJPAUHWND__@@IIJ@Z) already defined in class_window.obj
main.obj : error LNK2005: "private: static long __stdcall cWindowClass::stWin_Proc(struct HWND__ *,unsigned int,unsigned int,long)" (?stWin_Proc@cWindowClass@@CGJPAUHWND__@@IIJ@Z) already defined in class_window.obj
Debug/Windows Classer.exe : fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.

Windows Classer.exe - 4 error(s), 0 warning(s)
Zo ziet mijn class eruit in mijn header bestand voor de class:

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
#ifndef CLASS_WINDOW_H
#define CLASS_WINDOW_H

#include <windows.h>                ///////// LET HIEROP DEZE REGEL /////////

//
// Class for windowing
//

class cWindowClass
{

private:
    
    static LRESULT CALLBACK stWin_Proc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
    
public:
    
    bool Build( LPSTR caption, DWORD window_style, int pos_left, int pos_top, int pos_height, int pos_width, LPSTR class_name );
    
    virtual LRESULT CALLBACK Win_Proc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

    /**
    * Handle van de window die bij deze class object hoort
    *
    * HWND      window_handle
    */
    HWND window_handle;
    
    
    /**
    * Handle naar Process
    *
    * @var  HINSTANCE       h_main_instance
    */
    HINSTANCE h_main_instance;
    

}; // end class cWindowClass


#endif // CLASS_WINDOW_H


Zo ziet mijn window_class.cpp eruit:

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//
// Class en functie prototypen
//
#include "class_window.h"

//
// Array met alle window handles
//
int window_handles[];



/**
* Functie die de window class bouwt en alles klaar zet zodat de window kan worden geregistreerd
* 
* @param    LPSTR       caption         De titel van het window
* @param    INT         border          Border type
* @param    INT         pos_left        Positie links( in pixels )
* @param    INT         pos_top         Positie top( in pixels )
* @param    INT         pos_height      Window hoogte
* @param    INT         pos_width       Window breedte
* @param    LPSTR       window_id       ID van de window in de array van windows
*/

bool cWindowClass::Build( LPSTR caption, DWORD window_style, int pos_left, int pos_top, int pos_height, int pos_width, LPSTR class_name )
{


    WNDCLASSEX wnd_class;
    HWND hwnd;

    // Maak het window aan
    wnd_class.cbSize        = sizeof( WNDCLASSEX );
    wnd_class.style         = 0;
    wnd_class.lpfnWndProc   = stWin_Proc;
    wnd_class.cbClsExtra    = 0;
    wnd_class.cbWndExtra    = 0;
    wnd_class.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wnd_class.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wnd_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wnd_class.lpszMenuName  = NULL;
    wnd_class.lpszClassName = class_name;
    wnd_class.hInstance     = this->h_main_instance;
    wnd_class.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    // Registreer het window
    RegisterClassEx(&wnd_class);
    
    //
    // Maak het scherm daadwerkelijk aan
    //

    hwnd = CreateWindowEx
        (
            NULL,                           // extended style
            class_name,                     // class name waar gegevens van window in staan
            caption,                        // titel van het schermpje
            window_style,
            pos_left,
            pos_top, // initial x(left),y(top)
            pos_width,
            pos_height, // initial width, height
            NULL, // handle to parent
            NULL, // handle to menu
            cWindowClass::h_main_instance ,// instance of this application
            NULL
        ); // end function CreateWindowEx
    
    // sla de HWND handle op
    this->window_handle = hwnd;

    if( !hwnd )
    {
        return(0);
    }
    
    
    return 0;
                

} // end function Build( .. )



/**
* Virtual functie pointer van de window
*
* @param        HWND        Window handle
* @param        UINT        Bericht
* @param        WPARAM      Info over bericht
* @param        LPARAM      Info over bericht
*
*/

LRESULT CALLBACK cWindowClass::Win_Proc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{

    switch(uMsg)
    {
        // Het scherm word gesloten
        case WM_DESTROY:
        {
            // then close it
            MessageBox( hWnd, "Test berichtje!!", "Sluiten", MB_OK );
            
            // PostQuitMessage( WM_QUIT );
            break;

        } // end case WM_DESTROY

        default:
        {
            
            // Process the left-over messages
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
        }
    } // end switch uMsg


    return DefWindowProc( hWnd, uMsg, wParam, lParam );

    
}

/**
* Static functie pointer van de window
*
* @param        HWND        Window handle
* @param        UINT        Bericht
* @param        WPARAM      Info over bericht
* @param        LPARAM      Info over bericht
*
*/
LRESULT CALLBACK cWindowClass::stWin_Proc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    
    if (uMsg == WM_NCCREATE) 
    {
        
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam );
    
} 



Zo word er een window aangemaakt:

C++:
1
2
3
cWindowClass c_wnd;
    c_wnd.h_main_instance = hinstance;
    c_wnd.Build( "Schermpie met menu :D", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 500, 400, "Window1" );



Nougoed, zoals je ziet is er een static callback functie en een virtual callback functie..
De static functie word aangeroepen voor windows, die zou de pointer van het echte window moeten vinden en dan doorsturen naar de virtual function..

Geen idee ofals dit goed is hoe ik dit bedenk, heb een voorbeeld bekeken die ook een class had om windows te maken en die deed het ook ongeveer zo.

Verder, hoe laat ik mijn windows allemaal apart van elkaar werken ? Ik bedacht een systeem om dit zo te doen:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
cWindowClass c_wnd;
    c_wnd.h_main_instance = hinstance;
    c_wnd.Build( "Schermpie met menu :D", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 500, 400, "Window1" );

// window word hier gestart, hier kunnen variablen worden ingesteld, knoppen worden aangemaakt enz enz enz
c_wnd.OnLoad()
{
}

// window word gesloten, hier kunnen geheugen dingen weer vrij worden gegeven
c_wnd.OnClose()
{
}


Is dit een normale/goede denkwijze ? Of word dit totaal anders gedaan..
Ben een newbie in het Win32 programmeren.

HoI! Chris.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13-02 18:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je krijgt multiple definition link errors. Dat wil dus zeggen dat bepaalde entiteiten (methods in dit geval) in zowel main.cpp als class_window.cpp worden gedefinieerd. Wild guess: include je soms class_window.cpp ipv class_window.h vanuit main.cpp?

Verder is je denkwijze min of meer goed, behalve de aanroepen van OnLoad en OnClose door usercode. Die functies kun je beter aanroepen adhv bepaalde window messages (WM_CREATE, WM_CLOSE). Ik zie trouwens dat het fetchen van de juiste cWindowClass instance bij een HWND nog niet hebt geïmplementeerd in cWindowClass::stWin_Proc. Heb je hier ook problemen mee?

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
Hmm.. Lastig lastig.. Het includen gaat ergens fout he..

Ik dacht dat ik bij de message loop kon kijken voor een WM_CREATE bericht, als ik die ontvang word de functie [object].onLoad() aangeroepen indien die bestaat..

Zo maak ik eigenlijk een beetje mijn eigen Visual Basic merk ik.. :P

  • compufreak88
  • Registratie: November 2001
  • Laatst online: 02-05-2025
Je wil een soort events creeren, maar dat gaat niet op deze manier.

Wat je op deze manier alleen maar doet is de methods van een class aanroepen, ipv dat je class die functies aanroept.

Het beste kun je gewoon een soort addhanlder maken, waarmee je bepaalde messages koppelt aan een functie.

Als je dan een message krijgt, dan ga je alle handlers bij langs, en als je dan de juiste message vindt, dan roep je die functie aan.

Verwijderd

Topicstarter
Dat is dus precies wat ik beodle.. Ik wil dat mijn class functies gaat aanroepen in de class, maar die functies die moeten buiten de class staan.. Maar toch een classe functie zijn..

Pff.. moeilijk uit te leggen dit! :D

  • compufreak88
  • Registratie: November 2001
  • Laatst online: 02-05-2025
Je hebt 2 manieren:

1:

Je maakt de prototypes aan voor elke event in de class

Buiten de class gebruik je dan
C++:
1
2
3
4
window::OnCreate()
{

}


Het nadeel hier van is dat je bij alle lidfuncties van de class kan.

2:

Je maakt in de class een functie:

C++:
1
int AddHandler(UINT Message, void(*func));


In die functie voeg je die message en die functie aan een map oid toe.

En als je dan de message krijgt dan ga je die map bij langs en kijk je of die functie daarvoor bestaat.

Verwijderd

Topicstarter
Denk dat ik het op de tweede manier ga oplossen.. Maar dan moet ik eerst nog die fouten weg zien te krijgen :{

Verwijderd

Topicstarter
Ik realiseer me net, als je :: wilt gebruiken dan moet dat met de class dat kan niet met een classe object..

Hoe wil je de windows dan apart van mekaar laten functioneren ?

  • compufreak88
  • Registratie: November 2001
  • Laatst online: 02-05-2025
Jah, daar had ik nog niet bij nagedacht. Dan wordt het dus de tweede manier waarop je dat moet doen...

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13-02 18:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

En als je voor die tweede manier gaat, gebruik dan geen losse functies maar interfaces voor het afhandelen van je events. Een andere manier is om de gebruiker je window class te laten extenden zodat hij zelf de functies in de class kan 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.


Verwijderd

Topicstarter
Hmm, we hebben het hier nu mischien wel over.. Maar ik heb alsnog die errors.. :{

Ik heb mijn project geupload, dan hebben jullie een beter inzicht op wat er goed/fout gaat..

Project url: http://www.2flirt.nl/wnd_classer.rar
Het probleem is dus dat het includen niet goed gaat..

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13-02 18:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zoals ik al zei
C++: main.cpp
30
#include "class_window.cpp"

Waarom include je in hemelsnaam de cpp file?

[ Voor 5% gewijzigd door .oisyn op 04-09-2006 14:36 ]

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
weet nie.. moest toch :D
Whaha, is dat de fout ? Omg :P Wat dom :P

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13-02 18:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mja, anders is het wellicht handig om nog even na te lezen wat het includen van files in C/C++ nou eigenlijk precies inhoudt.

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
Jah, snap dat inderdaad niet helemaal blijkbaar..
Ok, nu include ik enkel .h bestanden..

Alles gaat goed totdat ik de bodys van de class functies ga bouwen..
Er word verteld dat die de class niet kent..

Ik include dit in main.cpp:

code:
1
#include "header.h"


Daar staat de class body in( prototypes enz, geen functie bodys enkel prototypes )
Dan include ik de volgende bestanden in het bestand header.h:

code:
1
2
3
// Include de windows bestanden waar de Win32 api zich in bevind
#include <windows.h>
#include <windowsx.h>


Dus het bestand window_classer.cpp word nergens geinclude, window_classer.cpp staan alle functie bodys van de class in.

Helemaal vergeten debrij te vertellen wat de fouten zijn :D
--------------------Configuration: Window Wrapper - Win32 Debug--------------------
Compiling...
window_wrapper.cpp
C:\Documents and Settings\Eigenaar\Bureaublad\C++\Win32\Window Wrapper\window_wrapper.cpp(30) : error C2653: 'cWindowClass' : is not a class or namespace name
C:\Documents and Settings\Eigenaar\Bureaublad\C++\Win32\Window Wrapper\window_wrapper.cpp(30) : error C2065: 'LPSTR' : undeclared identifier
C:\Documents and Settings\Eigenaar\Bureaublad\C++\Win32\Window Wrapper\window_wrapper.cpp(30) : error C2146: syntax error : missing ')' before identifier 'caption'
C:\Documents and Settings\Eigenaar\Bureaublad\C++\Win32\Window Wrapper\window_wrapper.cpp(30) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
C:\Documents and Settings\Eigenaar\Bureaublad\C++\Win32\Window Wrapper\window_wrapper.cpp(30) : error C2059: syntax error : ')'
C:\Documents and Settings\Eigenaar\Bureaublad\C++\Win32\Window Wrapper\window_wrapper.cpp(31) : error C2143: syntax error : missing ';' before '{'
C:\Documents and Settings\Eigenaar\Bureaublad\C++\Win32\Window Wrapper\window_wrapper.cpp(31) : error C2447: missing function header (old-style formal list?)
main.cpp
Error executing cl.exe.

Window Wrapper.exe - 6 error(s), 1 warning(s)
Ik wil weten waarom ik die fouten krijg, wil ze zelf oplossen anders schiet ut niet erg op dan ben ik hier over een week weer:{

[ Voor 52% gewijzigd door Verwijderd op 04-09-2006 16:53 ]


Verwijderd

Topicstarter
Werkt eindelijk, maar waarom moet ik in iedere CPP file men .H files includen ?

Goede tutorial: waar is het includen voor, hoe werkt het( dat je er diep op ingaat ) en dat je alle filetypes uitlegt die je kunt kiezen bij het kiezen van een nieuw project.. Is volgens niet echt een tutorial/duidelijke uitleg over.. In het NL.

  • KopjeThee
  • Registratie: Maart 2005
  • Niet online
Verwijderd schreef op maandag 04 september 2006 @ 17:21:
Werkt eindelijk, maar waarom moet ik in iedere CPP file men .H files includen ?

Goede tutorial: waar is het includen voor, hoe werkt het( dat je er diep op ingaat ) en dat je alle filetypes uitlegt die je kunt kiezen bij het kiezen van een nieuw project.. Is volgens niet echt een tutorial/duidelijke uitleg over.. In het NL.
Heel kort (correct me if I'm wrong):

Je hebt in C++ een preprocessor. Een programmaatje dat draait voor de compiler. De preprocessor begrijpt regels die met een # beginnen (#include, #define #ifndef, #endif etc). De preprocessor is eigenlijk een geavanceerde knip en plak tool. Met een #include plak je de inhoud van een bepaalde file op de plaats van de #include. De header van een class (bla.h) heb je nodig op tenminste 2 plaatsen: de implementatie van de class (bla.cpp) en de plaats waar je de class gebruikt. Dus op beide plaatsen moet je die bla.h includen. Aan de andere kant wil je niet graag dat die code in bla.h 2 keer gekopieerd wordt (dan klaagt de compiler), vandaar dat je bla.h meestal zo is opgebouwd:

#ifndef __BLA
#define __BLA

// code

#endif

Dit zegt de preprocessor dat alleen als __BLA niet bestaat de code tot de endif gekopieerd moet worden.

Op deze manier zorg je altijd dat de plaats waar de code in bla.h het eerst wordt gebruikt de plaats wordt waar de code geplakt wordt.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23:54
Verwijderd schreef op maandag 04 september 2006 @ 17:21:
Werkt eindelijk, maar waarom moet ik in iedere CPP file men .H files includen ?

Goede tutorial: waar is het includen voor, hoe werkt het( dat je er diep op ingaat ) en dat je alle filetypes uitlegt die je kunt kiezen bij het kiezen van een nieuw project.. Is volgens niet echt een tutorial/duidelijke uitleg over.. In het NL.
Ik denk dat je even moet googlen over hoe het build proces er nou eigenlijk uitziet, wat er allemaal gebeurt als je een applicatie compileert.

En als je geen Engels kunt wordt het tijd om het te leren als je door wilt gaan met programmeren, anders kun je 95% van de informatiebronnen niet gebruiken en wordt het communiceren met anderen over deze discipline erg moeilijk.

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.


Verwijderd

Topicstarter
farlane schreef op dinsdag 05 september 2006 @ 08:48:
[...]


Ik denk dat je even moet googlen over hoe het build proces er nou eigenlijk uitziet, wat er allemaal gebeurt als je een applicatie compileert.

En als je geen Engels kunt wordt het tijd om het te leren als je door wilt gaan met programmeren, anders kun je 95% van de informatiebronnen niet gebruiken en wordt het communiceren met anderen over deze discipline erg moeilijk.
Je hoeft niet aan men engels te twijfelen.

@kopjethee: Heel erg bedankt, 100% duidelijk ;)
Pagina: 1