X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/22f3361e1cf25c52a2da8fdfc5cb081809e18fb9..a5e3c24d7b0b954b0408697a211d004e4a55051d:/src/msw/listctrl.cpp diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index ee5bcf35af..e47b10a13d 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -5,8 +5,8 @@ // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Copyright: (c) Julian Smart +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -119,12 +119,7 @@ private: #if wxUSE_WCHAR_T if ( (item.mask & LVIF_TEXT) && item.pszText ) { -#ifdef __WXWINE__ - // FIXME - m_buf = new wxWC2WXbuf(wxConvLocal.cWC2WX((const __wchar_t* ) item.pszText)); -#else m_buf = new wxWC2WXbuf(wxConvLocal.cWC2WX(item.pszText)); -#endif m_item->pszText = (wxChar*)m_buf->data(); } else @@ -249,6 +244,8 @@ void wxListCtrl::Init() m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = FALSE; m_baseStyle = 0; m_colCount = 0; + m_count = 0; + m_ignoreChangeMessages = FALSE; m_textCtrl = NULL; m_AnyInternalData = FALSE; m_hasAnyAttr = FALSE; @@ -383,8 +380,10 @@ void wxListCtrl::FreeAllInternalData() int n = GetItemCount(); int i = 0; + m_ignoreChangeMessages = TRUE; for (i = 0; i < n; i++) wxDeleteInternalData(this, i); + m_ignoreChangeMessages = FALSE; m_AnyInternalData = FALSE; } @@ -396,8 +395,8 @@ wxListCtrl::~wxListCtrl() if ( m_textCtrl ) { - m_textCtrl->SetHWND(0); m_textCtrl->UnsubclassWin(); + m_textCtrl->SetHWND(0); delete m_textCtrl; m_textCtrl = NULL; } @@ -1019,7 +1018,7 @@ bool wxListCtrl::SetItemPosition(long item, const wxPoint& pos) // Gets the number of items in the list control int wxListCtrl::GetItemCount() const { - return ListView_GetItemCount(GetHwnd()); + return m_count; } // Retrieves the spacing between icons in pixels. @@ -1209,6 +1208,10 @@ bool wxListCtrl::DeleteItem(long item) return FALSE; } + m_count -= 1; + wxASSERT_MSG( m_count == ListView_GetItemCount(GetHwnd()), + wxT("m_count should match ListView_GetItemCount")); + // the virtual list control doesn't refresh itself correctly, help it if ( IsVirtual() ) { @@ -1237,6 +1240,7 @@ bool wxListCtrl::DeleteItem(long item) // Deletes all items bool wxListCtrl::DeleteAllItems() { + FreeAllInternalData(); return ListView_DeleteAllItems(GetHwnd()) != 0; } @@ -1295,8 +1299,8 @@ wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass) // [re]create the text control wrapping the HWND we got if ( m_textCtrl ) { - m_textCtrl->SetHWND(0); m_textCtrl->UnsubclassWin(); + m_textCtrl->SetHWND(0); delete m_textCtrl; } @@ -1453,8 +1457,12 @@ long wxListCtrl::InsertItem(wxListItem& info) } }; + long rv = ListView_InsertItem(GetHwnd(), & item); + m_count += 1; + wxASSERT_MSG( m_count == ListView_GetItemCount(GetHwnd()), + wxT("m_count should match ListView_GetItemCount")); - return (long) ListView_InsertItem(GetHwnd(), & item); + return rv; } long wxListCtrl::InsertItem(long index, const wxString& label) @@ -1646,6 +1654,7 @@ bool wxListCtrl::MSWCommand(WXUINT cmd, WXWORD id) bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { + // prepare the event // ----------------- @@ -1757,7 +1766,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // there's a GPF in Windows. // By returning TRUE here, we avoid further processing // of this strange message. - if (info->iItem > GetColumnCount()) + if ( info->iItem >= GetColumnCount() ) return TRUE; } // fall through @@ -1775,29 +1784,29 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) const int iItem = nmLV->iItem; - // set the data event field for all messages for which the system gives - // us a valid NM_LISTVIEW::lParam - switch ( nmLV->hdr.code ) + + // FreeAllInternalData will cause LVN_ITEMCHANG* messages, which can be + // ignored for efficiency. It is done here because the internal data is in the + // process of being deleted so we don't want to try and access it below. + if ( m_ignoreChangeMessages && + ( (nmLV->hdr.code == LVN_ITEMCHANGED) || (nmLV->hdr.code == LVN_ITEMCHANGING))) { - case LVN_BEGINDRAG: - case LVN_BEGINRDRAG: - case LVN_COLUMNCLICK: - case LVN_ITEMCHANGED: - case LVN_ITEMCHANGING: - if ( iItem != -1 ) - { - wxListItemInternalData *internaldata = - (wxListItemInternalData *) nmLV->lParam; + return TRUE; + } - if ( internaldata ) - event.m_item.m_data = internaldata->lParam; - } - default: - // fall through - ; + // If we have a valid item then check if there is a data value + // associated with it and put it in the event. + if ( iItem >= 0 && iItem < GetItemCount() ) + { + wxListItemInternalData *internaldata = + wxGetInternalData(GetHwnd(), iItem); + + if ( internaldata ) + event.m_item.m_data = internaldata->lParam; } + switch ( nmhdr->code ) { case LVN_BEGINRDRAG: @@ -1866,11 +1875,17 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) break; case LVN_DELETEALLITEMS: + m_count = 0; eventType = wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS; event.m_itemIndex = -1; break; case LVN_DELETEITEM: + if (m_count == 0) + // this should be prevented by the post-processing code below, + // but "just in case" + return FALSE; + eventType = wxEVT_COMMAND_LIST_DELETE_ITEM; event.m_itemIndex = iItem; // delete the assoicated internal data @@ -2114,12 +2129,10 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) event.SetEventType(eventType); - if ( !GetEventHandler()->ProcessEvent(event) ) - return FALSE; + bool processed = GetEventHandler()->ProcessEvent(event); // post processing // --------------- - switch ( nmhdr->code ) { case LVN_DELETEALLITEMS: @@ -2127,7 +2140,6 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // notifications - this makes deleting all items from a list ctrl // much faster *result = TRUE; - return TRUE; case LVN_ENDLABELEDITA: @@ -2140,8 +2152,8 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { // EDIT control will be deleted by the list control itself so // prevent us from deleting it as well - m_textCtrl->SetHWND(0); m_textCtrl->UnsubclassWin(); + m_textCtrl->SetHWND(0); delete m_textCtrl; m_textCtrl = NULL; } @@ -2149,9 +2161,10 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) return TRUE; } - *result = !event.IsAllowed(); + if ( processed ) + *result = !event.IsAllowed(); - return TRUE; + return processed; } #if defined(_WIN32_IE) && _WIN32_IE >= 0x300 @@ -2321,7 +2334,7 @@ wxString wxListCtrl::OnGetItemText(long WXUNUSED(item), long WXUNUSED(col)) cons { // this is a pure virtual function, in fact - which is not really pure // because the controls which are not virtual don't need to implement it - wxFAIL_MSG( _T("not supposed to be called") ); + wxFAIL_MSG( _T("wxListCtrl::OnGetItemText not supposed to be called") ); return wxEmptyString; } @@ -2329,7 +2342,7 @@ wxString wxListCtrl::OnGetItemText(long WXUNUSED(item), long WXUNUSED(col)) cons int wxListCtrl::OnGetItemImage(long WXUNUSED(item)) const { // same as above - wxFAIL_MSG( _T("not supposed to be called") ); + wxFAIL_MSG( _T("wxListCtrl::OnGetItemImage not supposed to be called") ); return -1; } @@ -2351,6 +2364,9 @@ void wxListCtrl::SetItemCount(long count) { wxLogLastError(_T("ListView_SetItemCount")); } + m_count = count; + wxASSERT_MSG( m_count == ListView_GetItemCount(GetHwnd()), + wxT("m_count should match ListView_GetItemCount")); } void wxListCtrl::RefreshItem(long item)