Zweites Fenster erzeugen



  • Hallo,

    danke für die Antworten, aber im Moment fällt es mir ziemlich schwer, das zu verstehen. Inwiefern soll ich meinen Ressourcen einen Dialog hinzufügen? Das klingt alles ziemlich kompliziert. Könntest du das etwas, nunja, genauer schreiben? Ich bin nämlich noch Anfänger und noch nicht so geübt im Umgang mit Fenstern ^^



  • Hi,
    erstmal 7 Sachen vorweg 😃 :
    1. Deine Anwendung ist nicht Zeichensatz unabhängig (ANSI/UNICODE).
    2. Das hier ist falsch:

    Itachi schrieb:

    CreateSolidBrush(RGB(999, 999, 999));
    

    RGB-Farbwerte setzen sich aus Teilwerten im Bereich von 0-255 zusammen. 999 ist viel zu groß!
    3. Von dieser Definition hier:

    Itachi schrieb:

    HWND hwndButton;
    

    in Deiner 'WndProc' hast Du rein gar nichts, da diese Variable nicht statisch ist und so ihren Wert nach WM_CREATE nicht behält.
    4. Du musst den Brush 'MyBrush' auch wieder freigeben, sonst gibts ein GDI-Leak (siehe WinMain).
    5. Es empfiehlt sich folgende Definitionen in den WM_PAINT-Handler mit hinein zunehmen, da diese Variablen auch nur als Reaktion auf WM_PAINT benötigt werden, nicht bei jeder Nachricht. Das ist etwas performanter.

    Itachi schrieb:

    HDC hdc;
            PAINTSTRUCT ps;
    

    6. Bei WM_PAINT fehlt das 'return (0);' 😉 .
    7. Es empfielt sich ID's (von Child-Controls) via #define o.ä. vorher festzulegen; dann behält man leichter den Überblick.

    Hier mal eine korrigierte Version die auch 2 Fenster erstellt (ohne Dialoge); die Nachrichten werden getrennt in 2 Message-Loops abgehandelt (Der Code ist getestet und sollte einwandfrei funktionieren).

    #include <windows.h>
    
    #define BTN_MAIN_BUTTON_ID	1
    #define BTN_SUB_BUTTON_ID	2 // ID's können auch gleich sein, da getrennte WndProc's
    
    LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);
    LRESULT CALLBACK SubWndProc	(HWND,UINT,WPARAM,LPARAM);
    
    int WINAPI WinMain(HINSTANCE hI, HINSTANCE hPrI, PSTR szCmdLine, int iCmdShow)
    {
        TCHAR szMainClass[] = TEXT("Main Window Class"),
    		  szSubClass[]  = TEXT("Sub Window Class");
        HBRUSH hbBkgndBrush = CreateSolidBrush(RGB(0, 255, 255)); // Farbe: Magenta
    
        WNDCLASS wc;
        wc.style         = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc   = MainWndProc;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = hI;
        wc.hIcon         = LoadIcon(NULL, IDI_INFORMATION);
        wc.hCursor       = 0;
        wc.hbrBackground = hbBkgndBrush;
        wc.lpszMenuName  = NULL;
        wc.lpszClassName = szMainClass;
    
        if(!RegisterClass(&wc))
    	{
    		MessageBox(NULL, TEXT("Fehler beim Registrieren der Fensterklasse!"),
    				   NULL, MB_OK | MB_ICONERROR);
    		return (0);
    	}
    
    	// Hier Änderungen die das 2. Fenster betreffen:
    	wc.lpfnWndProc   = SubWndProc;
    	wc.lpszClassName = szSubClass;
        if(!RegisterClass(&wc))
    	{
    		MessageBox(NULL, TEXT("Fehler beim Registrieren der Fensterklasse!"),
    				   NULL, MB_OK | MB_ICONERROR);
    		return (0);
    	}
    
        HWND hWndMain = CreateWindow(szMainClass, TEXT("Erstes Fenster"),
                                 WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX,
                                 50,                // Erster Wert: Abstand des Fensters zum linken Bildschirmrand.
                                 200,               // Zweiter Wert: Abstand des Fensters zum oberen Bildschirmrand.
                                 490,               // Dritter Wert: Fensterbreite.
                                 120,               // Vierter Wert: Fensterhöhe.
                                 NULL, NULL, hI, NULL);
    
        ShowWindow(hWndMain, iCmdShow);
        UpdateWindow(hWndMain);
    
        HWND hWndSub = CreateWindow(szSubClass, TEXT("Zweites Fenster"),
                             WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX,
                             50 + 490,          // Erster Wert: Abstand des Fensters zum linken Bildschirmrand.
                             200,               // Zweiter Wert: Abstand des Fensters zum oberen Bildschirmrand.
                             490,               // Dritter Wert: Fensterbreite.
                             120,               // Vierter Wert: Fensterhöhe.
                             NULL, NULL, hI, NULL);
    
        ShowWindow(hWndSub, iCmdShow);
        UpdateWindow(hWndSub);
    
        // Message handeln START
        MSG msg;
    
        while(GetMessage(&msg, NULL, 0, 0))
        {
              TranslateMessage(&msg);
              DispatchMessage(&msg);
        }
    
        DeleteObject(hbBkgndBrush);
    
        return (static_cast<int>(msg.wParam));
    
    }
    
    // Window Procedure of the first window:
    LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
    {
    	static HWND hWndButton;
    
    	switch(uiMessage)
    	{
    		case WM_CREATE:    
    			hWndButton = CreateWindow(TEXT("BUTTON"), TEXT("-> Blub <-"),
                                          WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
                                          155, 40, 170, 30, hWnd,
    									  reinterpret_cast<HMENU>(BTN_MAIN_BUTTON_ID),
                                          reinterpret_cast<HINSTANCE>(GetWindowLongPtr(hWnd, GWL_HINSTANCE)),
    									  NULL);
    			return (0);
    
    		case WM_PAINT: {
    			PAINTSTRUCT ps;
    			HDC hdc = BeginPaint(hWnd, &ps);
    			SetBkMode(hdc, TRANSPARENT); // Macht den weißen Texthintergrund transparent.
    			SetTextColor(hdc, RGB(0,0,0)); // Mit den RGB-Werten wird die Textfarbe festgelegt.
    			TextOut(hdc, 3, 5, TEXT("1. Fenster"), lstrlen(TEXT("1. Fenster")));
    			EndPaint(hWnd, &ps);
    			return (0); }
    
    		case WM_COMMAND:
    			return (0);
    
    		case WM_DESTROY:
    			PostQuitMessage(0);
    			return (0);
    	}
    	return (DefWindowProc(hWnd, uiMessage, wParam, lParam));
    }
    
    // Window Procedure of the second window:
    LRESULT CALLBACK SubWndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
    {
    	static HWND hWndButton;
    
    	switch(uiMessage)
    	{
    		case WM_CREATE:    
    			hWndButton = CreateWindow(TEXT("BUTTON"), TEXT("-> Blah <-"),
                                          WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
                                          155, 40, 170, 30, hWnd,
    									  reinterpret_cast<HMENU>(BTN_SUB_BUTTON_ID),
                                          reinterpret_cast<HINSTANCE>(GetWindowLongPtr(hWnd, GWL_HINSTANCE)),
    									  NULL);
    			return (0);
    
    		case WM_PAINT: {
    			PAINTSTRUCT ps;
    			HDC hdc = BeginPaint(hWnd, &ps);
    			SetBkMode(hdc, TRANSPARENT); // Macht den weißen Texthintergrund transparent.
    			SetTextColor(hdc, RGB(0,0,0)); // Mit den RGB-Werten wird die Textfarbe festgelegt.
    			TextOut(hdc, 3, 5, TEXT("2. Fenster"), lstrlen(TEXT("2. Fenster")));
    			EndPaint(hWnd, &ps);
    			return (0); }
    
    		case WM_COMMAND:
    			return (0);
    
    		case WM_DESTROY:
    			PostQuitMessage(0);
    			return (0);
    	}
    	return (DefWindowProc(hWnd, uiMessage, wParam, lParam));
    }
    

    Da drin sollten die oben aufgelisteten Fehler korrigiert sein. Guck Dir das mal an und versuch es auch zuverstehen 😉 .
    Nochwas zum Code: 'GetWindowLongPtr' ist im Gegensatz zu 'GetWindowLong' eine 64-Bit kompatible Version dieser Funktion. Ein reinterpret_cast bzw. static_cast sind Cast-Operatoren aus C++ 😋 .

    -------------------------------------------

    PS: @Mr Evil: Wenn Du es richtig gemacht hast, sollte dieser Cast unnötig sein und Du solltest ihn weglassen 😉 :

    Mr Evil schrieb:

    ::DialogBox(m_hInstance, MAKEINTRESOURCE(IDD_DIALOG), m_ParentWnd, (DLGPROC)DlgProg);
    


  • Hallo CodeFinder,

    du glaubst gar nicht, wie dankbar ich dir bin! Es funktioniert alles bestens. Genau so wollte ich das haben. Einige kleine Abschnitte des Codes verstehe ich zwar noch nicht ganz, aber im Großen und Ganzen ist alles nachvollziehbar.

    Ich danke dir vielmals 😃

    Gruß,
    Itachi (jetzt auch angemeldet *g*)



  • Jupp, kein Problem. Wenn Du willst kannst Du auch noch fragen, falls etwas unklar ist - oder einfach mal googeln 😉 .



  • CodeFinder schrieb:

    Jupp, kein Problem. Wenn Du willst kannst Du auch noch fragen, falls etwas unklar ist - oder einfach mal googeln 😉 .

    Hallo,

    drei Fragen haben sich da noch aufgeworfen 😉

    1. Weißt Du, wie ich TextOut mehrzeilig machen kann?
    2. Weißt Du auch, wie ich die Font und Schriftgröße des mit TextOut ausgegebenen Textes ändern kann?
    3. Kannst Du mir sagen, wie ich Musik in ein Projekt integriere und sie auch von dort mit PlaySound abspiele?

    Das wäre dann auch alles. Würde mich über Hilfe freuen 🙂

    Greetz



  • Itachi schrieb:

    1. Weißt Du, wie ich TextOut mehrzeilig machen kann?

    Ja es mehrfach, evtl. in einer Schleife, aufrufen. Alternativ kannst Du DrawText(Ex).

    Itachi schrieb:

    2. Weißt Du auch, wie ich die Font und Schriftgröße des mit TextOut ausgegebenen Textes ändern kann?

    Jupp, via: CreateFont(Indirect), SelectObject (DeleteObject)

    Itachi schrieb:

    3. Kannst Du mir sagen, wie ich Musik in ein Projekt integriere und sie auch von dort mit PlaySound abspiele?

    Entweder als Datei; dann den Dateinamen übergeben. Oder Du fügst eine WAVE-Resource in Dein Projekt ein und gibst dann diese Resource beim Funktionsaufruf an. Nähere Infos siehe: http://msdn2.microsoft.com/en-us/library/ms712879.aspx



  • lol? - das ganze nent sich child window aber egal .. 😉



  • Kann ich das zweites Fenster, welches ich erstellt habe (ob obrigen Quellcodebeispiel) schließen, ohne das sich das erste Fenster (MainWindow) auch schließt.

    Wenn ja, wie?
    Bitte mit Quellcodebeispielen wenn möglich

    HG
    BlackShadow281


  • Mod

    Mal grundsätzlich:

    Dein zweites Fenster schließt nihct. Die Ursache ist einfach, dass Dien Programm terminiert.

    Wenn das erste Fenster geschlossen wird dann rufst Du PostQuitMessage(0); auf.
    Das terminiert die Message Loop und damit das Programm.
    Wenn also das Programm weiter laufen soll, darfst Du PostQuitMessage(0); nicht aufrufen.

    Dann stellt sich für mich die Frage wie regelst Du das Programmende... 😉 möglich wäre ein globaler Zähler, der die Instanzen von Fenstern zählt und wenn das letzte schließt, wird auch PostQuitMessage(0); ausgeführt.



  • Vielen Dank an Martin Richter.

    Ich habe einfach den Aufruf der Methode PostQuitMessage(0); bei dem zweiten Fenster herausgenommen.
    Nun klappt alles so, wie ich mir das vorgestellt habe.

    Sollte ich weitere Fragen haben, melde ich mich

    Herzliche Grüße
    BlackShadow281


Anmelden zum Antworten