MFC Dialog Hintergrundfarbe funktioniert nicht

0XFF

Grünschnabel
Hallo,

ich habe eine Dialogbasierte Anwendung erstellt die auch super funktioniert mit einer kleinen einschränkung der Hintergrundfarbe

sobald ich eine andere Hintergrundfarbe einfüge hängt sich meine Applikation nach einer weile auf. Es funktioniert zwar noch, allerdings verschwinden die Farben einzelner Steuerelemente. Ich denke es ist besser wenn Ihr euch mal die Screenshots anschaut die sagen mehr aus.

kurz zum code :

Für die Hintergrundfarbe verwende ich die nachfolgenden Funktion:

1. Diese Funktion malt mir den Hintergrund an und es verursacht keinerlei Probleme ! ABER die Hintergrundfarben der Texte bleiben GRAU und das sieht nicht schön aus .

Code:
BOOL CddcontrolDlg::OnEraseBkgnd(CDC* pDC) {
    CRect rc;
	CWnd *pWnd;
    GetClientRect(&rc); 
    pDC->FillSolidRect(0,0,rc.Width(),rc.Height(),RGB(128,184,233)); // roter Hintergrund!!
	return 1;
}

deshalb habe ich noch eine weitere Funktion eingefügt die mir den Hintergrund von Statischen Texten usw. anmalt:

2.
Code:
HBRUSH CddcontrolDlg::OnCtlColor(CDC*pDC,CWnd*pWnd,UINT nCtlColor)
{
	// Hintergrundfarbe festlegen
	HBRUSH hBGBrush = CreateSolidBrush(RGB(128,184,223));//
	HBRUSH hBGEdit = CreateSolidBrush(RGB(255,255,255));
//
//	// Hintergrundfarbe einzelner Elemente ändern
	
//
	if(pWnd->GetDlgCtrlID()==IDC_LIST_SM)
	{
		pDC->SetBkMode(TRANSPARENT);
//		
		return hBGEdit;
//	
	}
//
	if(pWnd->GetDlgCtrlID()==IDC_LIST_IP)
	{
	pDC->SetBkMode(TRANSPARENT);
//	
	return hBGEdit;
//	
	}

	if(pWnd->GetDlgCtrlID()==IDC_LIST_MAC)
	{
		pDC->SetBkMode(TRANSPARENT);
//	
	return hBGEdit;
//	
	}
//
	if(pWnd->GetDlgCtrlID()==IDC_LIST_GW)
	{
		pDC->SetBkMode(TRANSPARENT);
//	
	return hBGEdit;
//	
	}
//
	if(pWnd->GetDlgCtrlID()==IDC_LIST_SEND)
	{
		pDC->SetBkMode(TRANSPARENT);
//	
	return hBGEdit;
//	
	}
//
	if(pWnd->GetDlgCtrlID()==IDC_EDIT1)
	{
		pDC->SetBkMode(TRANSPARENT);
//	
		return hBGEdit;
//	
	}
//
	if(pWnd->GetDlgCtrlID()==IDC_COMBO1)
	{
		pDC->SetBkMode(TRANSPARENT);
//	
		return hBGEdit ;
//	
	}
	if(pWnd->GetDlgCtrlID()==IDC_STATIC_INFO)pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_STATIC)pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_NONE)pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_DATUM)pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_timer1s)pDC->SetBkMode(TRANSPARENT);
	

	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_0 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_1 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_2 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_3 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_4 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_5 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_6 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_7 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_8 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_9 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_10 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_11 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_12 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_13 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_14 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_S_BIT_15 )pDC->SetBkMode(TRANSPARENT);
	

	if(pWnd->GetDlgCtrlID()==IDC_SPS_OUT_0 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_OUT_1 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_OUT_2 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_OUT_3 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_OUT_4 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_OUT_5 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_OUT_6 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_OUT_7 )pDC->SetBkMode(TRANSPARENT);

	if(pWnd->GetDlgCtrlID()==IDC_SPS_IN_0 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_IN_1 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_IN_2 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_IN_3 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_IN_4 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_IN_5 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_IN_6 )pDC->SetBkMode(TRANSPARENT);
	if(pWnd->GetDlgCtrlID()==IDC_SPS_IN_7 )pDC->SetBkMode(TRANSPARENT);
	
	
		
	return hBGBrush;
		
	
	

}

so und das verursacht den genanten bzw.sichtbaren(Screenshot) Effekt.

ich möchte noch erwähnen das 2 Timer im Hintergrund laufen ob das die Ursache ist weis ich allerdings nicht .

ach und nochwas wenn ich schon beim Timer bin ;) im INFO Fenster ist ein leichtes Flakern sichtbar was man nur beim genauen hinschauen bemerkt und beim ziehen des Dialog Fensters ruckelt es. Das ganze passiert wenn der Timer Aktiv ist wohlgemerkt.

Ich habe im Forum lange gesucht aber nicht wirklich was gefunden was mein Problem behebt.

Vielen Dank für eure Antworten im vorraus
 

Anhänge

  • Zwischenablage02.jpg
    Zwischenablage02.jpg
    59,4 KB · Aufrufe: 145
  • Zwischenablage01.jpg
    Zwischenablage01.jpg
    34,5 KB · Aufrufe: 77

Endurion

