WinXP Style => Label hat anderen Hintergrund als Elternfenster



  • Nabend allerseits,

    auf der Arbeit muss ich mit WinAPI eine GUI basteln und die soll beim Kunden
    natuerlich auch den schoenen XP-Style haben, wenn er eingestellt ist. Nun hab
    ich allerdings das Problem, dass der Hintergrund eines Labels oder Radio-Button
    nicht gleich dem Hintergrund des Elternfensters ist. Das sieht dann natuerlich
    furchtbar schrecklich aus.

    Wie kann ich die Hintergrundfarbe eines Labels oder allgemein eines Kontrols,
    dem Hintergrund des Elternfensters anpassen?

    gruss
    v R


  • Mod

    Dir Frage wäre eher: Was hast Du mit dem Hintergrund des Parents gemacht?

    Behandelst Du WM_CTLCOLOR... Nachrichten schon selbst?
    Wenn man nichts spezielles einbaut, funktioniert das wie gehabt...



  • Martin Richter schrieb:

    Dir Frage wäre eher: Was hast Du mit dem Hintergrund des Parents gemacht?

    Behandelst Du WM_CTLCOLOR... Nachrichten schon selbst?
    Wenn man nichts spezielles einbaut, funktioniert das wie gehabt...

    Ich habe mit dem Hintergrund nichts gemacht, ich habe nichts spezielles
    eingestellt.

    Testenshalber habe ich die WM_CTLCOLOR-Nachrichten jetzt mal abgefangen und
    setze den Hintergrund auf den Hintergrund des Parents. Leider wird bei z. B.
    Labels nur der Teil des Hintergrunds angepasst, welcher Text enthaelt. Ist das
    Label an sich groesser, so sieht man den hinteren Teil immer noch in einer
    anderen Farbe. Bei z. B. den Radio-Buttons hingegen passiert gar nichts.

    gruss
    v R



  • Hmmm...hat niemand eine Idee, woran das liegen koennte?

    Ich hab hier mal ein Bild hochgeladen:
    http://img204.imageshack.us/my.php?image=guiproblemrz6.jpg

    Es ist nur ein Ausschnitt, aber man kann erkennen, dass der Hintergrund des
    Parents weiss ist, aber z. B. die Labels nicht.

    gruss
    v R


  • Mod

    Ich vermute die Ursache ist folgende:
    Du hast eine eigene Fensterklasse definiert?
    Diese hast Du mit dem Hintergrund weiß gesetzt...
    Wenn Du das möchtest musst Du WM_CTLCOLOR... Nachrichten abfangen.

    Die Hintergrundfarbe von Dialogen ist COLOR_BTNFACE.

    Siehe auch:
    http://www.microsoft.com/msj/0597/c0597.aspx
    Auch wenn es MFC ist so wird doch das Nachrichten Verfahren gut erklärt.



  • virtuell Realisticer schrieb:

    Leider wird bei z. B.
    Labels nur der Teil des Hintergrunds angepasst, welcher Text enthaelt. Ist das
    Label an sich groesser, so sieht man den hinteren Teil immer noch in einer
    anderen Farbe. Bei z. B. den Radio-Buttons hingegen passiert gar nichts.

    Zeig mal den Code dazu, denke mal da liegt der Fehler. (Du musst sowohl den Text-Hintergrund des HDC's auf die entsprechende Farbe setzen, als auch den restlichen Hintergrund (durch das returnen eines Brushes).



  • Hallo,

    ja also das ist alles etwas verzwickt mit dem Code, da er gekapselt worden ist,
    trotzdem versuch ich die relervanten Codestellen zu posten, falls euch noch
    etwas fehlt, bitte kurz darauf hinweisen.

    Zunaechst einmal haben wir eine Klasse window, deren init-Funktion schaut
    wie folgt aus:

    void ds::window::init(const string_type& name,
                          const string_type& window_class,
                          const pos_type pos,
                          const dim_type dim,
    				      const DWORD style,
                          window* parent) {
    	HINSTANCE instance = ::GetModuleHandle(0);
    	static bool wndclass_created = false;
    	if(wndclass_created == false)
    	{
    		const COLORREF bgcolor = RGB(255,255,255);
    		WNDCLASSEX wndclass;
    		wndclass.cbClsExtra = 0;
    		wndclass.cbWndExtra = sizeof(void*);
    		wndclass.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME; //CreateSolidBrush(bgcolor);
    		wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
    		wndclass.hIcon = 0;
    		wndclass.hIconSm = 0;
    		wndclass.hInstance = instance;
    		wndclass.lpfnWndProc = wnd_proc;
    		wndclass.lpszClassName = default_class.c_str();
    		wndclass.lpszMenuName = 0;
    		wndclass.cbSize = sizeof(WNDCLASSEX);
    		wndclass.style = CS_HREDRAW | CS_VREDRAW;
    		if(!RegisterClassEx(&wndclass))
    			throw std::runtime_error("RegisterClassEx() failed");
    
    		wndclass_created = true;
    	}
    
    	DWORD exStyle (0);
            /*
    	if(window_class == default_class)
    		; //exStyle |= WS_EX_LAYERED;
            */
    
    	handle = CreateWindowEx(exStyle,
    			window_class.c_str(),
    			name.length() ? name.c_str() : 0,
    			style,
        		pos.x,
        		pos.y,
        		dim.w,
        		dim.h,
    			parent ? parent->handle : 0,
        		0,
        		instance,
        		this);
        if(!handle)
        	throw std::runtime_error("CreateWindow() failed!");
    
        /*
         Hier habe ich versucht, den hintergrund der fensterklasse anzupassen
         zum test einfach nur mal irgendwas. allerdings passiert gar nichts,
         es kann auch sein, dass das voelliger unsinn ist, aus der not heraus
         probiert man alles moegliche
        */
        if(window_class != default_class) {
    		int res = SetClassLongPtr(handle, GCLP_HBRBACKGROUND, RGB(167, 233, 100));//COLOR_WINDOWFRAME);
    		Debug::print(boost::str(boost::format("SetClassLongPtr %d; GetLastError %d \n"
    		                                      "%s; %s") % res % GetLastError() % convert(window_class).c_str() % convert(name).c_str()));
        }
    
    	//
    	//save old wndproc and set the new one to the parents wndproc
    	//
    	if(parent) {
    		old_wnd_proc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(handle, GWL_WNDPROC));
    		SetWindowLongPtr(handle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(wnd_proc));
    		CREATESTRUCT cs;
    		memset(&cs, 0, sizeof(CREATESTRUCT));
    		cs.lpCreateParams = this;
    		SendMessage(handle, WM_CREATE, 0, reinterpret_cast<LPARAM>(&cs));
    		this->parent = parent;
    	}
    
    	visible = (style & WS_VISIBLE);
    }
    

    Hier der Code, der fuer WM_CTLCOLOR... zustaendig ist:

    case WM_CTLCOLORSTATIC:
    		{
    			DWORD col = GetSysColor(COLOR_WINDOWFRAME);
    			COLORREF color = RGB(GetRValue(col), GetGValue(col), GetBValue(col));
    			static HBRUSH hbrush = (HBRUSH)CreateSolidBrush(col);
    			PAINTSTRUCT ps;
    				HDC hdc = BeginPaint(hwnd, &ps);
    				SetBkColor(hdc, color);
    				EndPaint(hwnd, &ps);
    				ds::Debug::print(boost::str(boost::format("WM_CTLCOLORSTATIC called for handle 0x%X") % hwnd));
    			return reinterpret_cast<LRESULT>(hbrush);
    		}
    

    Obiger Code fuehrt dazu, dass der Hintergrund des Controls nur fuehr den
    Bereich des Textes entsprechend angepasst wird, der Rest des Controls ist
    dann schwarz.

    Ich bin mir sicher, dass das Problem an meinem Code liegt und nirgends sonst
    zu suchen ist, aber ich weiss derzeit nicht wirklich weiter.

    Hilft euch das schon ein wenig? Falls ihr noch Codestellen braucht oder irgend
    was anderes unklar ist, sagt mir bitte bescheid.

    gruss
    v R



  • Hoi,

    Lass das mal weg:

    virtuell Realisticer schrieb:

    /*
         Hier habe ich versucht, den hintergrund der fensterklasse anzupassen
         zum test einfach nur mal irgendwas. allerdings passiert gar nichts,
         es kann auch sein, dass das voelliger unsinn ist, aus der not heraus
         probiert man alles moegliche
        */
        if(window_class != default_class) {
    		int res = SetClassLongPtr(handle, GCLP_HBRBACKGROUND, RGB(167, 233, 100));//COLOR_WINDOWFRAME);
    		Debug::print(boost::str(boost::format("SetClassLongPtr %d; GetLastError %d \n"
    		                                      "%s; %s") % res % GetLastError() % convert(window_class).c_str() % convert(name).c_str()));
        }
    

    Und ändere das:

    virtuell Realisticer schrieb:

    Hier der Code, der fuer WM_CTLCOLOR... zustaendig ist:

    case WM_CTLCOLORSTATIC:
    		{
    			DWORD col = GetSysColor(COLOR_WINDOWFRAME);
    			COLORREF color = RGB(GetRValue(col), GetGValue(col), GetBValue(col));
    			static HBRUSH hbrush = (HBRUSH)CreateSolidBrush(col);
    			PAINTSTRUCT ps;
    				HDC hdc = BeginPaint(hwnd, &ps);
    				SetBkColor(hdc, color);
    				EndPaint(hwnd, &ps);
    				ds::Debug::print(boost::str(boost::format("WM_CTLCOLORSTATIC called for handle 0x%X") % hwnd));
    			return reinterpret_cast<LRESULT>(hbrush);
    		}
    

    in das ab:

    case WM_CTLCOLORSTATIC:
    {
    	SetBkMode(reinterpret_cast<HDC>(wParam), TRANSPARENT);
    	ds::Debug::print(boost::str(boost::format("WM_CTLCOLORSTATIC called for handle 0x%X") % hwnd));
    	return (reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_WINDOWFRAME)));
    }
    

    Den HDC bekommst Du nämlich schon über wParam geliefert. BeginPaint bzw. EndPaint ist hier falsch 😉 .



  • Alles klar, das werd ich machen, danke. Kann aber erst naechste Woche berichten,
    ob es funktioniert hat, ich hoffe doch mal :).

    gruss
    v R



  • Den via

    GetSysColorBrush(COLOR_WINDOWFRAME)
    

    angeforderten Brush brauchste dann auch nicht wieder freigeben, ist ein System-Objekt 😉 .



  • Wenn ich den Code umaendere, dann erhalte ich folgendes Resultat:

    http://img218.imageshack.us/img218/5638/guiproblemrs4.jpg

    Irgendwie gehn mir so langsam die Ideen aus, woran es liegen koennte, habt ihr
    noch welche?

    gruss
    v R



  • Hmmm....wenn ich den Code folgendermassen abaendere:

    SetBkColor(reinterpret_cast<HDC>(wparam), RGB(GetRValue(COLOR_WINDOW), GetGValue(COLOR_WINDOW), GetBValue(COLOR_WINDOW)));
    		SetTextColor(reinterpret_cast<HDC>(wparam), RGB(255, 255, 255));
    		ds::Debug::print(boost::str(boost::format("WM_CTLCOLORSTATIC called for handle 0x%X") % hwnd));
    		return (reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_WINDOW)));
    

    bekomme ich folgendes Resultat:

    http://img214.imageshack.us/img214/415/guiproblemef4.jpg

    Ich verstehe nicht, warum der Textbereich auf dem Label schwarz ist?

    gruss
    v R



  • Ok, hab nochwas rumprobiert. Der Code:

    case WM_CTLCOLORSTATIC:
    	{
    		SetBkMode(reinterpret_cast<HDC>(wparam), TRANSPARENT);
    		SetBkColor(reinterpret_cast<HDC>(wparam), RGB(GetRValue(COLOR_WINDOW), GetGValue(COLOR_WINDOW), GetBValue(COLOR_WINDOW)));
    		SetTextColor(reinterpret_cast<HDC>(wparam), RGB(0, 0, 0));
    		ds::Debug::print(boost::str(boost::format("WM_CTLCOLORSTATIC called for handle 0x%X") % hwnd));
    		return (reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_WINDOW)));
    	}
    

    leistet das gewuenschte.

    gruss
    v R



  • Hmm ist aber nicht soo effektiv jedesmal neu zu casten. Mach es einmal und pack es in ne Variable.

    case WM_CTLCOLORSTATIC:
    {
        HDC hDC = reinterpret_cast<HDC>(wParam);
        SetBkMode(hDC, TRANSPARENT);
        SetBkColor(hDC, RGB(GetRValue(COLOR_WINDOW), GetGValue(COLOR_WINDOW), GetBValue(COLOR_WINDOW)));
        SetTextColor(hDC, RGB(0, 0, 0));
        return (reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_WINDOW)));
    }
    

    ...



  • Ja, da hast auch recht, danke.

    gruss
    v R


Anmelden zum Antworten