wxCheckListBox fixes: crash/memory leak when items are dynamically

inserted/deleted corrected and docs updated


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1829 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
1999-02-28 15:35:51 +00:00
parent 9018abe3ef
commit dd3c394ae4
6 changed files with 546 additions and 521 deletions

View File

@@ -1,13 +1,13 @@
wx.gid WX.GID
wx.hlp WX.HLP
wx.ref wx.ref
wx.cnt wx.cnt
wx.rtf Wx.rtf
wx.con Wx.con
minimald.hpj minimald.hpj
minimald.ref minimald.ref
minimald.con minimald.con
minimald.hlp MINIMALD.HLP
minimald.gid minimald.GID
minimald.cnt minimald.cnt
minimald.rtf minimald.rtf

View File

@@ -25,7 +25,11 @@ See \helpref{wxListBox}{wxlistbox}.
\wxheading{Event handling} \wxheading{Event handling}
See \helpref{wxListBox}{wxlistbox}. \twocolwidtha{7cm}
\begin{twocollist}\itemsep=0pt
\twocolitem{{\bf EVT\_CHECKLISTBOX(id, func)}}{Process a wxEVT\_COMMAND\_CHECKLISTBOX\_TOGGLE event,
when an item in the check list box is checked or unchecked.}
\end{twocollist}
\wxheading{See also} \wxheading{See also}

View File

@@ -40,14 +40,17 @@ public:
long style = 0, long style = 0,
const wxValidator& validator = wxDefaultValidator, const wxValidator& validator = wxDefaultValidator,
const wxString& name = wxListBoxNameStr); const wxString& name = wxListBoxNameStr);
// const wxFont& font = wxNullFont);
// override base class virtuals
virtual void Delete(int n);
virtual void InsertItems(int nItems, const wxString items[], int pos);
// items may be checked // items may be checked
bool IsChecked(size_t uiIndex) const; bool IsChecked(size_t uiIndex) const;
void Check(size_t uiIndex, bool bCheck = TRUE); void Check(size_t uiIndex, bool bCheck = TRUE);
// accessors // accessors
size_t GetItemHeight() const { return m_nItemHeight; } size_t GetItemHeight() const { return m_nItemHeight; }
protected: protected:
// we create our items ourselves and they have non-standard size, // we create our items ourselves and they have non-standard size,

View File

@@ -78,6 +78,9 @@ public:
// allows to get the item and use SetXXX functions to set it's appearance // allows to get the item and use SetXXX functions to set it's appearance
wxOwnerDrawn *GetItem(size_t n) const { return m_aItems[n]; } wxOwnerDrawn *GetItem(size_t n) const { return m_aItems[n]; }
// get the index of the given item
int GetItemIndex(wxOwnerDrawn *item) const { return m_aItems.Index(item); }
#endif // wxUSE_OWNER_DRAWN #endif // wxUSE_OWNER_DRAWN
virtual void Append(const wxString& item); virtual void Append(const wxString& item);

View File

