X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9d55bfef2cb35ac07972e76c786d265c9b35d230..ca21f825b50978500d5525f07682868ebf62ff6f:/src/msw/listctrl.cpp diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index cdc5123074..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" @@ -82,6 +83,33 @@ static void wxConvertToMSWListCol(HWND hwndList, const wxListItem& item, LV_COLUMN& lvCol); +namespace +{ + +// replacement for ListView_GetSubItemRect() which provokes warnings like +// "the address of 'rc' will always evaluate as 'true'" when used with mingw32 +// 4.3+ +// +// this function does no error checking on item and subitem parameters, notice +// 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) +{ + rect.top = subitem; + rect.left = flags; + return ::SendMessage(hwnd, LVM_GETSUBITEMRECT, item, (LPARAM)&rect) != 0; +} + +inline bool +wxGetListCtrlItemRect(HWND hwnd, int item, int flags, RECT& rect) +{ + return wxGetListCtrlSubItemRect(hwnd, item, 0, flags, rect); +} + +} // anonymous namespace + // ---------------------------------------------------------------------------- // private helper classes // ---------------------------------------------------------------------------- @@ -159,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); }; /////////////////////////////////////////////////////// @@ -207,7 +235,7 @@ public: delete attr; } - DECLARE_NO_COPY_CLASS(wxListItemInternalData) + wxDECLARE_NO_COPY_CLASS(wxListItemInternalData); }; // Get the internal data structure @@ -338,14 +366,26 @@ bool wxListCtrl::Create(wxWindow *parent, // GetTextColour will always return black SetTextColour(GetDefaultAttributes().colFg); + if ( InReportView() ) + MSWSetExListStyles(); + + return true; +} + +void wxListCtrl::MSWSetExListStyles() +{ // for comctl32.dll v 4.70+ we want to have some non default extended // styles because it's prettier (and also because wxGTK does it like this) - if ( InReportView() && wxApp::GetComCtl32Version() >= 470 ) + if ( wxApp::GetComCtl32Version() >= 470 ) { ::SendMessage ( GetHwnd(), LVM_SETEXTENDEDLISTVIEWSTYLE, 0, + // LVS_EX_LABELTIP shouldn't be used under Windows CE where it's + // not defined in the SDK headers +#ifdef LVS_EX_LABELTIP LVS_EX_LABELTIP | +#endif LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES | // normally this should be governed by a style as it's probably not @@ -354,8 +394,6 @@ bool wxListCtrl::Create(wxWindow *parent, LVS_EX_HEADERDRAGDROP ); } - - return true; } WXDWORD wxListCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const @@ -454,6 +492,11 @@ void wxListCtrl::UpdateStyle() if ( dwStyleOld != dwStyleNew ) { ::SetWindowLong(GetHwnd(), GWL_STYLE, dwStyleNew); + + // if we switched to the report view, set the extended styles for + // it too + if ( !(dwStyleOld & LVS_REPORT) && (dwStyleNew & LVS_REPORT) ) + MSWSetExListStyles(); } } } @@ -473,10 +516,8 @@ void wxListCtrl::FreeAllInternalData() } } -wxListCtrl::~wxListCtrl() +void wxListCtrl::DeleteEditControl() { - FreeAllInternalData(); - if ( m_textCtrl ) { m_textCtrl->UnsubclassWin(); @@ -484,6 +525,13 @@ wxListCtrl::~wxListCtrl() delete m_textCtrl; m_textCtrl = NULL; } +} + +wxListCtrl::~wxListCtrl() +{ + FreeAllInternalData(); + + DeleteEditControl(); if (m_ownsImageListNormal) delete m_imageListNormal; @@ -526,7 +574,7 @@ void wxListCtrl::SetWindowStyleFlag(long flag) { if ( flag != m_windowStyle ) { - m_windowStyle = flag; + wxControl::SetWindowStyleFlag(flag); UpdateStyle(); @@ -676,33 +724,32 @@ bool wxListCtrl::SetColumnWidth(int col, int width) // columns order // ---------------------------------------------------------------------------- -int wxListCtrl::GetColumnOrder(int col) const +int wxListCtrl::GetColumnIndexFromOrder(int order) const { const int numCols = GetColumnCount(); - wxCHECK_MSG( col >= 0 && col < numCols, -1, _T("Col index out of bounds") ); + wxCHECK_MSG( order >= 0 && order < numCols, -1, + _T("Column position out of bounds") ); wxArrayInt indexArray(numCols); - if ( !ListView_GetColumnOrderArray(GetHwnd(), numCols, &indexArray[0]) ) return -1; - return indexArray[col]; + return indexArray[order]; } -int wxListCtrl::GetColumnIndexFromOrder(int order) const +int wxListCtrl::GetColumnOrder(int col) const { const int numCols = GetColumnCount(); - wxASSERT_MSG( order >= 0 && order < numCols, _T("Col order out of bounds") ); + wxASSERT_MSG( col >= 0 && col < numCols, _T("Column index out of bounds") ); wxArrayInt indexArray(numCols); - if ( !ListView_GetColumnOrderArray(GetHwnd(), numCols, &indexArray[0]) ) return -1; - for ( int col = 0; col < numCols; col++ ) + for ( int pos = 0; pos < numCols; pos++ ) { - if ( indexArray[col] == order ) - return col; + if ( indexArray[pos] == col ) + return pos; } wxFAIL_MSG( _T("no column with with given order?") ); @@ -746,6 +793,25 @@ int wxListCtrl::GetCountPerPage() const // Gets the edit control for editing labels. wxTextCtrl* wxListCtrl::GetEditControl() const { + // first check corresponds to the case when the label editing was started + // by user and hence m_textCtrl wasn't created by EditLabel() at all, while + // the second case corresponds to us being called from inside EditLabel() + // (e.g. from a user wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT handler): in this + // case EditLabel() did create the control but it didn't have an HWND to + // initialize it with yet + if ( !m_textCtrl || !m_textCtrl->GetHWND() ) + { + HWND hwndEdit = ListView_GetEditControl(GetHwnd()); + if ( hwndEdit ) + { + wxListCtrl * const self = const_cast(this); + + if ( !m_textCtrl ) + self->m_textCtrl = new wxTextCtrl; + self->InitEditControl((WXHWND)hwndEdit); + } + } + return m_textCtrl; } @@ -923,14 +989,15 @@ bool wxListCtrl::SetItemState(long item, long state, long stateMask) wxConvertToMSWFlags(state, stateMask, lvItem); + const bool changingFocus = (stateMask & wxLIST_STATE_FOCUSED) && + (state & wxLIST_STATE_FOCUSED); + // for the virtual list controls we need to refresh the previously focused // item manually when changing focus without changing selection // programmatically because otherwise it keeps its focus rectangle until // next repaint (yet another comctl32 bug) long focusOld; - if ( IsVirtual() && - (stateMask & wxLIST_STATE_FOCUSED) && - (state & wxLIST_STATE_FOCUSED) ) + if ( IsVirtual() && changingFocus ) { focusOld = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED); } @@ -958,6 +1025,16 @@ bool wxListCtrl::SetItemState(long item, long state, long stateMask) } } + // we expect the selection anchor, i.e. the item from which multiple + // selection (such as performed with e.g. Shift-arrows) starts, to be the + // same as the currently focused item but the native control doesn't update + // it when we change focus and leaves at the last item it set itself focus + // to, so do it explicitly + if ( changingFocus && !HasFlag(wxLC_SINGLE_SEL) ) + { + ListView_SetSelectionMark(GetHwnd(), item); + } + return true; } @@ -1032,19 +1109,40 @@ bool wxListCtrl::SetItemPtrData(long item, wxUIntPtr data) wxRect wxListCtrl::GetViewRect() const { - wxASSERT_MSG( !HasFlag(wxLC_REPORT | wxLC_LIST), - _T("wxListCtrl::GetViewRect() only works in icon mode") ); + wxRect rect; - RECT rc; - if ( !ListView_GetViewRect(GetHwnd(), &rc) ) + // ListView_GetViewRect() can only be used in icon and small icon views + // (this is documented in MSDN and, indeed, it returns bogus results in + // report view, at least with comctl32.dll v6 under Windows 2003) + if ( HasFlag(wxLC_ICON | wxLC_SMALL_ICON) ) { - wxLogDebug(_T("ListView_GetViewRect() failed.")); + RECT rc; + if ( !ListView_GetViewRect(GetHwnd(), &rc) ) + { + wxLogDebug(_T("ListView_GetViewRect() failed.")); + + wxZeroMemory(rc); + } - wxZeroMemory(rc); + wxCopyRECTToRect(rc, rect); } + else if ( HasFlag(wxLC_REPORT) ) + { + const long count = GetItemCount(); + if ( count ) + { + GetItemRect(wxMin(GetTopItem() + GetCountPerPage(), count - 1), rect); - wxRect rect; - wxCopyRECTToRect(rc, rect); + // extend the rectangle to start at the top (we include the column + // headers, if any, for compatibility with the generic version) + rect.height += rect.y; + rect.y = 0; + } + } + else + { + wxFAIL_MSG( _T("not implemented in this mode") ); + } return rect; } @@ -1055,22 +1153,18 @@ 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 { - RECT rectWin; + // ListView_GetSubItemRect() doesn't do subItem error checking and returns + // true even for the out of range values of it (even if the results are + // completely bogus in this case), so we check item validity ourselves + wxCHECK_MSG( subItem == wxLIST_GETSUBITEMRECT_WHOLEITEM || + (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 ) @@ -1085,27 +1179,28 @@ bool wxListCtrl::GetSubItemRect(long item, long subItem, wxRect& rect, int code) codeWin = LVIR_BOUNDS; } - bool success; - if( subItem == wxLIST_GETSUBITEMRECT_WHOLEITEM) - { - success = ListView_GetItemRect(GetHwnd(), (int) item, &rectWin, codeWin) != 0; - } - else if( subItem >= 0) - { - success = ListView_GetSubItemRect( GetHwnd(), (int) item, (int) subItem, codeWin, &rectWin) != 0; - } - else + RECT rectWin; + if ( !wxGetListCtrlSubItemRect + ( + GetHwnd(), + item, + subItem == wxLIST_GETSUBITEMRECT_WHOLEITEM ? 0 : subItem, + codeWin, + rectWin + ) ) { - wxFAIL_MSG( _T("incorrect subItem number in GetSubItemRect()") ); - return false; + return false; } - rect.x = rectWin.left; - rect.y = rectWin.top; - rect.width = rectWin.right - rectWin.left; - rect.height = rectWin.bottom - rectWin.top; + wxCopyRECTToRect(rectWin, rect); - return success; + // 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; } @@ -1424,38 +1519,49 @@ void wxListCtrl::ClearAll() DeleteAllColumns(); } +void wxListCtrl::InitEditControl(WXHWND hWnd) +{ + m_textCtrl->SetHWND(hWnd); + m_textCtrl->SubclassWin(hWnd); + m_textCtrl->SetParent(this); + + // we must disallow TABbing away from the control while the edit contol is + // shown because this leaves it in some strange state (just try removing + // this line and then pressing TAB while editing an item in listctrl + // inside a panel) + m_textCtrl->SetWindowStyle(m_textCtrl->GetWindowStyle() | wxTE_PROCESS_TAB); +} + wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass) { - wxASSERT( (textControlClass->IsKindOf(CLASSINFO(wxTextCtrl))) ); + wxCHECK_MSG( textControlClass->IsKindOf(CLASSINFO(wxTextCtrl)), NULL, + "control used for label editing must be a wxTextCtrl" ); // ListView_EditLabel requires that the list has focus. SetFocus(); + // create m_textCtrl here before calling ListView_EditLabel() because it + // generates wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT event from inside it and + // the user handler for it can call GetEditControl() resulting in an on + // demand creation of a stock wxTextCtrl instead of the control of a + // (possibly) custom wxClassInfo + DeleteEditControl(); + m_textCtrl = (wxTextCtrl *)textControlClass->CreateObject(); + WXHWND hWnd = (WXHWND) ListView_EditLabel(GetHwnd(), item); if ( !hWnd ) { // failed to start editing - return NULL; - } - - // [re]create the text control wrapping the HWND we got - if ( m_textCtrl ) - { - m_textCtrl->UnsubclassWin(); - m_textCtrl->SetHWND(0); delete m_textCtrl; + m_textCtrl = NULL; + + return NULL; } - m_textCtrl = (wxTextCtrl *)textControlClass->CreateObject(); - m_textCtrl->SetHWND(hWnd); - m_textCtrl->SubclassWin(hWnd); - m_textCtrl->SetParent(this); - - // we must disallow TABbing away from the control while the edit contol is - // shown because this leaves it in some strange state (just try removing - // this line and then pressing TAB while editing an item in listctrl - // inside a panel) - m_textCtrl->SetWindowStyle(m_textCtrl->GetWindowStyle() | wxTE_PROCESS_TAB); + // if GetEditControl() hasn't been called, we need to initialize the edit + // control ourselves + if ( !m_textCtrl->GetHWND() ) + InitEditControl(hWnd); return m_textCtrl; } @@ -1841,15 +1947,12 @@ bool wxListCtrl::MSWCommand(WXUINT cmd, WXWORD id_) // utility used by wxListCtrl::MSWOnNotify and by wxDataViewHeaderWindowMSW::MSWOnNotify int WXDLLIMPEXP_CORE wxMSWGetColumnClicked(NMHDR *nmhdr, POINT *ptClick) { - wxASSERT(nmhdr && ptClick); - - // find the column clicked: we have to search for it - // ourselves as the notification message doesn't provide - // this info + // find the column clicked: we have to search for it ourselves as the + // notification message doesn't provide this info // where did the click occur? #if defined(__WXWINCE__) && !defined(__HANDHELDPC__) && _WIN32_WCE < 400 - if (nmhdr->code == GN_CONTEXTMENU) + if ( nmhdr->code == GN_CONTEXTMENU ) { *ptClick = ((NMRGINFO*)nmhdr)->ptAction; } @@ -1860,19 +1963,27 @@ int WXDLLIMPEXP_CORE wxMSWGetColumnClicked(NMHDR *nmhdr, POINT *ptClick) wxLogLastError(_T("GetCursorPos")); } - if ( !::ScreenToClient(nmhdr->hwndFrom, ptClick) ) + // we need to use listctrl coordinates for the event point so this is what + // we return in ptClick, but for comparison with Header_GetItemRect() + // result below we need to use header window coordinates + POINT ptClickHeader = *ptClick; + if ( !::ScreenToClient(nmhdr->hwndFrom, &ptClickHeader) ) { - wxLogLastError(_T("ScreenToClient(header)")); + wxLogLastError(_T("ScreenToClient(listctrl header)")); } - int colCount = Header_GetItemCount(nmhdr->hwndFrom); + if ( !::ScreenToClient(::GetParent(nmhdr->hwndFrom), ptClick) ) + { + wxLogLastError(_T("ScreenToClient(listctrl)")); + } - RECT rect; + const int colCount = Header_GetItemCount(nmhdr->hwndFrom); for ( int col = 0; col < colCount; col++ ) { + RECT rect; if ( Header_GetItemRect(nmhdr->hwndFrom, col, &rect) ) { - if ( ::PtInRect(&rect, *ptClick) ) + if ( ::PtInRect(&rect, ptClickHeader) ) { return col; } @@ -2062,16 +2173,9 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) const LV_ITEM& lvi = (LV_ITEM)item; if ( !lvi.pszText || lvi.iItem == -1 ) { - // don't keep a stale wxTextCtrl around - if ( m_textCtrl ) - { - // EDIT control will be deleted by the list control itself so - // prevent us from deleting it as well - m_textCtrl->UnsubclassWin(); - m_textCtrl->SetHWND(0); - delete m_textCtrl; - m_textCtrl = NULL; - } + // EDIT control will be deleted by the list control + // itself so prevent us from deleting it as well + DeleteEditControl(); event.SetEditCanceled(true); } @@ -2180,11 +2284,11 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) wxLIST_STATE_SELECTED); // or activate the selected item if any (but - // not with Shift and/or Ctrl as then they have a predefined - // meaning for the list view) + // not with any modifiers as they have a predefined meaning + // then) if ( lItem != -1 && (wVKey == VK_RETURN || wVKey == VK_SPACE) && - !(wxIsShiftDown() || wxIsCtrlDown()) ) + !wxIsAnyModifierDown() ) { eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED; } @@ -2377,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() @@ -2444,16 +2548,9 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // logic here is inverted compared to all the other messages *result = event.IsAllowed(); - // don't keep a stale wxTextCtrl around - if ( m_textCtrl ) - { - // EDIT control will be deleted by the list control itself so - // prevent us from deleting it as well - m_textCtrl->UnsubclassWin(); - m_textCtrl->SetHWND(0); - delete m_textCtrl; - m_textCtrl = NULL; - } + // EDIT control will be deleted by the list control itself so + // prevent us from deleting it as well + DeleteEditControl(); return true; } @@ -2474,10 +2571,10 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) static RECT GetCustomDrawnItemRect(const NMCUSTOMDRAW& nmcd) { RECT rc; - ListView_GetItemRect(nmcd.hdr.hwndFrom, nmcd.dwItemSpec, &rc, LVIR_BOUNDS); + wxGetListCtrlItemRect(nmcd.hdr.hwndFrom, nmcd.dwItemSpec, LVIR_BOUNDS, rc); RECT rcIcon; - ListView_GetItemRect(nmcd.hdr.hwndFrom, nmcd.dwItemSpec, &rcIcon, LVIR_ICON); + wxGetListCtrlItemRect(nmcd.hdr.hwndFrom, nmcd.dwItemSpec, LVIR_ICON, rcIcon); // exclude the icon part, neither the selection background nor focus rect // should cover it @@ -2500,22 +2597,10 @@ bool HandleSubItemPrepaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount) SelectInHDC selFont(hdc, hfont); // get the rectangle to paint + int subitem = colCount ? col + 1 : col; RECT rc; - ListView_GetSubItemRect(hwndList, item, col, LVIR_BOUNDS, &rc); - if ( !col && colCount > 1 ) - { - // broken ListView_GetSubItemRect() returns the entire item rect for - // 0th subitem while we really need just the part for this column - RECT rc2; - ListView_GetSubItemRect(hwndList, item, 1, LVIR_BOUNDS, &rc2); - - rc.right = rc2.left; - rc.left += 4; - } - else // not first subitem - { - rc.left += 6; - } + wxGetListCtrlSubItemRect(hwndList, item, subitem, LVIR_BOUNDS, rc); + rc.left += 6; // get the image and text to draw wxChar text[512]; @@ -2628,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, (WPARAM)-1, LVNI_FOCUSED) == item ) + ListView_GetNextItem( + hwndList, static_cast(-1), LVNI_FOCUSED) == item ) { nmcd.uItemState |= CDIS_FOCUS; } @@ -2736,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; @@ -2754,10 +2851,11 @@ WXLPARAM wxListCtrl::OnCustomDraw(WXLPARAM lParam) // Necessary for drawing hrules and vrules, if specified void wxListCtrl::OnPaint(wxPaintEvent& event) { - bool drawHRules = HasFlag(wxLC_HRULES); - bool drawVRules = HasFlag(wxLC_VRULES); + 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; @@ -2770,19 +2868,17 @@ void wxListCtrl::OnPaint(wxPaintEvent& event) // Reset the device origin since it may have been set dc.SetDeviceOrigin(0, 0); - wxPen pen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT), 1, wxSOLID); + wxPen pen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT)); 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++) + const long top = GetTopItem(); + for ( int i = top; i < top + GetCountPerPage() + 1; i++ ) { if (GetItemRect(i, itemRect)) { @@ -2796,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 @@ -2819,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(); @@ -2834,8 +2934,6 @@ void wxListCtrl::OnPaint(wxPaintEvent& event) dc.DrawLine(x-1, firstItemRect.GetY() - gap, x-1, itemRect.GetBottom()); } - - delete indexArray; } } } @@ -2904,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); }