JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=ff9e07da1626c4e98efea524eda40d64Medaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Klasse für Windows

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Leycarno
Mini JLI'ler



Anmeldedatum: 27.06.2006
Beiträge: 16

Medaillen: Keine

BeitragVerfasst am: 09.09.2006, 16:50    Titel: Klasse für Windows Antworten mit Zitat

Ich habe da ein kleines Problem - werden vielleicht noch mehr Very Happy
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
Benutzer-Profile anzeigen Private Nachricht senden
Fallen
JLI MVP
JLI MVP


Alter: 40
Anmeldedatum: 08.03.2003
Beiträge: 2860
Wohnort: Münster
Medaillen: 1 (mehr...)

BeitragVerfasst am: 09.09.2006, 16:54    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Leycarno
Mini JLI'ler



Anmeldedatum: 27.06.2006
Beiträge: 16

Medaillen: Keine

BeitragVerfasst am: 09.09.2006, 17:05    Titel: Antworten mit Zitat

Danke für die schnelle Antwort Smile

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
Benutzer-Profile anzeigen Private Nachricht senden
Fallen
JLI MVP
JLI MVP


Alter: 40
Anmeldedatum: 08.03.2003
Beiträge: 2860
Wohnort: Münster
Medaillen: 1 (mehr...)

BeitragVerfasst am: 09.09.2006, 17:08    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Leycarno
Mini JLI'ler



Anmeldedatum: 27.06.2006
Beiträge: 16

Medaillen: Keine

BeitragVerfasst am: 09.09.2006, 17:24    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
Leycarno
Mini JLI'ler



Anmeldedatum: 27.06.2006
Beiträge: 16

Medaillen: Keine

BeitragVerfasst am: 09.09.2006, 19:37    Titel: Antworten mit Zitat

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 Wink

Gruß Ley
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Kampfhund
Super JLI'ler


Alter: 42
Anmeldedatum: 20.07.2002
Beiträge: 408

Medaillen: Keine

BeitragVerfasst am: 10.09.2006, 02:34    Titel: Antworten mit Zitat

Das hier ist vielleicht ganz nützlich.
_________________
Kochen ist ein NP-schweres Optimierungsproblem.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
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

Impressum