diff --git a/include/wx/msw/listctrl.h b/include/wx/msw/listctrl.h index 42d0472c1d..af3a72c318 100644 --- a/include/wx/msw/listctrl.h +++ b/include/wx/msw/listctrl.h @@ -435,6 +435,11 @@ private: // UpdateStyle()), only should be called if InReportView() void MSWSetExListStyles(); + // initialize the (already created) m_textCtrl with the associated HWND + void InitEditControl(WXHWND hWnd); + + // destroy m_textCtrl if it's currently valid and reset it to NULL + void DeleteEditControl(); DECLARE_DYNAMIC_CLASS(wxListCtrl) DECLARE_EVENT_TABLE() diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index 292bb286ff..cd9e2a23a4 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -475,10 +475,8 @@ void wxListCtrl::FreeAllInternalData() } } -wxListCtrl::~wxListCtrl() +void wxListCtrl::DeleteEditControl() { - FreeAllInternalData(); - if ( m_textCtrl ) { m_textCtrl->UnsubclassWin(); @@ -486,6 +484,13 @@ wxListCtrl::~wxListCtrl() delete m_textCtrl; m_textCtrl = NULL; } +} + +wxListCtrl::~wxListCtrl() +{ + FreeAllInternalData(); + + DeleteEditControl(); if (m_ownsImageListNormal) delete m_imageListNormal; @@ -686,6 +691,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 = wx_const_cast(wxListCtrl *, this); + + if ( !m_textCtrl ) + self->m_textCtrl = new wxTextCtrl; + self->InitEditControl((WXHWND)hwndEdit); + } + } + return m_textCtrl; } @@ -1369,29 +1393,8 @@ void wxListCtrl::ClearAll() DeleteAllColumns(); } -wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass) +void wxListCtrl::InitEditControl(WXHWND hWnd) { - wxASSERT( (textControlClass->IsKindOf(CLASSINFO(wxTextCtrl))) ); - - // ListView_EditLabel requires that the list has focus. - SetFocus(); - - 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 = (wxTextCtrl *)textControlClass->CreateObject(); m_textCtrl->SetHWND(hWnd); m_textCtrl->SubclassWin(hWnd); m_textCtrl->SetParent(this); @@ -1401,6 +1404,38 @@ wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass) // 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) +{ + 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 + delete m_textCtrl; + m_textCtrl = NULL; + + return NULL; + } + + // if GetEditControl() hasn't been called, we need to initialize the edit + // control ourselves + if ( !m_textCtrl->GetHWND() ) + InitEditControl(hWnd); return m_textCtrl; }