From 974a12f86a2882b0999a441ce4ad07e0e2c4377c Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Wed, 25 Oct 2006 19:48:46 +0000 Subject: [PATCH] [ 1584680 ] wxComboCtrl Popup Animation git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42407 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/comboctrl.tex | 60 ++++++++++++ include/wx/combo.h | 36 +++++++- include/wx/msw/combo.h | 1 + samples/combo/combo.cpp | 85 ++++++++++++++++- src/common/combocmn.cpp | 179 +++++++++++++++++++++++------------- src/msw/combo.cpp | 91 +++++++++++++++++- 6 files changed, 383 insertions(+), 69 deletions(-) diff --git a/docs/latex/wx/comboctrl.tex b/docs/latex/wx/comboctrl.tex index 210f3c3e5a..aa8d440a6d 100644 --- a/docs/latex/wx/comboctrl.tex +++ b/docs/latex/wx/comboctrl.tex @@ -213,6 +213,25 @@ appropriately.} Destructor, destroying the combo control. +\membersection{wxComboCtrl::AnimateShow}\label{wxcomboctrlanimateshow} + +\func{virtual bool}{AnimateShow}{\param{const wxRect\& }{rect}, \param{int }{flags}} + +This member function is not normally called in application code. +Instead, it can be implemented in a derived class to create a +custom popup animation. + +\wxheading{Parameters} + +Same as in \helpref{DoShowPopup}{wxcomboctrldoshowpopup}. + +\wxheading{Return value} + +\true if animation finishes before the function returns. +\false otherwise. In the latter case you need to manually call DoShowPopup +after the animation ends. + + \membersection{wxComboCtrl::Create}\label{wxcomboctrlcreate} \func{bool}{Create}{\param{wxWindow*}{ parent}, \param{wxWindowID}{ id},\rtfsp @@ -251,6 +270,31 @@ something else than show the popup, then DoSetPopupControl must always return NULL. +\membersection{wxComboCtrl::DoShowPopup}\label{wxcomboctrldoshowpopup} + +\func{virtual void}{DoShowPopup}{\param{const wxRect\& }{rect}, \param{int }{flags}} + +This member function is not normally called in application code. +Instead, it must be called in a derived class to make sure popup +is properly shown after a popup animation has finished (but only +if \helpref{AnimateShow}{wxcomboctrlanimateshow} did not finish +the animation within it's function scope). + +\wxheading{Parameters} + +\docparam{rect}{Position to show the popup window at, in screen coordinates.} + +\docparam{flags}{Combination of any of the following:} +\twocolwidtha{8cm}% +\begin{twocollist}\itemsep=0pt +\twocolitem{{\tt wxComboCtrl::ShowAbove}}{Popup is shown above the control instead +of below.} +\twocolitem{{\tt wxComboCtrl::CanDeferShow}}{Showing the popup can be deferred +to happen sometime after \helpref{ShowPopup}{wxcomboctrlshowpopup} has finished. +In this case, \helpref{AnimateShow}{wxcomboctrlanimateshow} must return \false.} +\end{twocollist} + + \membersection{wxComboCtrl::GetBitmapDisabled}\label{wxcomboctrlgetbitmapdisabled} \constfunc{const wxBitmap\&}{GetBitmapDisabled}{\void} @@ -361,6 +405,22 @@ Returns the insertion point for the combo control's text field. doesn't have the focus. +\membersection{wxComboCtrl::IsPopupWindowState}\label{wxcomboctrlispopupwindowstate} + +\constfunc{bool}{IsPopupWindowState}{\param{int }{state}} + +Returns \true if the popup window is in the given state. +Possible values are: +\twocolwidtha{8cm}% +\begin{twocollist}\itemsep=0pt +\twocolitem{{\tt wxComboCtrl::Hidden}}{Popup window is hidden.} +\twocolitem{{\tt wxComboCtrl::Animating}}{Popup window is being shown, but the +popup animation has not yet finished.} +\twocolitem{{\tt wxComboCtrl::Visible}}{Popup window is fully visible.} +\end{twocollist} + + + \membersection{wxComboCtrl::GetLastPosition}\label{wxcomboctrlgetlastposition} \constfunc{long}{GetLastPosition}{\void} diff --git a/include/wx/combo.h b/include/wx/combo.h index e3723d0794..8aa155ed71 100644 --- a/include/wx/combo.h +++ b/include/wx/combo.h @@ -152,7 +152,7 @@ public: virtual void OnButtonClick(); // return true if the popup is currently shown - bool IsPopupShown() const { return m_isPopupShown; } + bool IsPopupShown() const { return m_popupWinState == Visible; } // set interface class instance derived from wxComboPopup // NULL popup can be used to indicate default in a derived class @@ -350,7 +350,7 @@ public: bool ShouldDrawFocus() const { const wxWindow* curFocus = FindFocus(); - return ( !m_isPopupShown && + return ( !IsPopupShown() && (curFocus == this || (m_btn && curFocus == m_btn)) && (m_windowStyle & wxCB_READONLY) ); } @@ -370,6 +370,19 @@ public: // common code to be called on popup hide/dismiss void OnPopupDismiss(); + // PopupShown states + enum + { + Hidden = 0, + //Closing = 1, + Animating = 2, + Visible = 3 + }; + + bool IsPopupWindowState( int state ) const { return (state == m_popupWinState) ? true : false; } + + wxByte GetPopupWindowState() const { return m_popupWinState; } + protected: // @@ -447,6 +460,23 @@ protected: // Dispatches size event and refreshes void RecalcAndRefresh(); + // Flags for DoShowPopup and AnimateShow + enum + { + ShowBelow = 0x0000, // Showing popup below the control + ShowAbove = 0x0001, // Showing popup above the control + CanDeferShow = 0x0002 // Can only return true from AnimateShow if this is set + }; + + // Shows and positions the popup. + virtual void DoShowPopup( const wxRect& rect, int flags ); + + // Implement in derived class to create a drop-down animation. + // Return true if finished immediately. Otherwise popup is only + // shown when the derived class call DoShowPopup. + // Flags are same as for DoShowPopup. + virtual bool AnimateShow( const wxRect& rect, int flags ); + #if wxUSE_TOOLTIPS virtual void DoSetToolTip( wxToolTip *tip ); #endif @@ -540,7 +570,7 @@ protected: bool m_blankButtonBg; // is the popup window currenty shown? - bool m_isPopupShown; + wxByte m_popupWinState; private: void Init(); diff --git a/include/wx/msw/combo.h b/include/wx/msw/combo.h index 1147db76e9..096d0798e2 100644 --- a/include/wx/msw/combo.h +++ b/include/wx/msw/combo.h @@ -60,6 +60,7 @@ public: virtual ~wxComboCtrl(); virtual void PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const; + virtual bool AnimateShow( const wxRect& rect, int flags ); virtual bool IsKeyPopupToggle(const wxKeyEvent& event) const; static int GetFeatures() { return wxComboCtrlFeatures::All; } diff --git a/samples/combo/combo.cpp b/samples/combo/combo.cpp index 4deda51fec..785a104038 100644 --- a/samples/combo/combo.cpp +++ b/samples/combo/combo.cpp @@ -85,6 +85,9 @@ public: void OnIdle( wxIdleEvent& event ); + + wxCheckBox* m_cbUseAnim; + protected: wxTextCtrl* m_logWin; wxLog* m_logOld; @@ -490,6 +493,66 @@ BEGIN_EVENT_TABLE(TreeCtrlComboPopup, wxTreeCtrl) EVT_LEFT_DOWN(TreeCtrlComboPopup::OnMouseClick) END_EVENT_TABLE() +// ---------------------------------------------------------------------------- +// wxComboCtrl with custom popup animation +// ---------------------------------------------------------------------------- + +class wxComboCtrlWithCustomPopupAnim : public wxComboCtrl +{ +public: + + virtual bool AnimateShow( const wxRect& rect, int WXUNUSED(flags) ) + { + MyFrame* myFrame = (MyFrame*) ::wxGetTopLevelParent(this); + + if ( !myFrame->m_cbUseAnim->GetValue() ) + return true; + + int width = rect.width; + int height = rect.height; + wxBitmap bitmap( width, height, -1 ); + wxScreenDC dc; + wxMemoryDC memdc( bitmap ); + memdc.Blit( 0, 0, width, height, &dc, rect.x, rect.y ); + memdc.SelectObject(wxNullBitmap); + + wxLongLong tStart = ::wxGetLocalTimeMillis(); + const int delay = 300; + const int resolution = 10; + + int center_x = rect.x + (width/2); + int center_y = rect.y + (height/2); + + double d_height = (double) height; + + dc.SetPen( *wxBLACK_PEN ); + dc.SetBrush( *wxTRANSPARENT_BRUSH ); + for (;;) + { + wxLongLong t = ::wxGetLocalTimeMillis(); + int pos = (int) (t-tStart).GetLo(); + if ( pos > delay ) + break; + + int w = (((pos*256)/delay)*width)/256; + + double ratio = ((double)w / (double)width); + int h = (int)(d_height * ratio); + dc.DrawRectangle( center_x - w/2, center_y - h/2, w, h ); + wxMilliSleep( resolution ); + wxYield(); + dc.DrawBitmap( bitmap, rect.x, rect.y ); + + if ( IsPopupWindowState(Hidden) ) + return true; + } + + return true; + } + +protected: +}; + // ---------------------------------------------------------------------------- // wxComboCtrl with entirely custom button action (opens file dialog) // ---------------------------------------------------------------------------- @@ -730,8 +793,8 @@ MyFrame::MyFrame(const wxString& title) colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 ); rowSizer = new wxBoxSizer( wxHORIZONTAL ); - cc = new wxComboCtrl(panel,2,wxEmptyString, - wxDefaultPosition, wxDefaultSize); + cc = new wxComboCtrlWithCustomPopupAnim(); + cc->Create(panel, wxID_ANY, wxEmptyString); // Make sure we use popup that allows focusing the listview. cc->UseAltPopupWindow(); @@ -879,7 +942,23 @@ MyFrame::MyFrame(const wxString& title) topRowSizer->Add( colSizer, 1, wxALL, 2 ); - topRowSizer->Add( m_logWin, 1, wxEXPAND|wxALL, 5 ); + colSizer = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer = new wxStaticBoxSizer( new wxStaticBox(panel, + wxID_ANY, + wxT("Options")), + wxVERTICAL ); + + m_cbUseAnim = new wxCheckBox(panel, wxID_ANY, wxT("Custom popup animation for ListView wxComboCtrl")); + m_cbUseAnim->SetValue(true); + sbSizer->Add( m_cbUseAnim, 0, wxALL, 3 ); + + colSizer->Add( sbSizer, 0, wxEXPAND|wxALL, 3 ); + colSizer->AddSpacer(8); + colSizer->Add( new wxStaticText(panel, wxID_ANY, wxT("Log Messages:")), 0, wxTOP|wxLEFT, 3 ); + colSizer->Add( m_logWin, 1, wxEXPAND|wxALL, 3 ); + + topRowSizer->Add( colSizer, 1, wxEXPAND|wxALL, 2 ); topSizer->Add( topRowSizer, 1, wxEXPAND ); panel->SetSizer( topSizer ); diff --git a/src/common/combocmn.cpp b/src/common/combocmn.cpp index 0b53234ca9..6139dfc179 100644 --- a/src/common/combocmn.cpp +++ b/src/common/combocmn.cpp @@ -44,10 +44,6 @@ // constants // ---------------------------------------------------------------------------- -// Milliseconds to wait for two mouse-ups after focus inorder -// to trigger a double-click. -#define DOUBLE_CLICK_CONVERSION_TRESHOLD 500 - #define DEFAULT_DROPBUTTON_WIDTH 19 #define BMP_BUTTON_MARGIN 4 @@ -344,20 +340,50 @@ public: style) #endif { + m_inShow = 0; } #if USES_WXPOPUPTRANSIENTWINDOW + virtual bool Show( bool show ); virtual bool ProcessLeftDown(wxMouseEvent& event); virtual void OnDismiss(); #endif +private: + wxByte m_inShow; }; #if USES_WXPOPUPTRANSIENTWINDOW -bool wxComboPopupWindow::ProcessLeftDown(wxMouseEvent& event ) +bool wxComboPopupWindow::Show( bool show ) { - return wxComboPopupWindowBase::ProcessLeftDown(event); + // Guard against recursion + if ( m_inShow ) + return wxComboPopupWindowBase::Show(show); + + m_inShow++; + + wxASSERT( IsKindOf(CLASSINFO(wxPopupTransientWindow)) ); + + wxPopupTransientWindow* ptw = (wxPopupTransientWindow*) this; + wxComboCtrlBase* combo = (wxComboCtrlBase*) GetParent(); + + if ( show != ptw->IsShown() ) + { + if ( show ) + ptw->Popup(combo->GetPopupControl()->GetControl()); + else + ptw->Dismiss(); + } + + m_inShow--; + + return true; +} + +bool wxComboPopupWindow::ProcessLeftDown(wxMouseEvent& event) +{ + return wxPopupTransientWindow::ProcessLeftDown(event); } // First thing that happens when a transient popup closes is that this method gets called. @@ -387,6 +413,7 @@ public: m_combo = parent; } + void OnSizeEvent( wxSizeEvent& event ); void OnKeyEvent(wxKeyEvent& event); #if USES_WXDIALOG void OnActivate( wxActivateEvent& event ); @@ -405,9 +432,15 @@ BEGIN_EVENT_TABLE(wxComboPopupWindowEvtHandler, wxEvtHandler) #if USES_WXDIALOG EVT_ACTIVATE(wxComboPopupWindowEvtHandler::OnActivate) #endif + EVT_SIZE(wxComboPopupWindowEvtHandler::OnSizeEvent) END_EVENT_TABLE() +void wxComboPopupWindowEvtHandler::OnSizeEvent( wxSizeEvent& WXUNUSED(event) ) +{ + // Block the event so that the popup control does not get auto-resized. +} + void wxComboPopupWindowEvtHandler::OnKeyEvent( wxKeyEvent& event ) { // Relay keyboard event to the main child controls @@ -621,7 +654,7 @@ void wxComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event ) evtType == wxEVT_RIGHT_DOWN ) { // Block motion and click events outside the popup - if ( !isInside ) + if ( !isInside || !m_combo->IsPopupShown() ) { event.Skip(false); return; @@ -629,11 +662,10 @@ void wxComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event ) } else if ( evtType == wxEVT_LEFT_UP ) { - // Don't let left-down events in if outside - if ( evtType == wxEVT_LEFT_DOWN ) + if ( !m_combo->IsPopupShown() ) { - if ( !isInside ) - return; + event.Skip(false); + return; } if ( !m_beenInside ) @@ -688,7 +720,7 @@ void wxComboCtrlBase::Init() { m_winPopup = (wxWindow *)NULL; m_popup = (wxWindow *)NULL; - m_isPopupShown = false; + m_popupWinState = Hidden; m_btn = (wxWindow*) NULL; m_text = (wxTextCtrl*) NULL; m_popupInterface = (wxComboPopup*) NULL; @@ -1212,7 +1244,7 @@ void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, bool paintBg ) int drawState = m_btnState; #ifdef __WXGTK__ - if ( m_isPopupShown ) + if ( GetPopupWindowState() >= Animating ) drawState |= wxCONTROL_PRESSED; #endif @@ -1365,7 +1397,7 @@ bool wxComboCtrlBase::HandleButtonMouseEvent( wxMouseEvent& event, Refresh(); } } - else if ( type == wxEVT_LEFT_DOWN ) + else if ( type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_DCLICK ) { if ( flags & (wxCC_MF_ON_CLICK_AREA|wxCC_MF_ON_BUTTON) ) { @@ -1406,7 +1438,7 @@ bool wxComboCtrlBase::HandleButtonMouseEvent( wxMouseEvent& event, m_btnState &= ~(wxCONTROL_CURRENT); // Mouse hover ends - if ( !m_isPopupShown ) + if ( IsPopupWindowState(Hidden) ) { m_btnState &= ~(wxCONTROL_PRESSED); Refresh(); @@ -1429,7 +1461,7 @@ bool wxComboCtrlBase::PreprocessMouseEvent( wxMouseEvent& event, #if USES_WXPOPUPWINDOW || USES_WXDIALOG if ( m_popupWinType != POPUPWIN_WXPOPUPTRANSIENTWINDOW ) { - if ( m_isPopupShown && + if ( IsPopupWindowState(Visible) && ( evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_RIGHT_DOWN ) ) { HidePopup(); @@ -1455,7 +1487,7 @@ void wxComboCtrlBase::HandleNormalMouseEvent( wxMouseEvent& event ) if ( (evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_LEFT_DCLICK) && (m_windowStyle & wxCB_READONLY) ) { - if ( m_isPopupShown ) + if ( GetPopupWindowState() >= Animating ) { #if USES_WXPOPUPWINDOW // Click here always hides the popup. @@ -1481,7 +1513,7 @@ void wxComboCtrlBase::HandleNormalMouseEvent( wxMouseEvent& event ) } } else - if ( m_isPopupShown ) + if ( IsPopupShown() ) { // relay (some) mouse events to the popup if ( evtType == wxEVT_MOUSEWHEEL ) @@ -1677,7 +1709,10 @@ void wxComboCtrlBase::OnButtonClick() void wxComboCtrlBase::ShowPopup() { EnsurePopupControl(); - wxCHECK_RET( !IsPopupShown(), wxT("popup window already shown") ); + wxCHECK_RET( !IsPopupWindowState(Visible), wxT("popup window already shown") ); + + if ( IsPopupWindowState(Animating) ) + return; SetFocus(); @@ -1793,22 +1828,27 @@ void wxComboCtrlBase::ShowPopup() else popupX = 0; + int showFlags = CanDeferShow; + if ( spaceBelow < szp.y ) { popupY = scrPos.y - szp.y; + showFlags |= ShowAbove; } - // Move to position - //wxLogDebug(wxT("popup scheduled position1: %i,%i"),ptp.x,ptp.y); - //wxLogDebug(wxT("popup position1: %i,%i"),winPopup->GetPosition().x,winPopup->GetPosition().y); - - // Some platforms (GTK) may need these two to be separate - winPopup->SetSize( szp.x, szp.y ); - winPopup->Move( popupX, popupY ); - - //wxLogDebug(wxT("popup position2: %i,%i"),winPopup->GetPosition().x,winPopup->GetPosition().y); +#if INSTALL_TOPLEV_HANDLER + // Put top level window event handler into place + if ( m_popupWinType == POPUPWIN_WXPOPUPWINDOW ) + { + if ( !m_toplevEvtHandler ) + m_toplevEvtHandler = new wxComboFrameEventHandler(this); - m_popup = popup; + wxWindow* toplev = ::wxGetTopLevelParent( this ); + wxASSERT( toplev ); + ((wxComboFrameEventHandler*)m_toplevEvtHandler)->OnPopup(); + toplev->PushEventHandler( m_toplevEvtHandler ); + } +#endif // Set string selection (must be this way instead of SetStringSelection) if ( m_text ) @@ -1825,51 +1865,68 @@ void wxComboCtrlBase::ShowPopup() } // This must be after SetStringValue - m_isPopupShown = true; + m_popupWinState = Animating; - // Show it -#if USES_WXPOPUPTRANSIENTWINDOW - if ( m_popupWinType == POPUPWIN_WXPOPUPTRANSIENTWINDOW ) - ((wxPopupTransientWindow*)winPopup)->Popup(popup); - else -#endif - winPopup->Show(); + wxRect popupWinRect( popupX, popupY, szp.x, szp.y ); -#if INSTALL_TOPLEV_HANDLER - // Put top level window event handler into place - if ( m_popupWinType == POPUPWIN_WXPOPUPWINDOW ) + m_popup = popup; + if ( AnimateShow( popupWinRect, showFlags ) ) { - if ( !m_toplevEvtHandler ) - m_toplevEvtHandler = new wxComboFrameEventHandler(this); + DoShowPopup( popupWinRect, showFlags ); + } +} - wxWindow* toplev = ::wxGetTopLevelParent( this ); - wxASSERT( toplev ); - ((wxComboFrameEventHandler*)m_toplevEvtHandler)->OnPopup(); - toplev->PushEventHandler( m_toplevEvtHandler ); +bool wxComboCtrlBase::AnimateShow( const wxRect& WXUNUSED(rect), int WXUNUSED(flags) ) +{ + return true; +} + +void wxComboCtrlBase::DoShowPopup( const wxRect& rect, int WXUNUSED(flags) ) +{ + wxWindow* winPopup = m_winPopup; + + if ( IsPopupWindowState(Animating) ) + { + // Make sure the popup window is shown in the right position. + // Should not matter even if animation already did this. + + // Some platforms (GTK) may like SetSize and Move to be separate + // (though the bug was probably fixed). + winPopup->SetSize( rect ); + + winPopup->Show(); + + m_popupWinState = Visible; } -#endif + else if ( IsPopupWindowState(Hidden) ) + { + // Animation was aborted + wxASSERT( !winPopup->IsShown() ); + + m_popupWinState = Hidden; + } } void wxComboCtrlBase::OnPopupDismiss() -{ +{ // Just in case, avoid double dismiss - if ( !m_isPopupShown ) + if ( IsPopupWindowState(Hidden) ) return; // NB: Focus setting is really funny, atleast on wxMSW. First of all, // we need to have SetFocus at the end. Otherwise wxTextCtrl may // freeze until focus goes somewhere else. Second, wxTreeCtrl as // popup, when dismissing, "steals" focus back to itself unless - // SetFocus is called also here, exactly before m_isPopupShown + // SetFocus is called also here, exactly before m_popupWinState // is set to false. Which is truly weird since SetFocus is just // wxWindowMSW method and does not call event handler or anything like - // that (ie. does not care about m_isPopupShown). + // that (ie. does not care about m_popupWinState). SetFocus(); // This should preferably be set before focus. - m_isPopupShown = false; + m_popupWinState = Hidden; // Inform popup control itself m_popupInterface->OnDismiss(); @@ -1887,7 +1944,10 @@ void wxComboCtrlBase::OnPopupDismiss() } #endif - m_timeCanAcceptClick = ::wxGetLocalTimeMillis() + 150; + m_timeCanAcceptClick = ::wxGetLocalTimeMillis(); + + if ( m_popupWinType == POPUPWIN_WXPOPUPTRANSIENTWINDOW ) + m_timeCanAcceptClick += 150; // If cursor not on dropdown button, then clear its state // (technically not required by all ports, but do it for all just in case) @@ -1912,19 +1972,14 @@ void wxComboCtrlBase::OnPopupDismiss() void wxComboCtrlBase::HidePopup() { // Should be able to call this without popup interface - //wxCHECK_RET( m_popupInterface, _T("no popup interface") ); - if ( !m_isPopupShown ) + if ( IsPopupWindowState(Hidden) ) return; // transfer value and show it in textctrl, if any - SetValue( m_popupInterface->GetStringValue() ); + if ( !IsPopupWindowState(Animating) ) + SetValue( m_popupInterface->GetStringValue() ); -#if USES_WXPOPUPTRANSIENTWINDOW - if ( m_popupWinType == POPUPWIN_WXPOPUPTRANSIENTWINDOW ) - ((wxPopupTransientWindow*)m_winPopup)->Dismiss(); - else -#endif - m_winPopup->Hide(); + m_winPopup->Hide(); OnPopupDismiss(); } diff --git a/src/msw/combo.cpp b/src/msw/combo.cpp index 762b82eadc..260ef98928 100644 --- a/src/msw/combo.cpp +++ b/src/msw/combo.cpp @@ -37,7 +37,7 @@ #include "wx/combo.h" - +#include "wx/msw/registry.h" #include "wx/msw/uxtheme.h" // Change to #if 1 to include tmschema.h for easier testing of theme @@ -70,6 +70,7 @@ #define TEXTCTRLXADJUST_CLASSIC 1 #define TEXTCTRLYADJUST_CLASSIC 2 +#define COMBOBOX_ANIMATION_DURATION 200 // In milliseconds // ============================================================================ // implementation @@ -529,6 +530,94 @@ void wxComboCtrl::OnMouseEvent( wxMouseEvent& event ) } +#if !defined(__WXWINCE__) +static wxUint32 GetUserPreferencesMask() +{ + static wxUint32 userPreferencesMask = 0; + static bool valueSet = false; + + if ( valueSet ) + return userPreferencesMask; + + wxRegKey key(wxRegKey::HKCU, wxT("Control Panel\\Desktop")); + if( key.Open(wxRegKey::Read) ) + { + wxMemoryBuffer buf; + if ( key.QueryValue(wxT("UserPreferencesMask"), buf) ) + { + if ( buf.GetDataLen() >= 4 ) + { + wxByte* p = (wxByte*) buf.GetData(); + userPreferencesMask = p[3] + (p[2]<<8) + (p[1]<<16) + (p[0]<<24); + } + } + } + + valueSet = true; + + return userPreferencesMask; +} +#endif + +bool wxComboCtrl::AnimateShow( const wxRect& rect, int flags ) +{ +#if !defined(__WXWINCE__) + if ( GetUserPreferencesMask() & (1<<26) ) + { + wxLongLong tStart = ::wxGetLocalTimeMillis(); + + int height = rect.height; + + wxWindow* win = GetPopupWindow(); + wxWindow* popup = GetPopupControl()->GetControl(); + + const int delay = COMBOBOX_ANIMATION_DURATION; + const int resolution = 10; + int h0 = popup->GetSize().y; + + win->SetSize( rect.x, rect.y, rect.width, 0 ); + win->Show(); + + for (;;) + { + wxLongLong t = ::wxGetLocalTimeMillis(); + int pos = (int) (t-tStart).GetLo(); + if ( pos > delay ) + break; + + int h = (((pos*256)/delay)*height)/256; + int y = (h0 - h); + if ( y < 0 ) + y = 0; + + if ( flags & ShowAbove ) + { + win->SetSize( rect.x, rect.y + h0 - h, rect.width, h ); + } + else + { + popup->Move( 0, -y ); + win->SetSize( rect.x, rect.y, rect.width, h ); + } + + wxMilliSleep( resolution ); + wxYield(); + + // Popup was hidden before it was fully shown? + if ( IsPopupWindowState(Hidden) ) + return true; + } + + popup->Move( 0, 0 ); + } +#else + wxUnusedVar(rect); + wxUnusedVar(flags); +#endif + + return true; +} + wxCoord wxComboCtrl::GetNativeTextIndent() const { if ( wxUxThemeEngine::GetIfActive() ) -- 2.45.2