1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/frame.cpp
3 // Purpose:     wxFrame
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     01/02/97
7 // RCS-ID:      $Id: frame.cpp 61213 2009-06-27 12:31:00Z JS $
8 // Copyright:   (c) Julian Smart
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // ============================================================================
13 // declarations
14 // ============================================================================
15 
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19 
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22 
23 #ifdef __BORLANDC__
24     #pragma hdrstop
25 #endif
26 
27 #include "wx/frame.h"
28 
29 #ifndef WX_PRECOMP
30     #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
31     #include "wx/app.h"
32     #include "wx/menu.h"
33     #include "wx/utils.h"
34     #include "wx/dialog.h"
35     #include "wx/settings.h"
36     #include "wx/dcclient.h"
37     #include "wx/mdi.h"
38     #include "wx/panel.h"
39     #include "wx/log.h"
40     #include "wx/toolbar.h"
41     #include "wx/statusbr.h"
42     #include "wx/menuitem.h"
43 #endif // WX_PRECOMP
44 
45 #include "wx/msw/private.h"
46 
47 #if defined(__POCKETPC__) || defined(__SMARTPHONE__)
48     #include <ole2.h>
49     #include <aygshell.h>
50     #include "wx/msw/winundef.h"
51 #endif
52 
53 #include "wx/generic/statusbr.h"
54 
55 #ifdef __WXUNIVERSAL__
56     #include "wx/univ/theme.h"
57     #include "wx/univ/colschem.h"
58 #endif // __WXUNIVERSAL__
59 
60 // ----------------------------------------------------------------------------
61 // globals
62 // ----------------------------------------------------------------------------
63 
64 #if wxUSE_MENUS_NATIVE
65     extern wxMenu *wxCurrentPopupMenu;
66 #endif // wxUSE_MENUS_NATIVE
67 
68 // ----------------------------------------------------------------------------
69 // event tables
70 // ----------------------------------------------------------------------------
71 
72 BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
73     EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
74 END_EVENT_TABLE()
75 
76 #if wxUSE_EXTENDED_RTTI
77 WX_DEFINE_FLAGS( wxFrameStyle )
78 
79 wxBEGIN_FLAGS( wxFrameStyle )
80     // new style border flags, we put them first to
81     // use them for streaming out
82     wxFLAGS_MEMBER(wxBORDER_SIMPLE)
83     wxFLAGS_MEMBER(wxBORDER_SUNKEN)
84     wxFLAGS_MEMBER(wxBORDER_DOUBLE)
85     wxFLAGS_MEMBER(wxBORDER_RAISED)
86     wxFLAGS_MEMBER(wxBORDER_STATIC)
87     wxFLAGS_MEMBER(wxBORDER_NONE)
88 
89     // old style border flags
90     wxFLAGS_MEMBER(wxSIMPLE_BORDER)
91     wxFLAGS_MEMBER(wxSUNKEN_BORDER)
92     wxFLAGS_MEMBER(wxDOUBLE_BORDER)
93     wxFLAGS_MEMBER(wxRAISED_BORDER)
94     wxFLAGS_MEMBER(wxSTATIC_BORDER)
95     wxFLAGS_MEMBER(wxBORDER)
96 
97     // standard window styles
98     wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
99     wxFLAGS_MEMBER(wxCLIP_CHILDREN)
100     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
101     wxFLAGS_MEMBER(wxWANTS_CHARS)
102     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
103     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
104     wxFLAGS_MEMBER(wxVSCROLL)
105     wxFLAGS_MEMBER(wxHSCROLL)
106 
107     // frame styles
108     wxFLAGS_MEMBER(wxSTAY_ON_TOP)
109     wxFLAGS_MEMBER(wxCAPTION)
110 #if WXWIN_COMPATIBILITY_2_6
111     wxFLAGS_MEMBER(wxTHICK_FRAME)
112 #endif // WXWIN_COMPATIBILITY_2_6
113     wxFLAGS_MEMBER(wxSYSTEM_MENU)
114     wxFLAGS_MEMBER(wxRESIZE_BORDER)
115 #if WXWIN_COMPATIBILITY_2_6
116     wxFLAGS_MEMBER(wxRESIZE_BOX)
117 #endif // WXWIN_COMPATIBILITY_2_6
118     wxFLAGS_MEMBER(wxCLOSE_BOX)
119     wxFLAGS_MEMBER(wxMAXIMIZE_BOX)
120     wxFLAGS_MEMBER(wxMINIMIZE_BOX)
121 
122     wxFLAGS_MEMBER(wxFRAME_TOOL_WINDOW)
123     wxFLAGS_MEMBER(wxFRAME_FLOAT_ON_PARENT)
124 
125     wxFLAGS_MEMBER(wxFRAME_SHAPED)
126 
127 wxEND_FLAGS( wxFrameStyle )
128 
129 IMPLEMENT_DYNAMIC_CLASS_XTI(wxFrame, wxTopLevelWindow,"wx/frame.h")
130 
131 wxBEGIN_PROPERTIES_TABLE(wxFrame)
132     wxEVENT_PROPERTY( Menu , wxEVT_COMMAND_MENU_SELECTED , wxCommandEvent)
133 
134     wxPROPERTY( Title,wxString, SetTitle, GetTitle, wxString() , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
135     wxPROPERTY_FLAGS( WindowStyle , wxFrameStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
136     wxPROPERTY( MenuBar , wxMenuBar * , SetMenuBar , GetMenuBar , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
137 wxEND_PROPERTIES_TABLE()
138 
139 wxBEGIN_HANDLERS_TABLE(wxFrame)
140 wxEND_HANDLERS_TABLE()
141 
142 wxCONSTRUCTOR_6( wxFrame , wxWindow* , Parent , wxWindowID , Id , wxString , Title , wxPoint , Position , wxSize , Size , long , WindowStyle)
143 
144 #else
145 IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxTopLevelWindow)
146 #endif
147 
148 // ============================================================================
149 // implementation
150 // ============================================================================
151 
152 // ----------------------------------------------------------------------------
153 // static class members
154 // ----------------------------------------------------------------------------
155 
156 #if wxUSE_STATUSBAR
157     #if wxUSE_NATIVE_STATUSBAR
158         bool wxFrame::m_useNativeStatusBar = true;
159     #else
160         bool wxFrame::m_useNativeStatusBar = false;
161     #endif
162 #endif // wxUSE_NATIVE_STATUSBAR
163 
164 // ----------------------------------------------------------------------------
165 // creation/destruction
166 // ----------------------------------------------------------------------------
167 
Init()168 void wxFrame::Init()
169 {
170 #if wxUSE_MENUS
171     m_hMenu = NULL;
172 #endif // wxUSE_MENUS
173 
174 #if wxUSE_TOOLTIPS
175     m_hwndToolTip = 0;
176 #endif
177 
178     m_wasMinimized = false;
179 }
180 
Create(wxWindow * parent,wxWindowID id,const wxString & title,const wxPoint & pos,const wxSize & size,long style,const wxString & name)181 bool wxFrame::Create(wxWindow *parent,
182                      wxWindowID id,
183                      const wxString& title,
184                      const wxPoint& pos,
185                      const wxSize& size,
186                      long style,
187                      const wxString& name)
188 {
189     if ( !wxTopLevelWindow::Create(parent, id, title, pos, size, style, name) )
190         return false;
191 
192     SetOwnBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
193 
194 #if defined(__SMARTPHONE__)
195     SetLeftMenu(wxID_EXIT, _("Done"));
196 #endif
197 
198 #if wxUSE_ACCEL && defined(__POCKETPC__)
199     // The guidelines state that Ctrl+Q should quit the app.
200     // Let's define an accelerator table to send wxID_EXIT.
201     wxAcceleratorEntry entries[1];
202     entries[0].Set(wxACCEL_CTRL,   'Q',         wxID_EXIT);
203     wxAcceleratorTable accel(1, entries);
204     SetAcceleratorTable(accel);
205 #endif // wxUSE_ACCEL && __POCKETPC__
206 
207     return true;
208 }
209 
~wxFrame()210 wxFrame::~wxFrame()
211 {
212     m_isBeingDeleted = true;
213     DeleteAllBars();
214 }
215 
216 // ----------------------------------------------------------------------------
217 // wxFrame client size calculations
218 // ----------------------------------------------------------------------------
219 
DoSetClientSize(int width,int height)220 void wxFrame::DoSetClientSize(int width, int height)
221 {
222     // leave enough space for the status bar if we have (and show) it
223 #if wxUSE_STATUSBAR
224     wxStatusBar *statbar = GetStatusBar();
225     if ( statbar && statbar->IsShown() )
226     {
227         height += statbar->GetSize().y;
228     }
229 #endif // wxUSE_STATUSBAR
230 
231     // call GetClientAreaOrigin() to take the toolbar into account
232     wxPoint pt = GetClientAreaOrigin();
233     width += pt.x;
234     height += pt.y;
235 
236 #if wxUSE_TOOLBAR
237     wxToolBar * const toolbar = GetToolBar();
238     if ( toolbar )
239     {
240         if ( toolbar->HasFlag(wxTB_RIGHT | wxTB_BOTTOM) )
241         {
242             const wxSize sizeTB = toolbar->GetSize();
243             if ( toolbar->HasFlag(wxTB_RIGHT) )
244                 width -= sizeTB.x;
245             else // wxTB_BOTTOM
246                 height -= sizeTB.y;
247         }
248         //else: toolbar already taken into account by GetClientAreaOrigin()
249     }
250 #endif // wxUSE_TOOLBAR
251 
252     wxTopLevelWindow::DoSetClientSize(width, height);
253 }
254 
255 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
DoGetClientSize(int * x,int * y) const256 void wxFrame::DoGetClientSize(int *x, int *y) const
257 {
258     wxTopLevelWindow::DoGetClientSize(x, y);
259 
260     // account for the possible toolbar
261     wxPoint pt = GetClientAreaOrigin();
262     if ( x )
263         *x -= pt.x;
264 
265     if ( y )
266         *y -= pt.y;
267 
268 #if wxUSE_TOOLBAR
269     wxToolBar * const toolbar = GetToolBar();
270     if ( toolbar )
271     {
272         if ( toolbar->HasFlag(wxTB_RIGHT | wxTB_BOTTOM) )
273         {
274             const wxSize sizeTB = toolbar->GetSize();
275             if ( toolbar->HasFlag(wxTB_RIGHT) )
276             {
277                 if ( x )
278                     *x -= sizeTB.x;
279             }
280             else // wxTB_BOTTOM
281             {
282                 if ( y )
283                     *y -= sizeTB.y;
284             }
285         }
286         //else: toolbar already taken into account by GetClientAreaOrigin()
287     }
288 #endif // wxUSE_TOOLBAR
289 
290 #if wxUSE_STATUSBAR
291     // adjust client area height to take the status bar into account
292     if ( y )
293     {
294         wxStatusBar *statbar = GetStatusBar();
295         if ( statbar && statbar->IsShown() )
296         {
297             *y -= statbar->GetClientSize().y;
298         }
299     }
300 #endif // wxUSE_STATUSBAR
301 }
302 
303 // ----------------------------------------------------------------------------
304 // wxFrame: various geometry-related functions
305 // ----------------------------------------------------------------------------
306 
Raise()307 void wxFrame::Raise()
308 {
309     ::SetForegroundWindow(GetHwnd());
310 }
311 
312 // generate an artificial resize event
SendSizeEvent()313 void wxFrame::SendSizeEvent()
314 {
315     if ( !m_iconized )
316     {
317         RECT r = wxGetWindowRect(GetHwnd());
318 
319         (void)::PostMessage(GetHwnd(), WM_SIZE,
320                             IsMaximized() ? SIZE_MAXIMIZED : SIZE_RESTORED,
321                             MAKELPARAM(r.right - r.left, r.bottom - r.top));
322     }
323 }
324 
325 #if wxUSE_STATUSBAR
OnCreateStatusBar(int number,long style,wxWindowID id,const wxString & name)326 wxStatusBar *wxFrame::OnCreateStatusBar(int number,
327                                         long style,
328                                         wxWindowID id,
329                                         const wxString& name)
330 {
331     wxStatusBar *statusBar wxDUMMY_INITIALIZE(NULL);
332 
333 #if wxUSE_NATIVE_STATUSBAR
334     if ( !UsesNativeStatusBar() )
335     {
336         statusBar = (wxStatusBar *)new wxStatusBarGeneric(this, id, style);
337     }
338     else
339 #endif
340     {
341         statusBar = new wxStatusBar(this, id, style, name);
342     }
343 
344     statusBar->SetFieldsCount(number);
345 
346     return statusBar;
347 }
348 
PositionStatusBar()349 void wxFrame::PositionStatusBar()
350 {
351     if ( !m_frameStatusBar || !m_frameStatusBar->IsShown() )
352         return;
353 
354     int w, h;
355     GetClientSize(&w, &h);
356 
357     int sw, sh;
358     m_frameStatusBar->GetSize(&sw, &sh);
359 
360     int x = 0;
361 #if wxUSE_TOOLBAR
362     wxToolBar * const toolbar = GetToolBar();
363     if ( toolbar && !toolbar->HasFlag(wxTB_TOP) )
364     {
365         const wxSize sizeTB = toolbar->GetSize();
366 
367         if ( toolbar->HasFlag(wxTB_LEFT | wxTB_RIGHT) )
368         {
369             if ( toolbar->HasFlag(wxTB_LEFT) )
370                 x -= sizeTB.x;
371 
372             w += sizeTB.x;
373         }
374         else // wxTB_BOTTOM
375         {
376             // we need to position the status bar below the toolbar
377             h += sizeTB.y;
378         }
379     }
380     //else: no adjustments necessary for the toolbar on top
381 #endif // wxUSE_TOOLBAR
382 
383     // Since we wish the status bar to be directly under the client area,
384     // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
385     m_frameStatusBar->SetSize(x, h, w, sh);
386 }
387 
388 #endif // wxUSE_STATUSBAR
389 
390 #if wxUSE_MENUS_NATIVE
391 
AttachMenuBar(wxMenuBar * menubar)392 void wxFrame::AttachMenuBar(wxMenuBar *menubar)
393 {
394 #if defined(__SMARTPHONE__) && defined(__WXWINCE__)
395 
396     wxMenu *autoMenu = NULL;
397 
398     if( menubar->GetMenuCount() == 1 )
399     {
400         autoMenu = wxTopLevelWindowMSW::ButtonMenu::DuplicateMenu(menubar->GetMenu(0));
401         SetRightMenu(wxID_ANY, menubar->GetLabelTop(0), autoMenu);
402     }
403     else
404     {
405         autoMenu = new wxMenu;
406 
407         for( size_t n = 0; n < menubar->GetMenuCount(); n++ )
408         {
409             wxMenu *item = menubar->GetMenu(n);
410             wxString label = menubar->GetLabelTop(n);
411             wxMenu *new_item = wxTopLevelWindowMSW::ButtonMenu::DuplicateMenu(item);
412             autoMenu->Append(wxID_ANY, label, new_item);
413         }
414 
415         SetRightMenu(wxID_ANY, _("Menu"), autoMenu);
416     }
417 
418 #elif defined(WINCE_WITHOUT_COMMANDBAR)
419     if (!GetToolBar())
420     {
421         wxToolMenuBar* toolBar = new wxToolMenuBar(this, wxID_ANY,
422                          wxDefaultPosition, wxDefaultSize,
423                          wxBORDER_NONE | wxTB_HORIZONTAL,
424                          wxToolBarNameStr, menubar);
425         SetToolBar(toolBar);
426         menubar->SetToolBar(toolBar);
427     }
428 
429     // When the main window is created using CW_USEDEFAULT the height of the
430     // menubar is not taken into account, so we resize it afterwards if a
431     // menubar is present
432     HWND hwndMenuBar = SHFindMenuBar(GetHwnd());
433     if ( hwndMenuBar )
434     {
435         RECT mbRect;
436         ::GetWindowRect(hwndMenuBar, &mbRect);
437         const int menuHeight = mbRect.bottom - mbRect.top;
438 
439         RECT rc;
440         ::GetWindowRect(GetHwnd(), &rc);
441         // adjust for menu / titlebar height
442         rc.bottom -= (2*menuHeight-1);
443 
444         ::MoveWindow(GetHwnd(), rc.left, rc.top, rc.right, rc.bottom, FALSE);
445     }
446 #endif
447 
448     wxFrameBase::AttachMenuBar(menubar);
449 
450     if ( !menubar )
451     {
452         // actually remove the menu from the frame
453         m_hMenu = (WXHMENU)0;
454         InternalSetMenuBar();
455     }
456     else // set new non NULL menu bar
457     {
458 #if !defined(__WXWINCE__) || defined(WINCE_WITH_COMMANDBAR)
459         // Can set a menubar several times.
460         if ( menubar->GetHMenu() )
461         {
462             m_hMenu = menubar->GetHMenu();
463         }
464         else // no HMENU yet
465         {
466             m_hMenu = menubar->Create();
467 
468             if ( !m_hMenu )
469             {
470                 wxFAIL_MSG( _T("failed to create menu bar") );
471                 return;
472             }
473         }
474 #endif
475         InternalSetMenuBar();
476     }
477 }
478 
InternalSetMenuBar()479 void wxFrame::InternalSetMenuBar()
480 {
481 #if defined(__WXMICROWIN__) || defined(__WXWINCE__)
482     // Nothing
483 #else
484     if ( !::SetMenu(GetHwnd(), (HMENU)m_hMenu) )
485     {
486         wxLogLastError(wxT("SetMenu"));
487     }
488 #endif
489 }
490 
491 #endif // wxUSE_MENUS_NATIVE
492 
493 // Responds to colour changes, and passes event on to children.
OnSysColourChanged(wxSysColourChangedEvent & event)494 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
495 {
496     SetOwnBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
497     Refresh();
498 
499 #if wxUSE_STATUSBAR
500     if ( m_frameStatusBar )
501     {
502         wxSysColourChangedEvent event2;
503         event2.SetEventObject( m_frameStatusBar );
504         m_frameStatusBar->GetEventHandler()->ProcessEvent(event2);
505     }
506 #endif // wxUSE_STATUSBAR
507 
508     // Propagate the event to the non-top-level children
509     wxWindow::OnSysColourChanged(event);
510 }
511 
512 // Pass true to show full screen, false to restore.
ShowFullScreen(bool show,long style)513 bool wxFrame::ShowFullScreen(bool show, long style)
514 {
515     // TODO-CE: add support for CE
516 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
517     if ( IsFullScreen() == show )
518         return false;
519 
520     if (show)
521     {
522         // zap the toolbar, menubar, and statusbar if needed
523         //
524         // TODO: hide commandbar for WINCE_WITH_COMMANDBAR
525 #if wxUSE_TOOLBAR
526         wxToolBar *theToolBar = GetToolBar();
527 
528         if ((style & wxFULLSCREEN_NOTOOLBAR) && theToolBar)
529         {
530             if ( theToolBar->IsShown() )
531             {
532                 theToolBar->SetSize(wxDefaultCoord,0);
533                 theToolBar->Show(false);
534             }
535             else // prevent it from being restored later
536             {
537                 style &= ~wxFULLSCREEN_NOTOOLBAR;
538             }
539         }
540 #endif // wxUSE_TOOLBAR
541 
542         if (style & wxFULLSCREEN_NOMENUBAR)
543             SetMenu((HWND)GetHWND(), (HMENU) NULL);
544 
545 #if wxUSE_STATUSBAR
546         wxStatusBar *theStatusBar = GetStatusBar();
547 
548         // Save the number of fields in the statusbar
549         if ((style & wxFULLSCREEN_NOSTATUSBAR) && theStatusBar)
550         {
551             if ( theStatusBar->IsShown() )
552                 theStatusBar->Show(false);
553             else
554                 style &= ~wxFULLSCREEN_NOSTATUSBAR;
555         }
556 #endif // wxUSE_STATUSBAR
557     }
558     else // restore to normal
559     {
560         // restore the toolbar, menubar, and statusbar if we had hid them
561 #if wxUSE_TOOLBAR
562         wxToolBar *theToolBar = GetToolBar();
563 
564         if ((m_fsStyle & wxFULLSCREEN_NOTOOLBAR) && theToolBar)
565         {
566             theToolBar->Show(true);
567         }
568 #endif // wxUSE_TOOLBAR
569 
570         if (m_fsStyle & wxFULLSCREEN_NOMENUBAR)
571         {
572             WXHMENU menu = m_hMenu;
573 
574 #if wxUSE_MDI_ARCHITECTURE
575             wxMDIParentFrame *frame = wxDynamicCast(this, wxMDIParentFrame);
576             if (frame)
577             {
578                 wxMDIChildFrame *child = frame->GetActiveChild();
579                 if (child)
580                 {
581                     menu = child->GetWinMenu();
582                 }
583             }
584 #endif // wxUSE_MDI_ARCHITECTURE
585 
586             if (menu)
587             {
588                 ::SetMenu(GetHwnd(), (HMENU)menu);
589             }
590         }
591 
592 #if wxUSE_STATUSBAR
593         wxStatusBar *theStatusBar = GetStatusBar();
594 
595         if ((m_fsStyle & wxFULLSCREEN_NOSTATUSBAR) && theStatusBar)
596         {
597             theStatusBar->Show(true);
598             PositionStatusBar();
599         }
600 #endif // wxUSE_STATUSBAR
601     }
602 #endif // !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
603 
604     return wxFrameBase::ShowFullScreen(show, style);
605 }
606 
607 // ----------------------------------------------------------------------------
608 // tool/status bar stuff
609 // ----------------------------------------------------------------------------
610 
611 #if wxUSE_TOOLBAR
612 
CreateToolBar(long style,wxWindowID id,const wxString & name)613 wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
614 {
615 #if defined(WINCE_WITHOUT_COMMANDBAR)
616     // We may already have a toolbar from calling SetMenuBar.
617     if (GetToolBar())
618         return GetToolBar();
619 #endif
620     if ( wxFrameBase::CreateToolBar(style, id, name) )
621     {
622         PositionToolBar();
623     }
624 
625     return m_frameToolBar;
626 }
627 
PositionToolBar()628 void wxFrame::PositionToolBar()
629 {
630     // TODO: we want to do something different in WinCE, because the toolbar
631     //       should be associated with the commandbar, instead of being
632     //       independent window.
633 #if !defined(WINCE_WITHOUT_COMMANDBAR)
634     wxToolBar *toolbar = GetToolBar();
635     if ( toolbar && toolbar->IsShown() )
636     {
637         // don't call our (or even wxTopLevelWindow) version because we want
638         // the real (full) client area size, not excluding the tool/status bar
639         int width, height;
640         wxWindow::DoGetClientSize(&width, &height);
641 
642 #if wxUSE_STATUSBAR
643         wxStatusBar *statbar = GetStatusBar();
644         if ( statbar && statbar->IsShown() )
645         {
646             height -= statbar->GetClientSize().y;
647         }
648 #endif // wxUSE_STATUSBAR
649 
650         int tx, ty, tw, th;
651         toolbar->GetPosition( &tx, &ty );
652         toolbar->GetSize( &tw, &th );
653 
654         int x = 0, y = 0;
655         if ( toolbar->HasFlag(wxTB_BOTTOM) )
656         {
657             x = 0;
658             y = height - th;
659         }
660         else if ( toolbar->HasFlag(wxTB_RIGHT) )
661         {
662             x = width - tw;
663             y = 0;
664         }
665         else // left or top
666         {
667             x = 0;
668             y = 0;
669         }
670 
671 #if defined(WINCE_WITH_COMMANDBAR)
672         // We're using a commandbar - so we have to allow for it.
673         if (GetMenuBar() && GetMenuBar()->GetCommandBar())
674         {
675             RECT rect;
676             ::GetWindowRect((HWND) GetMenuBar()->GetCommandBar(), &rect);
677             y = rect.bottom - rect.top;
678         }
679 #endif // WINCE_WITH_COMMANDBAR
680 
681         if ( toolbar->HasFlag(wxTB_BOTTOM) )
682         {
683             if ( ty < 0 && ( -ty == th ) )
684                 ty = height - th;
685             if ( tx < 0 && (-tx == tw ) )
686                 tx = 0;
687         }
688         else if ( toolbar->HasFlag(wxTB_RIGHT) )
689         {
690             if( ty < 0 && ( -ty == th ) )
691                 ty = 0;
692             if( tx < 0 && ( -tx == tw ) )
693                 tx = width - tw;
694         }
695         else // left or top
696         {
697             if (ty < 0 && (-ty == th))
698                 ty = 0;
699             if (tx < 0 && (-tx == tw))
700                 tx = 0;
701         }
702 
703         int desiredW = tw;
704         int desiredH = th;
705 
706         if ( toolbar->IsVertical() )
707         {
708             desiredH = height;
709         }
710         else
711         {
712             desiredW = width;
713         }
714 
715         // use the 'real' MSW position here, don't offset relativly to the
716         // client area origin
717 
718         // Optimise such that we don't have to always resize the toolbar
719         // when the frame changes, otherwise we'll get a lot of flicker.
720         bool heightChanging wxDUMMY_INITIALIZE(true);
721         bool widthChanging wxDUMMY_INITIALIZE(true);
722 
723         if ( toolbar->IsVertical() )
724         {
725             // It's OK if the current height is greater than what can be shown.
726             heightChanging = (desiredH > th) ;
727             widthChanging = (desiredW != tw) ;
728 
729             // The next time around, we may not have to set the size
730             if (heightChanging)
731                 desiredH = desiredH + 200;
732         }
733         else
734         {
735             // It's OK if the current width is greater than what can be shown.
736             widthChanging = (desiredW > tw) ;
737             heightChanging = (desiredH != th) ;
738 
739             // The next time around, we may not have to set the size
740             if (widthChanging)
741                 desiredW = desiredW + 200;
742         }
743 
744         if (tx != 0 || ty != 0 || widthChanging || heightChanging)
745             toolbar->SetSize(x, y, desiredW, desiredH, wxSIZE_NO_ADJUSTMENTS);
746 
747     }
748 #endif // !WINCE_WITH_COMMANDBAR
749 }
750 
751 #endif // wxUSE_TOOLBAR
752 
753 // ----------------------------------------------------------------------------
754 // frame state (iconized/maximized/...)
755 // ----------------------------------------------------------------------------
756 
757 // propagate our state change to all child frames: this allows us to emulate X
758 // Windows behaviour where child frames float independently of the parent one
759 // on the desktop, but are iconized/restored with it
IconizeChildFrames(bool bIconize)760 void wxFrame::IconizeChildFrames(bool bIconize)
761 {
762     m_iconized = bIconize;
763 
764     for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
765           node;
766           node = node->GetNext() )
767     {
768         wxWindow *win = node->GetData();
769 
770         // iconizing the frames with this style under Win95 shell puts them at
771         // the bottom of the screen (as the MDI children) instead of making
772         // them appear in the taskbar because they are, by virtue of this
773         // style, not managed by the taskbar - instead leave Windows take care
774         // of them
775         if ( win->GetWindowStyle() & wxFRAME_TOOL_WINDOW )
776             continue;
777 
778         // the child MDI frames are a special case and should not be touched by
779         // the parent frame - instead, they are managed by the user
780         wxFrame *frame = wxDynamicCast(win, wxFrame);
781         if ( frame
782 #if wxUSE_MDI_ARCHITECTURE
783                 && !frame->IsMDIChild()
784 #endif // wxUSE_MDI_ARCHITECTURE
785            )
786         {
787             // we don't want to restore the child frames which had been
788             // iconized even before we were iconized, so save the child frame
789             // status when iconizing the parent frame and check it when
790             // restoring it
791             if ( bIconize )
792             {
793                 frame->m_wasMinimized = frame->IsIconized();
794             }
795 
796             // note that we shouldn't touch the hidden frames neither because
797             // iconizing/restoring them would show them as a side effect
798             if ( !frame->m_wasMinimized && frame->IsShown() )
799                 frame->Iconize(bIconize);
800         }
801     }
802 }
803 
GetDefaultIcon() const804 WXHICON wxFrame::GetDefaultIcon() const
805 {
806     // we don't have any standard icons (any more)
807     return (WXHICON)0;
808 }
809 
810 // ===========================================================================
811 // message processing
812 // ===========================================================================
813 
814 // ---------------------------------------------------------------------------
815 // preprocessing
816 // ---------------------------------------------------------------------------
817 
MSWDoTranslateMessage(wxFrame * frame,WXMSG * pMsg)818 bool wxFrame::MSWDoTranslateMessage(wxFrame *frame, WXMSG *pMsg)
819 {
820     if ( wxWindow::MSWTranslateMessage(pMsg) )
821         return true;
822 
823 #if wxUSE_MENUS && wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
824     // try the menu bar accels
825     wxMenuBar *menuBar = GetMenuBar();
826     if ( menuBar )
827     {
828         const wxAcceleratorTable& acceleratorTable = menuBar->GetAccelTable();
829         return acceleratorTable.Translate(frame, pMsg);
830     }
831 #endif // wxUSE_MENUS && wxUSE_ACCEL
832 
833     return false;
834 }
835 
836 // ---------------------------------------------------------------------------
837 // our private (non virtual) message handlers
838 // ---------------------------------------------------------------------------
839 
HandlePaint()840 bool wxFrame::HandlePaint()
841 {
842     RECT rect;
843     if ( ::GetUpdateRect(GetHwnd(), &rect, FALSE) )
844     {
845 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
846         if ( m_iconized )
847         {
848             const wxIcon& icon = GetIcon();
849             HICON hIcon = icon.Ok() ? GetHiconOf(icon)
850                                     : (HICON)GetDefaultIcon();
851 
852             // Hold a pointer to the dc so long as the OnPaint() message
853             // is being processed
854             PAINTSTRUCT ps;
855             HDC hdc = ::BeginPaint(GetHwnd(), &ps);
856 
857             // Erase background before painting or we get white background
858             MSWDefWindowProc(WM_ICONERASEBKGND, (WORD)(LONG)ps.hdc, 0L);
859 
860             if ( hIcon )
861             {
862                 RECT rect;
863                 ::GetClientRect(GetHwnd(), &rect);
864 
865                 // FIXME: why hardcoded?
866                 static const int icon_width = 32;
867                 static const int icon_height = 32;
868 
869                 int icon_x = (int)((rect.right - icon_width)/2);
870                 int icon_y = (int)((rect.bottom - icon_height)/2);
871 
872                 ::DrawIcon(hdc, icon_x, icon_y, hIcon);
873             }
874 
875             ::EndPaint(GetHwnd(), &ps);
876 
877             return true;
878         }
879         else
880  #endif
881         {
882             return wxWindow::HandlePaint();
883         }
884     }
885     else
886     {
887         // nothing to paint - processed
888         return true;
889     }
890 }
891 
HandleSize(int WXUNUSED (x),int WXUNUSED (y),WXUINT id)892 bool wxFrame::HandleSize(int WXUNUSED(x), int WXUNUSED(y), WXUINT id)
893 {
894 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
895     switch ( id )
896     {
897         case SIZE_RESTORED:
898         case SIZE_MAXIMIZED:
899             // only do it it if we were iconized before, otherwise resizing the
900             // parent frame has a curious side effect of bringing it under it's
901             // children
902             if ( !m_iconized )
903                 break;
904 
905             // restore all child frames too
906             IconizeChildFrames(false);
907 
908             (void)SendIconizeEvent(false);
909             break;
910 
911         case SIZE_MINIMIZED:
912             // iconize all child frames too
913             IconizeChildFrames(true);
914             break;
915     }
916 #else
917     wxUnusedVar(id);
918 #endif // !__WXWINCE__
919 
920     if ( !m_iconized )
921     {
922 #if wxUSE_STATUSBAR
923         PositionStatusBar();
924 #endif // wxUSE_STATUSBAR
925 
926 #if wxUSE_TOOLBAR
927         PositionToolBar();
928 #endif // wxUSE_TOOLBAR
929 
930 #if defined(WINCE_WITH_COMMANDBAR)
931         // Position the menu command bar
932         if (GetMenuBar() && GetMenuBar()->GetCommandBar())
933         {
934             RECT rect;
935             ::GetWindowRect((HWND) GetMenuBar()->GetCommandBar(), &rect);
936             wxSize clientSz = GetClientSize();
937 
938             if ( !::MoveWindow((HWND) GetMenuBar()->GetCommandBar(), 0, 0, clientSz.x, rect.bottom - rect.top, true ) )
939             {
940                 wxLogLastError(wxT("MoveWindow"));
941             }
942 
943         }
944 #endif // WINCE_WITH_COMMANDBAR
945     }
946 
947     // call the base class version to generate the appropriate events
948     return false;
949 }
950 
HandleCommand(WXWORD id,WXWORD cmd,WXHWND control)951 bool wxFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
952 {
953     if ( control )
954     {
955         // In case it's e.g. a toolbar.
956         wxWindow *win = wxFindWinFromHandle(control);
957         if ( win )
958             return win->MSWCommand(cmd, id);
959     }
960 
961 #if defined(WINCE_WITHOUT_COMMANDBAR)
962     if (GetToolBar() && GetToolBar()->FindById(id))
963         return GetToolBar()->MSWCommand(cmd, id);
964 #endif
965 
966     // handle here commands from menus and accelerators for our menu bar items,
967     // all the rest is handled by wxWindow itself
968     if ( !control && (cmd == 0 /* menu */ || cmd == 1 /* accel */) )
969     {
970 #if wxUSE_MENUS_NATIVE
971         if ( !wxCurrentPopupMenu )
972 #endif // wxUSE_MENUS_NATIVE
973         {
974             if ( GetMenuBar() && ProcessCommand(id) )
975                 return true;
976         }
977     }
978 
979     return wxFrameBase::HandleCommand(id, cmd, control);
980 }
981 
HandleMenuSelect(WXWORD nItem,WXWORD flags,WXHMENU hMenu)982 bool wxFrame::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu)
983 {
984     int item;
985     if ( flags == 0xFFFF && hMenu == 0 )
986     {
987         // menu was removed from screen
988         item = -1;
989     }
990 #ifndef __WXMICROWIN__
991     else if ( !(flags & MF_POPUP) && !(flags & MF_SEPARATOR) )
992     {
993         item = nItem;
994     }
995 #endif
996     else
997     {
998         // don't give hints for separators (doesn't make sense) nor for the
999         // items opening popup menus (they don't have them anyhow) but do clear
1000         // the status line - otherwise, we would be left with the help message
1001         // for the previous item which doesn't apply any more
1002         DoGiveHelp(wxEmptyString, false);
1003 
1004         return false;
1005     }
1006 
1007     wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item);
1008     event.SetEventObject(this);
1009 
1010     return GetEventHandler()->ProcessEvent(event);
1011 }
1012 
HandleMenuLoop(const wxEventType & evtType,WXWORD isPopup)1013 bool wxFrame::HandleMenuLoop(const wxEventType& evtType, WXWORD isPopup)
1014 {
1015     // we don't have the menu id here, so we use the id to specify if the event
1016     // was from a popup menu or a normal one
1017     wxMenuEvent event(evtType, isPopup ? -1 : 0);
1018     event.SetEventObject(this);
1019 
1020     return GetEventHandler()->ProcessEvent(event);
1021 }
1022 
1023 // ---------------------------------------------------------------------------
1024 // the window proc for wxFrame
1025 // ---------------------------------------------------------------------------
1026 
MSWWindowProc(WXUINT message,WXWPARAM wParam,WXLPARAM lParam)1027 WXLRESULT wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
1028 {
1029     WXLRESULT rc = 0;
1030     bool processed = false;
1031 
1032     switch ( message )
1033     {
1034         case WM_CLOSE:
1035             // if we can't close, tell the system that we processed the
1036             // message - otherwise it would close us
1037             processed = !Close();
1038             break;
1039 
1040         case WM_SIZE:
1041             processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
1042             break;
1043 
1044         case WM_COMMAND:
1045             {
1046                 WORD id, cmd;
1047                 WXHWND hwnd;
1048                 UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam,
1049                               &id, &hwnd, &cmd);
1050 
1051                 HandleCommand(id, cmd, (WXHWND)hwnd);
1052 
1053                 // don't pass WM_COMMAND to the base class as it would generate
1054                 // another wxCommandEvent which would result in its handler
1055                 // being called twice if it uses event.Skip()
1056                 processed = true;
1057             }
1058             break;
1059 
1060         case WM_PAINT:
1061             processed = HandlePaint();
1062             break;
1063 
1064         case WM_INITMENUPOPUP:
1065             processed = HandleInitMenuPopup((WXHMENU) wParam);
1066             break;
1067 
1068 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1069         case WM_MENUSELECT:
1070             {
1071                 WXWORD item, flags;
1072                 WXHMENU hmenu;
1073                 UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
1074 
1075                 processed = HandleMenuSelect(item, flags, hmenu);
1076             }
1077             break;
1078 
1079         case WM_EXITMENULOOP:
1080             processed = HandleMenuLoop(wxEVT_MENU_CLOSE, (WXWORD)wParam);
1081             break;
1082 
1083         case WM_QUERYDRAGICON:
1084             {
1085                 const wxIcon& icon = GetIcon();
1086                 HICON hIcon = icon.Ok() ? GetHiconOf(icon)
1087                                         : (HICON)GetDefaultIcon();
1088                 rc = (long)hIcon;
1089                 processed = rc != 0;
1090             }
1091             break;
1092 #endif // !__WXMICROWIN__
1093     }
1094 
1095     if ( !processed )
1096         rc = wxFrameBase::MSWWindowProc(message, wParam, lParam);
1097 
1098     return rc;
1099 }
1100 
1101 // handle WM_INITMENUPOPUP message
HandleInitMenuPopup(WXHMENU hMenu)1102 bool wxFrame::HandleInitMenuPopup(WXHMENU hMenu)
1103 {
1104     wxMenu* menu = NULL;
1105     if (GetMenuBar())
1106     {
1107         int nCount = GetMenuBar()->GetMenuCount();
1108         for (int n = 0; n < nCount; n++)
1109         {
1110             if (GetMenuBar()->GetMenu(n)->GetHMenu() == hMenu)
1111             {
1112                 menu = GetMenuBar()->GetMenu(n);
1113                 break;
1114             }
1115         }
1116     }
1117 
1118     wxMenuEvent event(wxEVT_MENU_OPEN, 0, menu);
1119     event.SetEventObject(this);
1120 
1121     return GetEventHandler()->ProcessEvent(event);
1122 }
1123 
1124 // ----------------------------------------------------------------------------
1125 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
1126 // from the client area, so the client area is what's really available for the
1127 // frame contents
1128 // ----------------------------------------------------------------------------
1129 
1130 // get the origin of the client area in the client coordinates
GetClientAreaOrigin() const1131 wxPoint wxFrame::GetClientAreaOrigin() const
1132 {
1133     wxPoint pt = wxTopLevelWindow::GetClientAreaOrigin();
1134 
1135 #if wxUSE_TOOLBAR && !defined(__WXUNIVERSAL__) && \
1136   (!defined(__WXWINCE__) || (_WIN32_WCE >= 400 && !defined(__POCKETPC__) && !defined(__SMARTPHONE__)))
1137     wxToolBar * const toolbar = GetToolBar();
1138     if ( toolbar && toolbar->IsShown() )
1139     {
1140         const wxSize sizeTB = toolbar->GetSize();
1141 
1142         if ( toolbar->HasFlag(wxTB_TOP) )
1143         {
1144             pt.y += sizeTB.y;
1145         }
1146         else if ( toolbar->HasFlag(wxTB_LEFT) )
1147         {
1148             pt.x += sizeTB.x;
1149         }
1150     }
1151 #endif // wxUSE_TOOLBAR
1152 
1153 #if defined(WINCE_WITH_COMMANDBAR)
1154     if (GetMenuBar() && GetMenuBar()->GetCommandBar())
1155     {
1156         RECT rect;
1157         ::GetWindowRect((HWND) GetMenuBar()->GetCommandBar(), &rect);
1158         pt.y += (rect.bottom - rect.top);
1159     }
1160 #endif
1161 
1162     return pt;
1163 }
1164