1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        univ/window.cpp 
   3 // Purpose:     implementation of extra wxWindow methods for wxUniv port 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 2000 SciTech Software, Inc. (www.scitechsoft.com) 
   9 // Licence:     wxWindows license 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // =========================================================================== 
  14 // =========================================================================== 
  16 // --------------------------------------------------------------------------- 
  18 // --------------------------------------------------------------------------- 
  21     #pragma implementation "univwindow.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  33     #include "wx/window.h" 
  34     #include "wx/dcclient.h" 
  35     #include "wx/dcmemory.h" 
  37     #include "wx/scrolbar.h" 
  42 #include "wx/univ/colschem.h" 
  43 #include "wx/univ/renderer.h" 
  44 #include "wx/univ/theme.h" 
  50 // turn Refresh() debugging on/off 
  51 #define WXDEBUG_REFRESH 
  54     #undef WXDEBUG_REFRESH 
  57 // ============================================================================ 
  59 // ============================================================================ 
  61 // ---------------------------------------------------------------------------- 
  63 // ---------------------------------------------------------------------------- 
  65 // we can't use wxWindowNative here as it won't be expanded inside the macro 
  66 #if defined(__WXMSW__) 
  67     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowMSW
) 
  68 #elif defined(__WXGTK__) 
  69     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowGTK
) 
  70 #elif defined(__WXMGL__) 
  71     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowMGL
) 
  74 BEGIN_EVENT_TABLE(wxWindow
, wxWindowNative
) 
  75     EVT_SIZE(wxWindow::OnSize
) 
  77 #if wxUSE_ACCEL || wxUSE_MENUS 
  78     EVT_KEY_DOWN(wxWindow::OnKeyDown
) 
  82     EVT_CHAR(wxWindow::OnChar
) 
  83     EVT_KEY_UP(wxWindow::OnKeyUp
) 
  86     EVT_PAINT(wxWindow::OnPaint
) 
  87     EVT_NC_PAINT(wxWindow::OnNcPaint
) 
  88     EVT_ERASE_BACKGROUND(wxWindow::OnErase
) 
  91 // ---------------------------------------------------------------------------- 
  93 // ---------------------------------------------------------------------------- 
  98     m_scrollbarHorz 
= (wxScrollBar 
*)NULL
; 
 102     m_renderer 
= wxTheme::Get()->GetRenderer(); 
 105 bool wxWindow::Create(wxWindow 
*parent
, 
 110                       const wxString
& name
) 
 112     // we add wxCLIP_CHILDREN and wxNO_FULL_REPAINT_ON_RESIZE because without 
 113     // these styles we can't get rid of flicker on wxMSW 
 114     if ( !wxWindowNative::Create(parent
, id
, pos
, size
, 
 117                                  wxNO_FULL_REPAINT_ON_RESIZE
, name
) ) 
 122     // if we should always have the scrollbar, do show it 
 123     if ( GetWindowStyle() & wxALWAYS_SHOW_SB 
) 
 125         m_scrollbarVert 
