MFC CListCtrl CustomDraw()事件处理程序代码卡住了

时间:2015-01-09 03:53:41

标签: c++ mfc paint clistctrl custom-draw

我目前遇到的问题是我的OnNMCustomdrawlistctrlvalues()事件处理程序在我将CListCtrl行涂成红色(代码卡住)后不停地调用,导致我的应用程序冻结一旦我尝试执行另一个事件,例如单击按钮。

我有以下代码:

void CSPID_FQA_Test_ClientDlg::OnNMCustomdrawlistctrlvalues(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMLVCUSTOMDRAW lpLVCustomDraw = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
    int itemCnt = 0;
    CString text;
    RECT rc;

    switch(lpLVCustomDraw->nmcd.dwDrawStage)
    {
    case CDDS_ITEMPREPAINT:
    case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
        //get each row text for 2nd column
        itemCnt = mListCtrl.GetItemCount();
        for (int i = 0; i < itemCnt; i++)
        {
            text = mListCtrl.GetItemText(i, 2);
            if (text.Compare("No") == 0)
            {
                if (i == (lpLVCustomDraw->nmcd.dwItemSpec))
                {
                    lpLVCustomDraw->clrTextBk = RGB(255,50,50);
                    mListCtrl.GetItemRect(i,&rc,LVIR_BOUNDS);
                    mListCtrl.InvalidateRect(&rc, 0);
                }
            }
        }
        break;
    default: break;
    }

    *pResult = 0;
    *pResult |= CDRF_NOTIFYITEMDRAW;
    *pResult |= CDRF_NOTIFYSUBITEMDRAW;
    *pResult |= CDRF_NOTIFYPOSTPAINT;
}

结果是:

result1

在CListCtrl中,如果我滚动到一个没有涂成红色的区域,我的应用程序就可以了。

我不太确定如何阻止这种情况发生...也许我需要一种动态绘制红色的替代方法?


编辑:我已将代码更改为以下内容,但遇到此问题(仅第2和第3列被着色,但是当我重绘列表控件时,向下滚动然后备份,所有然后绘制列):

result2

void CSPID_FQA_Test_ClientDlg::OnNMCustomdrawlistctrlvalues(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMLVCUSTOMDRAW lpLVCustomDraw = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
    int itemCnt = 0;
    CString text;
    RECT rc;

    CDC* pDC = CDC::FromHandle (lpLVCustomDraw->nmcd.hdc);

    switch(lpLVCustomDraw->nmcd.dwDrawStage)
    {
    case CDDS_ITEMPOSTPAINT:
    //case CDDS_ITEMPREPAINT:
    //case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
        //get each row text for 2nd column
        itemCnt = mListCtrl.GetItemCount();
        for (int i = 0; i < itemCnt; i++)
        {
            text = mListCtrl.GetItemText(i, 2);
            if (text.Compare("No") == 0)
            {
                if (i == (lpLVCustomDraw->nmcd.dwItemSpec))
                {
                    //lpLVCustomDraw->clrTextBk = RGB(255,50,50);
                    mListCtrl.GetItemRect(i,&rc,LVIR_BOUNDS);
                    pDC->FillSolidRect (&rc, RGB (0, 255, 0));

                    //mListCtrl.InvalidateRect(&rc, 0);
                }
            }
        }
        break;
    default: break;
    }

    *pResult = 0;
    *pResult |= CDRF_NOTIFYITEMDRAW;
    *pResult |= CDRF_NOTIFYSUBITEMDRAW;
    *pResult |= CDRF_NOTIFYPOSTPAINT;
}

EDIT2:我更改为以下代码,但仍然遇到同样的问题:

LPNMLVCUSTOMDRAW lpLVCustomDraw = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
CString text;
RECT rc;

CDC* pDC = CDC::FromHandle (lpLVCustomDraw->nmcd.hdc);

switch(lpLVCustomDraw->nmcd.dwDrawStage)
{
case CDDS_ITEMPOSTPAINT:

    mListCtrl.GetItemRect(lpLVCustomDraw->nmcd.dwItemSpec,&rc,LVIR_BOUNDS);
    text = mListCtrl.GetItemText(lpLVCustomDraw->nmcd.dwItemSpec, 2);

    if (text.Compare("No") == 0)
    {
        pDC->FillSolidRect (&rc, RGB(0, 0, 255));
    }

    break;
default: break;
}

result3

2 个答案:

答案 0 :(得分:1)

我认为使用CDDS_ITEMPREPAINT稍微偏离了您的设计。我使用自定义绘画将CListCtrl中的行突出显示为黄色。我这样做是通过利用 CDDS_ITEMPOSTPAINT 并使用CDC的 FillSolidRect DrawText 方法实现的。正如马克提到的那样,一些简单的实验(我在这个答案中发布的内容)应该会有所帮助。

编辑:使用CDDS_ITEMPOSTPAINT,您可以通过

获取设备上下文
CDC*  pDC = CDC::FromHandle (pNMLVCD->nmcd.hdc);

获取您想要绘制的行corodinates可以通过

完成
GetItemRect (row, &rect, LVIR_BOUNDS);

通过

渲染行颜色
pDC->FillSolidRect (&rect, RGB (0, 255, 0));

最后,按

绘制每个列文本
//  draw each column's text into the corresponding CRect.
for (col=0; col<nCols; ++col)
    {
    GetSubItemRect (row, col, LVIR_BOUNDS, rect);
    rect.left += 6;
    CString text = pRow->GetColumnText (col);
    pDC->DrawText (text, &rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
    }

您需要对上述代码进行必要的调整以满足您的需求。

答案 1 :(得分:1)

试试这个:

void ColorListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) 
{
    NMLVCUSTOMDRAW *pNMLVCUSTOMDRAW = (NMLVCUSTOMDRAW *) pNMHDR;
    *pResult = CDRF_DODEFAULT;
    switch (pNMLVCUSTOMDRAW->nmcd.dwDrawStage)
    {   case CDDS_PREPAINT:
            *pResult |= CDRF_NOTIFYITEMDRAW;
            break;
        case CDDS_ITEMPREPAINT:
            // compare text in column 2
            // set background to special color if matches
            INT nItem = pNMLVCUSTOMDRAW->nmcd.dwItemSpec;
            CString strText = GetItemText(nItem, 2);
            if (strText==_T("No"))  pNMLVCUSTOMDRAW->clrTextBk = RGB(255,0,0);
            break;
    }
}