Fenstervergrößerung nur in bestimmten Seitenverhältnis erlauben



  • Schönen guten Abend zusammen! 🙂

    wie der Titel schon vermuten lässt, würde ich gerne das 'resizen' des Fenster auf ein bestimmtes Seitenverhältnis begrenzen: Verändert der Benutzer die Größe, soll sich die entsprechende andere Seite automatisch mit anpassen, so das das Verhältnis gewahrt bleibt 😉 . Hätte jemand eine Idee, wie ich das realisieren könnte?

    Mein Ansatz war Folgender:

    case WM_SIZE:
    			iX = LOWORD(lParam);
    			iY = HIWORD(lParam);
    			BITMAP bmInfo;
    			GetObject(hiCurrent, sizeof(BITMAP), &bmInfo);
    			double f = (double)bmInfo.bmWidth / (double)bmInfo.bmHeight; // Seitenverhältnis errechnen
    			if((double)iX / (double)iY != f)
    			{
    				//SetWindowPos(hWnd, NULL, 0, 0, f * iY, iY, SWP_NOMOVE | SWP_NOZORDER);
    				RECT rc;
    				GetWindowRect(hWnd, &rc);
    				MoveWindow(hWnd, rc.left, rc.top, f * iY, iY, TRUE);
    			}
    			break;
    

    Aber irgendwie ließ sich das Fenster danach gar nicht mehr verändern. Mit SetWindowPos (auskommentiert) hat es ebenfalls nicht funktioniert.

    Hat jmd. eine Idee? Wäre sehr dankbar!

    MfG Daniel



  • mit WM_SIZING

    Martin



  • jo! genau ich habe da mal was zusammengeschustert.
    Das funktioniert astrein und sehr benutzerfreundlich (für die mausfreaks)

    #include <windows.h>
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    BOOL AdjustWindowRatio(LPRECT lpRect, float fRatio, int nWindowEdge);
    
    int WINAPI wWinMain(HINSTANCE hInstance,
    					HINSTANCE hPrevInstance,
    					LPWSTR    lpCmdLine,
    					int       nShowCmd)
    {
    	WNDCLASS wcs;
    	HWND hWnd;
    	MSG msg;
    
    	ZeroMemory(&wcs, sizeof(WNDCLASS));
    	wcs.hInstance     = hInstance;
    	wcs.style         = CS_HREDRAW | CS_VREDRAW;
    	wcs.lpfnWndProc   = WndProc;
    	wcs.cbClsExtra    = 0;
    	wcs.cbWndExtra    = 0;
    	wcs.hCursor       = LoadCursor(NULL, IDC_ARROW);
    	wcs.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    	wcs.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	wcs.lpszClassName = L"HomeToGo";
    	wcs.lpszMenuName  = NULL;
    
    	if (!RegisterClass(&wcs))
    		return 0;
    
    	hWnd = CreateWindow(L"HomeToGO",
    						L"Home To Go",
    						WS_OVERLAPPEDWINDOW,
    						CW_USEDEFAULT,
    						CW_USEDEFAULT,
    						CW_USEDEFAULT,
    						CW_USEDEFAULT,
    						NULL,
    						NULL,
    						hInstance,
    						(LPVOID)lpCmdLine);
    
    	ShowWindow(hWnd, SW_SHOW);
    	UpdateWindow(hWnd);
    
    	while (GetMessage(&msg, NULL, 0, 0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    
    	return 0;
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	static float fRatio = 1.5;
    
    	RECT rect;
    
    	switch (uMsg)
    	{
    	case WM_CREATE:
    		GetWindowRect(hWnd, &rect);
    		AdjustWindowRatio(&rect, fRatio, WMSZ_BOTTOMRIGHT);
    		MoveWindow(hWnd, 
    				   rect.left,
    				   rect.top,
    				   rect.right - rect.left,
    				   rect.bottom - rect.top,
    				   TRUE);
    		return 0;
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		return 0;
    	case WM_SIZING:
    		AdjustWindowRatio((LPRECT)lParam, fRatio, wParam);
    		return 0;
    	default:
    		return DefWindowProc(hWnd, uMsg, wParam, lParam);
    	}
    }
    
    BOOL AdjustWindowRatio(LPRECT lpRect, float fRatio, int nWindowEdge)
    {
    	int nAvg, nWidth, nHeight;
    
    	switch (nWindowEdge)
    	{
    	case WMSZ_LEFT:
    	case WMSZ_RIGHT:
    		nAvg = (int)((lpRect->right - lpRect->left) / fRatio);
    		break;
    	case WMSZ_TOP:
    	case WMSZ_BOTTOM:
    		nAvg = (int)((lpRect->bottom - lpRect->top) * fRatio);
    		break;
    	case WMSZ_TOPLEFT:
    	case WMSZ_TOPRIGHT:
    	case WMSZ_BOTTOMLEFT:
    	case WMSZ_BOTTOMRIGHT:
    		nAvg = (int)(((lpRect->right - lpRect->left) / fRatio + (lpRect->bottom - lpRect->top) * fRatio) / 2.0);
    		break;
    	}
    	nWidth = (int)(nAvg * fRatio);
    	nHeight = (int)(nAvg / fRatio);
    
    	if (( (lpRect->right - lpRect->left) != nAvg) ||
    		( (lpRect->bottom - lpRect->top) != nAvg))
    	{
    		switch (nWindowEdge)
    		{
    		case WMSZ_BOTTOM:
    		case WMSZ_BOTTOMRIGHT:
    		case WMSZ_RIGHT:
    			lpRect->right = lpRect->left + nWidth;
    			lpRect->bottom = lpRect->top + nHeight;
    			break;
    		case WMSZ_LEFT:
    		case WMSZ_BOTTOMLEFT:
    			lpRect->left = lpRect->right - nWidth;
    			lpRect->bottom = lpRect->top + nHeight;
    			break;
    		case WMSZ_TOP:
    		case WMSZ_TOPRIGHT:
    			lpRect->right = lpRect->left + nWidth;
    			lpRect->top = lpRect->bottom - nHeight;
    			break;
    		case WMSZ_TOPLEFT:
    			lpRect->left = lpRect->right - nWidth;
    			lpRect->top = lpRect->bottom - nHeight;
    			break;
    		}
    	}
    
    	return TRUE;
    }
    

    have fun



  • Beim Ändern der Fenstergröße sendet Windows die Nachricht WM_SIZE. Darin sind in lParam die neuen Maße des Fensters angegeben. Mit SetWindowPos() kannst Du die Größe neu setzen.



  • Das ist doch schwachsinn...
    Wenn man das so macht, flackert das Fenster doch...

    Einfach WM_SIZING abfangen, (LPRECT)lParam ist dann das Fenster-RECT und wParam die Ecke, an der der user zieht.



  • Wieso sollte man das überhaupt machen wollen?

    Wenn man irgendwas nur in einem bestimmten Seitenverhältnis darstellen möchte kann man ja die Darstellung im Client-Bereich des Fensters entsprechend machen, z.B. so dass oben und unten bzw. seitlich 2 Balken freibleiben wenn das Seitenverhältnis nicht passt.

    Ist IMO immer noch userfreundlicher als beim Resizen des Fensters einzugreifen.



  • Danke erstmal für eure Antworten! (Und sry, dass ich mich jetzt erst melde 🙄 )

    Script-Styler Dein Code funktioniert soweit, danke!

    hustbear's Vorschlag gefällt mir allerdings noch besser nur:
    Irgendwie bekomme ich es nicht gebackten, die Bitmap entsprechenden dem Seitenverhältnis in mein Client-Bereich zu blitten.
    Zum Darstellen verwende ich StretchBlt. Aber die Berechnungen gehen irgendwie immer schief 😞 .

    Das Seitenverhältnis berechne ich doch mit:

    verhaeltnis = bitmap_breite / bitmap_hoehe;
    

    oder?

    Wenn nun wnd_x meine Client-Fensterbreite und wnd_y meinte Client-Fensterhöhe ist und bmp_x bzw. bmp_y entsprechend die Breite bzw. der Höhe der Bitmap, wie berechne ich dann gemäß dem Seitenverhältnis die neue Bitmap-Breite/Höhe, damit die Bitmap in mein Client passt? Glaube es ist ja trivial, aber es will nicht funktionieren 😞 .

    Ich danke schonmal für euer Interesse! 🙂



  • this->push();
    


  • Müsste doch etwa so gehen:

    // in:
    //   bmp_w, bmp_h = width/height der bitmap
    //   wnd_w, wnd_h = width/height des verwendbaren bereichs im fenster
    
    // out:
    //   view_w, view_h = width/height des bereichs den wir zur ausgabe verwenden
    
    // 1. versuch mit der max. breite und angepasster höhe
    view_w = wnd_w;
    view_h = (bmp_h * wnd_w) / bmp_w;
    
    // gucken ob höhe noch ok ist
    if (view_h > wnd_h)
    {
        // 2. versuch mit der max. höhe und angepasster breite
        view_h = wnd_h;
        view_w = (bmp_w * wnd_h) / bmp_h;
    }
    
    // fertig
    
    int offset_x = (wnd_w - view_w) / 2;
    int offset_y = (wnd_h - view_h) / 2;
    
    // ...
    


  • Hmm, haste auch float benutzt, bei int geht ja was verloren.


Anmelden zum Antworten