Search code examples
c++colorsmfclistcontrol

Changing MFC List Control header color


I am looking for the simplest way to change the header color of a 'List Control' header in MFC C++. I have found ways to change individual cells and rows, but can't get a working version that changes the header color. This is all the code I am using that deals with the header:

//Initializes the List Control with four columns
m_CListCtrl.InsertColumn(0, _T("Option"), LVCFMT_LEFT, 200);
m_CListCtrl.InsertColumn(1, _T("User"), LVCFMT_LEFT, 60);
m_CListCtrl.InsertColumn(2, _T("Value"), LVCFMT_LEFT, 80);
m_CListCtrl.InsertColumn(3, _T("Description"), LVCFMT_LEFT, 800);

Solution

  • This can be done, but, not without a little extra coding. What you’ll need to do:

    • Derive your own class from CListCtrl.
    • Derive your own class from CHeaderCtrl.
    • Replace the standard CListCtrl header with yours.
    • Use custom drawing for the header control.

    In derived CListCtrl,

    void MyListCtrl::PreSubclassWindow()
        {
        // TODO: Add your specialized code here and/or call the base class
        CHeaderCtrl* pHeader = NULL;
        pHeader = GetHeaderCtrl();
        if (pHeader != NULL)
            {
            VERIFY(m_HeaderCtrl.SubclassWindow(pHeader->m_hWnd)); // m_HeaderCtrl is the new wrapper object
            }
    
        CListCtrl::PreSubclassWindow();
        }
    

    In the header class,

    void MyHeader::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
        {
        LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
        // TODO: Add your control notification handler code here
        *pResult = CDRF_DODEFAULT;
    
        if (pNMCD->dwDrawStage == CDDS_PREPAINT)
            {
            CDC* pDC = CDC::FromHandle(pNMCD->hdc);
            CRect rect(0, 0, 0, 0);
            GetClientRect(&rect);
            pDC->FillSolidRect(&rect, RGB(255, 0, 0));
    
            *pResult = CDRF_NOTIFYITEMDRAW;
            }
        else if (pNMCD->dwDrawStage == CDDS_ITEMPREPAINT)
            {
            HDITEM hditem;
            TCHAR buffer[MAX_PATH] = { 0 };
            SecureZeroMemory(&hditem, sizeof(HDITEM));
            hditem.mask = HDI_TEXT;
            hditem.pszText = buffer;
            hditem.cchTextMax = MAX_PATH;
            GetItem(pNMCD->dwItemSpec, &hditem);
            CDC* pDC = CDC::FromHandle(pNMCD->hdc);
            pDC->SetTextColor(RGB(0, 0, 0));
            pDC->SetBkColor(RGB(255, 0, 0));
            CString str(buffer);
            pDC->DrawText(str, CRect(pNMCD->rc), DT_VCENTER | DT_LEFT);
            *pResult = CDRF_SKIPDEFAULT;
            }
        }
    

    Using my sample code, you should see....

    Red CListCtrl header

    I'll leave any customization for you to finish.