Hintergrundfarbe einer ComboBox ändern



  • @yahendrik

    Was genau bewirken denn die beiden Zeilen, die du in deinem ersten Post geschrieben hast?

    Warum den "Pinsel" am Schluss nochmal ausgeben, wenn die If-Bedingungen nicht erfüllt sind, ist der ja leer, oder?



  • @medic89 Es schadet nicht, wenn hasFocus immer bestimmt wird, in vielen Fällen ist dies nur nicht nötig:

    HBRUSH CDialog23::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
    	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    	if (nCtlColor == CTLCOLOR_STATIC || nCtlColor == CTLCOLOR_DLG)
    	{
    		...
    		return hbr;
    	}
    	if (nCtlColor == CTLCOLOR_LISTBOX)
    	{
    		...
    		return hbr;
    	}
    
    	// hier erst überprüfen:
    	const CWnd* focusWnd = GetParent() ? GetParent()->GetFocus() : nullptr;
    	bool hasFocus = focusWnd && focusWnd->GetSafeHwnd() == pWnd->GetSafeHwnd();
    	if (hasFocus)
    	{
    		...
    	}
    	// nCtrClr !=CTLCOLOR_STATIC, !=CTLCOLOR_DLG, !=CTLCOLOR_LISTBOX und !hasFocus
    	// Den Returnwert von CDialogEx::OnCtlColor zurückgeben
    	return hbr;
    }
    


  • @yahendrik

    ok, ich glaube ich habe einen Denkfehler. Ich dachte die Funktion OnCtlColor() ist dauernd aktiv, d. h. es werden ständig alle Elemente des Dialogs durchlaufen. Darum habe ich zuerst die Static und Dialoge eingefügt, denn diese sind immer weiß. Stimmt denn das?

    Bezüglich dem return am Schluss:

    wenn innerhalb der ganzen Abfragen schon der Pinsel zurückgegeben wird, kommt die Funktion doch nie an das Ende, wo nochmal ein return steht, denn mit den bereits innerhalb der Abfragen enthaltenen returns ist die Funktion doch vorzeitig am Ende, oder?



  • @yahendrik

    Habe ich mit meinen Gedanken im vorherigen Beitrag (nr. 9) die Funktion richtig verstanden?



  • Noch eine Frage:

    Ich würde gerne die entsprechende Box, welche grade den Fokus inne hat mit einem roten Rahmen versehen, mit folgendem Code funktioniert das schonmal, allerdings sieht man den roten Rahmen nur an der oberen und linken Kante der Box:

    CRect rect;
    GetWindowRect(&rect);
    rect.OffsetRect(-rect.left, -rect.top);
    CBrush brush(RGB(255, 0, 0));
    pDC->FrameRect(&rect, &brush);
    ReleaseDC(pDC);
    

    EDIT: Hab es gelöst, vor dem GetWindowRect hat ein "pWnd->" gefehlt. Allerdings kann ich die Comboboxen (formatiert als Dropdown) so nicht färben, hat da jemand eine Idee?



  • @yahendrik

    HBRUSH CDialog23::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
    	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    	if (nCtlColor == CTLCOLOR_STATIC || nCtlColor == CTLCOLOR_DLG)
    	{
    		pDC->SetBkMode(TRANSPARENT);
    		pDC->SetBkColor(RGB(255, 255, 255));
    		hbr = m_Weiss;
    		return hbr;
    	}
    	if (nCtlColor == CTLCOLOR_LISTBOX)
    	{
    		pDC->SetBkMode(TRANSPARENT);
    		pDC->SetBkColor(RGB(255, 230, 153));
    		hbr = m_Gelb;
    		return hbr;
    	}
    	const CWnd* focusWnd = GetParent() ? GetParent()->GetFocus() : nullptr;
    	bool hasFocus = focusWnd && focusWnd->GetSafeHwnd() == pWnd->GetSafeHwnd();
    	if (hasFocus)
    	{
    		if (pWnd->GetDlgCtrlID() == pWnd->GetFocus()->GetDlgCtrlID() && nCtlColor != CTLCOLOR_STATIC)
    		{
    			pDC->SetBkMode(TRANSPARENT);
    			pDC->SetBkColor(RGB(255, 230, 153));
    
    			CRect rect;
    			pWnd->GetWindowRect(&rect);
    			rect.OffsetRect(-rect.left, -rect.top);
    			CBrush brush(RGB(255, 0, 0));
    			pDC->FrameRect(&rect, &brush);
    			ReleaseDC(pDC);
    
    			hbr = m_Gelb;
    			return hbr;
    		}
    		else
    		{
    			pDC->SetBkMode(TRANSPARENT);
    			pDC->SetBkColor(RGB(255, 255, 255));
    			hbr = m_Weiss;
    			return hbr;
    		}
    	}
    	return hbr;
    }
    

    Hier noch einmal mein aktueller Stand mit deinen Anmerkungen und den rot gefärbten TextBoxen (bei den Comboboxen bin ich noch nicht weiter gekommen).



  • Zeichnen würde ich da nichts. Meiner Meinung nach hast du mindestens 2 Möglichkeiten, das wie von Windows vorgesehen zu bewerkstelligen:

    1. Subclassing der Controls. Also WS_BORDER hinzufügen und WM_NCPAINT bearbeiten und den Rahmen selber zeichnen, allerdings könnte die Strichstärke nicht ausreichend sein, sodass auch noch WM_NCCALCSIZE und WM_NCHITTEST selber bearbeitet werden müssen.
    2. Die mMn wesentlich einfachere Methode: Beim Zeichnen des Dialogs das Control mit dem Fokus bestimmen und einen Rahmen um dieses Control zeichnen. Wenn der Fokus wechselt, ein Neuzeichnen veranlassen. Wenn du das zuletzt gewählte Element bzw. die Position speicherst, reichen auch bis zu zwei Rahmen: Einmal in der Hintergrundfarbe des Dialogs um das zuletzt gezeichnete Element und dann in der gewünschten Farbe um das aktuelle.


  • @yahendrik

    Also Zeichnen mithilfe von DrawRect()? Das habe ich grade versucht, allerdings kennt er die Funktion nicht, obwohl ich den Header afxdrawmanager.h includiert habe.



  • FrameRect (bzw. hier). Für einen Rahmen mit einer Strichstärke von mehr als einer logischen Einheit kannst du auch eine Funktion schreiben, die vier Rechtecke zeichnet.



  • @yahendrik

    Aber das habe ich ja schon in meiner Funktion stehen, aber die ComboBoxen werden da nicht eingefärbt.



  • Ja, aber OnCtlColor wird aufgerufen, bevor das Control gezeichnet wird. Alles was du zeichnest, wird wohl übermalt. Die zweite Möglichkeit, die ich kurz beschrieben habe, bezieht sich auf die Paint-Methode des Dialogs. Edit: Und hier muss natürlich das Rechteck entsprechend vergrößert werden, sodass genau außen herum gezeichnet wird.



  • @yahendrik

    Woran liegt es denn, dass der Bereich überschrieben wird? Die OnCtlColor Message wird ja gesendet, sobald ich zb die Edit Box 1 anklicke, und dann wird der Rahmen gezeichnet, der das Febster überdeckt, und erst wenn ich die Maus bewege, wird onCtlColor nochmal aktiviert, und der Text wird wieder sichtbar?



  • Mal eine ganz "blöde" Frage:

    Wenn ich den Focus auf ein Edit Control setze, färbt sich dessen Rahmen per Default blau. Kann man da nicht irgendwo eingreifen und das Ändern? Irgendwo muss ja festgelegt sein, dass es die Farbe blau sein soll.



  • Ich vermute mal dass das Blau die System-Farbe COLOR_HIGHLIGHT ist. Die einzige Möglichkeit diese Farbe zu ändern die ich gefunden habe ist SetSysColors:

    static const int count = 1;
    INT elements[count] = {COLOR_HIGHLIGHT};
    COLORREF colors[count] = {RGB(255, 0, 0)};
    
    SetSysColors(count, elements, colors);
    

    Dummerweise gilt das dann global für alle Fenster/Anwendungen der aktuellen Session.



  • @hustbaer
    Danke für deinen Tipp, leider war das die Farbe für den markierten Text.



  • Vllt. hilft der vorletzte Beitrag aus changing CEdit border color (WS_EX_STATICEDGE + WM_NCPAINT)?

    Ansonsten habe ich noch einen Beitrag für WinForms (C#) gefunden: Change the borderColor of the TextBox


Anmelden zum Antworten