Reputation: 1040
I'm currently experiencing a problem with my OnNMCustomdrawlistctrlvalues() event handler being called non-stop once I've painted a CListCtrl row red (code gets stuck), causing my application to freeze once I try to perform another event, such as clicking a button.
I have the following code:
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;
}
Which results in:
Within the CListCtrl, if I scroll to an area which isn't painted red, my application is fine.
I'm not too sure how to stop this from happening... maybe I need an alternative way of dynamically painting a row red?
EDIT: I have changed my code to the below, but am experiencing this issue (only 2nd and 3rd column being coloured, but when I redraw the list control i.e. scroll down then back up, all columns are then drawn):
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: I changed to the below code, but am still getting the same issue:
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;
}
Upvotes: 1
Views: 4086
Reputation: 565
Try this:
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;
}
}
Upvotes: 1
Reputation: 4590
I think your design is slightly off by using CDDS_ITEMPREPAINT. I use custom painting to highlight a row in a CListCtrl to the color yellow. I do this by leveraging CDDS_ITEMPOSTPAINT and using the FillSolidRect and DrawText methods of the CDC. As Mark alluded to, some simple experimenting (with what I've posted in this answer) should help.
Edit: Using CDDS_ITEMPOSTPAINT, you can get the device context by
CDC* pDC = CDC::FromHandle (pNMLVCD->nmcd.hdc);
Getting the row corodinates that you want to paint can be done by
GetItemRect (row, &rect, LVIR_BOUNDS);
Rendering the row color is done by
pDC->FillSolidRect (&rect, RGB (0, 255, 0));
And, lastly, draw each column text by
// 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);
}
You'll need to make the necessary adjustments to the above code to meet your needs.
Upvotes: 1