📄 odcombo.cpp
字号:
int index = m_strings.Index(value);
m_stringValue = value;
if ( index >= 0 && index < (int)wxVListBox::GetItemCount() )
{
wxVListBox::SetSelection(index);
m_value = index;
}
}
wxSize wxPGVListBoxComboPopup::GetAdjustedSize( int minWidth, int prefHeight, int maxHeight )
{
int height = 250;
if ( m_strings.GetCount() )
{
if ( prefHeight > 0 )
height = prefHeight;
if ( height > maxHeight )
height = maxHeight;
int totalHeight = GetTotalHeight(); // + 3;
if ( height >= totalHeight )
{
height = totalHeight;
}
else
{
// Adjust height to a multiple of the height of the first item
// NB: Calculations that take variable height into account
// are unnecessary.
int fih = GetLineHeight(0);
int shown = height/fih;
height = shown * fih;
}
}
else
height = 50;
// Take scrollbar into account in width calculations
int widestWidth = m_widestWidth + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
return wxSize(minWidth > widestWidth ? minWidth : widestWidth,
height+2);
}
void wxPGVListBoxComboPopup::Populate( int n, const wxString choices[] )
{
int i;
for ( i=0; i<n; i++ )
{
const wxString& item = choices[i];
m_strings.Add(item);
CheckWidth(i);
}
if ( IsCreated() )
wxVListBox::SetItemCount(n);
// Sort the initial choices
if ( m_combo->GetWindowStyle() & wxCB_SORT )
m_strings.Sort();
// Find initial selection
wxString strValue = m_combo->GetValue();
if ( strValue.Length() )
m_value = m_strings.Index(strValue);
}
// ----------------------------------------------------------------------------
// input handling
// ----------------------------------------------------------------------------
//
// This is pushed to the event handler queue of either combo box
// or its textctrl (latter if not readonly combo).
//
class wxPGComboBoxTextCtrlHandler : public wxEvtHandler
{
public:
wxPGComboBoxTextCtrlHandler( wxPGComboControlBase* combo )
: wxEvtHandler()
{
m_combo = combo;
}
~wxPGComboBoxTextCtrlHandler() { }
void OnKey(wxKeyEvent& event);
void OnFocus(wxFocusEvent& event);
protected:
wxPGComboControlBase* m_combo;
private:
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(wxPGComboBoxTextCtrlHandler, wxEvtHandler)
EVT_KEY_DOWN(wxPGComboBoxTextCtrlHandler::OnKey)
EVT_SET_FOCUS(wxPGComboBoxTextCtrlHandler::OnFocus)
END_EVENT_TABLE()
void wxPGComboBoxTextCtrlHandler::OnKey(wxKeyEvent& event)
{
// Let the wxComboCtrl event handler have a go first. wxPGComboControlBase* combo = m_combo; wxObject* prevObj = event.GetEventObject(); event.SetId(combo->GetId()); event.SetEventObject(combo); combo->GetEventHandler()->ProcessEvent(event);
event.SetId(((wxWindow*)prevObj)->GetId()); event.SetEventObject(prevObj);
}
void wxPGComboBoxTextCtrlHandler::OnFocus(wxFocusEvent& event)
{
// FIXME: This code does run when control is clicked,
// yet on Windows it doesn't select all the text.
if ( !(m_combo->GetInternalFlags() & wxPGCC_NO_TEXT_AUTO_SELECT) )
{
if ( m_combo->GetTextCtrl() )
m_combo->GetTextCtrl()->SelectAll();
else
m_combo->SetSelection(-1,-1);
}
// Send focus indication to parent. // NB: This is needed for cases where the textctrl gets focus // instead of its parent. We'll check if the focus came from
// in order to prevent a possible infinite recursion.
if ( m_combo->ConsumingTextCtrlFocusEvent() )
{ wxFocusEvent evt2(wxEVT_SET_FOCUS,m_combo->GetId()); evt2.SetEventObject(m_combo); m_combo->GetEventHandler()->ProcessEvent(evt2);
}
event.Skip();
}
//
// This is pushed to the event handler queue of the control in popup.
//
class wxPGComboPopupExtraEventHandler : public wxEvtHandler
{
public:
wxPGComboPopupExtraEventHandler( wxPGComboControlBase* combo )
: wxEvtHandler()
{
m_combo = combo;
m_beenInside = false;
}
~wxPGComboPopupExtraEventHandler() { }
void OnMouseEvent( wxMouseEvent& event );
// Called from wxPGComboControlBase::OnPopupDismiss
void OnPopupDismiss()
{
m_beenInside = false;
}
protected:
wxPGComboControlBase* m_combo;
bool m_beenInside;
private:
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(wxPGComboPopupExtraEventHandler, wxEvtHandler)
EVT_MOUSE_EVENTS(wxPGComboPopupExtraEventHandler::OnMouseEvent)
END_EVENT_TABLE()
void wxPGComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event )
{
wxPoint pt = event.GetPosition();
wxSize sz = m_combo->GetPopupControl()->GetClientSize();
int evtType = event.GetEventType();
bool isInside = pt.x >= 0 && pt.y >= 0 && pt.x < sz.x && pt.y < sz.y;
if ( evtType == wxEVT_MOTION ||
evtType == wxEVT_LEFT_DOWN ||
evtType == wxEVT_RIGHT_DOWN )
{
// Block motion and click events outside the popup
if ( !isInside )
{
event.Skip(false);
return;
}
}
else if ( evtType == wxEVT_LEFT_UP )
{
// Don't let left-down events in if outside
if ( evtType == wxEVT_LEFT_DOWN )
{
if ( !isInside )
return;
}
if ( !m_beenInside )
{
if ( isInside )
{
m_beenInside = true;
}
else
{
//
// Some mouse events to popup that happen outside it, before cursor
// has been inside the popu, need to be ignored by it but relayed to
// the dropbutton.
//
wxWindow* btn = m_combo->GetButton();
if ( btn )
btn->GetEventHandler()->AddPendingEvent(event);
else
m_combo->GetEventHandler()->AddPendingEvent(event);
return;
}
event.Skip();
}
}
event.Skip();
}
// ----------------------------------------------------------------------------
// wxPGComboControlBase
// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(wxPGComboControlBase, wxControl)
EVT_TEXT(wxID_ANY,wxPGComboControlBase::OnTextCtrlEvent)
EVT_SIZE(wxPGComboControlBase::OnSizeEvent)
EVT_KEY_DOWN(wxPGComboControlBase::OnKeyEvent)
EVT_SET_FOCUS(wxPGComboControlBase::OnFocusEvent)
EVT_KILL_FOCUS(wxPGComboControlBase::OnFocusEvent)
//EVT_BUTTON(wxID_ANY,wxPGComboControlBase::OnButtonClickEvent)
EVT_TEXT_ENTER(wxID_ANY,wxPGComboControlBase::OnTextCtrlEvent)
EVT_SYS_COLOUR_CHANGED(wxPGComboControlBase::OnSysColourChanged)
END_EVENT_TABLE()
IMPLEMENT_ABSTRACT_CLASS(wxPGComboControlBase, wxControl)
// Have global double buffer - should be enough for multiple combos
static wxBitmap* gs_doubleBuffer = (wxBitmap*) NULL;
void wxPGComboControlBase::Init()
{
m_winPopup = (wxWindow *)NULL;
m_popup = (wxWindow *)NULL;
m_isPopupShown = false;
m_btn = (wxWindow*) NULL;
m_text = (wxTextCtrl*) NULL;
m_popupInterface = (wxPGComboPopup*) NULL;
m_popupExtraHandler = (wxEvtHandler*) NULL;
m_textEvtHandler = (wxEvtHandler*) NULL;
#if INSTALL_TOPLEV_HANDLER
m_toplevEvtHandler = (wxEvtHandler*) NULL;
#endif
m_heightPopup = -1;
m_widthMinPopup = -1;
m_widthCustomPaint = 0;
m_widthCustomBorder = 0;
m_btnState = 0;
m_btnWidDefault = 0;
m_blankButtonBg = false;
m_btnWid = m_btnHei = 0;
m_btnSide = wxRIGHT;
m_btnSpacingX = 0;
m_extLeft = 0;
m_extRight = 0;
m_absIndent = -1;
m_iFlags = 0;
m_fakePopupUsage = 0;
m_skipTextCtrlFocusEvents = 0;
m_timeCanAcceptClick = 0;
}
bool wxPGComboControlBase::Create(wxWindow *parent,
wxWindowID id,
const wxString& value,
const wxPoint& pos,
const wxSize& size,
long style,
const wxValidator& validator,
const wxString& name)
{
if ( !wxControl::Create(parent,
id,
pos,
size,
style | wxWANTS_CHARS,
validator,
name) )
return false;
m_valueString = value;
// Get colours
OnThemeChange();
m_absIndent = GetNativeTextIndent();
return true;
}
void wxPGComboControlBase::InstallInputHandlers()
{
if ( m_text )
{
m_textEvtHandler = new wxPGComboBoxTextCtrlHandler(this);
m_text->PushEventHandler(m_textEvtHandler);
}
}
void wxPGComboControlBase::CreateTextCtrl( int extraStyle, const wxValidator& validator )
{
if ( !(m_windowStyle & wxCB_READONLY) )
{
m_text = new wxTextCtrl(this,
12345,
m_valueString,
wxDefaultPosition,
wxDefaultSize,
// wxTE_PROCESS_TAB is needed because on Windows, wxTAB_TRAVERSAL is
// not used by the wxPropertyGrid and therefore the tab is
// processed by looking at ancestors to see if they have
// wxTAB_TRAVERSAL. The navigation event is then sent to
// the wrong window.
wxTE_PROCESS_TAB |
wxTE_PROCESS_ENTER |
//wxWANTS_CHARS |
extraStyle,
validator);
#if defined(__WXMSW__) && !defined(__WXWINCE__)
::SendMessage(GetHwndOf(m_text), EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3));
#endif
// This is required for some platforms (GTK+ atleast)
m_text->SetSizeHints(2,4);
}
}
void wxPGComboControlBase::OnThemeChange()
{
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
}
bool wxPGComboControlBase::Destroy()
{
return wxControl::Destroy();
}
wxPGComboControlBase::~wxPGComboControlBase()
{
if ( HasCapture() )
ReleaseMouse();
HidePopup();
delete gs_doubleBuffer;
gs_doubleBuffer = (wxBitmap*) NULL;
#if INSTALL_TOPLEV_HANDLER
delete ((wxPGComboFrameEventHandler*)m_toplevEvtHandler);
m_toplevEvtHandler = (wxEvtHandler*) NULL;
#endif
if ( m_popup )
m_popup->RemoveEventHandler(m_popupExtraHandler);
delete m_popupExtraHandler;
delete m_popupInterface;
delete m_winPopup;
if ( m_text )
m_text->RemoveEventHandler(m_textEvtHandler);
delete m_textEvtHandler;
}
// ----------------------------------------------------------------------------
// geometry stuff
// ----------------------------------------------------------------------------
// Recalculates button and textctrl areas
void wxPGComboControlBase::CalculateAreas( int btnWidth )
{
wxSize sz = GetClientSize();
int customBorder = m_widthCustomBorder;
bool buttonOutside;
int btnBorder; // border for button only
if ( ( (m_iFlags & wxPGCC_BUTTON_OUTSIDE_BORDER) || m_blankButtonBg ) &&
m_btnSpacingX == 0 && m_btnWid == 0 && m_btnHei == 0 &&
(!m_bmpNormal.Ok() || m_blankButtonBg) )
{
buttonOutside = true;
m_iFlags |= wxPGCC_IFLAG_BUTTON_OUTSIDE;
btnBorder = 0;
}
else
{
buttonOutside = false;
m_iFlags &= ~(wxPGCC_IFLAG_BUTTON_OUTSIDE);
btnBorder = customBorder;
}
// Defaul indentation
if ( m_absIndent < 0 )
m_absIndent = GetNativeTextIndent();
int butWidth = btnWidth;
if ( butWidth <= 0 )
butWidth = m_btnWidDefault;
else
m_btnWidDefault = butWidth;
if ( butWidth <= 0 )
return;
// Adjust button width
if ( m_btnWid < 0 )
butWidth += m_btnWid;
else if ( m_btnWid > 0 )
butWidth = m_btnWid;
int butHeight = sz.y;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -