]> git.saurik.com Git - wxWidgets.git/blame - src/msw/combo.cpp
Commit FM's GTK+ native assert dialog code.
[wxWidgets.git] / src / msw / combo.cpp
CommitLineData
a340b80d 1/////////////////////////////////////////////////////////////////////////////
93f7f8be 2// Name: src/msw/combo.cpp
a57d600f 3// Purpose: wxMSW wxComboCtrl
a340b80d
VZ
4// Author: Jaakko Salli
5// Modified by:
6// Created: Apr-30-2006
7// RCS-ID: $Id$
8// Copyright: (c) 2005 Jaakko Salli
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
a57d600f 26#if wxUSE_COMBOCTRL
a340b80d
VZ
27
28#ifndef WX_PRECOMP
29 #include "wx/log.h"
30 #include "wx/combobox.h"
31 #include "wx/dcclient.h"
32 #include "wx/settings.h"
33 #include "wx/dialog.h"
2835f3cf 34 #include "wx/stopwatch.h"
a340b80d
VZ
35#endif
36
37#include "wx/dcbuffer.h"
a340b80d
VZ
38#include "wx/combo.h"
39
974a12f8 40#include "wx/msw/registry.h"
a340b80d
VZ
41#include "wx/msw/uxtheme.h"
42
43// Change to #if 1 to include tmschema.h for easier testing of theme
44// parameters.
45#if 0
46 #include <tmschema.h>
47#else
48 //----------------------------------
49 #define EP_EDITTEXT 1
50 #define ETS_NORMAL 1
51 #define ETS_HOT 2
52 #define ETS_SELECTED 3
53 #define ETS_DISABLED 4
54 #define ETS_FOCUSED 5
55 #define ETS_READONLY 6
56 #define ETS_ASSIST 7
57 #define TMT_FILLCOLOR 3802
58 #define TMT_TEXTCOLOR 3803
59 #define TMT_BORDERCOLOR 3801
60 #define TMT_EDGEFILLCOLOR 3808
61 //----------------------------------
62#endif
63
64
65#define NATIVE_TEXT_INDENT_XP 4
66#define NATIVE_TEXT_INDENT_CLASSIC 2
67
68#define TEXTCTRLXADJUST_XP 1
69#define TEXTCTRLYADJUST_XP 3
70#define TEXTCTRLXADJUST_CLASSIC 1
53a64063 71#define TEXTCTRLYADJUST_CLASSIC 2
a340b80d 72
30be036c
RR
73#define COMBOBOX_ANIMATION_RESOLUTION 10
74
974a12f8 75#define COMBOBOX_ANIMATION_DURATION 200 // In milliseconds
a340b80d 76
53a64063 77#define wxMSW_DESKTOP_USERPREFERENCESMASK_COMBOBOXANIM (1<<2)
30be036c
RR
78
79
a340b80d
VZ
80// ============================================================================
81// implementation
82// ============================================================================
83
84
a57d600f
VZ
85BEGIN_EVENT_TABLE(wxComboCtrl, wxComboCtrlBase)
86 EVT_PAINT(wxComboCtrl::OnPaintEvent)
87 EVT_MOUSE_EVENTS(wxComboCtrl::OnMouseEvent)
53a64063 88#if wxUSE_COMBOCTRL_POPUP_ANIMATION
30be036c 89 EVT_TIMER(wxID_ANY, wxComboCtrl::OnTimerEvent)
53a64063 90#endif
a340b80d
VZ
91END_EVENT_TABLE()
92
93
a57d600f 94IMPLEMENT_DYNAMIC_CLASS(wxComboCtrl, wxComboCtrlBase)
a340b80d 95
a57d600f 96void wxComboCtrl::Init()
a340b80d
VZ
97{
98}
99
a57d600f 100bool wxComboCtrl::Create(wxWindow *parent,
a340b80d
VZ
101 wxWindowID id,
102 const wxString& value,
103 const wxPoint& pos,
104 const wxSize& size,
105 long style,
106 const wxValidator& validator,
107 const wxString& name)
108{
109
110 // Set border
111 long border = style & wxBORDER_MASK;
112
113 wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
114
115 if ( !border )
116 {
117 // For XP, have 1-width custom border, for older version use sunken
118 if ( theme )
119 {
120 border = wxBORDER_NONE;
121 m_widthCustomBorder = 1;
122 }
123 else
124 border = wxBORDER_SUNKEN;
125
126 style = (style & ~(wxBORDER_MASK)) | border;
127 }
128
129 // create main window
a57d600f 130 if ( !wxComboCtrlBase::Create(parent,
93f7f8be
WS
131 id,
132 value,
133 pos,
134 size,
135 style | wxFULL_REPAINT_ON_RESIZE,
136 wxDefaultValidator,
137 name) )
a340b80d
VZ
138 return false;
139
140 if ( style & wxCC_STD_BUTTON )
141 m_iFlags |= wxCC_POPUP_ON_MOUSE_UP;
142
143 // Create textctrl, if necessary
144 CreateTextCtrl( wxNO_BORDER, validator );
145
146 // Add keyboard input handlers for main control and textctrl
b445b6a7 147 InstallInputHandlers();
a340b80d
VZ
148
149 // Prepare background for double-buffering
150 SetBackgroundStyle( wxBG_STYLE_CUSTOM );
151
170acdc9
RD
152 // SetInitialSize should be called last
153 SetInitialSize(size);
a340b80d
VZ
154
155 return true;
156}
157
a57d600f 158wxComboCtrl::~wxComboCtrl()
a340b80d
VZ
159{
160}
161
a57d600f 162void wxComboCtrl::OnThemeChange()
a340b80d
VZ
163{
164 wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
165 if ( theme )
166 {
167 wxUxThemeHandle hTheme(this, L"COMBOBOX");
168
169 COLORREF col;
170 theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_NORMAL,TMT_FILLCOLOR,&col);
171 SetBackgroundColour(wxRGBToColour(col));
172 theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_NORMAL,TMT_TEXTCOLOR,&col);
173 SetForegroundColour(wxRGBToColour(col));
174 }
175 else
176 {
177 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
178 SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
179 }
180}
181
a57d600f 182void wxComboCtrl::OnResize()
a340b80d
VZ
183{
184 //
185 // Recalculates button and textctrl areas
186
187 int textCtrlXAdjust;
188 int textCtrlYAdjust;
189
190 if ( wxUxThemeEngine::GetIfActive() )
191 {
192 textCtrlXAdjust = TEXTCTRLXADJUST_XP;
193 textCtrlYAdjust = TEXTCTRLYADJUST_XP;
194 }
195 else
196 {
197 textCtrlXAdjust = TEXTCTRLXADJUST_CLASSIC;
198 textCtrlYAdjust = TEXTCTRLYADJUST_CLASSIC;
199 }
200
201 // Technically Classic Windows style combo has more narrow button,
202 // but the native renderer doesn't paint it well like that.
203 int btnWidth = 17;
204 CalculateAreas(btnWidth);
205
206 // Position textctrl using standard routine
207 PositionTextCtrl(textCtrlXAdjust,textCtrlYAdjust);
208}
209
210// Draws non-XP GUI dotted line around the focus area
211static void wxMSWDrawFocusRect( wxDC& dc, const wxRect& rect )
212{
213#if !defined(__WXWINCE__)
214 /*
215 RECT mswRect;
216 mswRect.left = rect.x;
217 mswRect.top = rect.y;
218 mswRect.right = rect.x + rect.width;
219 mswRect.bottom = rect.y + rect.height;
220 HDC hdc = (HDC) dc.GetHDC();
221 SetMapMode(hdc,MM_TEXT); // Just in case...
222 DrawFocusRect(hdc,&mswRect);
223 */
224 // FIXME: Use DrawFocusRect code above (currently it draws solid line
225 // for caption focus but works ok for other stuff).
226 // Also, this code below may not work in future wx versions, since
227 // it employs wxCAP_BUTT hack to have line of width 1.
228 dc.SetLogicalFunction(wxINVERT);
229
230 wxPen pen(*wxBLACK,1,wxDOT);
231 pen.SetCap(wxCAP_BUTT);
232 dc.SetPen(pen);
233 dc.SetBrush(*wxTRANSPARENT_BRUSH);
234
235 dc.DrawRectangle(rect);
236
237 dc.SetLogicalFunction(wxCOPY);
238#else
239 dc.SetLogicalFunction(wxINVERT);
240
241 dc.SetPen(wxPen(*wxBLACK,1,wxDOT));
242 dc.SetBrush(*wxTRANSPARENT_BRUSH);
243
244 dc.DrawRectangle(rect);
245
246 dc.SetLogicalFunction(wxCOPY);
247#endif
248}
249
250// draw focus background on area in a way typical on platform
0d203f87
VZ
251void
252wxComboCtrl::PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const
a340b80d 253{
a340b80d
VZ
254 wxUxThemeHandle hTheme(this, L"COMBOBOX");
255 //COLORREF cref;
256
257 wxSize sz = GetClientSize();
258 bool isEnabled;
259 bool isFocused; // also selected
260
261 // For smaller size control (and for disabled background) use less spacing
262 int focusSpacingX;
263 int focusSpacingY;
264
265 if ( !(flags & wxCONTROL_ISSUBMENU) )
266 {
267 // Drawing control
268 isEnabled = IsEnabled();
269 isFocused = ShouldDrawFocus();
270
271 // Windows-style: for smaller size control (and for disabled background) use less spacing
272 if ( hTheme )
273 {
274 // WinXP Theme
275 focusSpacingX = isEnabled ? 2 : 1;
276 focusSpacingY = sz.y > (GetCharHeight()+2) && isEnabled ? 2 : 1;
277 }
278 else
279 {
280 // Classic Theme
281 if ( isEnabled )
282 {
283 focusSpacingX = 1;
284 focusSpacingY = 1;
285 }
286 else
287 {
288 focusSpacingX = 0;
289 focusSpacingY = 0;
290 }
291 }
292 }
293 else
294 {
295 // Drawing a list item
296 isEnabled = true; // they are never disabled
297 isFocused = flags & wxCONTROL_SELECTED ? true : false;
298
299 focusSpacingX = 0;
300 focusSpacingY = 0;
301 }
302
303 // Set the background sub-rectangle for selection, disabled etc
304 wxRect selRect(rect);
305 selRect.y += focusSpacingY;
306 selRect.height -= (focusSpacingY*2);
8e5ec129
WS
307
308 int wcp = 0;
309
310 if ( !(flags & wxCONTROL_ISSUBMENU) )
311 wcp += m_widthCustomPaint;
312
313 selRect.x += wcp + focusSpacingX;
314 selRect.width -= wcp + (focusSpacingX*2);
a340b80d 315
0d203f87
VZ
316 //wxUxThemeEngine* theme = (wxUxThemeEngine*) NULL;
317 //if ( hTheme )
318 // theme = wxUxThemeEngine::GetIfActive();
a340b80d
VZ
319
320 wxColour bgCol;
321 bool drawDottedEdge = false;
322
323 if ( isEnabled )
324 {
325 // If popup is hidden and this control is focused,
326 // then draw the focus-indicator (selbgcolor background etc.).
327 if ( isFocused )
328 {
329 #if 0
330 // TODO: Proper theme color getting (JMS: I don't know which parts/colors to use,
331 // those below don't work)
332 if ( hTheme )
333 {
334 theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_SELECTED,TMT_TEXTCOLOR,&cref);
335 dc.SetTextForeground( wxRGBToColour(cref) );
336 theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_SELECTED,TMT_FILLCOLOR,&cref);
337 bgCol = wxRGBToColour(cref);
338 }
339 else
340 #endif
341 {
342 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) );
343 bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
344 if ( m_windowStyle & wxCB_READONLY )
345 drawDottedEdge = true;
346 }
347 }
348 else
349 {
350 /*if ( hTheme )
351 {
352 theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_NORMAL,TMT_TEXTCOLOR,&cref);
353 dc.SetTextForeground( wxRGBToColour(cref) );
354 theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_NORMAL,TMT_FILLCOLOR,&cref);
355 bgCol = wxRGBToColour(cref);
356 }
357 else
358 {*/
359 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) );
360 bgCol = GetBackgroundColour();
361 //}
362 }
363 }
364 else
365 {
366 /*if ( hTheme )
367 {
368 theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_DISABLED,TMT_TEXTCOLOR,&cref);
369 dc.SetTextForeground( wxRGBToColour(cref) );
370 theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_DISABLED,TMT_EDGEFILLCOLOR,&cref);
371 bgCol = wxRGBToColour(cref);
372 }
373 else
374 {*/
375 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT) );
376 bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
377 //}
378 }
379
380 dc.SetBrush(bgCol);
381 dc.SetPen(bgCol);
382 dc.DrawRectangle(selRect);
383 if ( drawDottedEdge )
384 wxMSWDrawFocusRect(dc,selRect);
385
118f5fbd
RR
386 // Don't clip exactly to the selection rectangle so we can draw
387 // to the non-selected area in front of it.
388 wxRect clipRect(rect.x,rect.y,
389 (selRect.x+selRect.width)-rect.x-1,rect.height);
390 dc.SetClippingRegion(clipRect);
a340b80d
VZ
391}
392
a57d600f 393void wxComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) )
a340b80d
VZ
394{
395 // TODO: Convert drawing in this function to Windows API Code
396
397 wxSize sz = GetClientSize();
2e992e06 398 wxAutoBufferedPaintDC dc(this);
a340b80d
VZ
399
400 const wxRect& rectb = m_btnArea;
401 wxRect rect = m_tcArea;
402 bool isEnabled = IsEnabled();
403 wxColour bgCol = GetBackgroundColour();
404 wxColour fgCol;
405
406 wxUxThemeEngine* theme = NULL;
407 wxUxThemeHandle hTheme(this, L"COMBOBOX");
408 int etsState;
409
410 // area around both controls
411 wxRect rect2(0,0,sz.x,sz.y);
412 if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE )
413 {
414 rect2 = m_tcArea;
415 rect2.Inflate(1);
416 }
417
418 // Use theme to draw border on XP
419 if ( hTheme )
420 {
421 theme = wxUxThemeEngine::GetIfActive();
422 COLORREF cref;
423
424 // Select correct border colour
425 if ( !isEnabled )
426 etsState = ETS_DISABLED;
427 else
428 etsState = ETS_NORMAL;
429
430 if ( m_widthCustomBorder )
431 {
432 theme->GetThemeColor(hTheme,EP_EDITTEXT,etsState,TMT_BORDERCOLOR,&cref);
433
434 // Set border colour
435 dc.SetPen( wxRGBToColour(cref) );
436
437 dc.SetBrush( *wxTRANSPARENT_BRUSH );
438 dc.DrawRectangle(rect2);
439 }
440
441 theme->GetThemeColor(hTheme,EP_EDITTEXT,etsState,TMT_TEXTCOLOR,&cref);
442 fgCol = wxRGBToColour(cref);
443 }
444 else
445 {
446 // draw regular background
447 fgCol = GetForegroundColour();
448 }
449
450 rect2.Deflate(m_widthCustomBorder);
451
452 dc.SetBrush(bgCol);
453 dc.SetPen(bgCol);
454
455 // clear main background
456 dc.DrawRectangle(rect);
457
458 // Button background with theme?
373d466f 459 int drawButFlags = Draw_PaintBg;
a340b80d
VZ
460 if ( hTheme && m_blankButtonBg )
461 {
462 RECT r;
463 wxCopyRectToRECT(rectb, r);
464
465 // Draw parent background if needed (since button looks like its out of
466 // the combo, this is preferred).
467 theme->DrawThemeParentBackground(GetHwndOf(this),
468 GetHdcOf(dc),
469 &r);
470
373d466f 471 drawButFlags = 0;
93f7f8be 472 }
a340b80d
VZ
473
474 // Standard button rendering
373d466f 475 DrawButton(dc,rectb,drawButFlags);
a340b80d
VZ
476
477 // paint required portion on the control
6d0ce565 478 if ( (!m_text || m_widthCustomPaint) )
a340b80d
VZ
479 {
480 wxASSERT( m_widthCustomPaint >= 0 );
481
482 // this is intentionally here to allow drawed rectangle's
483 // right edge to be hidden
484 if ( m_text )
485 rect.width = m_widthCustomPaint;
486
487 dc.SetFont( GetFont() );
488
489 dc.SetClippingRegion(rect);
6d0ce565
VZ
490 if ( m_popupInterface )
491 m_popupInterface->PaintComboControl(dc,rect);
492 else
493 wxComboPopup::DefaultPaintComboControl(this,dc,rect);
a340b80d
VZ
494 }
495}
496
a57d600f 497void wxComboCtrl::OnMouseEvent( wxMouseEvent& event )
a340b80d 498{
1efad474
RR
499 int mx = event.m_x;
500 bool isOnButtonArea = m_btnArea.Contains(mx,event.m_y);
a340b80d
VZ
501 int handlerFlags = isOnButtonArea ? wxCC_MF_ON_BUTTON : 0;
502
a340b80d
VZ
503 if ( PreprocessMouseEvent(event,isOnButtonArea) )
504 return;
505
506 if ( (m_windowStyle & (wxCC_SPECIAL_DCLICK|wxCB_READONLY)) == wxCB_READONLY )
507 {
508 // if no textctrl and no special double-click, then the entire control acts
509 // as a button
510 handlerFlags |= wxCC_MF_ON_BUTTON;
511 if ( HandleButtonMouseEvent(event,handlerFlags) )
512 return;
513 }
514 else
515 {
1efad474
RR
516 if ( isOnButtonArea || HasCapture() ||
517 (m_widthCustomPaint && mx < (m_tcArea.x+m_widthCustomPaint)) )
a340b80d 518 {
1efad474
RR
519 handlerFlags |= wxCC_MF_ON_CLICK_AREA;
520
a340b80d
VZ
521 if ( HandleButtonMouseEvent(event,handlerFlags) )
522 return;
523 }
524 else if ( m_btnState )
525 {
526 // otherwise need to clear the hover status
527 m_btnState = 0;
528 RefreshRect(m_btnArea);
529 }
530 }
531
532 //
533 // This will handle left_down and left_dclick events outside button in a Windows-like manner.
534 // See header file for further information on this method.
535 HandleNormalMouseEvent(event);
536
537}
538
30be036c 539#if wxUSE_COMBOCTRL_POPUP_ANIMATION
974a12f8
RR
540static wxUint32 GetUserPreferencesMask()
541{
542 static wxUint32 userPreferencesMask = 0;
543 static bool valueSet = false;
544
545 if ( valueSet )
546 return userPreferencesMask;
547
53a64063
JS
548 wxRegKey* pKey = NULL;
549 wxRegKey key1(wxRegKey::HKCU, wxT("Software\\Policies\\Microsoft\\Control Panel"));
550 wxRegKey key2(wxRegKey::HKCU, wxT("Software\\Policies\\Microsoft\\Windows\\Control Panel"));
551 wxRegKey key3(wxRegKey::HKCU, wxT("Control Panel\\Desktop"));
552
553 if ( key1.Exists() )
554 pKey = &key1;
555 else if ( key2.Exists() )
556 pKey = &key2;
557 else if ( key3.Exists() )
558 pKey = &key3;
559
560 if ( pKey && pKey->Open(wxRegKey::Read) )
974a12f8
RR
561 {
562 wxMemoryBuffer buf;
53a64063
JS
563 if ( pKey->HasValue(wxT("UserPreferencesMask")) &&
564 pKey->QueryValue(wxT("UserPreferencesMask"), buf) )
974a12f8
RR
565 {
566 if ( buf.GetDataLen() >= 4 )
567 {
53a64063
JS
568 wxUint32* p = (wxUint32*) buf.GetData();
569 userPreferencesMask = *p;
974a12f8
RR
570 }
571 }
572 }
573
574 valueSet = true;
575
576 return userPreferencesMask;
577}
578#endif
579
30be036c
RR
580#if wxUSE_COMBOCTRL_POPUP_ANIMATION
581void wxComboCtrl::OnTimerEvent( wxTimerEvent& WXUNUSED(event) )
974a12f8 582{
30be036c 583 bool stopTimer = false;
974a12f8 584
30be036c 585 wxWindow* popup = GetPopupControl()->GetControl();
974a12f8 586
30be036c
RR
587 // Popup was hidden before it was fully shown?
588 if ( IsPopupWindowState(Hidden) )
589 {
590 stopTimer = true;
591 }
592 else
593 {
594 wxLongLong t = ::wxGetLocalTimeMillis();
595 const wxRect& rect = m_animRect;
974a12f8 596 wxWindow* win = GetPopupWindow();
974a12f8 597
30be036c
RR
598 int pos = (int) (t-m_animStart).GetLo();
599 if ( pos < COMBOBOX_ANIMATION_DURATION )
974a12f8 600 {
30be036c
RR
601 int height = rect.height;
602 //int h0 = rect.height;
603 int h = (((pos*256)/COMBOBOX_ANIMATION_DURATION)*height)/256;
604 int y = (height - h);
974a12f8
RR
605 if ( y < 0 )
606 y = 0;
607
30be036c 608 if ( m_animFlags & ShowAbove )
974a12f8 609 {
30be036c 610 win->SetSize( rect.x, rect.y + height - h, rect.width, h );
974a12f8
RR
611 }
612 else
613 {
614 popup->Move( 0, -y );
615 win->SetSize( rect.x, rect.y, rect.width, h );
616 }
974a12f8 617 }
30be036c
RR
618 else
619 {
620 stopTimer = true;
621 }
622 }
974a12f8 623
30be036c
RR
624 if ( stopTimer )
625 {
974a12f8 626 popup->Move( 0, 0 );
30be036c
RR
627 m_animTimer.Stop();
628 DoShowPopup( m_animRect, m_animFlags );
974a12f8 629 }
30be036c 630}
974a12f8
RR
631#endif
632
30be036c
RR
633#if wxUSE_COMBOCTRL_POPUP_ANIMATION
634bool wxComboCtrl::AnimateShow( const wxRect& rect, int flags )
635{
636 if ( GetUserPreferencesMask() & wxMSW_DESKTOP_USERPREFERENCESMASK_COMBOBOXANIM )
637 {
638 m_animStart = ::wxGetLocalTimeMillis();
639 m_animRect = rect;
640 m_animFlags = flags;
641
642 wxWindow* win = GetPopupWindow();
643 win->SetSize( rect.x, rect.y, rect.width, 0 );
644 win->Show();
645
646 m_animTimer.SetOwner( this, wxID_ANY );
647 m_animTimer.Start( COMBOBOX_ANIMATION_RESOLUTION, wxTIMER_CONTINUOUS );
648
649 OnTimerEvent(*((wxTimerEvent*)NULL)); // Event is never used, so we can give NULL
650
651 return false;
652 }
653
974a12f8
RR
654 return true;
655}
30be036c 656#endif
974a12f8 657
a57d600f 658wxCoord wxComboCtrl::GetNativeTextIndent() const
a340b80d
VZ
659{
660 if ( wxUxThemeEngine::GetIfActive() )
661 return NATIVE_TEXT_INDENT_XP;
662 return NATIVE_TEXT_INDENT_CLASSIC;
663}
664
b445b6a7
VZ
665bool wxComboCtrl::IsKeyPopupToggle(const wxKeyEvent& event) const
666{
9e68717c 667 const bool isPopupShown = IsPopupShown();
b445b6a7 668
9e68717c 669 switch ( event.GetKeyCode() )
b445b6a7 670 {
9e68717c
VZ
671 case WXK_F4:
672 // F4 toggles the popup in the native comboboxes, so emulate them
673 if ( !event.AltDown() )
674 return true;
675 break;
676
677 case WXK_ESCAPE:
678 if ( isPopupShown )
679 return true;
680 break;
681
682 case WXK_DOWN:
683 case WXK_UP:
684 // On XP or with writable combo in Classic, arrows don't open the
685 // popup but Alt-arrow does
686 if ( event.AltDown() ||
687 ( !isPopupShown &&
688 HasFlag(wxCB_READONLY) &&
689 !wxUxThemeEngine::GetIfActive()
690 ) )
691 {
692 return true;
693 }
694 break;
b445b6a7
VZ
695 }
696
697 return false;
698}
a340b80d 699
a57d600f 700#endif // wxUSE_COMBOCTRL