1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "frame.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
36 #include "wx/dialog.h"
37 #include "wx/settings.h"
38 #include "wx/dcclient.h"
43 #include "wx/msw/private.h"
50 #include "wx/statusbr.h"
51 #include "wx/generic/statusbr.h"
52 #endif // wxUSE_STATUSBAR
55 #include "wx/toolbar.h"
56 #endif // wxUSE_TOOLBAR
58 #include "wx/menuitem.h"
61 #ifdef __WXUNIVERSAL__
62 #include "wx/univ/theme.h"
63 #include "wx/univ/colschem.h"
64 #endif // __WXUNIVERSAL__
66 // ----------------------------------------------------------------------------
68 // ----------------------------------------------------------------------------
70 #if wxUSE_MENUS_NATIVE
71 extern wxMenu
*wxCurrentPopupMenu
;
72 #endif // wxUSE_MENUS_NATIVE
74 // ----------------------------------------------------------------------------
76 // ----------------------------------------------------------------------------
78 BEGIN_EVENT_TABLE(wxFrame
, wxFrameBase
)
79 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged
)
82 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxTopLevelWindow
)
84 // ============================================================================
86 // ============================================================================
88 // ----------------------------------------------------------------------------
89 // static class members
90 // ----------------------------------------------------------------------------
93 #if wxUSE_NATIVE_STATUSBAR
94 bool wxFrame::m_useNativeStatusBar
= TRUE
;
96 bool wxFrame::m_useNativeStatusBar
= FALSE
;
98 #endif // wxUSE_NATIVE_STATUSBAR
100 // ----------------------------------------------------------------------------
101 // creation/destruction
102 // ----------------------------------------------------------------------------
113 // Data to save/restore when calling ShowFullScreen
114 m_fsStatusBarFields
= 0;
115 m_fsStatusBarHeight
= 0;
116 m_fsToolBarHeight
= 0;
118 m_wasMinimized
= FALSE
;
121 bool wxFrame::Create(wxWindow
*parent
,
123 const wxString
& title
,
127 const wxString
& name
)
129 if ( !wxTopLevelWindow::Create(parent
, id
, title
, pos
, size
, style
, name
) )
132 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
134 wxModelessWindows
.Append(this);
141 m_isBeingDeleted
= TRUE
;
149 // ----------------------------------------------------------------------------
150 // wxFrame client size calculations
151 // ----------------------------------------------------------------------------
153 void wxFrame::DoSetClientSize(int width
, int height
)
155 // leave enough space for the status bar if we have (and show) it
157 wxStatusBar
*statbar
= GetStatusBar();
158 if ( statbar
&& statbar
->IsShown() )
160 height
+= statbar
->GetSize().y
;
162 #endif // wxUSE_STATUSBAR
164 // call GetClientAreaOrigin() to take the toolbar into account
165 wxPoint pt
= GetClientAreaOrigin();
169 wxTopLevelWindow::DoSetClientSize(width
, height
);
172 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
173 void wxFrame::DoGetClientSize(int *x
, int *y
) const
175 wxTopLevelWindow::DoGetClientSize(x
, y
);
177 // account for the possible toolbar
178 wxPoint pt
= GetClientAreaOrigin();
186 // adjust client area height to take the status bar into account
189 wxStatusBar
*statbar
= GetStatusBar();
190 if ( statbar
&& statbar
->IsShown() )
192 *y
-= statbar
->GetClientSize().y
;
195 #endif // wxUSE_STATUSBAR
198 // ----------------------------------------------------------------------------
199 // wxFrame: various geometry-related functions
200 // ----------------------------------------------------------------------------
202 void wxFrame::Raise()
204 ::SetForegroundWindow(GetHwnd());
207 // generate an artificial resize event
208 void wxFrame::SendSizeEvent()
212 RECT r
= wxGetWindowRect(GetHwnd());
214 (void)::PostMessage(GetHwnd(), WM_SIZE
,
215 IsMaximized() ? SIZE_MAXIMIZED
: SIZE_RESTORED
,
216 MAKELPARAM(r
.right
- r
.left
, r
.bottom
- r
.top
));
221 wxStatusBar
*wxFrame::OnCreateStatusBar(int number
,
224 const wxString
& name
)
226 wxStatusBar
*statusBar
= NULL
;
228 #if wxUSE_NATIVE_STATUSBAR
229 if ( !UsesNativeStatusBar() )
231 statusBar
= (wxStatusBar
*)new wxStatusBarGeneric(this, id
, style
);
236 statusBar
= new wxStatusBar(this, id
, style
, name
);
239 statusBar
->SetFieldsCount(number
);
244 void wxFrame::PositionStatusBar()
246 if ( !m_frameStatusBar
|| !m_frameStatusBar
->IsShown() )
250 GetClientSize(&w
, &h
);
252 m_frameStatusBar
->GetSize(&sw
, &sh
);
254 // Since we wish the status bar to be directly under the client area,
255 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
256 m_frameStatusBar
->SetSize(0, h
, w
, sh
);
258 #endif // wxUSE_STATUSBAR
260 #if wxUSE_MENUS_NATIVE
262 void wxFrame::AttachMenuBar(wxMenuBar
*menubar
)
264 wxFrameBase::AttachMenuBar(menubar
);
268 // actually remove the menu from the frame
269 m_hMenu
= (WXHMENU
)0;
270 InternalSetMenuBar();
272 else // set new non NULL menu bar
274 // Can set a menubar several times.
275 if ( menubar
->GetHMenu() )
277 m_hMenu
= menubar
->GetHMenu();
281 m_hMenu
= menubar
->Create();
285 wxFAIL_MSG( _T("failed to create menu bar") );
290 InternalSetMenuBar();
294 void wxFrame::InternalSetMenuBar()
296 #ifdef __WXMICROWIN__
298 #elif defined(__WXWINCE__)
304 if (!CommandBar_InsertMenubarEx((HWND
) m_commandBar
, NULL
,
305 (LPTSTR
) (HMENU
) m_hMenu
, 0))
307 wxFAIL_MSG( _T("failed to set menubar") );
310 CommandBar_DrawMenuBar((HWND
) m_commandBar
, 0);
313 if ( !::SetMenu(GetHwnd(), (HMENU
)m_hMenu
) )
315 wxLogLastError(wxT("SetMenu"));
320 #endif // wxUSE_MENUS_NATIVE
322 // Responds to colour changes, and passes event on to children.
323 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
325 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
329 if ( m_frameStatusBar
)
331 wxSysColourChangedEvent event2
;
332 event2
.SetEventObject( m_frameStatusBar
);
333 m_frameStatusBar
->GetEventHandler()->ProcessEvent(event2
);
335 #endif // wxUSE_STATUSBAR
337 // Propagate the event to the non-top-level children
338 wxWindow::OnSysColourChanged(event
);
341 // Pass TRUE to show full screen, FALSE to restore.
342 bool wxFrame::ShowFullScreen(bool show
, long style
)
344 if ( IsFullScreen() == show
)
351 // TODO: hide commandbar
353 wxToolBar
*theToolBar
= GetToolBar();
355 theToolBar
->GetSize(NULL
, &m_fsToolBarHeight
);
357 // zap the toolbar, menubar, and statusbar
359 if ((style
& wxFULLSCREEN_NOTOOLBAR
) && theToolBar
)
361 theToolBar
->SetSize(-1,0);
362 theToolBar
->Show(FALSE
);
364 #endif // __WXWINCE__
365 #endif // wxUSE_TOOLBAR
367 // TODO: make it work for WinCE
368 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
369 if (style
& wxFULLSCREEN_NOMENUBAR
)
370 SetMenu((HWND
)GetHWND(), (HMENU
) NULL
);
374 wxStatusBar
*theStatusBar
= GetStatusBar();
376 theStatusBar
->GetSize(NULL
, &m_fsStatusBarHeight
);
378 // Save the number of fields in the statusbar
379 if ((style
& wxFULLSCREEN_NOSTATUSBAR
) && theStatusBar
)
381 //m_fsStatusBarFields = theStatusBar->GetFieldsCount();
382 //SetStatusBar((wxStatusBar*) NULL);
383 //delete theStatusBar;
384 theStatusBar
->Show(FALSE
);
387 m_fsStatusBarFields
= 0;
388 #endif // wxUSE_STATUSBAR
394 // TODO: show commandbar
396 wxToolBar
*theToolBar
= GetToolBar();
398 // restore the toolbar, menubar, and statusbar
399 if (theToolBar
&& (m_fsStyle
& wxFULLSCREEN_NOTOOLBAR
))
401 theToolBar
->SetSize(-1, m_fsToolBarHeight
);
402 theToolBar
->Show(TRUE
);
404 #endif // __WXWINCE__
405 #endif // wxUSE_TOOLBAR
408 if ( m_fsStyle
& wxFULLSCREEN_NOSTATUSBAR
)
410 //CreateStatusBar(m_fsStatusBarFields);
413 GetStatusBar()->Show(TRUE
);
417 #endif // wxUSE_STATUSBAR
419 // TODO: make it work for WinCE
420 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
421 if ((m_fsStyle
& wxFULLSCREEN_NOMENUBAR
) && (m_hMenu
!= 0))
422 SetMenu((HWND
)GetHWND(), (HMENU
)m_hMenu
);
426 return wxFrameBase::ShowFullScreen(show
, style
);
429 // ----------------------------------------------------------------------------
430 // tool/status bar stuff
431 // ----------------------------------------------------------------------------
435 wxToolBar
* wxFrame::CreateToolBar(long style
, wxWindowID id
, const wxString
& name
)
437 if ( wxFrameBase::CreateToolBar(style
, id
, name
) )
442 return m_frameToolBar
;
445 void wxFrame::PositionToolBar()
447 wxToolBar
*toolbar
= GetToolBar();
448 if ( toolbar
&& toolbar
->IsShown() )
451 // We want to do something different in WinCE, because
452 // the toolbar should be associated with the commandbar,
453 // and not an independent window.
456 // don't call our (or even wxTopLevelWindow) version because we want
457 // the real (full) client area size, not excluding the tool/status bar
459 wxWindow::DoGetClientSize(&width
, &height
);
462 wxStatusBar
*statbar
= GetStatusBar();
463 if ( statbar
&& statbar
->IsShown() )
465 height
-= statbar
->GetClientSize().y
;
467 #endif // wxUSE_STATUSBAR
470 toolbar
->GetSize(&tw
, &th
);
472 if ( toolbar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
479 if ( toolbar
->GetWindowStyleFlag() & wxTB_FLAT
)
483 // use the 'real' MSW position here, don't offset relativly to the
484 // client area origin
485 toolbar
->SetSize(0, 0, tw
, th
, wxSIZE_NO_ADJUSTMENTS
);
486 #endif // __WXWINCE__
490 #endif // wxUSE_TOOLBAR
492 // ----------------------------------------------------------------------------
493 // frame state (iconized/maximized/...)
494 // ----------------------------------------------------------------------------
496 // propagate our state change to all child frames: this allows us to emulate X
497 // Windows behaviour where child frames float independently of the parent one
498 // on the desktop, but are iconized/restored with it
499 void wxFrame::IconizeChildFrames(bool bIconize
)
501 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
503 node
= node
->GetNext() )
505 wxWindow
*win
= node
->GetData();
507 // iconizing the frames with this style under Win95 shell puts them at
508 // the bottom of the screen (as the MDI children) instead of making
509 // them appear in the taskbar because they are, by virtue of this
510 // style, not managed by the taskbar - instead leave Windows take care
513 if ( win
->GetWindowStyle() & wxFRAME_TOOL_WINDOW
)
517 // the child MDI frames are a special case and should not be touched by
518 // the parent frame - instead, they are managed by the user
519 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
521 #if wxUSE_MDI_ARCHITECTURE
522 && !wxDynamicCast(frame
, wxMDIChildFrame
)
523 #endif // wxUSE_MDI_ARCHITECTURE
526 // we don't want to restore the child frames which had been
527 // iconized even before we were iconized, so save the child frame
528 // status when iconizing the parent frame and check it when
532 // note that we shouldn't touch the hidden frames neither
533 // because iconizing/restoring them would show them as a side
535 frame
->m_wasMinimized
= frame
->IsIconized() || !frame
->IsShown();
538 // this test works for both iconizing and restoring
539 if ( !frame
->m_wasMinimized
)
540 frame
->Iconize(bIconize
);
545 WXHICON
wxFrame::GetDefaultIcon() const
547 // we don't have any standard icons (any more)
551 // ===========================================================================
552 // message processing
553 // ===========================================================================
555 // ---------------------------------------------------------------------------
557 // ---------------------------------------------------------------------------
559 bool wxFrame::MSWTranslateMessage(WXMSG
* pMsg
)
561 if ( wxWindow::MSWTranslateMessage(pMsg
) )
564 #if wxUSE_MENUS && wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
565 // try the menu bar accels
566 wxMenuBar
*menuBar
= GetMenuBar();
570 const wxAcceleratorTable
& acceleratorTable
= menuBar
->GetAccelTable();
571 return acceleratorTable
.Translate(this, pMsg
);
574 #endif // wxUSE_MENUS && wxUSE_ACCEL
577 // ---------------------------------------------------------------------------
578 // our private (non virtual) message handlers
579 // ---------------------------------------------------------------------------
581 bool wxFrame::HandlePaint()
584 if ( GetUpdateRect(GetHwnd(), &rect
, FALSE
) )
586 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
589 const wxIcon
& icon
= GetIcon();
590 HICON hIcon
= icon
.Ok() ? GetHiconOf(icon
)
591 : (HICON
)GetDefaultIcon();
593 // Hold a pointer to the dc so long as the OnPaint() message
594 // is being processed
596 HDC hdc
= ::BeginPaint(GetHwnd(), &ps
);
598 // Erase background before painting or we get white background
599 MSWDefWindowProc(WM_ICONERASEBKGND
, (WORD
)(LONG
)ps
.hdc
, 0L);
604 ::GetClientRect(GetHwnd(), &rect
);
606 // FIXME: why hardcoded?
607 static const int icon_width
= 32;
608 static const int icon_height
= 32;
610 int icon_x
= (int)((rect
.right
- icon_width
)/2);
611 int icon_y
= (int)((rect
.bottom
- icon_height
)/2);
613 ::DrawIcon(hdc
, icon_x
, icon_y
, hIcon
);
616 ::EndPaint(GetHwnd(), &ps
);
623 return wxWindow::HandlePaint();
628 // nothing to paint - processed
633 bool wxFrame::HandleSize(int x
, int y
, WXUINT id
)
635 bool processed
= FALSE
;
636 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
641 // only do it it if we were iconized before, otherwise resizing the
642 // parent frame has a curious side effect of bringing it under it's
647 // restore all child frames too
648 IconizeChildFrames(FALSE
);
650 (void)SendIconizeEvent(FALSE
);
659 // iconize all child frames too
660 IconizeChildFrames(TRUE
);
662 (void)SendIconizeEvent();
673 #endif // wxUSE_STATUSBAR
677 #endif // wxUSE_TOOLBAR
679 processed
= wxWindow::HandleSize(x
, y
, id
);
685 bool wxFrame::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
689 // In case it's e.g. a toolbar.
690 wxWindow
*win
= wxFindWinFromHandle(control
);
692 return win
->MSWCommand(cmd
, id
);
695 // handle here commands from menus and accelerators
696 if ( cmd
== 0 || cmd
== 1 )
698 #if wxUSE_MENUS_NATIVE
699 if ( wxCurrentPopupMenu
)
701 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
702 wxCurrentPopupMenu
= NULL
;
704 return popupMenu
->MSWCommand(cmd
, id
);
706 #endif // wxUSE_MENUS_NATIVE
708 if ( ProcessCommand(id
) )
717 bool wxFrame::HandleMenuSelect(WXWORD nItem
, WXWORD flags
, WXHMENU hMenu
)
720 if ( flags
== 0xFFFF && hMenu
== 0 )
722 // menu was removed from screen
725 #ifndef __WXMICROWIN__
726 else if ( !(flags
& MF_POPUP
) && !(flags
& MF_SEPARATOR
) )
733 // don't give hints for separators (doesn't make sense) nor for the
734 // items opening popup menus (they don't have them anyhow) but do clear
735 // the status line - otherwise, we would be left with the help message
736 // for the previous item which doesn't apply any more
737 DoGiveHelp(wxEmptyString
, FALSE
);
742 wxMenuEvent
event(wxEVT_MENU_HIGHLIGHT
, item
);
743 event
.SetEventObject(this);
745 return GetEventHandler()->ProcessEvent(event
);
748 bool wxFrame::HandleMenuLoop(const wxEventType
& evtType
, WXWORD isPopup
)
750 // we don't have the menu id here, so we use the id to specify if the event
751 // was from a popup menu or a normal one
752 wxMenuEvent
event(evtType
, isPopup
? -1 : 0);
753 event
.SetEventObject(this);
755 return GetEventHandler()->ProcessEvent(event
);
758 // ---------------------------------------------------------------------------
759 // the window proc for wxFrame
760 // ---------------------------------------------------------------------------
762 long wxFrame::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
765 bool processed
= FALSE
;
770 // if we can't close, tell the system that we processed the
771 // message - otherwise it would close us
772 processed
= !Close();
776 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), wParam
);
783 UnpackCommand((WXWPARAM
)wParam
, (WXLPARAM
)lParam
,
786 processed
= HandleCommand(id
, cmd
, (WXHWND
)hwnd
);
791 processed
= HandlePaint();
794 case WM_INITMENUPOPUP
:
795 processed
= HandleInitMenuPopup((WXHMENU
) wParam
);
798 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
803 UnpackMenuSelect(wParam
, lParam
, &item
, &flags
, &hmenu
);
805 processed
= HandleMenuSelect(item
, flags
, hmenu
);
809 case WM_EXITMENULOOP
:
810 processed
= HandleMenuLoop(wxEVT_MENU_CLOSE
, wParam
);
813 case WM_QUERYDRAGICON
:
815 const wxIcon
& icon
= GetIcon();
816 HICON hIcon
= icon
.Ok() ? GetHiconOf(icon
)
817 : (HICON
)GetDefaultIcon();
822 #endif // !__WXMICROWIN__
826 rc
= wxFrameBase::MSWWindowProc(message
, wParam
, lParam
);
831 // handle WM_INITMENUPOPUP message
832 bool wxFrame::HandleInitMenuPopup(WXHMENU hMenu
)
837 int nCount
= GetMenuBar()->GetMenuCount();
838 for (int n
= 0; n
< nCount
; n
++)
840 if (GetMenuBar()->GetMenu(n
)->GetHMenu() == hMenu
)
842 menu
= GetMenuBar()->GetMenu(n
);
848 wxMenuEvent
event(wxEVT_MENU_OPEN
, 0, menu
);
849 event
.SetEventObject(this);
851 return GetEventHandler()->ProcessEvent(event
);
855 WXHWND
wxFrame::CreateCommandBar()
860 m_commandBar
= (WXHWND
) CommandBar_Create(wxGetInstance(), GetHwnd(), NewControlId());
863 wxFAIL_MSG( _T("failed to create commandbar") );
869 void wxFrame::RemoveCommandBar()
873 ::DestroyWindow((HWND
) m_commandBar
);