|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Leycarno Mini JLI'ler
Anmeldedatum: 27.06.2006 Beiträge: 16
Medaillen: Keine
|
Verfasst am: 09.09.2006, 16:50 Titel: Klasse für Windows |
|
|
Ich habe da ein kleines Problem - werden vielleicht noch mehr
Und zwar ersuche ich mir grade eine Klasse zu erstellen, mit der ich die Windows-Initialisierung objektorientiert abhandeln kann.
Folgender erster Stein an dem ich seit ner Weile knabber:
Code: |
void cWindows::Init(int width, int height)
{
// doppelte Initialisierung verhindern
if(this->hWnd != NULL)
return;
// ---------- WIN-Struktur definieren ----------
// Die Größe der Struktur(wird unter Windows häufig benötigt)
this->wndClass.cbSize = sizeof(WNDCLASSEX);
// Flags für spezielle Eigenschaften - hier Standard-Stile
this->wndClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
// Name der Funktion, die Nachrichten entgegen nimmt
this->wndClass.lpfnWndProc = this->MessageHandler; // <<< HIER IST DAS PROBLEM !
// Zusätzliche Angaben (unwichtig)
this->wndClass.cbClsExtra = 0;
// nicht benötigt (unwichtig)
this->wndClass.cbWndExtra = 0;
// Anwendungsinstanz
this->wndClass.hInstance = this->hInstance;
// Eigenschaften des Fenster-Hintergrundes (wirkt sich nicht auf DX aus)
this->wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
// Der Mauscursor, der erscheint, wenn die Maus über unserem Fenster ist
this->wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
// Soll Fenster Menu haben?
this->wndClass.lpszMenuName = NULL;
// wird noch in CreateWindowEx() benötigt
this->wndClass.lpszClassName ="WindowClass";
// Icons für das Fenster
this->wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
this->wndClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
//Fensterklase registrieren, damit sie von CreateWindowEx() benutzt werden kann
RegisterClassEx(&this->wndClass);
this->hWnd = CreateWindowEx(NULL, // Keine erweiterten Stile nutzen
"WindowClass", // Klassenname
"SpriteClass", // Fenstertitel
WS_POPUP | // Fenster
WS_VISIBLE, // Eigenschaften
0, 0, // Anfangsposition
width, height, // und Größe des Fensters
NULL, // Handle des Elternfensters
NULL, // Handle des Menüs
this->hInstance, // Anwendungsinstanz
NULL); // wird nicht benötigt
}
// ----------------------------------------------------------------------
// Diese Funktion wird von Windows aufgrufen, wenn
// eine Nachricht für das Programm vorliegt
LRESULT CALLBACK cWindows::MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// testen, um welche Nachricht es sich handelt
switch(msg)
{
// Programm beenden, wenn das Fenster
// geschlossen wird
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
case WM_KEYDOWN:
switch(wParam)
{
// ------------------------------------------------------------
// ----- Wenn ESC gedrückt, Programm beenden -----
// Diese Extra-Tastaturabfrage ist eigentlich nicht mehr nötig
// Zur Sicherheit vor Abstürzen, lasse ich sie erst mal drinn..
case VK_ESCAPE:
this->~cWindows(); // Destruktor aufrufen um das WinHandle zu zerstören
break;
// ----- Wenn ESC gedrückt, Programm beenden -----ENDE
// ------------------------------------------------------------
}
break;
}
// Standardnachrichtenverarbeitung von Windows
return DefWindowProc(this->hWnd, msg, wParam, lParam);
}
|
Fehlermeldung : error C2440: '=' : 'long (__stdcall cWindows::*)(struct HWND__ *,unsigned int,unsigned int,long)' kann nicht in 'long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)' konvertiert werden
Anscheinend ist das Problem, das der Message-Handler nicht als Methode akzeptiert wird...
Über Antworten wäre ich froh
Gruß Ley |
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 09.09.2006, 16:54 Titel: |
|
|
CPP: | class cWindows
{
...
static LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
};
|
Du müsstest die Methode static machen dann sollte es gehen. _________________ "I have a Core2Quad at 3.2GHz, 4GB of RAM at 1066 and an Nvidia 8800 GTS 512 on Vista64 and this game runs like ass whereas everything else I own runs like melted butter over a smokin' hot 18 year old catholic schoolgirl's arse." |
|
Nach oben |
|
|
Leycarno Mini JLI'ler
Anmeldedatum: 27.06.2006 Beiträge: 16
Medaillen: Keine
|
Verfasst am: 09.09.2006, 17:05 Titel: |
|
|
Danke für die schnelle Antwort
ich musste dafür jedoch alle this-Zeiger rausnehmen, was aber nicht unbedingt schlimm ist, da ich nun einfach statt den Desturktor aufzurufen, das Handle direkt zerstöre...
ist es sinnvoll in Destruktor diese Zeilen zu haben, damit das Windowshandle auch wirklich zerstört wird, oder ist es ausreichend, die Zerstörung im Message-Handler zu machen?
Code: |
cWindows::~cWindows(void)
{
// Windows-Handle zerstören
if(this->hWnd != NULL)
DestroyWindow(this->hWnd);
} |
bzw... muss ich was beachten, was ich bei einer Windows-Klasse im Konstruktor/Destruktor behandeln muss? |
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 09.09.2006, 17:08 Titel: |
|
|
Eigentlich sollte das der MessageHandler erledigen, im DTor kannst du aber eine Nachricht an das Fenster senden sich bitte zu vernichten wenn dies noch nicht passiert ist.
Was genau möchtest du denn über CTor und Dtor bei Klassen wissen? Eigentlich passiert da nicht vieles:
CTor: Variablen initialisieren wichtige Dinge aufbauen.
DTor: Speicher frei geben _________________ "I have a Core2Quad at 3.2GHz, 4GB of RAM at 1066 and an Nvidia 8800 GTS 512 on Vista64 and this game runs like ass whereas everything else I own runs like melted butter over a smokin' hot 18 year old catholic schoolgirl's arse." |
|
Nach oben |
|
|
Leycarno Mini JLI'ler
Anmeldedatum: 27.06.2006 Beiträge: 16
Medaillen: Keine
|
Verfasst am: 09.09.2006, 17:24 Titel: |
|
|
im Moment setzt der Konstruktor
HWND hWnd = NULL;
ich weiß nicht genau, ob ich das mit
HINSTANCE hInstance;
auch machen soll und ob ich evtl noch etwas im Destruktor machen muss...
Wobei whrscheinlich durch die Zerstörung des Fensters der SPeicher komplett freigegeben wird, zu dem ja auch die Struktur WNDCLASSEX wndClass gehört...
Im INet habe ich leider keine Klasse gefunden, bei der ich mal schaun kann, worauf ich achten muss... und da ich etwas wenig Ahnung von Windows-Programmierung habe weiß ich nicht worauf ich vor allem beim Speicher achten muss...
Ich mache erst mal weiter und versuche das zum Laufen zu bringen.
Es kommen sicherlich später noch etwas konkretere Fragen... |
|
Nach oben |
|
|
Leycarno Mini JLI'ler
Anmeldedatum: 27.06.2006 Beiträge: 16
Medaillen: Keine
|
Verfasst am: 09.09.2006, 19:37 Titel: |
|
|
ok, hier mal die Klasse und ihre Einbindung
Main.h
CPP: | #ifndef _LEY_MAIN_H_
#define _LEY_MAIN_H_
// Größe der Anwendung definieren
#define LEY_SCR_WIDTH 1024
#define LEY_SCR_HEIGHT 768
// Klasse zum Erstellen eines Objektes, das den Programmablauf steuert
#include "LeyWin.h"
#endif // _LEY_MAIN_H_
|
Main.cpp
CPP: | #include "main.h"
// ------------------------------------------------------------
// Windows main-Funktion
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// --------------------------------------------------------
// Windows Objekt erstellen und initialisieren
cWindows Windows;
if (!Windows.Init(LEY_SCR_WIDTH, LEY_SCR_HEIGHT))
{
// Fehler ist aufgetreten - beenden!
return 0;
}
// --------------------------------------------------------
// Programm-Object erstellen und initialisieren
cLeyWin LeyWin;
LeyWin.Init(Windows.getWnd(), Windows.getInstance());
// --------------------------------------------------------
// ***--------------------------------------------------***
// Schleife, bis Windows sich selbst zerstört...
while(Windows.getMessage().message != WM_QUIT)
{
// ----------------------------------------------------
// ----- PROGRAMMVERLAUF -----
LeyWin.Run(Windows.RefreshAndGetTime());
// --- PROGRAMMVERLAUF --- ENDE
// ----------------------------------------------------
}
// ***--------------------------------------------------***
return 0;
}
|
windows.h
CPP: | #ifndef _LEY_WINDOWS_H_
#define _LEY_WINDOWS_H_
// Einbinden des Win-Headers von Microsoft
#include <windows.h>
// **********************************************************************
class cWindows
{
public:
cWindows(void);
~cWindows(void);
// Windows initialisieren, Übergabe der gewünschten Fenstergröße
bool Init(int width, int height);
// Zugriff auf Handler
// wichtig für DirectX
HWND getWnd(void);
HINSTANCE getInstance(void);
// Zugriff auf die Nachrichten
// wichtig für die Schleife
MSG getMessage(void);
// Verarbeitung eventuell vorhandener Nachrichten
// und Rückgabe der vergangenen Zeit
double RefreshAndGetTime();
private:
HWND hWnd;
HINSTANCE hInstance;
MSG Msg;
// Deklarieren der Struktur WNDCLASSEX, in der unsere Fenster-Daten gespeichert werden.
WNDCLASSEX wndClass;
// Funktion zur Nachrichtenverarbeitung,
static LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
// interne TimerVariablen zur Steuerung der Geschwindigkeit
LONGLONG Frequency, CurrentTime, LastTime;
double TimeElapsed, TimeScale;
bool CounterAvailable;
};
#endif // _LEY_WINDOWS_H_
|
windows.cpp
CPP: | #include "windows.h"
// ----------------------------------------------------------------------
cWindows::cWindows(void)
{
this->hWnd = NULL;
this->hInstance = NULL;
}
// ----------------------------------------------------------------------
cWindows::~cWindows(void)
{
}
// ----------------------------------------------------------------------
bool cWindows::Init(int width, int height)
{
// doppelte Initialisierung verhindern
if(this->hWnd != NULL)
return false;
// ---------- WIN-Struktur definieren ----------
// Die Größe der Struktur(wird unter Windows häufig benötigt)
this->wndClass.cbSize = sizeof(WNDCLASSEX);
// Flags für spezielle Eigenschaften - hier Standard-Stile
this->wndClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
// Name der Funktion, die Nachrichten entgegen nimmt
this->wndClass.lpfnWndProc = this->MessageHandler;
// Zusätzliche Angaben (unwichtig)
this->wndClass.cbClsExtra = 0;
// nicht benötigt (unwichtig)
this->wndClass.cbWndExtra = 0;
// Anwendungsinstanz
this->wndClass.hInstance = this->hInstance;
// Eigenschaften des Fenster-Hintergrundes (wirkt sich nicht auf DX aus)
this->wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
// Der Mauscursor, der erscheint, wenn die Maus über unserem Fenster ist
this->wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
// Soll Fenster Menu haben?
this->wndClass.lpszMenuName = NULL;
// wird noch in CreateWindowEx() benötigt
this->wndClass.lpszClassName ="WindowClass";
// Icons für das Fenster
this->wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
this->wndClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
//Fensterklase registrieren, damit sie von CreateWindowEx() benutzt werden kann
RegisterClassEx(&this->wndClass);
this->hWnd = CreateWindowEx(NULL, // Keine erweiterten Stile nutzen
"WindowClass", // Klassenname
"SpriteClass", // Fenstertitel
WS_POPUP | // Fenster
WS_VISIBLE, // Eigenschaften
0, 0, // Anfangsposition
width, height, // und Größe des Fensters
NULL, // Handle des Elternfensters
NULL, // Handle des Menüs
this->hInstance, // Anwendungsinstanz
NULL); // wird nicht benötigt
// Wenn der Rückgabewert 0 ist, ist ein Fehler aufgetreten
if(0 == hWnd)
{
MessageBox(0,"Fenster konnte nicht erzeugt werden","Fehler",MB_OK);
return false;
}
// --------------------------------------------
// --- Timer initialisieren ---
this->CounterAvailable = false;
if (QueryPerformanceFrequency( (LARGE_INTEGER*) &this->Frequency))
{
this->CounterAvailable = true;
this->TimeScale = 1.0/Frequency;
QueryPerformanceCounter( (LARGE_INTEGER*) &this->LastTime);
}
else
{
this->LastTime = timeGetTime();
this->TimeScale = 0.001;
}
// --- Timer initialisiert ---
// --------------------------------------------
// alles ok, Windows ist bereit
return true;
}
// ----------------------------------------------------------------------
HWND cWindows::getWnd(void) { return this->hWnd; }
HINSTANCE cWindows::getInstance(void) { return this->hInstance; }
MSG cWindows::getMessage(void) { return this->Msg; }
// ----------------------------------------------------------------------
double cWindows::RefreshAndGetTime()
{
// Wenn eine Nachricht vorliegt, wird diese zur Bearbeitung weitergeleitet.
while(GetMessage(&this->Msg ,NULL, 0, 0))
{
TranslateMessage(&this->Msg);
DispatchMessage (&this->Msg);
}
// ------------------------------------
// --- Timer aktualisieren ---
if (this->CounterAvailable)
QueryPerformanceCounter((LARGE_INTEGER*) &this->CurrentTime);
else
this->CurrentTime = timeGetTime();
this->TimeElapsed = (this->CurrentTime - LastTime) * this->TimeScale;
this->LastTime = this->CurrentTime;
// --- Timer aktualisiert ---
// ------------------------------------
// Rückgabe der vergangenen Zeit
return this->TimeElapsed;
}
// ----------------------------------------------------------------------
// Diese Funktion wird von Windows aufgrufen, wenn
// eine Nachricht für das Programm vorliegt
LRESULT CALLBACK cWindows::MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// testen, um welche Nachricht es sich handelt
switch(msg)
{
// Programm beenden, wenn das Fenster
// geschlossen wird
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
case WM_KEYDOWN:
switch(wParam)
{
// ------------------------------------------------------------
// ----- Wenn ESC gedrückt, Programm beenden -----
// Diese Extra-Tastaturabfrage ist eigentlich nicht mehr nötig
// Zur Sicherheit vor Abstürzen, lasse ich sie erst mal drinn..
case VK_ESCAPE:
DestroyWindow(hwnd);
break;
// ----- Wenn ESC gedrückt, Programm beenden -----ENDE
// ------------------------------------------------------------
}
break;
}
// Wenn die Nachricht keine der oben aufgeführten ist,
// kümmert sich Windows um ihre Abarbeitung (mit einem Standardvorgang)
return DefWindowProc(hwnd, msg, wParam, lParam);
}
|
Wäre super, wenn ihr eure Verbesserungsvorschläge zum Besten geben würdet
Gruß Ley |
|
Nach oben |
|
|
Kampfhund Super JLI'ler
Alter: 42 Anmeldedatum: 20.07.2002 Beiträge: 408
Medaillen: Keine
|
Verfasst am: 10.09.2006, 02:34 Titel: |
|
|
Das hier ist vielleicht ganz nützlich. _________________ Kochen ist ein NP-schweres Optimierungsproblem. |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|