2015-01-09 77 views
1

目前我遇到一个问题,我OnNMCustomdrawlistctrlvalues()事件处理函数被调用不停一旦我画一个CListCtrl一行红色(代码卡),导致我的应用一旦我尝试执行另一个事件(例如单击按钮)就会冻结。MFC的CListCtrl CustomDraw()事件处理程序代码陷入

我有以下代码:

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,如果我滚动到未涂成红色的区域,我的应用程序是精细。

我不是太清楚如何阻止这种情况发生......也许我需要动态地画一排红色的另一种方式?


编辑:我已经改变了我的代码以下,但我遇到了这个问题(仅适用于第二和第三列是彩色的,但是当我重新绘制列表控件即向下滚动然后备份,所有列然后绘制):

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

+5

这段代码被称为列表项的绘图的一部分;通过调用'InvalidateRect',您可以再次执行绘图。无限循环! –

+0

嗨@MarkRansom,谢谢你的回复!啊,当然。我注释掉了'InvalidateRect'行,它已经停止冻结。我在绘图时得到以下结果(但如果我向下滚动并重新备份,则会正确重绘) - http://i.imgur.com/umiH6zI.png 任何想法如何解决这个问题? – LKB

+0

如果我知道如何解决它,我会留下一个答案而不是评论。一点点实验应该引导你找到解决方案。 –

回答

1

我觉得你的设计稍微偏离用CDDS_ITEMPREPAINT。我使用自定义绘制突出显示行中一个CListCtrl的颜色发黄。我这样做是通过利用CDDS_ITEMPOSTPAINT和使用FillSolidRectDrawText CDC的方法。正如马克暗示,一些简单的运行实验(用什么我已在这个答案)应帮助。

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

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

获得设备上下文获取,你要画可以通过

GetItemRect (row, &rect, LVIR_BOUNDS); 

进行渲染行的颜色是排corodinates完成

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); 
    } 

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

+0

感谢您的回答!你能分享一些代码片段吗? – LKB

+1

@LBran请参阅更新以解答。 – rrirower

+0

谢谢!我实现了一些你的代码(请参阅我的更新后的文章),我不担心文本绘图,但这是我最终得到的(这是我上面的问题)。 http://i.imgur.com/4RREvcp.png 这也发生在你身上吗? – LKB

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; 
    } 
} 
+0

感谢您的回答!我实现了你的代码,并且它工作正常,除了我仍然遇到与上面相同的问题,与此类似:i.imgur.com/4RREvcp.png – LKB

+0

@LBran - 您的图像显示列中的文本缺失,这只能在后处理事件中使用'FillSolidRect'发生,如原始文章的EDIT2中的代码所示。标记具有不同颜色的项目的要求实际上非常简单,只需要更改自定义绘制结构中的颜色,不需要绘图/填充,因为后面的默认绘图将处理其余的绘图/填充。有没有其他的绘图代码在其他地方,你忘记了? – mfc