Erfahrenes Mitglied
Warum es sich "weghängt" ist klar ein Resourcenproblem. Du erzeugst bei jeden Aufruf zwei neue HBRUSHES, die musst du auch wieder plattmachen.

Bzw. in diesem Fall besser einmal in WM_INITDIALOG erzeugen, bei WM_CTLCOLOR immer die gleichen Handles reinreichen und bei WM_DESTROY wieder zerstören.
 

0XFF

Grünschnabel
Warum es sich "weghängt" ist klar ein Resourcenproblem. Du erzeugst bei jeden Aufruf zwei neue HBRUSHES, die musst du auch wieder plattmachen.

Bzw. in diesem Fall besser einmal in WM_INITDIALOG erzeugen, bei WM_CTLCOLOR immer die gleichen Handles reinreichen und bei WM_DESTROY wieder zerstören.

ok das dachte ich mir schon das dies Probleme bereiten würde.

kannst du mir ein tipp geben wie ich diesen HBRUSH wieder platt mache? ich habe versucht einen destruktor aufzurufen aber das klappt nicht bzw. der Kompiler sagt das es ein ungültiger destruktor sei.


danke im vorraus
 

0XFF

Grünschnabel
also ich hab jetzt folgendes ergänzt:

im InitDialog ON_WM_DESTROY() eingefügt.

Zusätzlich den Konstruktor :

Code:
void CddcontrolDlg::OnDestroy()
{
     HBRUSH hBGEdit;
     HBRUSH hBGBrush;

     DeleteObject(hBGEdit);
     DeleteObject(hBGBrush);
}

Der Kompiler meckert zwar nicht aber er springt auch nie in diesen abschnitt rein was habe ich vergessen?

danke im vorraus
 

Endurion

Erfahrenes Mitglied
Sollte eigentlich angesprungen werden. Wie erzeugst du denn den Dialog?

Da ist noch ein Haken mit den Brushes; so wie du das machst, wird da nichts zerstört. Es müssen schon wirklich die gleichen Handles sein (nicht nur den gleichen Namen in verschiedenen Scopes haben).

Am besten machst du die HBRUSHes als Member-Variablen in den Dialog. Einmal in OnInitDialog erzeugen, dann in OnDestroy nur die DeleteObject-Aufrufe drin lassen.
 

0XFF

Grünschnabel
Hi Endurion,

danke für deine natwort erstmal.

Ich hab deine Anweisungen befolgt und hBGBrush und hBGEdit im OnInintDlg initialisiert

Code:
HBRUSH hBGBrush = CreateSolidBrush(RGB(128,184,223));
	HBRUSH hBGEdit = CreateSolidBrush(RGB(255,255,255));

und in OnDestroy habe ich das DeleteObject zeug dringelassen.

Jetzt habe ich folgenden Effekt. Der Hintergrund wird garnicht mehr angemalt und er springt jetzt in die OnDestroy Routine ABER erst wenn ich das Fenster Schließe

Das sollte er doch früher tun oder nicht ?

mit
Wie erzeugst du denn den Dialog?
meinst du wohl ob es ein modal oder Nichtmodales Dialog ist?

also ich habe nur ein Fenster keine weiteren unterfenster bis auf eine mesage box der beim Deaktivieren des Timers erscheint und der ist modal.

danke im voraus
 

MCoder

Erfahrenes Mitglied
Hallo,

du solltest die Anwort von Endurion noch mal genau lesen: Die Brushes sollten als Member-Variablen verwendet werden. Das heißt, die Deklaration erfolgt innerhalb der Kassendefinition (Header) und die Zuweisung dann in OnInitDialog.
Dass OnDestroy erst aufgerufen wird, wenn das Fenster geschlossen wird, ist richtig und so gewollt. Die Brushes sollen ja solange "leben", wie auch das Fenster existiert.

Gruß
MCoder
 

0XFF

Grünschnabel
Hallo,

ja du hast natürlich recht die deklaration muss in der klasse geschehen. Was ich auch prompt verbessert habe, aber allerdings habe ich dann immer noch den effekt das er den Hintergrund nicht anmalt.

Er springt in OnCtlColor hinein führt es aus doch der Hintergrund bleibt in der Standartfarbe.

was ich nicht verstehe warum ich die Objekte mit OnDestroy plattmachen muss da es sowieso beim schließen des Fensters erst aufgerufen wird. Ich dachte die die HBRUSHES sollten direkt nach dem erstellen der Hintergrundfarbe wieder Platt gemacht werden da diese die Gründe dafür sind das sich die Hintergrundfarbe aufhängt ,oder habe ich da was falsch verstanden....

danke im voraus
 

Endurion

Erfahrenes Mitglied
Das hast du falsch verstanden. Wenn du einen HBRUSH erzeugst, ist das HBRUSH eine Art Zeiger oder Index auf ein Windows-internes Datengebilde. Der HBRUSH selbst ist nur eine Zahl und hat keinen Inhalt in Form der Farben. Wenn du das mit DeleteObject freigibst, gibt es das nicht mehr.

Wenn du also Windows über OnCtlColor einen HBRUSH gibst, musst du auch sicherstellen, dass das zugrundeliegende Datenobjekt auch bestehen bleibt. Windows kann solange auf den Dialog malen, bis er zerstört ist. Deshalb packt man in dem Fall das Freigeben in OnDestroy.