+ ImageList_Draw(himl, it.iImage, hdc, rc.left, rc.top,
+ nmcd.uItemState & CDIS_SELECTED ? ILD_SELECTED
+ : ILD_TRANSPARENT);
+ }
+
+ // notice that even if this item doesn't have any image, the list
+ // control still leaves space for the image in the first column if the
+ // image list is not empty (presumably so that items with and without
+ // images align?)
+ if ( it.iImage != -1 || it.iSubItem == 0 )
+ {
+ int wImage, hImage;
+ ImageList_GetIconSize(himl, &wImage, &hImage);
+
+ rc.left += wImage + 2;
+ }
+ }
+
+ ::SetBkMode(hdc, TRANSPARENT);
+
+ // TODO: support for centred/right aligned columns
+ ::DrawText(hdc, text, -1, &rc,
+#ifndef __WXWINCE__
+ DT_WORD_ELLIPSIS |
+#endif // __WXWINCE__
+ DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER);
+}
+
+static void HandleItemPostpaint(NMCUSTOMDRAW nmcd)
+{
+ if ( nmcd.uItemState & CDIS_FOCUS )
+ {
+ RECT rc = GetCustomDrawnItemRect(nmcd);
+
+ // don't use the provided HDC, it's in some strange state by now
+ ::DrawFocusRect(WindowHDC(nmcd.hdr.hwndFrom), &rc);
+ }
+}
+
+// pLVCD->clrText and clrTextBk should contain the colours to use
+static void HandleItemPaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont)
+{
+ NMCUSTOMDRAW& nmcd = pLVCD->nmcd; // just a shortcut
+
+ const HWND hwndList = nmcd.hdr.hwndFrom;
+ const int item = nmcd.dwItemSpec;
+
+ // unfortunately we can't trust CDIS_SELECTED, it is often set even when
+ // the item is not at all selected for some reason (comctl32 6), but we
+ // also can't always trust ListView_GetItem() as it could return the old
+ // item status if we're called just after the (de)selection, so remember
+ // the last item to gain selection and also check for it here
+ for ( int i = -1;; )
+ {
+ i = ListView_GetNextItem(hwndList, i, LVNI_SELECTED);
+ if ( i == -1 )
+ {
+ nmcd.uItemState &= ~CDIS_SELECTED;
+ break;
+ }
+
+ if ( i == item )
+ {
+ nmcd.uItemState |= CDIS_SELECTED;
+ break;
+ }
+ }
+
+ // same thing for CDIS_FOCUS (except simpler as there is only one of them)
+ if ( ::GetFocus() == hwndList &&
+ ListView_GetNextItem(hwndList, (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);
+ }
+
+ 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:
+ const int item = nmcd.dwItemSpec;
+
+ // 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;
+
+ return HandleItemPrepaint(this, pLVCD, DoGetItemAttr(item));
+ }
+
+ return CDRF_DODEFAULT;
+}
+
+#endif // NM_CUSTOMDRAW supported
+
+// Necessary for drawing hrules and vrules, if specified
+void wxListCtrl::OnPaint(wxPaintEvent& event)
+{
+ bool drawHRules = HasFlag(wxLC_HRULES);
+ bool drawVRules = HasFlag(wxLC_VRULES);
+
+ if (!InReportView() || !drawHRules && !drawVRules)
+ {
+ event.Skip();
+ return;
+ }
+
+ wxPaintDC dc(this);
+
+ wxControl::OnPaint(event);
+
+ // Reset the device origin since it may have been set
+ dc.SetDeviceOrigin(0, 0);
+
+ wxPen pen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT), 1, wxSOLID);
+ dc.SetPen(pen);
+ dc.SetBrush(* wxTRANSPARENT_BRUSH);
+
+ wxSize clientSize = GetClientSize();
+ wxRect itemRect;
+
+ int itemCount = GetItemCount();
+ int i;
+ if (drawHRules)
+ {
+ long top = GetTopItem();
+ for (i = top; i < top + GetCountPerPage() + 1; i++)
+ {
+ if (GetItemRect(i, itemRect))