-
- case NM_RCLICK:
- /* TECH NOTE: NM_RCLICK isn't really good enough here. We want to
- subclass and check for the actual WM_RBUTTONDOWN message, because
- NM_RCLICK waits for the WM_RBUTTONUP message as well before firing off.
- We want to have notify events for both down -and- up. */
- {
- // if the user processes it in wxEVT_COMMAND_RIGHT_CLICK(), don't do
- // anything else
- if ( wxControl::MSWOnNotify(idCtrl, lParam, result) ) {
- return TRUE;
- }
-
- // else translate it into wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK event
- LVHITTESTINFO lvhti;
-#ifdef __GNUWIN32__
- memset(&lvhti,0,sizeof(LVHITTESTINFO));
-#else
- ZeroMemory(&lvhti, sizeof(LVHITTESTINFO)); // must set all fields to 0
-#endif
- ::GetCursorPos(&(lvhti.pt));
- ::ScreenToClient(GetHwnd(),&(lvhti.pt));
- if(ListView_HitTest(GetHwnd(),&lvhti)!=-1) {
- if(lvhti.flags & LVHT_ONITEM) {
- eventType = wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK;
- event.m_itemIndex = lvhti.iItem;
- }
- }
- }
- break;
-
- /*
- case NM_MCLICK: // ***** THERE IS NO NM_MCLICK. Subclass anyone? ******
- {
- // if the user processes it in wxEVT_COMMAND_MIDDLE_CLICK(), don't do
- // anything else
- if ( wxControl::MSWOnNotify(idCtrl, lParam, result) )
- {
- return TRUE;
- }
-
- // else translate it into wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK event
- eventType = wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK;
- NMITEMACTIVATE* hdr = (NMITEMACTIVATE*)lParam;
- event.m_itemIndex = hdr->iItem;
- }
- break;
- */
-
- case LVN_SETDISPINFO:
- {
- eventType = wxEVT_COMMAND_LIST_SET_INFO;
- LV_DISPINFO *info = (LV_DISPINFO *)lParam;
- wxConvertFromMSWListItem(this, event.m_item, info->item, GetHwnd());
+ }
+
+ if ( i == item )
+ {
+ nmcd.uItemState |= CDIS_SELECTED;
+ break;
+ }
+ }
+
+ // same thing for CDIS_FOCUS (except simpler as there is only one of them)
+ //
+ // NB: cast is needed to work around the bug in mingw32 headers which don't
+ // have it inside ListView_GetNextItem() itself (unlike SDK ones)
+ if ( ::GetFocus() == hwndList &&
+ ListView_GetNextItem(
+ hwndList, static_cast<WPARAM>(-1), LVNI_FOCUSED) == item )
+ {
+ nmcd.uItemState |= CDIS_FOCUS;
+ }
+ else
+ {
+ nmcd.uItemState &= ~CDIS_FOCUS;
+ }
+
+ if ( nmcd.uItemState & CDIS_SELECTED )
+ {
+ int syscolFg, syscolBg;
+ if ( ::GetFocus() == hwndList )
+ {
+ syscolFg = COLOR_HIGHLIGHTTEXT;
+ syscolBg = COLOR_HIGHLIGHT;
+ }
+ else // selected but unfocused
+ {
+ syscolFg = COLOR_WINDOWTEXT;
+ syscolBg = COLOR_BTNFACE;
+
+ // don't grey out the icon in this case neither
+ nmcd.uItemState &= ~CDIS_SELECTED;
+ }
+
+ pLVCD->clrText = ::GetSysColor(syscolFg);
+ pLVCD->clrTextBk = ::GetSysColor(syscolBg);
+ }
+ //else: not selected, use normal colours from pLVCD
+
+ HDC hdc = nmcd.hdc;
+ RECT rc = GetCustomDrawnItemRect(nmcd);
+
+ ::SetTextColor(hdc, pLVCD->clrText);
+ ::FillRect(hdc, &rc, AutoHBRUSH(pLVCD->clrTextBk));
+
+ // we could use CDRF_NOTIFYSUBITEMDRAW here but it results in weird repaint
+ // problems so just draw everything except the focus rect from here instead
+ const int colCount = Header_GetItemCount(ListView_GetHeader(hwndList));
+ for ( int col = 0; col < colCount; col++ )
+ {
+ pLVCD->iSubItem = col;
+ HandleSubItemPrepaint(pLVCD, hfont, colCount);
+ }
+
+ HandleItemPostpaint(nmcd);
+}
+
+static WXLPARAM HandleItemPrepaint(wxListCtrl *listctrl,
+ LPNMLVCUSTOMDRAW pLVCD,
+ wxListItemAttr *attr)
+{
+ if ( !attr )
+ {
+ // nothing to do for this item
+ return CDRF_DODEFAULT;
+ }
+
+
+ // set the colours to use for text drawing
+ pLVCD->clrText = attr->HasTextColour()
+ ? wxColourToRGB(attr->GetTextColour())
+ : wxColourToRGB(listctrl->GetTextColour());
+ pLVCD->clrTextBk = attr->HasBackgroundColour()
+ ? wxColourToRGB(attr->GetBackgroundColour())
+ : wxColourToRGB(listctrl->GetBackgroundColour());
+
+ // select the font if non default one is specified
+ if ( attr->HasFont() )
+ {
+ wxFont font = attr->GetFont();
+ if ( font.GetEncoding() != wxFONTENCODING_SYSTEM )
+ {
+ // the standard control ignores the font encoding/charset, at least
+ // with recent comctl32.dll versions (5 and 6, it uses to work with
+ // 4.something) so we have to draw the item entirely ourselves in
+ // this case
+ HandleItemPaint(pLVCD, GetHfontOf(font));
+ return CDRF_SKIPDEFAULT;
+ }
+
+ ::SelectObject(pLVCD->nmcd.hdc, GetHfontOf(font));
+
+ return CDRF_NEWFONT;
+ }
+
+ return CDRF_DODEFAULT;
+}
+
+WXLPARAM wxListCtrl::OnCustomDraw(WXLPARAM lParam)
+{
+ LPNMLVCUSTOMDRAW pLVCD = (LPNMLVCUSTOMDRAW)lParam;
+ NMCUSTOMDRAW& nmcd = pLVCD->nmcd;
+ switch ( nmcd.dwDrawStage )
+ {
+ case CDDS_PREPAINT:
+ // if we've got any items with non standard attributes,
+ // notify us before painting each item
+ //
+ // for virtual controls, always suppose that we have attributes as
+ // there is no way to check for this
+ if ( IsVirtual() || m_hasAnyAttr )
+ return CDRF_NOTIFYITEMDRAW;
+ break;
+
+ case CDDS_ITEMPREPAINT:
+ // get a message for each subitem
+ return CDRF_NOTIFYITEMDRAW;
+
+ case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
+ const int item = nmcd.dwItemSpec;
+ const int column = pLVCD->iSubItem;
+
+ // we get this message with item == 0 for an empty control, we
+ // must ignore it as calling OnGetItemAttr() would be wrong
+ if ( item < 0 || item >= GetItemCount() )
+ break;
+ // same for columns
+ if ( column < 0 || column >= GetColumnCount() )