Background color TabCtrl



  • Hallo,
    wie ist es möglich die Hintergrundfarbe einer TabCtrl zu ändern?
    Die Hintergrundfarbe der TabCtrl sollte die gleiche sein, wie die des Dialoges.
    Habe es in der OnCtlColor()-Methode versucht mit:

    if(pWnd->GetDlgCtrlID() == IDC_TAB)
    {
        return hBrush1;
    }
    

    Die if-Abfrage wird aber nicht erfüllt?! Weiß jemand warum?



  • Habe jetzt was im Netz gefunden. Weiß aber nicht so genau wie ich es anwenden muss.

    Ich überschreibe die OnDrawItem()-Methode.

    void CMFCTabCtrlDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis)
           {
              CDialog::OnDrawItem(nIDCtl, lpdis);
    
              RECT        rect;
              UINT        bkColor;
              CBrush      *cbr;
              TC_ITEM     tci;
    
              CTabCtrl    *pTabCtrl = (CTabCtrl *)GetDlgItem(IDC_TAB1);
    
              if (pTabCtrl->m_hWnd == lpdis->hwndItem)
              {
                  pTabCtrl->GetItem(lpdis->itemID, &tci);
    
                  CDC *dc = CDC::FromHandle(lpdis->hDC);
    
                  dc->FillRect(&lpdis->rcItem, cbr);
                  dc->SetBkColor(bkColor);
               }
           }
    

    Durch welches Ereignis wird diese Methode nun aufgerufen?


  • Mod

    1. CTabCtrl arbeitet nicht mit WM_CTLCOLOR
    2. Dieser Code, den Du hier zeigst, wird nur ausgeführt wenn Dein Control Ownerdraw ist! (Stil TCS_OWNERDRAWFIXED)

    Leider wird NM_CUSTOMDRAW auch nicht unterstützt.

    IMHO musst Du in diesem Fall zu Ownerdraw greifen.



  • Wie heißt denn die Struktur in der ich die Styles festlegen kann? Habe in der MSDN nichts gefunden. Oder kann ich die Styles nur mit Create() festlegen?

    Würde mein Code überhaupt funktionieren, da er ja in einer Klasse ist die von CDialog abgeleitet ist? Oder muss ich die Klasse dann von CTabCtrl ableiten?


  • Mod

    Das ist keine Struktur! Fenster werden mit bestimmten Stilen erzeugt.
    Du kannst die entsprechenden Stile im Create festlegen oder eben im Dialog Template.



  • Habe jetzt mal versucht Create() zu implementieren, da diese Methode ja nicht durch den Assistenten bereitgestellt wird, wenn man die Fenster mit dem Ressourceneditor hinzufügt.

    Doch ich kriege leider ein ASSERT.

    m_Tab.Create(TCS_OWNERDRAWFIXED, rect, AfxGetMainWnd(), IDC_TAB);
    


  • suchst du vielleicht solch einen code?

    Hintergrund-und Schriftfarbe ändern:
    in progname.cpp

    1. TabCtrl.cpp BOOL *App::InitInstance()
      nach m_pMainWnd = &dlg;
    2. SetDialogBkColor(RGB(0,0,12),RGB(12,12,12));

  • Mod

    Du musst mindestens auch noch WS_CHILD als Stil definieren.

    Grundsätzlich: Wenn Du einen ASSERT bekommts, dann sag uns wo Du bei welchem Statement (Datei, Teilennummer, evtl. Kopie des ASSERT's) den ASSERT bekommst.

    Dir hilft evtl. auch der Stack-Trace.
    Evt. kannst Du dan auch selber herausbekommen wo die Ursache ist.



  • Kann mit dem Code der die Assertion auslöst nicht viel anfangen.
    Die Assertion kommt an folgender Stelle:

    ASSERT(pWnd->m_hWnd == NULL);   // only do once
    

    der komplette Code lautet:

    void AFXAPI AfxHookWindowCreate(CWnd* pWnd)
    {
    	_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
    	if (pThreadState->m_pWndInit == pWnd)
    		return;
    
    	if (pThreadState->m_hHookOldCbtFilter == NULL)
    	{
    		pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,
    			_AfxCbtFilterHook, NULL, ::GetCurrentThreadId());
    		if (pThreadState->m_hHookOldCbtFilter == NULL)
    			AfxThrowMemoryException();
    	}
    	ASSERT(pThreadState->m_hHookOldCbtFilter != NULL);
    	ASSERT(pWnd != NULL);
    	ASSERT(pWnd->m_hWnd == NULL);   // only do once
    
    	ASSERT(pThreadState->m_pWndInit == NULL);   // hook not already in progress
    	pThreadState->m_pWndInit = pWnd;
    }
    

  • Mod

    Ganz einfach: Das Control existiert schon. Du kannst es nicht nochmal erzeugen.
    Wahrscheinlich hast Du es im Dialog-Editor schon zugewiesen und nun erzeugst Du es erneut.



  • So was hab ich mir auch gedacht. Was könnte ich jetzt denn tun?
    Die TabCtrl aus dem Dialog editor und die ID aus ressource.h löschen und dann mit Create() erstellen?



  • So jetzt klappts!
    2 Fragen bleiben aber noch bestehen:

    1.Wie kann man festlegen das die TabCtrl einen Rahmen hat?
    2.Wenn ich die Hintergrundfarbe der TabCtrl mit dc->FillRect(rect, cbr) zeichne, kann ich nicht über die Tabs zeichnen, da ich sonst den Text dieser Tabs überpinsle. Wie kann man die Hintergrundfarbe dieser Tabs zeichnen?

    Hiermal mein Code:

    void CDeviceStateDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis)
    {
    	char        szTabText[100];
        RECT        rect;
        UINT        bkColor;
        CBrush      *cbr;
        TC_ITEM     tci;
    
        CTabCtrl    *pTabCtrl = (CTabCtrl *)GetDlgItem(IDC_TAB);
    
    	tci.mask        = TCIF_TEXT;
        tci.pszText     = szTabText;
        tci.cchTextMax  = sizeof(szTabText)-1; 
    
        pTabCtrl->GetItem(lpdis->itemID, &tci);
    
        CDC *dc = CDC::FromHandle(lpdis->hDC);
    
    	rect.bottom = 460;
    	rect.top = 20;
    	rect.left = 0;
    	rect.right= 690;
    
    	cbr = &brTabColor;
        dc->FillRect(&rect, cbr);
    
        TextOut(lpdis->hDC,
        lpdis->rcItem.left,
        lpdis->rcItem.top,
        tci.pszText,
        lstrlen(tci.pszText));
    }
    

  • Mod

    1. Stil WS_BORDER
    2. Schau Dir mal bitte die Drawitem Struct besser an. Da wird Dir detailiert gesagt was zu zeichnen ist, auch das Rectangle. Wieso holst Du die Daten separat.



  • Habe in der MSDN nix gefunden, was mir weiterhelft.
    Welche Daten meinst du?


Anmelden zum Antworten