= new wxScrollBar(this, -1, 
 126                                           wxDefaultPosition
, wxDefaultSize
, 
 130         PositionScrollbars(); 
 133     // the colours/fonts are default 
 141 // ---------------------------------------------------------------------------- 
 143 // ---------------------------------------------------------------------------- 
 145 void wxWindow::SetBackground(const wxBitmap
& bitmap
, 
 150     m_alignBgBitmap 
= alignment
; 
 151     m_stretchBgBitmap 
= stretch
; 
 154 const wxBitmap
& wxWindow::GetBackgroundBitmap(int *alignment
, 
 155                                                wxStretch 
*stretch
) const 
 157     if ( m_bitmapBg
.Ok() ) 
 160             *alignment 
= m_alignBgBitmap
; 
 162             *stretch 
= m_stretchBgBitmap
; 
 168 // ---------------------------------------------------------------------------- 
 170 // ---------------------------------------------------------------------------- 
 172 // the event handler executed when the window background must be painted 
 173 void wxWindow::OnErase(wxEraseEvent
& event
) 
 182     DoDrawBackground(*event
.GetDC()); 
 184     // if we have both scrollbars, we also have a square in the corner between 
 185     // them which we must paint 
 186     if ( m_scrollbarVert 
&& m_scrollbarHorz 
) 
 188         wxSize size 
= GetSize(); 
 189         wxRect rectClient 
= GetClientRect(), 
 190                rectBorder 
= m_renderer
->GetBorderDimensions(GetBorder()); 
 193         rectCorner
.x 
= rectClient
.GetRight() + 1; 
 194         rectCorner
.y 
= rectClient
.GetBottom() + 1; 
 195         rectCorner
.SetRight(size
.x 
- rectBorder
.width
); 
 196         rectCorner
.SetBottom(size
.y 
- rectBorder
.height
); 
 198         if ( GetUpdateRegion().Contains(rectCorner
) ) 
 200             m_renderer
->DrawScrollCorner(*event
.GetDC(), rectCorner
); 
 205 // the event handlers executed when the window must be repainted 
 206 void wxWindow::OnNcPaint(wxPaintEvent
& event
) 
 210         // get the window rect 
 212         wxSize size 
= GetSize(); 
 216         rect
.height 
= size
.y
; 
 218         // if the scrollbars are outside the border, we must adjust the rect to 
 220         if ( !m_renderer
->AreScrollbarsInsideBorder() ) 
 222             wxScrollBar 
*scrollbar 
= GetScrollbar(wxVERTICAL
); 
 224                 rect
.width 
-= scrollbar
->GetSize().x
; 
 226             scrollbar 
= GetScrollbar(wxHORIZONTAL
); 
 228                 rect
.height 
-= scrollbar
->GetSize().y
; 
 231         // get the DC and draw the border on it 
 233         DoDrawBorder(dc
, rect
); 
 237 void wxWindow::OnPaint(wxPaintEvent
& event
) 
 241         // it is a native control which paints itself 
 246         // get the DC to use and create renderer on it 
 248         wxControlRenderer 
renderer(this, dc
, m_renderer
); 
 255 bool wxWindow::DoDrawBackground(wxDC
& dc
) 
 257     // FIXME: leaving this code in leads to partial bg redraws sometimes under 
 261     rect 
= GetUpdateRegion().GetBox(); 
 262     if ( !rect
.width 
&& !rect
.height 
) 
 265         wxSize size 
= GetSize(); 
 267         rect
.height 
= size
.y
; 
 270     if ( GetBackgroundBitmap().Ok() ) 
 272         // get the bitmap and the flags 
 275         wxBitmap bmp 
= GetBackgroundBitmap(&alignment
, &stretch
); 
 276         wxControlRenderer::DrawBitmap(dc
, bmp
, rect
, alignment
, stretch
); 
 278     else // just fill it with bg colour if no bitmap 
 280         m_renderer
->DrawBackground(dc
, wxTHEME_BG_COLOUR(this), 
 281                                    rect
, GetStateFlags()); 
 287 void wxWindow::EraseBackground(wxDC
& dc
, const wxRect
& rect
) 
 289     // TODO: handle bg bitmaps here! 
 291     m_renderer
->DrawBackground(dc
, wxTHEME_BG_COLOUR(this), rect
, GetStateFlags()); 
 294 void wxWindow::DoDrawBorder(wxDC
& dc
, const wxRect
& rect
) 
 296     // draw outline unless the update region is enitrely inside it in which 
 297     // case we don't need to do it 
 298 #if 0 // doesn't seem to work, why? 
 299     if ( wxRegion(rect
).Contains(GetUpdateRegion().GetBox()) != wxInRegion 
) 
 302         m_renderer
->DrawBorder(dc
, GetBorder(), rect
, GetStateFlags()); 
 306 void wxWindow::DoDraw(wxControlRenderer 
*renderer
) 
 310 void wxWindow::Refresh(bool eraseBackground
, const wxRect 
*rectClient
) 
 313     wxPoint pt 
= GetClientAreaOrigin(); 
 315     wxSize size 
= GetClientSize(); 
 319         rectWin 
= *rectClient
; 
 321         // don't refresh anything beyond the client area (scrollbars for 
 323         if ( rectWin
.GetRight() > size
.x 
) 
 324             rectWin
.SetRight(size
.x
); 
 325         if ( rectWin
.GetBottom() > size
.y 
) 
 326             rectWin
.SetBottom(size
.y
); 
 330     else // refresh the entire client area 
 334         rectWin
.width 
= size
.x
; 
 335         rectWin
.height 
= size
.y
; 
 339 #ifdef WXDEBUG_REFRESH 
 340     static bool s_refreshDebug 
= FALSE
; 
 341     if ( s_refreshDebug 
) 
 344         dc
.SetBrush(*wxCYAN_BRUSH
); 
 345         dc
.SetPen(*wxTRANSPARENT_PEN
); 
 346         dc
.DrawRectangle(rectWin
); 
 348         // under Unix we use "--sync" X option for this 
 349         #if defined(__WXMSW__) && !defined(__WXMICROWIN__) 
 354 #endif // WXDEBUG_REFRESH 
 356     wxWindowNative::Refresh(eraseBackground
, &rectWin
); 
 359 // ---------------------------------------------------------------------------- 
 361 // ---------------------------------------------------------------------------- 
 363 bool wxWindow::Enable(bool enable
) 
 365     if ( !wxWindowNative::Enable(enable
) ) 
 368     // disabled window can't keep focus 
 369     if ( FindFocus() == this ) 
 371         GetParent()->SetFocus(); 
 376         // a window with renderer is drawn by ourselves and it has to be 
 377         // refreshed to reflect its new status 
 384 bool wxWindow::IsFocused() const 
 386     wxWindow 
*self 
= wxConstCast(this, wxWindow
); 
 387     return self
->FindFocus() == self
; 
 390 bool wxWindow::IsPressed() const 
 395 bool wxWindow::IsDefault() const 
 400 bool wxWindow::IsCurrent() const 
 405 bool wxWindow::SetCurrent(bool doit
) 
 407     if ( doit 
== m_isCurrent 
) 
 412     if ( CanBeHighlighted() ) 
 418 int wxWindow::GetStateFlags() const 
 422         flags 
|= wxCONTROL_DISABLED
; 
 424     // the following states are only possible if our application is active - if 
 425     // it is not, even our default/focused controls shouldn't appear as such 
 426     if ( wxTheApp
->IsActive() ) 
 429             flags 
|= wxCONTROL_CURRENT
; 
 431             flags 
|= wxCONTROL_FOCUSED
; 
 433             flags 
|= wxCONTROL_PRESSED
; 
 435             flags 
|= wxCONTROL_ISDEFAULT
; 
 441 // ---------------------------------------------------------------------------- 
 443 // ---------------------------------------------------------------------------- 
 445 void wxWindow::OnSize(wxSizeEvent
& event
) 
 447     if ( m_scrollbarVert 
|| m_scrollbarHorz 
) 
 449         PositionScrollbars(); 
 455 wxSize 
wxWindow::DoGetBestSize() const 
 457     return AdjustSize(DoGetBestClientSize()); 
 460 wxSize 
wxWindow::DoGetBestClientSize() const 
 462     return wxWindowNative::DoGetBestSize(); 
 465 wxSize 
wxWindow::AdjustSize(const wxSize
& size
) const 
 469         m_renderer
->AdjustSize(&sz
, this); 
 473 wxPoint 
wxWindow::GetClientAreaOrigin() const 
 475     wxPoint pt 
= wxWindowBase::GetClientAreaOrigin(); 
 478         pt 
+= m_renderer
->GetBorderDimensions(GetBorder()).GetPosition(); 
 483 void wxWindow::DoGetClientSize(int *width
, int *height
) const 
 485     // if it is a native window, we assume it handles the scrollbars itself 
 486     // too - and if it doesn't, there is not much we can do 
 489         wxWindowNative::DoGetClientSize(width
, height
); 
 495     wxWindowNative::DoGetClientSize(&w
, &h
); 
 497     // we assume that the scrollbars are positioned correctly (by a previous 
 498     // call to PositionScrollbars()) here 
 502         rectBorder 
= m_renderer
->GetBorderDimensions(GetBorder()); 
 504     bool inside 
= m_renderer
->AreScrollbarsInsideBorder(); 
 508         // in any case, take account of the scrollbar 
 509         if ( m_scrollbarVert 
) 
 510             w 
-= m_scrollbarVert
->GetSize().x
; 
 512         // if we don't have scrollbar or if it is outside the border (and not 
 513         // blended into it), take account of the right border as well 
 514         if ( !m_scrollbarVert 
|| inside 
) 
 515             w 
-= rectBorder
.width
; 
 517         // and always account for the left border 
 518         *width 
= w 
- rectBorder
.x
; 
 520         // we shouldn't return invalid width 
 527         if ( m_scrollbarHorz 
) 
 528             h 
-= m_scrollbarHorz
->GetSize().y
; 
 530         if ( !m_scrollbarHorz 
|| inside 
) 
 531             h 
-= rectBorder
.height
; 
 533         *height 
= h 
- rectBorder
.y
; 
 535         // we shouldn't return invalid height 
 541 void wxWindow::DoSetClientSize(int width
, int height
) 
 543     // take into account the borders 
 544     wxRect rectBorder 
= m_renderer
->GetBorderDimensions(GetBorder()); 
 545     width 
+= rectBorder
.x
; 
 546     height 
+= rectBorder
.y
; 
 548     // and the scrollbars (as they may be offset into the border, use the 
 549     // scrollbar position, not size - this supposes that PositionScrollbars() 
 550     // had been called before) 
 551     bool inside 
= m_renderer
->AreScrollbarsInsideBorder(); 
 552     wxSize size 
= GetSize(); 
 553     if ( m_scrollbarVert 
) 
 554         width 
+= size
.x 
- m_scrollbarVert
->GetPosition().x
; 
 555     if ( !m_scrollbarVert 
|| inside 
) 
 556         width 
+= rectBorder
.width
; 
 558     if ( m_scrollbarHorz 
) 
 559         height 
+= size
.y 
- m_scrollbarHorz
->GetPosition().y
; 
 560     if ( !m_scrollbarHorz 
|| inside 
) 
 561         height 
+= rectBorder
.height
; 
 563     wxWindowNative::DoSetClientSize(width
, height
); 
 566 wxHitTest 
wxWindow::DoHitTest(wxCoord x
, wxCoord y
) const 
 568     wxHitTest ht 
= wxWindowNative::DoHitTest(x
, y
); 
 569     if ( ht 
== wxHT_WINDOW_INSIDE 
) 
 571         if ( m_scrollbarVert 
&& x 
>= m_scrollbarVert
->GetPosition().x 
) 
 573             // it can still be changed below because it may also be the corner 
 574             ht 
= wxHT_WINDOW_VERT_SCROLLBAR
; 
 577         if ( m_scrollbarHorz 
&& y 
>= m_scrollbarHorz
->GetPosition().y 
) 
 579             ht 
= ht 
== wxHT_WINDOW_VERT_SCROLLBAR 
? wxHT_WINDOW_CORNER
 
 580                                                   : wxHT_WINDOW_HORZ_SCROLLBAR
; 
 587 // ---------------------------------------------------------------------------- 
 588 // scrolling: we implement it entirely ourselves except for ScrollWindow() 
 589 // function which is supposed to be (efficiently) implemented by the native 
 591 // ---------------------------------------------------------------------------- 
 593 void wxWindow::RefreshScrollbars() 
 595     if ( m_scrollbarHorz 
) 
 596         m_scrollbarHorz
->Refresh(); 
 598     if ( m_scrollbarVert 
) 
 599         m_scrollbarVert
->Refresh(); 
 602 void wxWindow::PositionScrollbars() 
 604     // do not use GetClientSize/Rect as it relies on the scrollbars being 
 605     // correctly positioned 
 607     wxSize size 
= GetSize(); 
 608     wxBorder border 
= GetBorder(); 
 609     wxRect rectBorder 
= m_renderer
->GetBorderDimensions(border
); 
 610     bool inside 
= m_renderer
->AreScrollbarsInsideBorder(); 
 612     int height 
= m_scrollbarHorz 
? m_scrollbarHorz
->GetSize().y 
: 0; 
 613     int width 
= m_scrollbarVert 
? m_scrollbarVert
->GetSize().x 
: 0; 
 616     if ( m_scrollbarVert 
) 
 618         rectBar
.x 
= size
.x 
- width
; 
 620            rectBar
.x 
-= rectBorder
.width
; 
 621         rectBar
.width 
= width
; 
 624             rectBar
.y 
+= rectBorder
.y
; 
 625         rectBar
.height 
= size
.y 
- height
; 
 627             rectBar
.height 
-= rectBorder
.y 
+ rectBorder
.height
; 
 629         m_scrollbarVert
->SetSize(rectBar
, wxSIZE_NO_ADJUSTMENTS
); 
 632     if ( m_scrollbarHorz 
) 
 634         rectBar
.y 
= size
.y 
- height
; 
 636             rectBar
.y 
-= rectBorder
.height
; 
 637         rectBar
.height 
= height
; 
 640             rectBar
.x 
+= rectBorder
.x
; 
 641         rectBar
.width 
= size
.x 
- width
; 
 643             rectBar
.width 
-= rectBorder
.x 
+ rectBorder
.width
; 
 645         m_scrollbarHorz
->SetSize(rectBar
, wxSIZE_NO_ADJUSTMENTS
); 
 651 void wxWindow::SetScrollbar(int orient
, 
 657     bool hasClientSizeChanged 
= FALSE
; 
 658     wxScrollBar 
*scrollbar 
= GetScrollbar(orient
); 
 664             scrollbar 
= new wxScrollBar(this, -1, 
 665                                         wxDefaultPosition
, wxDefaultSize
, 
 666                                         orient 
& wxVERTICAL 
? wxSB_VERTICAL
 
 668             if ( orient 
& wxVERTICAL 
) 
 669                 m_scrollbarVert 
= scrollbar
; 
 671                 m_scrollbarHorz 
= scrollbar
; 
 673             // the client area diminished as we created a scrollbar 
 674             hasClientSizeChanged 
= TRUE
; 
 676             PositionScrollbars(); 
 678         else if ( GetWindowStyle() & wxALWAYS_SHOW_SB 
) 
 680             // we might have disabled it before 
 684         scrollbar
->SetScrollbar(pos
, pageSize
, range
, pageSize
, refresh
); 
 686     else // no range means no scrollbar 
 690             // wxALWAYS_SHOW_SB only applies to the vertical scrollbar 
 691             if ( (orient 
& wxVERTICAL
) && (GetWindowStyle() & wxALWAYS_SHOW_SB
) ) 
 693                 // just disable the scrollbar 
 694                 scrollbar
->SetScrollbar(pos
, pageSize
, range
, pageSize
, refresh
); 
 695                 scrollbar
->Disable(); 
 697             else // really remove the scrollbar 
 701                 if ( orient 
& wxVERTICAL 
) 
 702                     m_scrollbarVert 
= NULL
; 
 704                     m_scrollbarHorz 
= NULL
; 
 706                 // the client area increased as we removed a scrollbar 
 707                 hasClientSizeChanged 
= TRUE
; 
 709                 // the size of the remaining scrollbar must be adjusted 
 710                 if ( m_scrollbarHorz 
|| m_scrollbarVert 
) 
 712                     PositionScrollbars(); 
 718     // give the window a chance to relayout 
 719     if ( hasClientSizeChanged 
) 
 721         wxSizeEvent 
event(GetSize()); 
 722         (void)GetEventHandler()->ProcessEvent(event
); 
 726 void wxWindow::SetScrollPos(int orient
, int pos
, bool refresh
) 
 728     wxScrollBar 
*scrollbar 
= GetScrollbar(orient
); 
 729     wxCHECK_RET( scrollbar
, _T("no scrollbar to set position for") ); 
 731     scrollbar
->SetThumbPosition(pos
); 
 736 int wxWindow::GetScrollPos(int orient
) const 
 738     wxScrollBar 
*scrollbar 
= GetScrollbar(orient
); 
 739     return scrollbar 
? scrollbar
->GetThumbPosition() : 0; 
 742 int wxWindow::GetScrollThumb(int orient
) const 
 744     wxScrollBar 
*scrollbar 
= GetScrollbar(orient
); 
 745     return scrollbar 
? scrollbar
->GetThumbSize() : 0; 
 748 int wxWindow::GetScrollRange(int orient
) const 
 750     wxScrollBar 
*scrollbar 
= GetScrollbar(orient
); 
 751     return scrollbar 
? scrollbar
->GetRange() : 0; 
 754 void wxWindow::ScrollWindow(int dx
, int dy
, const wxRect 
*rect
) 
 756     // before scrolling it, ensure that we don't have any unpainted areas 
 763         r 
= ScrollNoRefresh(dx
, 0, rect
); 
 764         Refresh(TRUE 
/* erase bkgnd */, &r
); 
 769         r 
= ScrollNoRefresh(0, dy
, rect
); 
 770         Refresh(TRUE 
/* erase bkgnd */, &r
); 
 774 wxRect 
wxWindow::ScrollNoRefresh(int dx
, int dy
, const wxRect 
*rectTotal
) 
 776     wxASSERT_MSG( !dx 
|| !dy
, _T("can't be used for diag scrolling") ); 
 778     // the rect to refresh (which we will calculate) 
 787     // calculate the part of the window which we can just redraw in the new 
 789     wxSize sizeTotal 
= rectTotal 
? rectTotal
->GetSize() : GetClientSize(); 
 791     wxLogTrace(_T("scroll"), _T("rect is %dx%d, scroll by %d, %d"), 
 792                sizeTotal
.x
, sizeTotal
.y
, dx
, dy
); 
 794     // the initial and end point of the region we move in client coords 
 795     wxPoint ptSource
, ptDest
; 
 798         ptSource 
= rectTotal
->GetPosition(); 
 799         ptDest 
= rectTotal
->GetPosition(); 
 802     // the size of this region 
 804     size
.x 
= sizeTotal
.x 
- abs(dx
); 
 805     size
.y 
= sizeTotal
.y 
- abs(dy
); 
 806     if ( size
.x 
<= 0 || size
.y 
<= 0 ) 
 808         // just redraw everything as nothing of the displayed image will stay 
 809         wxLogTrace(_T("scroll"), _T("refreshing everything")); 
 811         rect 
= rectTotal 
? *rectTotal 
: wxRect(0, 0, sizeTotal
.x
, sizeTotal
.y
); 
 813     else // move the part which doesn't change to the new location 
 815         // note that when we scroll the canvas in some direction we move the 
 816         // block which doesn't need to be refreshed in the opposite direction 
 820             // scroll to the right, move to the left 
 825             // scroll to the left, move to the right 
 831             // scroll down, move up 
 836             // scroll up, move down 
 841         // we need to hide the caret before moving or it will erase itself at 
 842         // the wrong (old) location 
 843         wxCaret 
*caret 
= GetCaret(); 
 846 #endif // wxUSE_CARET 
 850         wxBitmap 
bmp(size
.x
, size
.y
); 
 852         dcMem
.SelectObject(bmp
); 
 854         dcMem
.Blit(wxPoint(0, 0), size
, &dc
, ptSource
 
 855 #if defined(__WXGTK__) && !defined(__WX_DC_BLIT_FIXED__) 
 856                 + GetClientAreaOrigin() 
 857 #endif // broken wxGTK wxDC::Blit 
 859         dc
.Blit(ptDest
, size
, &dcMem
, wxPoint(0, 0)); 
 861         wxLogTrace(_T("scroll"), 
 862                    _T("Blit: (%d, %d) of size %dx%d -> (%d, %d)"), 
 863                    ptSource
.x
, ptSource
.y
, 
 867         // and now repaint the uncovered area 
 869         // FIXME: We repaint the intersection of these rectangles twice - is 
 870         //        it bad? I don't think so as it is rare to scroll the window 
 871         //        diagonally anyhow and so adding extra logic to compute 
 872         //        rectangle intersection is probably not worth the effort 
 881                 // refresh the area along the right border 
 882                 rect
.x 
+= size
.x 
+ dx
; 
 887                 // refresh the area along the left border 
 891             rect
.height 
= sizeTotal
.y
; 
 893             wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"), 
 895                        rect
.GetRight() + 1, rect
.GetBottom() + 1); 
 902                 // refresh the area along the bottom border 
 903                 rect
.y 
+= size
.y 
+ dy
; 
 908                 // refresh the area along the top border 
 912             rect
.width 
= sizeTotal
.x
; 
 914             wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"), 
 916                        rect
.GetRight() + 1, rect
.GetBottom() + 1); 
 922 #endif // wxUSE_CARET 
 928 // ---------------------------------------------------------------------------- 
 930 // ---------------------------------------------------------------------------- 
 932 bool wxWindow::SetBackgroundColour(const wxColour
& colour
) 
 934     if ( !wxWindowNative::SetBackgroundColour(colour
) ) 
 942 bool wxWindow::SetForegroundColour(const wxColour
& colour
) 
 944     if ( !wxWindowNative::SetForegroundColour(colour
) ) 
 952 bool wxWindow::SetFont(const wxFont
& font
) 
 954     if ( !wxWindowNative::SetFont(font
) ) 
 962 // ---------------------------------------------------------------------------- 
 964 // ---------------------------------------------------------------------------- 
 966 struct WXDLLEXPORT wxWindowNext
 
 970 } *wxWindow::ms_winCaptureNext 
= NULL
; 
 972 void wxWindow::CaptureMouse() 
 974     wxWindow 
*winOld 
= GetCapture(); 
 978         wxWindowNext 
*item 
= new wxWindowNext
; 
 980         item
->next 
= ms_winCaptureNext
; 
 981         ms_winCaptureNext 
= item
; 
 983     //else: no mouse capture to save 
 985     wxWindowNative::CaptureMouse(); 
 988 void wxWindow::ReleaseMouse() 
 990     wxWindowNative::ReleaseMouse(); 
 992     if ( ms_winCaptureNext 
) 
 994         ms_winCaptureNext
->win
->CaptureMouse(); 
 996         wxWindowNext 
*item 
= ms_winCaptureNext
; 
 997         ms_winCaptureNext 
= item
->next
; 
1000     //else: stack is empty, no previous capture 
1003 // ---------------------------------------------------------------------------- 
1004 // accelerators and menu hot keys 
1005 // ---------------------------------------------------------------------------- 
1008     // the last window over which Alt was pressed (used by OnKeyUp) 
1009     wxWindow 
*wxWindow::ms_winLastAltPress 
= NULL
; 
1010 #endif // wxUSE_MENUS 
1012 #if wxUSE_ACCEL || wxUSE_MENUS 
1014 void wxWindow::OnKeyDown(wxKeyEvent
& event
) 
1017     int key 
= event
.GetKeyCode(); 
1018     if ( !event
.ControlDown() && (key 
== WXK_MENU 
|| key 
== WXK_F10
) ) 
1020         ms_winLastAltPress 
= this; 
1022         // it can't be an accel anyhow 
1026     ms_winLastAltPress 
= NULL
; 
1027 #endif // wxUSE_MENUS 
1030     for ( wxWindow 
*win 
= this; win
; win 
= win
->GetParent() ) 
1032         int command 
= win
->GetAcceleratorTable()->GetCommand(event
); 
1033         if ( command 
!= -1 ) 
1035             wxCommandEvent 
eventCmd(wxEVT_COMMAND_MENU_SELECTED
, command
); 
1036             if ( win
->GetEventHandler()->ProcessEvent(eventCmd
) ) 
1038                 // skip "event.Skip()" below 
1043         if ( win
->IsTopLevel() ) 
1045             // try the frame menu bar 
1047             wxFrame 
*frame 
= wxDynamicCast(win
, wxFrame
); 
1050                 wxMenuBar 
*menubar 
= frame
->GetMenuBar(); 
1051                 if ( menubar 
&& menubar
->ProcessAccelEvent(event
) ) 
1053                     // skip "event.Skip()" below 
1057 #endif // wxUSE_MENUS 
1059             // don't propagate accels from the child frame to the parent one 
1063 #endif // wxUSE_ACCEL 
1068 #endif // wxUSE_ACCEL 
1072 wxMenuBar 
*wxWindow::GetParentFrameMenuBar() const 
1074     for ( const wxWindow 
*win 
= this; win
; win 
= win
->GetParent() ) 
1076         if ( win
->IsTopLevel() ) 
1078             wxFrame 
*frame 
= wxDynamicCast(win
, wxFrame
); 
1081                 return frame
->GetMenuBar(); 
1084             // don't look further - we don't want to return the menubar of the 
1093 void wxWindow::OnChar(wxKeyEvent
& event
) 
1095     if ( event
.AltDown() && !event
.ControlDown() ) 
1097         int key 
= event
.GetKeyCode(); 
1099         wxMenuBar 
*menubar 
= GetParentFrameMenuBar(); 
1102             int item 
= menubar
->FindNextItemForAccel(-1, key
); 
1105                 menubar
->PopupMenu((size_t)item
); 
1107                 // skip "event.Skip()" below 
1116 void wxWindow::OnKeyUp(wxKeyEvent
& event
) 
1118     int key 
= event
.GetKeyCode(); 
1119     if ( !event
.HasModifiers() && (key 
== WXK_MENU 
|| key 
== WXK_F10
) ) 
1121         // only process Alt release specially if there were no other key 
1122         // presses since Alt had been pressed and if both events happened in 
1124         if ( ms_winLastAltPress 
== this ) 
1126             wxMenuBar 
*menubar 
= GetParentFrameMenuBar(); 
1127             if ( menubar 
&& this != menubar 
) 
1129                 menubar
->SelectMenu(0); 
1138     // in any case reset it 
1139     ms_winLastAltPress 
= NULL
; 
1142 #endif // wxUSE_MENUS