📄 odcombo.cpp
字号:
int type = event.GetEventType();
if ( type == wxEVT_MOTION )
{
if ( flags & wxPGCC_MF_ON_BUTTON )
{
if ( !(m_btnState & wxCONTROL_CURRENT) )
{
// Mouse hover begins
m_btnState |= wxCONTROL_CURRENT;
if ( HasCapture() ) // Retain pressed state.
m_btnState |= wxCONTROL_PRESSED;
Refresh();
}
}
else if ( (m_btnState & wxCONTROL_CURRENT) )
{
// Mouse hover ends
m_btnState &= ~(wxCONTROL_CURRENT|wxCONTROL_PRESSED);
Refresh();
}
}
// else if ( type == wxEVT_LEFT_DOWN ) // O.C.: first click on combobox drops down the list immediately !!!!
else if ( type == wxEVT_LEFT_DOWN || (type == wxEVT_ENTER_WINDOW && event.LeftIsDown()) )
{
// Only accept event if it wasn't right after popup dismiss
//if ( ::wxGetLocalTimeMillis() > m_timeCanClick )
{
if( type == wxEVT_ENTER_WINDOW && m_popup ) // O.C.: click again hides the list !!!!
{
HidePopup();
}
else
// Need to test this, because it might be outside.
if ( flags & wxPGCC_MF_ON_BUTTON )
{
m_btnState |= wxCONTROL_PRESSED;
Refresh();
if ( !(m_iFlags & wxPGCC_POPUP_ON_MOUSE_UP) )
OnButtonClick();
else
// If showing popup now, do not capture mouse or there will be interference
CaptureMouse();
}
}
/*else
{
m_btnState = 0;
}*/
}
else if ( type == wxEVT_LEFT_UP )
{
// Only accept event if mouse was left-press was previously accepted
if ( HasCapture() )
ReleaseMouse();
if ( m_btnState & wxCONTROL_PRESSED )
{
// If mouse was inside, fire the click event.
if ( m_iFlags & wxPGCC_POPUP_ON_MOUSE_UP )
{
if ( flags & wxPGCC_MF_ON_BUTTON )
OnButtonClick();
}
m_btnState &= ~(wxCONTROL_PRESSED);
Refresh();
}
}
else if ( type == wxEVT_LEAVE_WINDOW )
{
if ( m_btnState & (wxCONTROL_CURRENT|wxCONTROL_PRESSED) )
{
m_btnState &= ~(wxCONTROL_CURRENT);
// Mouse hover ends
if ( !m_isPopupShown )
{
m_btnState &= ~(wxCONTROL_PRESSED);
Refresh();
}
}
}
else
return false;
return true;
}
// Conversion to double-clicks and some basic filtering
// returns true if event was consumed or filtered
bool wxPGComboControlBase::PreprocessMouseEvent( wxMouseEvent& event,
int WXUNUSED(flags) )
{
wxLongLong t = ::wxGetLocalTimeMillis();
int evtType = event.GetEventType();
if ( m_isPopupShown &&
( evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_RIGHT_DOWN ) )
{
HidePopup();
return true;
}
//
// Generate our own double-clicks
// (to allow on-focus dc-event on double-clicks instead of triple-clicks)
/*if ( (m_windowStyle & wxPGCC_DCLICK_CYCLES) &&
!m_isPopupShown &&
//!(handlerFlags & wxPGCC_MF_ON_BUTTON) )
!(flags & wxPGCC_MF_ON_BUTTON) )
{
if ( evtType == wxEVT_LEFT_DOWN )
{
// Set value to avoid up-events without corresponding downs
m_downReceived = true;
}
else if ( evtType == wxEVT_LEFT_DCLICK )
{
// We'll make our own double-clicks
//evtType = 0;
event.SetEventType(0);
return true;
}
else if ( evtType == wxEVT_LEFT_UP )
{
if ( m_downReceived || m_timeLastMouseUp == 1 )
{
wxLongLong timeFromLastUp = (t-m_timeLastMouseUp);
if ( timeFromLastUp < DOUBLE_CLICK_CONVERSION_TRESHOLD )
{
//type = wxEVT_LEFT_DCLICK;
event.SetEventType(wxEVT_LEFT_DCLICK);
m_timeLastMouseUp = 1;
}
else
{
m_timeLastMouseUp = t;
}
//m_downReceived = false;
}
}
}*/
// Filter out clicks on button immediately after popup dismiss (Windows like behaviour)
if ( evtType == wxEVT_LEFT_DOWN && t < m_timeCanAcceptClick )
{
event.SetEventType(0);
return true;
}
return false;
}
void wxPGComboControlBase::HandleNormalMouseEvent( wxMouseEvent& event )
{
int evtType = event.GetEventType();
if ( (evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_LEFT_DCLICK) &&
(m_windowStyle & wxCB_READONLY) )
{
if ( m_isPopupShown )
{
#if !wxUSE_POPUPWIN
// Normally do nothing - evt handler should close it for us
#if ALLOW_FAKE_POPUP
if ( m_fakePopupUsage == 2 )
HidePopup();
#endif
#elif !USE_TRANSIENT_POPUP
// Click here always hides the popup.
HidePopup();
#endif
}
else
{
if ( !(m_windowStyle & wxPGCC_DCLICK_CYCLES) )
{
// In read-only mode, clicking the text is the
// same as clicking the button.
OnButtonClick();
}
else if ( /*evtType == wxEVT_LEFT_UP || */evtType == wxEVT_LEFT_DCLICK )
{
//if ( m_popupInterface->CycleValue() )
// Refresh();
if ( m_popupInterface )
m_popupInterface->OnComboDoubleClick();
}
}
}
else
if ( m_isPopupShown )
{
// relay (some) mouse events to the popup
if ( evtType == wxEVT_MOUSEWHEEL )
m_popup->AddPendingEvent(event);
}
else if ( evtType )
event.Skip();
}
void wxPGComboControlBase::OnKeyEvent( wxKeyEvent& event )
{
int keycode = event.GetKeyCode();
if ( keycode == WXK_TAB &&
!IsPopupShown() )
{
wxNavigationKeyEvent evt;
evt.SetFlags(wxNavigationKeyEvent::FromTab|
(!event.ShiftDown()?wxNavigationKeyEvent::IsForward:
wxNavigationKeyEvent::IsBackward));
evt.SetEventObject(this);
GetParent()->GetEventHandler()->AddPendingEvent(evt);
return;
}
if ( IsPopupShown() )
{
// pass it to the popped up control
GetPopupControl()->AddPendingEvent(event);
}
else // no popup
{
int comboStyle = GetWindowStyle();
wxPGComboPopup* popupInterface = GetPopup();
if ( !popupInterface )
{
event.Skip();
return;
}
if ( (comboStyle & wxCB_READONLY) ||
( keycode != WXK_RIGHT && keycode != WXK_LEFT )
)
{
// Alternate keys: UP and DOWN show the popup instead of cycling
if ( (comboStyle & wxPGCC_ALT_KEYS) )
{
if ( keycode == WXK_UP || keycode == WXK_DOWN )
{
OnButtonClick();
return;
}
else
event.Skip();
}
else
popupInterface->OnComboKeyEvent(event);
}
else
event.Skip();
}
}
void wxPGComboControlBase::OnFocusEvent( wxFocusEvent& event )
{
if ( event.GetEventType() == wxEVT_SET_FOCUS )
{
if ( m_text && m_text != ::wxWindow::FindFocus() )
{
m_skipTextCtrlFocusEvents++;
m_text->SetFocus();
}
}
Refresh();
}
void wxPGComboControlBase::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
{
OnThemeChange();
// indentation may also have changed
if ( !(m_iFlags & wxPGCC_IFLAG_INDENT_SET) )
m_absIndent = GetNativeTextIndent();
RecalcAndRefresh();
}
// ----------------------------------------------------------------------------
// popup handling
// ----------------------------------------------------------------------------
// Create popup window and the child control
void wxPGComboControlBase::CreatePopup()
{
wxPGComboPopup* popupInterface = m_popupInterface;
wxWindow* popup;
if ( !m_winPopup )
m_winPopup = new wxPGComboPopupWindow( this, wxNO_BORDER );
popupInterface->Create(m_winPopup);
m_popup = popup = popupInterface->GetControl();
m_popupExtraHandler = new wxPGComboPopupExtraEventHandler(this);
popup->PushEventHandler( m_popupExtraHandler );
popupInterface->m_iFlags |= wxPGCP_IFLAG_CREATED;
}
void wxPGComboControlBase::SetPopup( wxPGComboPopup* iface )
{
delete m_popupInterface;
delete m_winPopup;
m_popupInterface = iface;
#if ALLOW_FAKE_POPUP
m_fakePopupUsage = 0;
#endif
if ( !iface->LazyCreate() || m_winPopup )
{
CreatePopup();
/*
m_winPopup = new wxPGComboPopupWindow( this, wxNO_BORDER );
// Create popup right away
iface->Create(m_winPopup);
m_popup = iface->GetControl();
m_popupExtraHandler = new wxPGComboPopupExtraEventHandler(this);
m_popup->PushEventHandler( m_popupExtraHandler );
// Add interface as event handler
//m_popup->PushEventHandler( iface );
*/
// FIXME: This bypasses wxGTK popupwindow bug
// (i.e. window is not initially hidden when it should be)
m_winPopup->Hide();
#if ALLOW_FAKE_POPUP
m_fakePopupUsage = 1;
#endif
}
else
{
m_popup = (wxWindow*) NULL;
}
// This must be after creation
if ( m_valueString )
iface->SetStringValue(m_valueString);
}
void wxPGComboControlBase::OnButtonClick()
{
// Derived classes can override this method for totally custom
// popup action
ShowPopup();
}
void wxPGComboControlBase::ShowPopup()
{
wxCHECK_RET( m_popupInterface, wxT("no popup interface set for wxComboControl") );
wxCHECK_RET( !IsPopupShown(), wxT("popup window already shown") );
SetFocus();
// Space above and below
int screenHeight;
wxPoint scrPos;
int spaceAbove;
int spaceBelow;
int maxHeightPopup;
wxSize ctrlSz = GetSize();
#if ALLOW_FAKE_POPUP
int existingHeight = 200;
if ( m_popup )
existingHeight = m_popup->GetSize().y;
int screenWidth;
GetParent()->GetClientSize(&screenWidth,&screenHeight);
screenWidth -= 2;
scrPos = GetPosition();
spaceAbove = scrPos.y - 2;
spaceBelow = screenHeight - spaceAbove - ctrlSz.y - 4;
maxHeightPopup = spaceBelow;
if ( spaceAbove > spaceBelow )
maxHeightPopup = spaceAbove;
if ( maxHeightPopup >= existingHeight )
{
if ( m_winPopup && m_fakePopupUsage!=2 )
{
delete m_winPopup;
m_winPopup = (wxWindow*) NULL;
m_popup = (wxWindow*) NULL;
}
m_fakePopupUsage = 2;
}
else
{
if ( m_winPopup && m_fakePopupUsage!=1 )
{
delete m_winPopup;
m_winPopup = (wxWindow*) NULL;
m_popup = (wxWindow*) NULL;
}
m_fakePopupUsage = 1;
#else
{
#endif
screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
scrPos = GetParent()->ClientToScreen(GetPosition());
spaceAbove = scrPos.y;
spaceBelow = screenHeight - spaceAbove - ctrlSz.y;
maxHeightPopup = spaceBelow;
if ( spaceAbove > spaceBelow )
maxHeightPopup = spaceAbove;
}
// Width
int widthPopup = ctrlSz.x + m_extLeft + m_extRight;
if ( widthPopup < m_widthMinPopup )
widthPopup = m_widthMinPopup;
wxWindow* winPopup = m_winPopup;
wxWindow* popup;
// Need to disable tab traversal of parent
//
// NB: This is to fix a bug in wxMSW. In theory it could also be fixed
// by, for instance, adding check to window.cpp:wxWindowMSW::MSWProcessMessage
// that if transient popup is open, then tab traversal is to be ignored.
// However, I think this code would still be needed for cases where
// transient popup doesn't work yet (wxWINCE?).
wxWindow* parent = GetParent();
int parentFlags = parent->GetWindowStyle();
if ( parentFlags & wxTAB_TRAVERSAL )
{
parent->SetWindowStyle( parentFlags & ~(wxTAB_TRAVERSAL) );
m_iFlags |= wxPGCC_IFLAG_PARENT_TAB_TRAVERSAL;
}
if ( !winPopup )
{
#if ALLOW_FAKE_POPUP
if ( m_fakePopupUsage == 2 )
{
winPopup = new wxWindow();
#ifdef __WXMSW__
// Only wxMSW supports this
winPopup->Hide();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -