Windowsfenster



  • Hallo,
    ich habe den folgenden Code für ein Windowsfenster:

    /*
        Jetzt lerne ich Spieleprogrammierung mit DirectX und Visual C++
    
        Listing:      11.1
    
        Programmname: Hello Windows
    
        Beschreibung: Dieses Programm zeigt ein einfaches Windows-Programm
    
                      Führen Sie das Programm durch Drücken
                      der Tastenkombination Strg +  F5 aus.
    */
    
    // Headerdatei
    #include <windows.h>
    
    // Anwendungsfenster erzeugen
    HWND CreateMainWindow(HINSTANCE hInstance);
    
    //Callback Funktion zur Nachrichtenbehandlung
    LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
    
    // Das Fensterhandle
    HWND hWnd = 0;
    
    // Windows main-Funktion
    int WINAPI WinMain(HINSTANCE hInstance,      // Handle der Programminstanz
                       HINSTANCE hPrevInstance,  // Handle der letzten Instanz
                       LPSTR lpCmdLine,          // Kommandozeile
                       int nCmdShow)             // Art wie das Fenster angezeigt werden soll
    {   
        // Fenster erzeugen und Handle speichern
        hWnd = CreateMainWindow(hInstance);
    
        // Wenn der Rückgabewert 0 ist, ist ein Fehler aufgetreten
        if(0 == hWnd)
        {
            MessageBox(0,"Fenster konnte nicht erzeugt werden","Fehler",MB_OK);
            return 0;
        }
    
    	// Struktur, in der Informationen zur Nachricht gespeichert werden
        MSG msg;
    
        // Diese Schleife läuft bis die Nachricht WM_QUIT empfangen wird
        while(GetMessage(&msg,NULL,0,0))
    	{
        		// Nachricht an die Callbackfunktion senden
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
        }
    
        // Rückgabewert an Windows
        return 0;
    }
    
    HWND CreateMainWindow(HINSTANCE hInstance)
    {
        WNDCLASSEX wndClass;                                   // WNDCLASSEX Struktur
    
        // Struktur initialisieren
        wndClass.cbSize        = sizeof(WNDCLASSEX);           // Größe angeben (nie vergessen!)
        wndClass.style         = CS_DBLCLKS | CS_OWNDC |
                                 CS_HREDRAW | CS_VREDRAW;      // Standard Stile
        wndClass.lpfnWndProc   = MessageHandler;               // Die Callback Funktion angeben
    
        wndClass.cbClsExtra    = 0;                            // Zusätzliche Angaben, wird nicht benötigt
        wndClass.cbWndExtra    = 0;                            // Zusätzliche Angaben, wird nicht benötigt
        wndClass.hInstance     = hInstance;                    // Anwendungsinstanz
    
        wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);  // Weisser Pinsel
        wndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);  // Normaler Cursor
        wndClass.lpszMenuName  = NULL;                         // Das Fenster hat kein Menü
        wndClass.lpszClassName = "WindowClass";                // Der Name der Klasse
        wndClass.hIcon         = LoadIcon(NULL, IDI_WINLOGO);  // Windows Logo
        wndClass.hIconSm       = LoadIcon(NULL, IDI_WINLOGO);  // Windows Logo
    
        RegisterClassEx(&wndClass);
    
        return CreateWindowEx(NULL,                   // Keine erweiterten Stile nutzen
                              "WindowClass",          // Klassenname
                              "Hello Windows",        // Fenstertitel
                              WS_OVERLAPPEDWINDOW |   // Fenster
                              WS_VISIBLE,             // Eigenschaften
                              0, 0, 400, 300,         // Anfangsposition und Größe
                              NULL,                   // Handle des Elternfensters
                              NULL,                   // Handle des Menüs
                              hInstance,              // Anwendungsinstanz
                              NULL);                  // wird nicht benötigt
    }
    
    // Diese Funktion wird von Windows aufgrufen, wenn eine Nachricht
    // für Ihr Programm vorliegt
    LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        // testen, um welche Nachticht es sich handelt
        switch(msg)
        {
            // wenn das Fenster geschlossen wird, eine Nachricht senden,
            // die das Programm beendet
            case WM_DESTROY:
                        PostQuitMessage(0);
                        return 0;
                    break;       
        }
    
        // Wenn wir uns nicht um die Nachricht gekümmert haben
        // wird sie an die Standardnachrichtenverarbeitung von Windows
        // geschickt
        return (DefWindowProc(hwnd, msg, wParam, lParam));
    }
    

    Duzu hätte ich eine Frage, und zwar wie ich die Funktion
    HWND CreateMainWindow(HINSTANCE hInstance) samt Prototyp in eine headerdatei "reinpacken" kann, und die dateien nicht mehr zu sehen brauch, sondern nurnoch per #include einbinden muss.
    Ich bedanke mcih selbstverständlich für Antworten 🙂



  • Du fügst deinem Projekt einfach noch 2 Dateien hinzu: eine Header-Datei (.h) in die du die Deklaration / Funktionsprototyp packst und eine Quellcode-Datei (.cpp) in die du die Definitionen packst 🙂



  • moin meister ...

    überhaupt nicht ! In Header komt kein Code.

    Lege eine base.c Datei an schreibe dort den Code hin. Erstelle eien base.h mit den Prototypen und fertig.

    mfg
    RB



  • Das hat auch keine performenceeinbußen oder?



  • Ich nutze c++ muss ich unbedingt c dateien einbinden, kannst du vieleicht ein bsp geben für mein problem, ich bin noch recht neu und verstehe das noch nicht so richtig. Ich weis zwar wie funktionen... funktionieren aber das klappt nicht
    Bedanke mich schonma für die hilfe



  • Ich hab die Lösung:
    Cpp:

    // Headerdatei
    #include <windows.h>
    #include "asd.h"
    
    // Windows main-Funktion
    int WINAPI WinMain(HINSTANCE hInstance,      // Handle der Programminstanz
                       HINSTANCE hPrevInstance,  // Handle der letzten Instanz
                       LPSTR lpCmdLine,          // Kommandozeile
                       int nCmdShow)             // Art wie das Fenster angezeigt werden soll
    {   
        // Fenster erzeugen und Handle speichern
        hWnd = CreateMainWindow(hInstance);
    
        // Wenn der Rückgabewert 0 ist, ist ein Fehler aufgetreten
        if(0 == hWnd)
        {
            MessageBox(0,"Fenster konnte nicht erzeugt werden","Fehler",MB_OK);
            return 0;
        }
    
    	// Struktur, in der Informationen zur Nachricht gespeichert werden
        MSG msg;
    
        // Diese Schleife läuft bis die Nachricht WM_QUIT empfangen wird
        while(GetMessage(&msg,NULL,0,0))
    	{
        		// Nachricht an die Callbackfunktion senden
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
        }
    
        // Rückgabewert an Windows
        return 0;
    }
    
    // Diese Funktion wird von Windows aufgrufen, wenn eine Nachricht
    // für Ihr Programm vorliegt
    LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        // testen, um welche Nachticht es sich handelt
        switch(msg)
        {
            // wenn das Fenster geschlossen wird, eine Nachricht senden,
            // die das Programm beendet
            case WM_DESTROY:
                        PostQuitMessage(0);
                        return 0;
                    break;       
        }
    
        // Wenn wir uns nicht um die Nachricht gekümmert haben
        // wird sie an die Standardnachrichtenverarbeitung von Windows
        // geschickt
        return (DefWindowProc(hwnd, msg, wParam, lParam));
    }
    

    Header:

    //Callback Funktion zur Nachrichtenbehandlung
    LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
    
    // Das Fensterhandle
    HWND hWnd = 0;
    
    // Anwendungsfenster erzeugen
    
    HWND CreateMainWindow(HINSTANCE hInstance)
    {
        WNDCLASSEX wndClass;                                   // WNDCLASSEX Struktur
    
        // Struktur initialisieren
        wndClass.cbSize        = sizeof(WNDCLASSEX);           // Größe angeben (nie vergessen!)
        wndClass.style         = CS_DBLCLKS | CS_OWNDC |
                                 CS_HREDRAW | CS_VREDRAW;      // Standard Stile
        wndClass.lpfnWndProc   = MessageHandler;               // Die Callback Funktion angeben
    
        wndClass.cbClsExtra    = 0;                            // Zusätzliche Angaben, wird nicht benötigt
        wndClass.cbWndExtra    = 0;                            // Zusätzliche Angaben, wird nicht benötigt
        wndClass.hInstance     = hInstance;                    // Anwendungsinstanz
    
        wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);  // Weisser Pinsel
        wndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);  // Normaler Cursor
        wndClass.lpszMenuName  = NULL;                         // Das Fenster hat kein Menü
        wndClass.lpszClassName = "WindowClass";                // Der Name der Klasse
        wndClass.hIcon         = LoadIcon(NULL, IDI_WINLOGO);  // Windows Logo
        wndClass.hIconSm       = LoadIcon(NULL, IDI_WINLOGO);  // Windows Logo
    
        RegisterClassEx(&wndClass);
    
        return CreateWindowEx(NULL,                   // Keine erweiterten Stile nutzen
                              "WindowClass",          // Klassenname
                              "Hello Windows",        // Fenstertitel
                              WS_OVERLAPPEDWINDOW |   // Fenster
                              WS_VISIBLE,             // Eigenschaften
                              0, 0, 400, 300,         // Anfangsposition und Größe
                              NULL,                   // Handle des Elternfensters
                              NULL,                   // Handle des Menüs
                              hInstance,              // Anwendungsinstanz
                              NULL);                  // wird nicht benötigt
    }
    

    Es läst sich kompielieren 🙂
    Hat diese Schreibweise ihrgendwelche nachteile oder performenceeinschrenkungen oder so?



  • moin meister ...

    in eine Header kommt kein Code, und keine globalen Variablen !!!

    x.cpp:

    func()
    {

    }

    x.h
    #ifndef _x_h_
    #define _x_h_

    func();

    #endif // x_h_

    wenn es Dir nur darum geht, die Funktion WinMain nicht in Deinem Code zu sehen
    würde ich eine start.cpp und start.h anlegen mit WinMain anlegen.

    Der MessageHandler ist in jedem Programm anders also kommt er nicht mit in start.cpp

    Anstatt dessen kommt in start.h

    extern LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

    Da hast Du die Möglichkeit praktisch vorzugeben, daß es eine Funktion mit dem Namen MessageHandler geben muß ( in irgend einer anderen *.cpp Deines Projektes) sonst kommt es schon mal zu einem Fehler beim Linken.

    Jetzt ist auch sichergestellt, daß diese Zeile korrekt ist

    start.cpp
    ...
    wndClass.lpfnWndProc = MessageHandler;
    ...

    Oder Du machst Dir nen großen Merkzettel das eine solche Vorhanden sein muß.

    Performanceverluste habe ich durch Modularisierung noch nicht feststellen können 🤡

    mfg
    RB



  • ...??? Ich verstehe nicht so ganz. Kannst du das bitte an meinem Code mal anwenden und posten, damit ich das verstehe wie du das meinst.



  • Was gibt es dann da nicht zu verstehen - du hast jetzt doch außerdem schon ein Beispiel bekommen!
    Wenn dir das nicht weiterhilft würde ich dir sehr empfehlen erstmal ein C/C++ Buch zu lesen 🕶



  • RED-BARON schrieb:

    #ifndef _x_h_
    #define _x_h_

    Kleine Bemerkung am Rande:
    Das Präprozessorsymbol darf nicht mit einem Unterstrich beginnen (steht so im Standard).
    Es muss also so heißen:
    #ifndef X_H_
    #define X_H_

    #endif



  • Sorry, ber ich verstehe nicht ganz wie ich das anwenden soll 😞 ,
    kann einer von euch das mal an meinein code anwenden, damit ich sehe wie man das anwendet.
    Bedanke mich an alle die schon geschrieben haben und werden 😉



  • Was bedeutet zum bsp der befehl #ifndef???



  • Damit überprüfst du, ob die Konstante noch nicht definiert ist 😉



  • @Gott der 2.: Du stellst dich ja blöde an. Der erste Tipp reicht schon vollkommen aus. Mach dir eine Headerdatei (*.h), in du die Deklarationen der Funktionen und Konstanten schreibst. Sowas wie

    HWND CreateMainWindow(HINSTANCE hInstance);
    

    In die dazugehörigen cpp-Datei (*.cpp) kommt dann der dazugehörige Code. Also sowas wie

    HWND CreateMainWindow(HINSTANCE hInstance) 
    { 
        WNDCLASSEX wndClass;                                   // WNDCLASSEX Struktur 
    
        // Struktur initialisieren 
        wndClass.cbSize        = sizeof(WNDCLASSEX);           // Größe angeben (nie vergessen!) 
        wndClass.style         = CS_DBLCLKS | CS_OWNDC | 
                                 CS_HREDRAW | CS_VREDRAW;      // Standard Stile 
        wndClass.lpfnWndProc   = MessageHandler;               // Die Callback Funktion angeben 
       ...
       ...
    }
    

    Das ist die herkömmliche Methode, um Code auszulagern.


Anmelden zum Antworten