@@ -9,6 +9,14 @@
// Licence: wxWindows license // Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#ifdef __GNUG__ #ifdef __GNUG__
#pragma implementation "checklst.h" #pragma implementation "checklst.h"
#endif #endif
@@ -34,6 +42,14 @@
#include "wx/msw/checklst.h" #include "wx/msw/checklst.h"
#include <windows.h> #include <windows.h>
#include <windowsx.h>
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
// get item (converted to right type)
#define GetItem(n) ((wxCheckListBoxItem *)(GetItem(n)))
// ============================================================================ // ============================================================================
// implementation // implementation
@@ -49,6 +65,7 @@
class wxCheckListBoxItem : public wxOwnerDrawn class wxCheckListBoxItem : public wxOwnerDrawn
{ {
friend class wxCheckListBox;
public: public:
// ctor // ctor
wxCheckListBoxItem(wxCheckListBox *pParent, size_t nIndex); wxCheckListBoxItem(wxCheckListBox *pParent, size_t nIndex);
@@ -58,8 +75,8 @@ public:
// simple accessors // simple accessors
bool IsChecked() const { return m_bChecked; } bool IsChecked() const { return m_bChecked; }
void Check(bool bCheck) { m_bChecked = bCheck; } void Check(bool bCheck);
void Toggle(); void Toggle() { Check(!IsChecked()); }
private: private:
bool m_bChecked; bool m_bChecked;
@@ -190,19 +207,30 @@ bool wxCheckListBoxItem::OnDrawItem(wxDC& dc, const wxRect& rc,
} }
// change the state of the item and redraw it // change the state of the item and redraw it
void wxCheckListBoxItem::Toggle() void wxCheckListBoxItem::Check(bool check)
{ {
m_bChecked = !m_bChecked; m_bChecked = check;
size_t nHeight = m_pParent->GetItemHeight(); // index may be chanegd because new items were added/deleted
size_t y = m_nIndex * nHeight; if ( m_pParent->GetItemIndex(this) != (int)m_nIndex )
RECT rcUpdate = { 0, y, GetDefaultMarginWidth(), y + nHeight}; {
InvalidateRect((HWND)m_pParent->GetHWND(), &rcUpdate, FALSE); // update it
int index = m_pParent->GetItemIndex(this);
wxCommandEvent event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, m_pParent->GetId()); wxASSERT_MSG( index != wxNOT_FOUND, "what does this item do here?" );
event.SetInt(m_nIndex);
event.SetEventObject(m_pParent); m_nIndex = (size_t)index;
m_pParent->ProcessCommand(event); }
size_t nHeight = m_pParent->GetItemHeight();
size_t y = m_nIndex * nHeight;
RECT rcUpdate = { 0, y, GetDefaultMarginWidth(), y + nHeight};
InvalidateRect((HWND)m_pParent->GetHWND(), &rcUpdate, FALSE);
wxCommandEvent event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, m_pParent->GetId());
event.SetInt(m_nIndex);
event.SetEventObject(m_pParent);
m_pParent->ProcessCommand(event);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -229,13 +257,40 @@ wxCheckListBox::wxCheckListBox(wxWindow *parent, wxWindowID id,
const wxPoint& pos, const wxSize& size, const wxPoint& pos, const wxSize& size,
int nStrings, const wxString choices[], int nStrings, const wxString choices[],
long style, const wxValidator& val, long style, const wxValidator& val,
const wxString& name) // , const wxFont& font) const wxString& name)
// don't use ctor with arguments! we must call Create()
// ourselves from here.
: wxListBox() : wxListBox()
// , m_font(font)
{ {
Create(parent, id, pos, size, nStrings, choices, style|wxLB_OWNERDRAW, val, name); Create(parent, id, pos, size, nStrings, choices,
style | wxLB_OWNERDRAW, val, name);
}
void wxCheckListBox::Delete(int N)
{
wxCHECK_RET( N >= 0 && N < m_noItems,
"invalid index in wxListBox::Delete" );
wxListBox::Delete(N);
// free memory
delete m_aItems[N];
m_aItems.Remove(N);
}
void wxCheckListBox::InsertItems(int nItems, const wxString items[], int pos)
{
wxCHECK_RET( pos >= 0 && pos <= m_noItems,
"invalid index in wxCheckListBox::InsertItems" );
wxListBox::InsertItems(nItems, items, pos);
int i;
for ( i = 0; i < nItems; i++ ) {
wxOwnerDrawn *pNewItem = CreateItem((size_t)(pos + i));
pNewItem->SetName(items[i]);
m_aItems.Insert(pNewItem, (size_t)(pos + i));
ListBox_SetItemData((HWND)GetHWND(), i + pos, pNewItem);
}
} }
// create/retrieve item // create/retrieve item
@@ -251,9 +306,6 @@ wxOwnerDrawn *wxCheckListBox::CreateItem(size_t nIndex)
return pItem; return pItem;
} }
// get item (converted to right type)
#define GetItem(n) ((wxCheckListBoxItem *)(GetItem(n)))
// return item size // return item size
// ---------------- // ----------------
bool wxCheckListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item) bool wxCheckListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
@@ -301,7 +353,7 @@ void wxCheckListBox::OnLeftClick(wxMouseEvent& event)
{ {
// clicking on the item selects it, clicking on the checkmark toggles // clicking on the item selects it, clicking on the checkmark toggles
if ( event.GetX() <= wxOwnerDrawn::GetDefaultMarginWidth() ) { if ( event.GetX() <= wxOwnerDrawn::GetDefaultMarginWidth() ) {
// # better use LB_ITEMFROMPOINT perhaps? // FIXME better use LB_ITEMFROMPOINT perhaps?
size_t nItem = ((size_t)event.GetY()) / m_nItemHeight; size_t nItem = ((size_t)event.GetY()) / m_nItemHeight;
if ( nItem < (size_t)m_noItems ) if ( nItem < (size_t)m_noItems )
GetItem(nItem)->Toggle(); GetItem(nItem)->Toggle();

File diff suppressed because it is too large Load Diff