2016-08-22 68 views
1

我创建了一个所有者绘制列表框,并将其绑定为如下所示的向量。最好的方式来告诉所有者绘制listbox重绘一个项目?

vector<wchar_t*> texts; 

lbHWND = CreateWindowExW(NULL, WC_LISTBOX, NULL, 
     WS_CHILD | WS_BORDER | WS_VISIBLE | LBS_NODATA | 
     LBS_OWNERDRAWFIXED | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT, 
     0, 0, 400, 400, tkHWND, (HMENU)IDC_LISTBOX_ENTRY, hInstance, 0); 

SCROLLINFO lbSi = { 0 }; 
lbSi.cbSize = sizeof(SCROLLINFO); 
lbSi.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; 
lbSi.nMin = 0; 
lbSi.nMax = text.size(); 
lbSi.nPage = 20; 
lbSi.nPos = 0; 
SetScrollInfo(lbHWND, SB_VERT, &lbSi, TRUE); 

SendMessageW(lbHWND, LB_RESETCONTENT, 0, 0); 
SendMessage(lbHWND, LB_SETCOUNT, iTotal, 0); 

LRESULT CALLBACK WndProc(HWND phwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch (message) 
    { 
     case WM_MEASUREITEM: 
     { 
      MEASUREITEMSTRUCT* lpmis = (LPMEASUREITEMSTRUCT)lParam; 
      switch (lpmis->CtlID) 
      { 
       case IDC_LISTBOX_ENTRY: 
        lpmis->itemHeight = 20; 
        break; 
       default: 
        break; 
      } 
      return TRUE; 
     } 
     case WM_DRAWITEM: 
     { 
      DRAWITEMSTRUCT* lpdis = (LPDRAWITEMSTRUCT)lParam; 

      if (lpdis->itemID == -1) return; 
      HBRUSH hb = NULL; 
      HPEN hp = NULL; 

      switch (lpdis->itemAction) 
      { 
       case ODA_SELECT: 
       case ODA_DRAWENTIRE: 
        SetBkMode(lpdis->hDC, TRANSPARENT); 
        hb = CreateSolidBrush(lpdis->itemState & ODS_SELECTED ? 0xf1f1f1 : 0xffffff); 
        hp = CreatePen(PS_SOLID, 1, lpdis->itemState & ODS_SELECTED ? 0xcfcfcf : 0xffffff); 
        SelectObject(lpdis->hDC, hp); 
        SelectObject(lpdis->hDC, hb); 

        Rectangle(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, lpdis->rcItem.right, lpdis->rcItem.bottom); 

        TextOut(lpdis->hDC, 
         lpdis->rcItem.left + 5, 
         lpdis->rcItem.top + 2, 
         texts[i], 
         wcslen(texts[i]); 
        break; 
      } 
      if (hp) DeleteObject(hp); 
      if (hb) DeleteObject(hb); 
     } 
    } 
} 

现在假设我在texts更新项目,你能告诉我一个很好的方式来告诉列表框重绘该项目?

目前,我使用下面的代码:

texts[2] = L"Some text"; 
SendMessageW(lbHWND, LB_RESETCONTENT, 0, 0); 
SendMessage(lbHWND, LB_SETCOUNT, iTotal, 0); 

迫使列表框重绘所有项目,不仅是第三项。有一个更好的方法吗?

回答

2

您可以使用LB_GETITEMRECT检索项目的坐标,然后InvalidateRect()迫使窗口的特定区域的重绘:

RECT r = {}; 
if (SendMessage(lbHWND, LB_GETITEMRECT, index, &r) != LB_ERR) 
    InvalidateRect(lbHWND, &r, 0); 
+0

好的解决办法,谢谢:) – Sakura

相关问题