CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Apr 1999
    Posts
    5

    Change Color of single row in CListCtrl and CTreeCtrl

    How may I change a single row in a CListCtrl and a CTreeCtrl? SetTextColor changes all rows!

    Thanks
    Markus


  2. #2
    Join Date
    Apr 1999
    Posts
    26

    Re: Change Color of single row in CListCtrl and CTreeCtrl

    I have the same problem as your. Did you find out the solution?
    Will appreciate your help.
    Thanks.


  3. #3
    Join Date
    May 1999
    Location
    Canada
    Posts
    36

    Re: Change Color of single row in CListCtrl and CTreeCtrl

    Do your own DrawItem and control the color from within there. I send a message back to the control's owner to config the color and another message to config the font.
    This is a farly lengthly function it comes from several locations mostly CodeGuru.

    void CMyListCtrl:rawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
    // Get the display context for the control.
    CDC* pCDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    RECT UpdateRect = lpDrawItemStruct->rcItem;
    RECT UpdateRect2;
    pCDC->GetClipBox(&UpdateRect2);

    // Use mask if there is one.
    UINT uiFlags(ILD_TRANSPARENT);

    COLORREF OldTextColor = pCDC->GetTextColor();
    COLORREF OldBackColor;
    COLORREF TextColor, NewTextColor;

    // Check to see if this item is selected.
    if(lpDrawItemStruct->itemState & ODS_SELECTED)
    {
    TextColor = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
    OldBackColor = pCDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
    uiFlags |= ILD_BLEND50;
    }
    else
    {
    TextColor = GetTextColor();// ::GetSysColor(COLOR_WINDOWTEXT); //
    OldBackColor = pCDC->SetBkColor(GetBkColor()); // ::GetSysColor(COLOR_WINDOW));
    }

    CPen* penOld;
    // Create the pen used to draw the gridlines.
    CPen pen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNFACE));//COLOR_WINDOWTEXT 1999 05 18

    bool bVert = m_dwFlag & fVertGrid ? true : false;
    bool bHorz = m_dwFlag & fHorizGrid ? true : false;

    if(bVert || bHorz)
    {
    penOld = pCDC->SelectObject(&pen);
    }

    // Now walk through columns and draw text.
    char szText[256]; // Increase this if you have longer text.
    char * pStr;
    int offset;
    LV_COLUMN lvc;
    memset(&lvc, 0, sizeof(lvc));
    lvc.mask = LVCF_WIDTH | LVCF_SUBITEM | LVCF_FMT | LVCF_ORDER; // *** added LVCF_SUBITEM and LVCF_FMT to get the columne id and justification
    // Get the image list and draw.
    CImageList* plistImages = GetImageList(LVSIL_SMALL);
    LV_ITEM lvi;

    CFont * pOldFont = pCDC->GetCurrentFont();
    LOGFONT defaultLF, curLF, newLF;

    memset(&defaultLF, 0, sizeof(defaultLF));
    GetFont()->GetLogFont(&defaultLF);

    if(lpDrawItemStruct->itemState & ODS_FOCUS)
    defaultLF.lfWeight = FW_BOLD;

    // Create a font now and load it in
    HFONT hNewFont = ::CreateFontIndirect(&defaultLF);
    SelectObject(pCDC->m_hDC, hNewFont);
    curLF = defaultLF;

    // Calculate the start and end column from the rectangel that needs to be updated
    int nStartCol = 0;
    int nEndCol = -1;
    bool bDidColorChange = false;

    for (int nColumn = nStartCol; GetColumn(nColumn, &lvc); nColumn++)
    {
    CRect rTextClip;

    // First time.
    if (nStartCol == nColumn)
    {
    rTextClip.left = lpDrawItemStruct->rcItem.left + (plistImages ? 16 : 0);
    rTextClip.top = lpDrawItemStruct->rcItem.top;
    rTextClip.right = lpDrawItemStruct->rcItem.left + lvc.cx;
    rTextClip.bottom = lpDrawItemStruct->rcItem.bottom;
    }
    else
    {
    // Just "move" the rect to the right.
    rTextClip.left = rTextClip.right;
    rTextClip.right = rTextClip.left + lvc.cx;
    }

    // Second column selected and only selecting first column
    if( lpDrawItemStruct->itemState & ODS_SELECTED &&
    false == bDidColorChange &&
    1 <= nColumn &&
    fHighRowSelect != (m_dwFlag & fHighRowSelect) )
    {
    bDidColorChange = true;
    TextColor = GetTextColor();//TextColor = ::GetSysColor(COLOR_WINDOWTEXT);
    pCDC->SetBkColor(GetBkColor()); //pCDC->SetBkColor(::GetSysColor(COLOR_WINDOW));
    }

    // Check to see if this needs to be updated If not go to the next column
    if(UpdateRect2.right < rTextClip.left || UpdateRect2.left > rTextClip.right)
    continue;

    memset(&lvi, 0, sizeof(lvi));
    lvi.mask = LVIF_IMAGE | LVIF_STATE;
    lvi.iItem = lpDrawItemStruct->itemData;
    lvi.iSubItem = lvc.iSubItem;

    if(m_fpGetItemText != NULL && m_pOwnerWnd != NULL)
    {
    GetItem(&lvi);
    pStr = (m_pOwnerWnd->*m_fpGetItemText)(lvc.iSubItem, lpDrawItemStruct->itemData);//itemID);
    }
    else
    {
    // Get the text.
    lvi.mask |= LVIF_TEXT;
    lvi.iItem = lpDrawItemStruct->itemID;
    lvi.iSubItem = lvc.iOrder;
    lvi.pszText = szText;
    lvi.cchTextMax = sizeof(szText);
    GetItem(&lvi);
    pStr = szText;
    }

    // If valid, draw.
    if (plistImages)
    {
    if(lvi.iImage)
    {
    //CPoint ptAt(lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top);
    CPoint ptAt(rTextClip.left, rTextClip.top);
    plistImages->Draw(pCDC, lvi.iImage, ptAt, uiFlags);
    }
    }

    if(m_dwFlag & fCellFont)
    {
    newLF = defaultLF;
    GetParent()->SendMessage(UM_MLC_GETFONT, (WPARAM)&newLF, MAKELONG(lvi.iItem, lvi.iSubItem));
    if(memcmp(&newLF, &curLF, sizeof(curLF)) != 0)// Something changed then change the DC
    {
    HFONT hOldFont = hNewFont;
    hNewFont = ::CreateFontIndirect(&newLF);
    SelectObject(pCDC->m_hDC, hNewFont);
    :eleteObject(hOldFont);
    curLF = newLF;
    }
    }

    NewTextColor = TextColor;
    if(m_dwFlag & fCellColor)
    GetParent()->SendMessage(UM_MLC_GETCOLOR, (WPARAM)&NewTextColor, MAKELONG(lvi.iItem, lvi.iSubItem));
    pCDC->SetTextColor(NewTextColor);

    // Add ellipses if necessary.
    int nTextCount(lstrlen(pStr));
    CSize sizText(pCDC->GetOutputTextExtent(pStr, nTextCount));

    // Make the clipping rectangle a little smaller for a gap effect between columns.
    rTextClip.right -= 4;

    if (sizText.cx >= rTextClip.Width())
    {
    // Make a shorter string, including "..." that fits.
    CSize sizEllipse = pCDC->GetOutputTextExtent("...", 3);

    // Now start dropping characters at the tail until width is correct.
    while (sizText.cx+sizEllipse.cx > (rTextClip.Width()) && nTextCount > 1)
    {
    pStr[--nTextCount] = 0;
    sizText = pCDC->GetOutputTextExtent(pStr, nTextCount);
    }

    // Ok, append "...".
    pStr[nTextCount] = '.';
    pStr[nTextCount + 1] = '.';
    pStr[nTextCount + 2] = '.';
    pStr[nTextCount + 3] = 0;

    sizText = pCDC->GetOutputTextExtent(pStr, lstrlen(pStr));
    }

    // Restore full rect.
    rTextClip.right += 4;

    // we know know it will fit know check the justification
    offset =0; //default if(lvc.fmt == LVCFMT_LEFT)
    if((lvc.fmt & LVCFMT_RIGHT) == LVCFMT_RIGHT)
    offset = max((rTextClip.Width() - sizText.cx) -8 , 0);
    else if((lvc.fmt &LVCFMT_CENTER) == LVCFMT_CENTER)
    offset = ((rTextClip.Width() - sizText.cx) -4)/2;

    // Print the text.
    pCDC->ExtTextOut(rTextClip.left + offset + 2, rTextClip.top + 1,
    ETO_CLIPPED | ETO_OPAQUE, &rTextClip, pStr,
    lstrlen(pStr), NULL);

    // Draw the gridlines. leave a gap iff both hor and vert
    if (bHorz)
    {
    pCDC->MoveTo(rTextClip.left + bVert*2, rTextClip.bottom - 1);
    pCDC->LineTo(rTextClip.right - bVert, rTextClip.bottom - 1);
    }

    if (bVert)
    {
    pCDC->MoveTo(rTextClip.right - 1, rTextClip.top + bHorz);
    pCDC->LineTo(rTextClip.right - 1, rTextClip.bottom - bHorz);
    }
    }

    // Reset Font
    pCDC->SelectObject(pOldFont);
    :eleteObject(hNewFont);

    // Reset colors
    pCDC->SetTextColor(OldTextColor); //::GetSysColor(COLOR_WINDOWTEXT));
    pCDC->SetBkColor(OldBackColor); //::GetSysColor(COLOR_WINDOW));

    // If focused draw focus rect.
    if (lpDrawItemStruct->itemState & ODS_FOCUS)
    {
    CRect rTextClip(lpDrawItemStruct->rcItem);
    // rTextClip.left += (plistImages ? 16 : 0);
    pCDC->DrawFocusRect(&rTextClip);
    }

    // We must leave the display context as we found it.
    if(bVert || bHorz)
    pCDC->SelectObject(penOld);
    }


    void CMyListCtrl::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
    {
    TEXTMETRIC tm;
    HDC hDC = ::GetDC(NULL);
    CFont* pFont = GetFont();
    HFONT hFontOld = (HFONT)SelectObject(hDC, pFont->GetSafeHandle());
    GetTextMetrics(hDC, &tm);
    lpMeasureItemStruct->itemHeight = tm.tmHeight + tm.tmExternalLeading + 1;
    SelectObject(hDC, hFontOld);
    ::ReleaseDC(NULL, hDC);
    }




    In the view I capture my UserMessages


    ON_MESSAGE(UM_MLC_GETFONT, OnGetFont)
    ON_MESSAGE(UM_MLC_GETCOLOR, OnGetColor)

    void CView_List::OnGetFont(WPARAM Wparm, LPARAM Lparm)
    {
    int row = LOWORD(Lparm);
    int col = HIWORD(Lparm);
    LOGFONT * pLF = (LOGFONT *)Wparm;
    if(pLF)
    {
    if(col == ID_DESCRIPTION)
    pLF->lfItalic = TRUE;
    }
    }

    void CView_List::OnGetColor(WPARAM Wparm, LPARAM Lparm)
    {
    int row = LOWORD(Lparm);
    int col = HIWORD(Lparm);
    COLORREF * pColor = (COLORREF *)Wparm;

    if(pColor)
    {
    BYTE Red = GetRValue(*pColor);
    BYTE Green = GetGValue(*pColor);
    BYTE Blue = GetBValue(*pColor);
    double top, bottom, depth;

    GetDocument()->GetTopBottom(&top, &bottom);
    depth = ((GetItemDouble(LDL_Depth, row) * 2) + GetItemDouble(LDL_Length, row))/2;

    Red = (BYTE)((depth + top) * (255.0 / max(1, top - bottom)));
    Blue = 255 - Red;

    COLORREF Color = RGB(Red, Green, Blue);
    *pColor = Color;
    }
    }







Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured