3

everyone. https://i.stack.imgur.com/ugfY4.jpg

I've got this kind of list-view color editor, every item represents separate color. So the user clicks on the COLOR_CODE subItem, the color picker updates to the selected HSV value and then the user drags color picker cursor on the pallete and the COLOR_CODE subItem should update in real-time as well as the color ID text. Most of the time the update performs nice and smooth, but sometimes it just flickers in a manner of - ---- It happens in a really flickering manner as if there was no time to draw it quickly.

I've started my search and found lots of posts, all leading to double buffering. Ok, I've got DOUBLE BUFFERING enabled in my list view like that

case WM_INITDIALOG:
ListView_SetExtendedListViewStyle(GetDlgItem(hDlg,id_listview),LVS_EX_DOUBLEBUFFER);

also tried it this way

SendDlgItemMessage(hWnd,id_listview,LVM_SETEXTENDEDLISTVIEWSTYLE,NULL,(LPARAM)LVS_EX_DOUBLEBUFFER);

But it did not help. Here is my custom draw routine It basicly takes whatever string is written in the ID subItem - 0xffb400 for example and converts it to COLORREF, then sets BG color of subItem 2 to the resulting color;

case WM_NOTIFY:
if(((LPNMHDR)lParam)->code == NM_CUSTOMDRAW)
        {
            SetWindowLong(hDlg, DWL_MSGRESULT, (LONG)ProcessCustomDraw(lParam,hDlg));
            return TRUE;
        }
        break;

LRESULT colorEditor::ProcessCustomDraw (LPARAM lParam,HWND hDlg)
{
    LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;

    switch(lplvcd->nmcd.dwDrawStage) 
    {
        case CDDS_PREPAINT:
            return CDRF_NOTIFYITEMDRAW;
        case CDDS_ITEMPREPAINT: 
            return CDRF_NOTIFYSUBITEMDRAW;
        case CDDS_ITEMPREPAINT|CDDS_SUBITEM: //Before an item is drawn//
            if (lplvcd->iSubItem==2)
            {
                item_redraw.iItem=lplvcd->nmcd.dwItemSpec;
                SendDlgItemMessageA(hWnd,id_listview,LVM_GETITEM,0,(LPARAM)&item_redraw);
                lplvcd->clrTextBk = colorrefFromString(item_redraw.pszText);
            }
            return CDRF_NEWFONT;
    }
    return CDRF_DODEFAULT;
}

Just in case you think colorrefFromString is the case I provide it's listing:

COLORREF colorEditor::colorrefFromString(wchar_t *color)
{
    COLORREF res_color;
    unsigned short i=0,di=0;
    int digits[6];
    int h_digits[3];
    if (color[i]=='0'&&(color[i+1]=='x'||color[i+1]=='X')) i=2;
    int ix=0;

    while (color[(ix++)+i]!='\0'){}
    if (--ix!=5) while((ix++)<5)
        digits[di++]=0;

    while (color[i]!='\0')
    {
        if (color[i]>47&&color[i]<58) digits[di++]=color[i]-48;
        else if (color[i]>64&&color[i]<71) digits[di++]=color[i]-65+10;
        else if (color[i]>96&&color[i]<103) digits[di++]=color[i]-97+10;
        i++;
    }
    h_digits[0]=digits[0]*16+digits[1];
    h_digits[1]=digits[2]*16+digits[3];
    h_digits[2]=digits[4]*16+digits[5];
    res_color=0x00000000|(h_digits[2]<<16)|(h_digits[1]<<8)|h_digits[0];
    return res_color;
}

And now the QUESTION: Why do i have flickering?

Antiusninja
  • 157
  • 1
  • 17
  • Ok, I'm not sure if it is a good way of solving the situation, – Antiusninja Aug 04 '14 at 15:02
  • Ok , I've completely forgot to put one more function that I use in mousemove message while colorpicking. It's LVM_REDRAWITEMS sent to the current item. Instead of sending this message which makes all the item line go white - I just find out the rectangle of the COLOR_CODE subitem and fill it with current color. The problem is that I get the subitem rectangle with offset. So I need to set the OffsetRect(13,13) by hand. Then everything looks perfect, but the fact that I'm doing that by hand looks WRONG! – Antiusninja Aug 04 '14 at 15:08

1 Answers1

0

On the first look I can see no real reason for flickering.

But try to do all drawing here by yourself., may be this works.

Just calculate the color. Call FillRect on the item rectangle with the given dc and return CDRF_SKIPDEFAULT.

xMRi
  • 14,982
  • 3
  • 26
  • 59
  • All right, I've made some step debug. Here is what i've noticed. First I send out the CDRF_NOTIFYITEMDRAW to get the CDDS_ITEMPREPAINT stage, Then I return CDRF_NOTIFYSUBITEMDRAW to get the CDDS_ITEMPREPAINT|CDDS_SUBITEM. When I get this last notification, my subitem is already drawn white / ERASED. Even if I FillRectangle with some color on that step, it's already flickering because the before the ITEM PREPAINT goes erase procedure. I'm trying to actually catch the erase now. case CDDS_ITEMPREERASE somewhy is not catching anything. Any more suggestions would be great – Antiusninja Aug 04 '14 at 13:38