Nachrichtenbehandlung in BasisKlasse möglich? (OnCtlColor)



  • Hallo!

    Ich habe eine Anwendung mit zig Views und Dialogen.
    Nun möchte ich, dass bei ALLEN deaktivierten Edits, Comboboxen, Listcontrols usw die Schrift schwarz ist.

    Die ideale Stelle dafür sind der BasisView und der BasisDlg, die ich habe. Dann wären das nur zwei statt zig Stellen.
    Ich habe OnCtlColor auch schon hinzugefügt, aber das reagiert nicht. 😕

    Was nun? Muss ich in JEDE Klasse ein OnCtlColor einbauen und dann die Basisklasse aufrufen? 🙄

    Edit:
    Ich habe jetzt drei Varianten ausprobiert und ich schaffe es nicht, dass der Text schwarz wird. Ich rufe die Funktion momentan einfach aus der abgeleiteten Klasse auf (die Frage oben ist also noch offen) und er geht auch in die if.

    Hier sind die Versionen:

    HBRUSH CBasisView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
    {
    	HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor); 
     	CEdit* pEdit = dynamic_cast<CEdit*>(pWnd);
     	CComboBox* pCbx = dynamic_cast<CComboBox*>(pWnd);
     	CListBox* pLst = dynamic_cast<CListBox*>(pWnd);
     	CSortListCtrl* pLsc = dynamic_cast<CSortListCtrl*>(pWnd);
    
    	// ALLE EDT, CBX, LSC, LST sollen immer schwarzen Text haben.
         if ((pEdit || pCbx || pLst || pLsc) && (m_nViewMode == VIEW_MODE_VIEW))
        { 
    		pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
    		pDC->SetBkMode(TRANSPARENT);
            HBRUSH B = CreateSolidBrush(::GetSysColor(COLOR_3DFACE)); //Hintergrundfarbe 
            return (HBRUSH) B; 
        } 
    
        return hbr; 
    }
    
    HBRUSH CBasisView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
    {
    	HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor); 
    
    	// ALLE EDT, CBX, LSC, LST sollen immer schwarzen Text haben.
         if (!pWnd->IsWindowEnabled())
        { 
    		pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
    		pDC->SetBkMode(TRANSPARENT);
            HBRUSH B = CreateSolidBrush(::GetSysColor(COLOR_3DFACE)); //Hintergrundfarbe 
            return (HBRUSH) B; 
        } 
        return hbr; 
    }
    
    HBRUSH CBasisView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
    {
    	HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor); 
    
    	// ALLE EDT, CBX, LSC, LST sollen immer schwarzen Text haben.
        if ((pWnd->IsKindOf(RUNTIME_CLASS(CEdit))) || 
    		(pWnd->IsKindOf(RUNTIME_CLASS(CComboBox))) || 
    		(pWnd->IsKindOf(RUNTIME_CLASS(CListBox)))|| 
    		(pWnd->IsKindOf(RUNTIME_CLASS(CListCtrl))))
        { 
    		pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
    		pDC->SetBkMode(TRANSPARENT);
            HBRUSH B = CreateSolidBrush(::GetSysColor(COLOR_3DFACE)); //Hintergrundfarbe 
            return (HBRUSH) B; 
        } 
        return hbr; 
    }
    


  • Wird OnCtlColor denn auch aus der Messagemap heraus aufgerufen, d.h. steht dort auch der Eintrag ON_WM_CTLCOLOR() ?



  • Ja, in BEIDEN Klassen steht das in der MessageMap.

    Ich hatte ja auch geschrieben, dass der Code in der if durchlaufen wird. 🙂



  • ... wenn ich mich recht entsinne muss der Brush eine Membervarsein, sonst zerstört Windows den Brush nach dem verlassen der Funktion und man sieht maximal schwarzen Adler auf schwarzem Hintergrund: sprich er nimmt den original brush wieder her.



  • estardu, auch wenn es bei dem Problem nicht hilft: Der Brush den du von CreateSolidBrush bekommst muss wieder freigegeben werden.



  • Wenn ich den wieder freigeben muss, dann sag mir doch bitte mit welchem Befehl und wo. Ich bin mit dem Brush und Malereikram überhaupt nicht vertraut. 😞

    @DaDings: Mit fast identischem Code funktioniert es in einer anderen Klasse. 😕
    Guck:

    HBRUSH CFilView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
    	HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor); 
    
    	// Die Listbox für die Mitarbeiter soll bitte deaktiviert aussehen.
        if ((pWnd->GetDlgCtrlID() == IDC_LST_MITARBEITER) && (m_nViewMode == VIEW_MODE_VIEW))
        { 
    		pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
    		pDC->SetBkMode(TRANSPARENT);
            HBRUSH B = CreateSolidBrush(::GetSysColor(COLOR_3DFACE)); //Hintergrundfarbe 
            return (HBRUSH) B; 
        } 
        return hbr; 
    }
    


  • Wenn du Steuerelementre hast hat jede seine eigene Klasse. Da musst du ansetzen.
    z.B. CEdit.
    Von dieser brauchst du eine abgeleitete Klasse und da kannst du dann ändern was du willst.



  • Okay, das wäre nicht das Problem, ich habe schon eine Edit und eine Combobox Klasse.

    Aber dann muss ich für jedes Edit eine Controlvariable anlegen - ist das Sinn der Sache? 😕



  • Ich habe das in dem Edit jetzt eingebaut - aber jetzt stürzt das Programm immer sofort ab. 😞

    BEGIN_MESSAGE_MAP(CAdEdit, CEdit)
    	//{{AFX_MSG_MAP(CAdEdit)
    	ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
    	ON_WM_CTLCOLOR_REFLECT()
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    HBRUSH CAdEdit::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
    {
    	HBRUSH hbr = CEdit::OnCtlColor(pDC, pWnd, nCtlColor);
    
        if (!pWnd->IsWindowEnabled())
        { 
    		pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
    		pDC->SetBkMode(TRANSPARENT);
            HBRUSH B = CreateSolidBrush(::GetSysColor(COLOR_3DFACE)); //Hintergrundfarbe 
            return (HBRUSH) B; 
        } 
    
    	return hbr;
    }
    
    HBRUSH CWnd::OnCtlColor(CDC*, CWnd* pWnd, UINT)
    {
    	ASSERT(pWnd != NULL && pWnd->m_hWnd != NULL); // Auf dem ASSERT komme ich an, aber wegen einer unbehandelten Ausnahme
    	LRESULT lResult;
    	if (pWnd->SendChildNotifyLastMsg(&lResult))
    		return (HBRUSH)lResult;     // eat it
    	return (HBRUSH)Default();
    }
    

    Und noch ein Teil des Aufrufstacks, falls es hilft:

    CWnd::OnCtlColor(CDC * 0x0012f288 {hDC=0x04010a0e attrib=0x00000000}, CWnd * 0x00000006 {CWnd hWnd=???}, CDC * 0x0012f288 {hDC=0x04010a0e attrib=0x00000000}) line 3016 + 9 bytes
    CAdEdit::CtlColor(CDC * 0x0012f288 {hDC=0x04010a0e attrib=0x00000000}, CWnd * 0x00000006 {CWnd hWnd=???}, unsigned int 1242820) line 177 + 20 bytes
    CWnd::OnWndMsg(unsigned int 48153, unsigned int 0, long 1241964, long * 0x0012f3e8) line 1789 + 23 bytes
    CWnd::ReflectChildNotify(unsigned int 312, unsigned int 67176974, long 133792, long * 0x0012f3e8) line 2804 + 23 bytes
    CWnd::OnChildNotify(unsigned int 312, unsigned int 67176974, long 133792, long * 0x0012f3e8) line 2743
    CWnd::SendChildNotifyLastMsg(long * 0x0012f3e8) line 2683
    CWnd::OnCtlColor(CDC * 0x0012f45c {hDC=0x04010a0e attrib=0x00000000}, CWnd * 0x006c6f90 {CAdEdit hWnd=???}, CDC * 0x0012f45c {hDC=0x04010a0e attrib=0x00000000}) line 3018 + 12 bytes
    CWnd::OnWndMsg(unsigned int 25, unsigned int 0, long 1242420, long * 0x0012f50c) line 1774 + 24 bytes
    CWnd::WindowProc(unsigned int 25, unsigned int 0, long 1242420) line 1585 + 30 bytes
    CWnd::OnNTCtlColor(unsigned int 67176974, long 133792) line 1415
    CWnd::OnWndMsg(unsigned int 312, unsigned int 67176974, long 133792, long * 0x0012f660) line 1815 + 17 bytes
    CWnd::WindowProc(unsigned int 312, unsigned int 67176974, long 133792) line 1585 + 30 bytes
    AfxCallWndProc(CWnd * 0x006c6f08 {CKundenView hWnd=???}, HWND__ * 0x00040a04, unsigned int 312, unsigned int 67176974, long 133792) line 215 + 26 bytes
    AfxWndProc(HWND__ * 0x00040a04, unsigned int 312, unsigned int 67176974, long 133792) line 368
    AfxWndProcBase(HWND__ * 0x00040a04, unsigned int 312, unsigned int 67176974, long 133792) line 220 + 21 bytes
    USER32! 77e01ef0()
    USER32! 77e03523()
    USER32! 77e0c801()
    
    ...
    

    Wenn ich die Funktion so ändere:

    HBRUSH CAdEdit::CtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
    {
    // 	HBRUSH hbr = CEdit::OnCtlColor(pDC, pWnd, nCtlColor);
    // 	
    //     if (!pWnd->IsWindowEnabled())
    //     { 
    		pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
    		pDC->SetBkMode(TRANSPARENT);
            HBRUSH B = CreateSolidBrush(::GetSysColor(COLOR_3DFACE)); //Hintergrundfarbe 
            return (HBRUSH) B; 
    //     } 
    // 
    // 	return hbr;
    }
    

    ...stürzt er nicht mehr ab, läuft auf den Breakpoint auf - aber es funktioniert trotzdem nicht. 😞



  • Ich gebe Dir mal ein Codeschnipsel, das funzt, läuft seit längerem in einer von mir erstellten Software. Das ganze wird aus dem Dialog gemacht, also ohne das für die Felder extra abgeleitete Klassen erstellt worden sind.

    [cpp]
    HBRUSH CPleZbDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
    	HBRUSH hbr = CGBTPLEDialogBase::OnCtlColor(pDC, pWnd, nCtlColor);
    
    	switch (pWnd->GetDlgCtrlID())
    	{
    		case IDC_LISTET:
    		case IDC_LISTAT:
    		case IDC_LSTVIEWET:
    		case IDC_LSTVIEWAT:	pDC->SetBkColor(::GetSysColor(COLOR_BTNFACE));
    								   hbr = CreateSolidBrush(::GetSysColor(COLOR_BTNFACE)); 
    									break;
    	}
    
    	// TODO:  Change any attributes of the DC here
    
    	// TODO:  Return a different brush if the default is not desired
    	return hbr;
    [/cpp]
    


  • Danke! 🙂

    Darauf wird es wohl auch hinauslaufen, wenn ich nicht noch was anderes finde. 😞


Anmelden zum Antworten