X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/80cc5fc7ad102221a1ce9e160eac3c29a0586664..ca21f825b50978500d5525f07682868ebf62ff6f:/src/msw/listctrl.cpp diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index 4d7e28177a..b102317312 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -39,6 +39,7 @@ #endif #include "wx/imaglist.h" +#include "wx/vector.h" #include "wx/msw/private.h" @@ -90,7 +91,9 @@ namespace // 4.3+ // // this function does no error checking on item and subitem parameters, notice -// that subitem is 0 for whole item or 1-based for the individual columns +// that subitem 0 means the whole item so there is no way to retrieve the +// rectangle of the first subitem using this function, in particular notice +// that the index is *not* 1-based, in spite of what MSDN says inline bool wxGetListCtrlSubItemRect(HWND hwnd, int item, int subitem, int flags, RECT& rect) { @@ -184,7 +187,7 @@ private: LV_ITEM_NATIVE *m_pItem; LV_ITEM_NATIVE m_item; - DECLARE_NO_COPY_CLASS(wxLV_ITEM) + wxDECLARE_NO_COPY_CLASS(wxLV_ITEM); }; /////////////////////////////////////////////////////// @@ -232,7 +235,7 @@ public: delete attr; } - DECLARE_NO_COPY_CLASS(wxListItemInternalData) + wxDECLARE_NO_COPY_CLASS(wxListItemInternalData); }; // Get the internal data structure @@ -1150,19 +1153,6 @@ bool wxListCtrl::GetItemRect(long item, wxRect& rect, int code) const return GetSubItemRect( item, wxLIST_GETSUBITEMRECT_WHOLEITEM, rect, code) ; } -/*! - * Retrieve coordinates and size of a specified subitem of a listview control. - * This function only works if the listview control is in the report mode. - * - * @param item : Item number - * @param subItem : Subitem or column number, use -1 for the whole row including - * all columns or subitems - * @param rect : A pointer to an allocated wxRect object - * @param code : Specify the part of the subitem coordinates you need. Choices are - * wxLIST_RECT_BOUNDS, wxLIST_RECT_ICON, wxLIST_RECT_LABEL - * - * @return bool : True if successful. - */ bool wxListCtrl::GetSubItemRect(long item, long subItem, wxRect& rect, int code) const { // ListView_GetSubItemRect() doesn't do subItem error checking and returns @@ -1172,6 +1162,10 @@ bool wxListCtrl::GetSubItemRect(long item, long subItem, wxRect& rect, int code) (subItem >= 0 && subItem < GetColumnCount()), false, _T("invalid sub item index") ); + // use wxCHECK_MSG against "item" too, for coherency with the generic implementation: + wxCHECK_MSG( item >= 0 && item < GetItemCount(), false, + _T("invalid item in GetSubItemRect") ); + int codeWin; if ( code == wxLIST_RECT_BOUNDS ) codeWin = LVIR_BOUNDS; @@ -1200,9 +1194,11 @@ bool wxListCtrl::GetSubItemRect(long item, long subItem, wxRect& rect, int code) wxCopyRECTToRect(rectWin, rect); - // for the first sub item, i.e. the main item itself, the returned rect is - // the whole line one, we need to truncate it at first column ourselves - rect.width = GetColumnWidth(0); + // there is no way to retrieve the first sub item bounding rectangle using + // wxGetListCtrlSubItemRect() as 0 means the whole item, so we need to + // truncate it at first column ourselves + if ( subItem == 0 ) + rect.width = GetColumnWidth(0); return true; } @@ -2485,7 +2481,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) if ( lvi.mask & LVIF_TEXT ) { wxString text = OnGetItemText(item, lvi.iSubItem); - wxStrncpy(lvi.pszText, text, lvi.cchTextMax); + wxStrlcpy(lvi.pszText, text.c_str(), lvi.cchTextMax); } // see comment at the end of wxListCtrl::GetColumn() @@ -2717,8 +2713,12 @@ static void HandleItemPaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont) } // 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, -1, LVNI_FOCUSED) == item ) + ListView_GetNextItem( + hwndList, static_cast(-1), LVNI_FOCUSED) == item ) { nmcd.uItemState |= CDIS_FOCUS; } @@ -2825,14 +2825,22 @@ WXLPARAM wxListCtrl::OnCustomDraw(WXLPARAM lParam) 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() ) + break; - return HandleItemPrepaint(this, pLVCD, DoGetItemAttr(item)); + return HandleItemPrepaint(this, pLVCD, DoGetItemColumnAttr(item, column)); } return CDRF_DODEFAULT; @@ -2843,10 +2851,11 @@ WXLPARAM wxListCtrl::OnCustomDraw(WXLPARAM lParam) // Necessary for drawing hrules and vrules, if specified void wxListCtrl::OnPaint(wxPaintEvent& event) { + const int itemCount = GetItemCount(); const bool drawHRules = HasFlag(wxLC_HRULES); const bool drawVRules = HasFlag(wxLC_VRULES); - if (!InReportView() || !(drawHRules || drawVRules)) + if (!InReportView() || !(drawHRules || drawVRules) || !itemCount) { event.Skip(); return; @@ -2866,12 +2875,10 @@ void wxListCtrl::OnPaint(wxPaintEvent& event) wxSize clientSize = GetClientSize(); wxRect itemRect; - int itemCount = GetItemCount(); - int i; if (drawHRules) { - long top = GetTopItem(); - for (i = top; i < top + GetCountPerPage() + 1; i++) + const long top = GetTopItem(); + for ( int i = top; i < top + GetCountPerPage() + 1; i++ ) { if (GetItemRect(i, itemRect)) { @@ -2885,17 +2892,18 @@ void wxListCtrl::OnPaint(wxPaintEvent& event) { cy = itemRect.GetBottom(); dc.DrawLine(0, cy, clientSize.x, cy); + break; } } } } - i = itemCount - 1; - if (drawVRules && (i > -1)) + + if (drawVRules) { wxRect firstItemRect; GetItemRect(0, firstItemRect); - if (GetItemRect(i, itemRect)) + if (GetItemRect(itemCount - 1, itemRect)) { // this is a fix for bug 673394: erase the pixels which we would // otherwise leave on the screen @@ -2908,11 +2916,14 @@ void wxListCtrl::OnPaint(wxPaintEvent& event) dc.SetPen(pen); dc.SetBrush(*wxTRANSPARENT_BRUSH); - int numCols = GetColumnCount(); - int* indexArray = new int[numCols]; - if ( !ListView_GetColumnOrderArray( GetHwnd(), numCols, indexArray) ) + const int numCols = GetColumnCount(); + wxVector indexArray(numCols); + if ( !ListView_GetColumnOrderArray(GetHwnd(), + numCols, + &indexArray[0]) ) { wxFAIL_MSG( _T("invalid column index array in OnPaint()") ); + return; } int x = itemRect.GetX(); @@ -2923,8 +2934,6 @@ void wxListCtrl::OnPaint(wxPaintEvent& event) dc.DrawLine(x-1, firstItemRect.GetY() - gap, x-1, itemRect.GetBottom()); } - - delete indexArray; } } } @@ -2993,9 +3002,9 @@ wxListItemAttr *wxListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item)) cons return NULL; } -wxListItemAttr *wxListCtrl::DoGetItemAttr(long item) const +wxListItemAttr *wxListCtrl::DoGetItemColumnAttr(long item, long column) const { - return IsVirtual() ? OnGetItemAttr(item) + return IsVirtual() ? OnGetItemColumnAttr(item, column) : wxGetInternalDataAttr(this, item); }