Застревание кода обработчика событий MFC CListCtrl CustomDraw ()

В настоящее время я испытываю проблему с тем, что мой обработчик события 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

1

Решение

Я думаю, что ваш дизайн немного отличается от использования CDDS_ITEMPREPAINT. Я использую пользовательскую живопись, чтобы выделить строку в CListCtrl до желтого цвета. Я делаю это, используя CDDS_ITEMPOSTPAINT и используя FillSolidRect а также DrawText методы CDC. Как намекал Марк, некоторые простые эксперименты (с тем, что я разместил в этом ответе) должны помочь.

редактировать: Используя CDDS_ITEMPOSTPAINT, вы можете получить контекст устройства

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

Получение ряда кородинатов, которые вы хотите нарисовать, может быть выполнено

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

Другие решения

Попробуй это:

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