Merge branch 'bmpcombo-enter-event'

Fix getting wxEVT_TEXT_ENTER and other events from wxBitmapComboBox.

See #16318, #22850.
This commit is contained in:
Vadim Zeitlin 2022-10-07 02:07:03 +02:00
commit 8a77fae68b
4 changed files with 120 additions and 92 deletions

View file

@ -154,6 +154,12 @@ protected:
m_allowTextEvents = enable;
}
// Recreate the native control entirely while preserving its initial
// contents and attributes: this is useful if the height of the items must
// be changed as the native control doesn't seem to support doing this once
// it had been already determined.
void MSWRecreate();
private:
// there are the overridden wxTextEntry methods which should only be called
// when we do have an edit control so they assert if this is not the case

View file

@ -169,6 +169,7 @@ protected:
// the checkboxes for styles
wxCheckBox *m_chkSort,
*m_chkProcessEnter,
*m_chkReadonly;
// the combobox itself and the sizer it is in
@ -250,6 +251,7 @@ BitmapComboBoxWidgetsPage::BitmapComboBoxWidgetsPage(WidgetsBookCtrl *book,
{
// init everything
m_chkSort =
m_chkProcessEnter =
m_chkReadonly = NULL;
m_combobox = NULL;
@ -314,6 +316,7 @@ void BitmapComboBoxWidgetsPage::CreateContent()
wxSizer *sizerStyle = new wxStaticBoxSizer(box, wxVERTICAL);
m_chkSort = CreateCheckBoxAndAddToSizer(sizerStyle, "&Sort items");
m_chkProcessEnter = CreateCheckBoxAndAddToSizer(sizerStyle, "Process &Enter");
m_chkReadonly = CreateCheckBoxAndAddToSizer(sizerStyle, "&Read only");
wxButton *btn = new wxButton(this, BitmapComboBoxPage_Reset, "&Reset");
@ -385,7 +388,8 @@ void BitmapComboBoxWidgetsPage::CreateContent()
m_combobox->Create(this, BitmapComboBoxPage_Combo, wxEmptyString,
wxDefaultPosition, wxDefaultSize,
0, NULL,
wxCB_READONLY);
// Flags correspond to the checkboxes state in Reset().
wxTE_PROCESS_ENTER);
#if defined(wxGENERIC_BITMAPCOMBOBOX)
// This will sure make the list look nicer when larger images are used.
@ -414,7 +418,8 @@ void BitmapComboBoxWidgetsPage::CreateContent()
void BitmapComboBoxWidgetsPage::Reset()
{
m_chkSort->SetValue(false);
m_chkReadonly->SetValue(true);
m_chkProcessEnter->SetValue(true);
m_chkReadonly->SetValue(false);
}
void BitmapComboBoxWidgetsPage::CreateCombo()
@ -423,6 +428,8 @@ void BitmapComboBoxWidgetsPage::CreateCombo()
if ( m_chkSort->GetValue() )
flags |= wxCB_SORT;
if ( m_chkProcessEnter->GetValue() )
flags |= wxTE_PROCESS_ENTER;
if ( m_chkReadonly->GetValue() )
flags |= wxCB_READONLY;
@ -752,7 +759,9 @@ void BitmapComboBoxWidgetsPage::OnButtonAddWidgetIcons(wxCommandEvent& WXUNUSED(
void BitmapComboBoxWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
{
if (m_combobox)
event.Enable( m_chkSort->GetValue() || m_chkReadonly->GetValue() );
event.Enable( m_chkSort->GetValue()
|| !m_chkProcessEnter->GetValue()
|| m_chkReadonly->GetValue() );
}
void BitmapComboBoxWidgetsPage::OnUpdateUIInsert(wxUpdateUIEvent& event)

View file

@ -123,97 +123,9 @@ void wxBitmapComboBox::RecreateControl()
// Can't use CBS_OWNERDRAWVARIABLE because it has odd
// mouse-wheel behaviour.
//
wxString value = GetValue();
int selection = GetSelection();
wxPoint pos = GetPosition();
wxSize size = GetSize();
size.y = GetBestSize().y;
const wxArrayString strings = GetStrings();
const unsigned numItems = strings.size();
unsigned i;
// Save the client data pointers before clearing the control, if any.
const wxClientDataType clientDataType = GetClientDataType();
wxVector<wxClientData*> objectClientData;
wxVector<void*> voidClientData;
switch ( clientDataType )
{
case wxClientData_None:
break;
case wxClientData_Object:
objectClientData.reserve(numItems);
for ( i = 0; i < numItems; ++i )
objectClientData.push_back(GetClientObject(i));
break;
case wxClientData_Void:
voidClientData.reserve(numItems);
for ( i = 0; i < numItems; ++i )
voidClientData.push_back(GetClientData(i));
break;
}
wxComboBox::DoClear();
HWND hwnd = GetHwnd();
DissociateHandle();
::DestroyWindow(hwnd);
if ( !MSWCreateControl(wxT("COMBOBOX"), wxEmptyString, pos, size) )
return;
// initialize the controls contents
for ( i = 0; i < numItems; i++ )
{
wxComboBox::Append(strings[i]);
if ( !objectClientData.empty() )
SetClientObject(i, objectClientData[i]);
else if ( !voidClientData.empty() )
SetClientData(i, voidClientData[i]);
}
// and make sure it has the same attributes as before
if ( m_hasFont )
{
// calling SetFont(m_font) would do nothing as the code would
// notice that the font didn't change, so force it to believe
// that it did
wxFont font = m_font;
m_font = wxNullFont;
SetFont(font);
}
if ( m_hasFgCol )
{
wxColour colFg = m_foregroundColour;
m_foregroundColour = wxNullColour;
SetForegroundColour(colFg);
}
if ( m_hasBgCol )
{
wxColour colBg = m_backgroundColour;
m_backgroundColour = wxNullColour;
SetBackgroundColour(colBg);
}
else
{
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
}
MSWRecreate();
::SendMessage(GetHwnd(), CB_SETITEMHEIGHT, 0, MeasureItem(0));
// Revert the old string value
if ( !HasFlag(wxCB_READONLY) )
ChangeValue(value);
else if ( selection != wxNOT_FOUND )
SetSelection(selection);
// If disabled we'll have to disable it again after re-creating
if ( !IsEnabled() )
DoEnable(false);
}
wxBitmapComboBox::~wxBitmapComboBox()

View file

@ -440,6 +440,107 @@ wxWindow *wxComboBox::GetEditableWindow()
// wxComboBox creation
// ----------------------------------------------------------------------------
void wxComboBox::MSWRecreate()
{
wxString value = GetValue();
int selection = GetSelection();
wxPoint pos = GetPosition();
wxSize size = GetSize();
size.y = GetBestSize().y;
const wxArrayString strings = GetStrings();
const unsigned numItems = strings.size();
unsigned i;
// Save the client data pointers before clearing the control, if any.
const wxClientDataType clientDataType = GetClientDataType();
wxVector<wxClientData*> objectClientData;
wxVector<void*> voidClientData;
switch ( clientDataType )
{
case wxClientData_None:
break;
case wxClientData_Object:
objectClientData.reserve(numItems);
for ( i = 0; i < numItems; ++i )
objectClientData.push_back(GetClientObject(i));
break;
case wxClientData_Void:
voidClientData.reserve(numItems);
for ( i = 0; i < numItems; ++i )
voidClientData.push_back(GetClientData(i));
break;
}
wxComboBox::DoClear();
HWND hwnd = GetHwnd();
DissociateHandle();
::DestroyWindow(hwnd);
if ( !MSWCreateControl(wxT("COMBOBOX"), wxEmptyString, pos, size) )
return;
if ( !HasFlag(wxCB_READONLY) )
{
// A new EDIT control was created as well, we need to subclass it just
// as when creating the combobox, see Create(). However we don't need
// to assign to gs_wndprocEdit as it must have been already set.
wxSetWindowProc((HWND)GetEditHWND(), wxComboEditWndProc);
}
// initialize the controls contents
for ( i = 0; i < numItems; i++ )
{
wxComboBox::Append(strings[i]);
if ( !objectClientData.empty() )
SetClientObject(i, objectClientData[i]);
else if ( !voidClientData.empty() )
SetClientData(i, voidClientData[i]);
}
// and make sure it has the same attributes as before
if ( m_hasFont )
{
// calling SetFont(m_font) would do nothing as the code would
// notice that the font didn't change, so force it to believe
// that it did
wxFont font = m_font;
m_font = wxNullFont;
SetFont(font);
}
if ( m_hasFgCol )
{
wxColour colFg = m_foregroundColour;
m_foregroundColour = wxNullColour;
SetForegroundColour(colFg);
}
if ( m_hasBgCol )
{
wxColour colBg = m_backgroundColour;
m_backgroundColour = wxNullColour;
SetBackgroundColour(colBg);
}
else
{
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
}
// Revert the old string value
if ( !HasFlag(wxCB_READONLY) )
ChangeValue(value);
else if ( selection != wxNOT_FOUND )
SetSelection(selection);
// If disabled we'll have to disable it again after re-creating
if ( !IsEnabled() )
DoEnable(false);
}
bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
const wxString& value,
const wxPoint& pos,