Child-Window Anzeigefehler



  • Huhu!
    Ich habe (mal wieder) ein Problem!
    Undzwar will ich in einem Fenster mehrere "Unterfenster" haben. Das ist ansich auch noch kein Hinderniss, jedoch werden diese nichtt richtig neu gezeichnet, nachdem ich sie verschoben habe. Also wenn ich 2 Fenster übereinander schiebe und dann eines wegziehe hat dieses immernoch den "Inhalt" des Anderen (ich hoffe man versteht was ich meine - ich hänge auch mal 2 Bilder & die Exe an).
    Da ich dachte ich habe irgendwo einen Fehler gemacht habe ich mr einen Beispielcode genommen, jedoch ists bei diesem genauso 😞

    Hier 2 Bilder und diese Exe:
    http://mitglied.multimania.de/verim/data/Error/index.html

    Achja: ich benutze Eclipse CDT und den GNU compiler(g++)

    Ich hoffe jemand hat eine hilfreiche Idee 💡

    #include <windows.h>
    
    #define IDM_USER_LOGIN	1
    #define IDM_FILE_QUIT	0
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK LoginProc(HWND, UINT, WPARAM, LPARAM);
    HWND login;
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {
        MSG Msg;
    
        // Für 2 Fenster (Parent und Child) die Struktur
    	WNDCLASS WndClass, wc;
    
    	WndClass.style = sizeof(WNDCLASS);
    	WndClass.cbClsExtra = 0;
    	WndClass.cbWndExtra = 0;
    	WndClass.lpfnWndProc = WndProc;
    	WndClass.hInstance = hInstance;
    	WndClass.hbrBackground = (HBRUSH) CreateSolidBrush (RGB ( 128, 128, 128));
    	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	WndClass.lpszMenuName = "Test";
    	WndClass.lpszClassName = "WindowClass";
    
    	RegisterClass(&WndClass);
    
    	wc.style = sizeof(WNDCLASS);
    	wc.cbClsExtra = 0;
    	wc.cbWndExtra = 0;
    	wc.lpfnWndProc = LoginProc;
    	wc.hInstance = hInstance;
    	wc.hbrBackground = (HBRUSH) CreateSolidBrush (RGB ( 128, 128, 128));
    	wc.hCursor = 0;
    	wc.hIcon = 0;
    	wc.lpszMenuName = NULL;
    	wc.lpszClassName = "Login";
    
    	RegisterClass(&wc);
    
    	// Parent wird erstellt!
        HWND hWnd = CreateWindow("WindowClass","GenixX",
    		WS_OVERLAPPEDWINDOW,
    		((GetSystemMetrics(SM_CXSCREEN)/2)-400),
            ((GetSystemMetrics(SM_CYSCREEN)/2)-300),
            800,600,
            NULL,
            NULL,
    		hInstance,
            NULL);
    
        ShowWindow (hWnd, nCmdShow);
    	UpdateWindow (hWnd);
    	SendMessageA(hWnd,WM_COMMAND,IDM_USER_LOGIN,0);
    	SendMessageA(hWnd,WM_COMMAND,IDM_USER_LOGIN,0);
    
    	while (GetMessage(&Msg, NULL, 0, 0))
    	{
    		DispatchMessage(&Msg);
    	}
    	return (Msg.wParam);
    }
    
    LRESULT CALLBACK WndProc (HWND hWnd, UINT uiMessage, WPARAM wParam,LPARAM lParam)
    {
    
    	switch(uiMessage)
    	{
        case WM_CREATE:
             {
                return 0;
             }
             break;
    
        case WM_SIZE:
             {
                     MoveWindow(login, 300,200,200,100, true);
                     return 0;
             }
             break;
    
        case WM_COMMAND:
              switch(LOWORD(wParam))
                 {
                   case IDM_USER_LOGIN:
                    {
                        login = CreateWindow("Login",
                                     "Login",
                                     WS_CHILDWINDOW | WS_OVERLAPPEDWINDOW,
                                     300,
                                     200,
                                     200,
                                     100,
                                     hWnd,
                                     NULL,
                                     (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE),
                                     NULL);
                        ShowWindow(login, SW_SHOW);
                    }
                   break;
    
                   case IDM_FILE_QUIT:
                      DestroyWindow(hWnd);
                   break;
                   }
             break;
    
        case WM_DESTROY:
    		PostQuitMessage(0);
    		return 0;
    		break;
    
    	default:
    		return DefWindowProc (hWnd, uiMessage,
    			wParam, lParam);
    	}
    }
    
    LRESULT CALLBACK LoginProc (HWND login, UINT uiMessage, WPARAM wParam, LPARAM lParam)
    {
    	switch(uiMessage)
    	{
    
    	default:
    		return DefWindowProc (login, uiMessage,
    			wParam, lParam);
    	}
    }
    


  • Die Nachricht WM_PAINT wird an deine Fenster geschickt, wenn sie sich neu zeichnen sollen.

    Solange du diese Nachricht nicht behandelst, ist dieses Verhalten normal.



  • Ich hätte gemeint, dass

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

    diesen behandelt, genau wie bei normalen Fenstern.
    Ich versuche es aber gleich mal 🙂



  • Verim schrieb:

    Ich hätte gemeint, dass DefWindowProc diesen behandelt, genau wie bei normalen Fenstern.

    Tut sie auch, aber was genau sie tut, solltest du dir schon ansehen:

    MSDN Library schrieb:

    The DefWindowProc function validates the update region.

    Der aktuelle Fensterinhalt wird also als gültig abgesegnet, ansonsten würde gleich wieder eine Paint-Nachricht kommen. Der Rahmen wird neu gezeichnet, aber woher soll DefWindowProc wissen, was dein Fensterinhalt sein soll?



  • Bei nem "normalen" Fenster weiß sie es doch auch?
    Außerdem: sobald ich mit einem Fenster wieder über das "kaputte" überfahre (also einfach einmal drüber her bewege) wird es wieder korrekt dargestellt.

    Edit:
    Ne, auch mit eingebauter WM_PAINT macht ers nicht...aufgerufen wird sie, aber ändern tut sich nichts.
    Habe einfach mal diesen Code benutzt zum Probieren:

    case WM_PAINT:
        	MessageBox(NULL,"PAINT","TST",MB_OK|MB_TOPMOST);
        	HDC hDc;
        	PAINTSTRUCT ps;
        	hDc = BeginPaint(hWnd,&ps);
        	TextOutA(hDc,5,5,"TEST",4);
        	EndPaint(hWnd,&ps);
        	return 0;
        	break;
    

    Habe aber noch nie mit WM_PAINT gearbeitet, könnnte also auch falsch sein (er gibt TEST aus - malt es aber trotzdem nicht neu)



  • Fail:

    WndClass.style = sizeof(WNDCLASS);
    

    Bei WNDCLASS muss gar kein sizeof(WNDCLASS) irgendwo gesetzt werden, nur bei WNDCLASSEX

    Nimm auch besser gleich WNDCLASSEX:

    WNDCLASSEX wcex;
    
    wcex.cbSize        = sizeof(WNDCLASSEX); // WNDCLASSEX hat nen cbSize-Member ;D
    wcex.style         = CS_HREDRAW | CS_VREDRAW; // !!!!!!
    wcex.lpfnWndProc   = WndProc;
    wcex.cbClsExtra    = 0;
    wcex.cbWndExtra    = 0;
    wcex.hInstance     = hInstance;
    wcex.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LOESCHMICH));
    wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName  = MAKEINTRESOURCE(IDC_LOESCHMICH);
    wcex.lpszClassName = TEXT("MeinKlassenName");
    wcex.hIconSm       = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
    if (!RegisterClassEx(&wcex))
    {
        MessageBox(NULL,TEXT("RegisterClassEx() failed!"),TEXT("Fehler"),MB_OK);
    }
    

    Zu CS_HREDRAW|CS_VREDRAW:
    "Redraws the entire window if a movement or size adjustment changes the width/height of the client area."
    Diese beiden Flags hat man normalerweise immer dabei.

    DefWindowProc macht im Prinzip bei WM_PAINT nichts außer das Fenster als "neugezeichnet" markieren.
    Allerdings würde WM_ERASEBKGND vorher das Fenster mit der Brush/Farbe aus wcex.hbrBackground färben...
    ...es sei denn CS_HREDRAW|CS_VREDRAW sind nicht dabei - dann passiert genau der "zeichnet nix neu"-Effekt.



  • Wegen dem Fehler: tut mir leid, habe das wie gesagt von wo anders übernommen und den Fehler übersehen 😞
    Bei mir habe ich CS_HREDRAW | CS_VREDRAW natürlich gesesetzt und habe es jetzt auch nochmal bei dem Beispielcode versucht - Hilft leider auch nicht 😞

    Edit:
    Mir ist eben aufgefallen, dass die Fenster auch keinen Fokus erhalten - jedenfalls optisch nicht. Wenn ein Fenster den Fokus hat hat dessen Statusleiste ja eine andere Farbe als sonst. Bei mir bleiben sie immer gleich (gräulich - sehen also alle eher inaktiv aus). Evtl hilft das bei deim Lösen *hoff*



  • Basis dein Quelltext mit folgenden Änderungen =>

    Mein gcc will Zeile 83:

    MoveWindow(login, 300,200,200,100, TRUE);
    

    Ist eventuell von gcc-Version oder eingebundenen Headern abhängig.

    und schau dir mal die Zeilen 60 + 61 an und ändere das.

    Dann sollte es rennen.

    MfG f.-th.



  • Ich habe den Code nochmal überarbeitet und eure Tipps aufgenommen - geholfen hat es leider reichlich wenig 😞
    Auch kann man jetzt die Größe der ChildFenster ändern - und dabei werden sie dann wieder richtg gezeichnet...

    Hier nochmal den aktuellen Code:

    #include <windows.h>
    
    #define IDM_USER_LOGIN	1
    #define IDM_FILE_QUIT	0
    
    HWND hWnd, hChild;
    HINSTANCE hInstance;
    int xy=100;
    
    void CreateChildWindow(char*);
    void CreateWndClass();
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK ChildProc(HWND, UINT, WPARAM, LPARAM);
    
    int APIENTRY WinMain(HINSTANCE hinstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {
        MSG Msg;
        hInstance = hinstance;
        CreateWndClass();
    	// Parent wird erstellt!
        hWnd = CreateWindowEx((DWORD)0,
    			   "MainWnd",
    			   NULL,
    			   WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZE,
    			   0,
    			   0,
    			   GetSystemMetrics(SM_CXSCREEN),
    			   GetSystemMetrics(SM_CYSCREEN),
    			   hWnd,
    			   NULL,
    			   hInstance,
    			   0);
    
    	CreateChildWindow("Child 1");
    	CreateChildWindow("Child 2");
    
    	while (GetMessage(&Msg, NULL, 0, 0))
    	{
    		TranslateMessage(&Msg);
    		DispatchMessage(&Msg);
    	}
    	return (Msg.wParam);
    }
    
    void CreateWndClass()
    {
        WNDCLASSEX WndClassMain = {
    			sizeof(WNDCLASSEX),
    			CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
    			WndProc,
    			0,
    			0,
    			hInstance,
    			LoadIcon(NULL, IDI_WINLOGO),
    			LoadCursorA(NULL,IDC_ARROW),
    			(HBRUSH) GetStockObject(WHITE_BRUSH),
    			NULL,
    			"MainWnd",
    			LoadIcon(NULL, IDI_WINLOGO)};
    
        WNDCLASSEX WndClassChild = {
    			sizeof(WNDCLASSEX),
    			CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
    			ChildProc,
    			0,
    			0,
    			hInstance,
    			LoadIcon(NULL, IDI_WINLOGO),
    			LoadCursorA(NULL,IDC_ARROW),
    			(HBRUSH) GetStockObject(BLACK_BRUSH),
    			NULL,
    			"ChildWnd",
    			LoadIcon(NULL, IDI_WINLOGO)};
    
    	RegisterClassEx(&WndClassChild);
    	RegisterClassEx(&WndClassMain);
    }
    
    void CreateChildWindow(char *title)
    {
    	hChild = CreateWindowEx((DWORD)0,
    			   "ChildWnd",
    			   title,
    			   WS_VISIBLE | WS_CHILD | WS_CAPTION | WS_SYSMENU | WS_SIZEBOX,
    			   xy,
    			   xy,
    			   200,
    			   300,
    			   hWnd,
    			   NULL,
    			   hInstance,
    			   0);
    	xy += 100;
    }
    LRESULT CALLBACK WndProc (HWND hWnd, UINT uiMessage, WPARAM wParam,LPARAM lParam)
    {
    
    	switch(uiMessage)
    	{
        case WM_CREATE:
             {
                return 0;
             }
             break;
        case WM_COMMAND:
              switch(LOWORD(wParam))
                 {
                   case IDM_FILE_QUIT:
                      DestroyWindow(hWnd);
                   break;
                   }
             break;
    
        case WM_DESTROY:
    		PostQuitMessage(0);
    		return 0;
    		break;
    
    	default:
    		return DefWindowProc (hWnd, uiMessage,
    			wParam, lParam);
    	}
    	return 0;
    }
    
    LRESULT CALLBACK ChildProc (HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
    {
    	switch(uiMessage)
    	{
    
    	default:
    		return DefWindowProc (hWnd, uiMessage,
    			wParam, lParam);
    	}
    }
    


  • Was heisst recht wenig?
    Präzise Fehlermeldung oder Fehlfunktion?



  • Immernoch die gleiche wie vorher...

    Verim schrieb:

    Undzwar will ich in einem Fenster mehrere "Unterfenster" haben. Das ist ansich auch noch kein Hinderniss, jedoch werden diese nichtt richtig neu gezeichnet, nachdem ich sie verschoben habe. Also wenn ich 2 Fenster übereinander schiebe und dann eines wegziehe hat dieses immernoch den "Inhalt" des Anderen (ich hoffe man versteht was ich meine - ich hänge auch mal 2 Bilder & die Exe an).
    Da ich dachte ich habe irgendwo einen Fehler gemacht habe ich mr einen Beispielcode genommen, jedoch ists bei diesem genauso 😞

    Hier 2 Bilder und diese Exe:
    http://mitglied.multimania.de/verim/data/Error/index.html



  • Bin jetzt zu bequem 😉

    Gib mal in die Suchmaschine: winapi window mdi
    ein.

    Irgendwie werden deine "Unterfenster" nicht richtig verwaltet.
    Wie die "Unterfenster" bei WinAPI korrekt heissen solltest du ja inzwischen mitbekommen haben => da funktioniert das dann auch mit der Suche besser.



  • über mdi ansich habe ich mir schon die Finger wund gesucht. MDI-Child-Fenster funktionieren ohne Probleme, jedcoch stört mich bei diesen, dass sie immer einen Standart Style (Mini/Maximieren,schließen). Mich stört zumindest der Maximieren Button.
    Sobald ich jedoch mit SetWindowLong() den Style ändere haben diese genau die gleichen Probleme wie diese "normalen" Child-Windows. 😞
    Hat Niemand eine Idee?

    Wo ich euch Experten grade schonmal hier habe: Wie kann man ein Fenster in Frames aufteilen? Ich weiß nichtmals, ob das in C++ auch Frames heißt, aber ich meine, dass man ein Fenster in mehrer kleine "Zonen" aufteilen kann. Sowas
    Wenn das relativ einfach geht könnte ich darauf umsteigen - sobei es mich Wurmt nicht zu wissen wo mein verdammter (denk?)-Fehler liegt! 😡



  • Um bei deinen Worten zu bleiben:
    Unterfenster mit automatischer Positions- und Grössenanpassung - musst du dir dann ansehen wie du die Automatik programmierst.

    Geht natürlich mit der WinAPI - wird aber ein wenig umfangreicher.


Log in to reply