1 /////////////////////////////////////////////////////////////////////////////
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
21 #include "wx/dialog.h"
22 #include "wx/settings.h"
23 #include "wx/dcclient.h"
26 #include "wx/os2/private.h"
29 #include "wx/statusbr.h"
30 #include "wx/generic/statusbr.h"
31 #endif // wxUSE_STATUSBAR
34 #include "wx/toolbar.h"
35 #endif // wxUSE_TOOLBAR
37 #include "wx/menuitem.h"
40 // ----------------------------------------------------------------------------
42 // ----------------------------------------------------------------------------
44 extern wxWindowList wxModelessWindows
;
45 extern wxList WXDLLEXPORT wxPendingDelete
;
46 extern wxChar wxFrameClassName
[];
47 extern wxMenu
*wxCurrentPopupMenu
;
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 BEGIN_EVENT_TABLE(wxFrame
, wxFrameBase
)
54 EVT_ACTIVATE(wxFrame::OnActivate
)
55 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged
)
58 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxWindow
)
60 // ============================================================================
62 // ============================================================================
64 // ----------------------------------------------------------------------------
65 // static class members
66 // ----------------------------------------------------------------------------
68 #if wxUSE_NATIVE_STATUSBAR
69 bool wxFrame::m_useNativeStatusBar
= TRUE
;
71 bool wxFrame::m_useNativeStatusBar
= FALSE
;
74 // ----------------------------------------------------------------------------
75 // creation/destruction
76 // ----------------------------------------------------------------------------
85 // Data to save/restore when calling ShowFullScreen
87 m_lFsOldWindowStyle
= 0L;
88 m_nFsStatusBarFields
= 0;
89 m_nFsStatusBarHeight
= 0;
90 m_nFsToolBarHeight
= 0;
91 m_bFsIsMaximized
= FALSE
;
92 m_bFsIsShowing
= FALSE
;
93 } // end of wxFrame::Init
98 , const wxString
& rsTitle
100 , const wxSize
& rSize
102 , const wxString
& rsName
107 int nWidth
= rSize
.x
;
108 int nHeight
= rSize
.y
;
112 m_windowStyle
= lStyle
;
113 m_frameMenuBar
= NULL
;
114 m_frameToolBar
= NULL
;
115 m_frameStatusBar
= NULL
;
117 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
122 m_windowId
= (int)NewControlId();
125 pParent
->AddChild(this);
130 // We pass NULL as parent to MSWCreate because frames with parents behave
131 // very strangely under Win95 shell.
132 // Alteration by JACS: keep normal Windows behaviour (float on top of parent)
135 if ((m_windowStyle
& wxFRAME_FLOAT_ON_PARENT
) == 0)
139 wxTopLevelWindows
.Append(this);
141 OS2Create( m_windowId
153 wxModelessWindows
.Append(this);
155 } // end of wxFrame::Create
159 m_isBeingDeleted
= TRUE
;
160 wxTopLevelWindows
.DeleteObject(this);
164 if (wxTheApp
&& (wxTopLevelWindows
.Number() == 0))
166 wxTheApp
->SetTopWindow(NULL
);
168 if (wxTheApp
->GetExitOnFrameDelete())
170 ::WinPostMsg(m_hwnd
, WM_QUIT
, 0, 0);
173 wxModelessWindows
.DeleteObject(this);
176 // For some reason, wxWindows can activate another task altogether
177 // when a frame is destroyed after a modal dialog has been invoked.
178 // Try to bring the parent to the top.
180 // MT:Only do this if this frame is currently the active window, else weird
181 // things start to happen.
183 if (wxGetActiveWindow() == this)
185 if (GetParent() && GetParent()->GetHWND())
187 ::WinQueryWindowPos( (HWND
) GetParent()->GetHWND()
190 ::WinSetWindowPos( (HWND
) GetParent()->GetHWND()
196 ,SWP_ACTIVATE
| SWP_MOVE
| SWP_SIZE
| SWP_SHOW
200 } // end of wxFrame::~wxFrame
203 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
205 void wxFrame::DoGetClientSize(int *x
, int *y
) const
210 ::GetClientRect(GetHwnd(), &rect);
213 if ( GetStatusBar() )
215 int statusX, statusY;
216 GetStatusBar()->GetClientSize(&statusX, &statusY);
217 rect.bottom -= statusY;
219 #endif // wxUSE_STATUSBAR
221 wxPoint pt(GetClientAreaOrigin());
232 // Set the client size (i.e. leave the calculation of borders etc.
234 void wxFrame::DoSetClientSize(int width
, int height
)
236 HWND hWnd
= GetHwnd();
241 ::GetClientRect(hWnd, &rect);
244 GetWindowRect(hWnd, &rect2);
246 // Find the difference between the entire window (title bar and all)
247 // and the client area; add this to the new client size to move the
249 int actual_width = rect2.right - rect2.left - rect.right + width;
250 int actual_height = rect2.bottom - rect2.top - rect.bottom + height;
253 if ( GetStatusBar() )
255 int statusX, statusY;
256 GetStatusBar()->GetClientSize(&statusX, &statusY);
257 actual_height += statusY;
259 #endif // wxUSE_STATUSBAR
261 wxPoint pt(GetClientAreaOrigin());
262 actual_width += pt.y;
263 actual_height += pt.x;
266 point.x = rect2.left;
269 MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)TRUE);
271 wxSizeEvent event(wxSize(width, height), m_windowId);
272 event.SetEventObject( this );
273 GetEventHandler()->ProcessEvent(event);
277 void wxFrame::DoGetSize(int *width
, int *height
) const
282 GetWindowRect(GetHwnd(), &rect);
283 *width = rect.right - rect.left;
284 *height = rect.bottom - rect.top;
288 void wxFrame::DoGetPosition(int *x
, int *y
) const
293 GetWindowRect(GetHwnd(), &rect);
303 // ----------------------------------------------------------------------------
304 // variations around ::ShowWindow()
305 // ----------------------------------------------------------------------------
307 void wxFrame::DoShowWindow(int nShowCmd
)
311 ::ShowWindow(GetHwnd(), nShowCmd);
313 m_iconized = nShowCmd == SW_MINIMIZE;
317 bool wxFrame::Show(bool show
)
321 DoShowWindow(show ? SW_SHOW : SW_HIDE);
325 ::BringWindowToTop(GetHwnd());
327 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_windowId);
328 event.SetEventObject( this );
329 GetEventHandler()->ProcessEvent(event);
333 // Try to highlight the correct window (the parent)
336 HWND hWndParent = GetHwndOf(GetParent());
338 ::BringWindowToTop(hWndParent);
345 void wxFrame::Iconize(bool iconize
)
347 // DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE);
350 void wxFrame::Maximize(bool maximize
)
352 // DoShowWindow(maximize ? SW_MAXIMIZE : SW_RESTORE);
355 void wxFrame::Restore()
357 // DoShowWindow(SW_RESTORE);
360 bool wxFrame::IsIconized() const
364 ((wxFrame *)this)->m_iconized = (::IsIconic(GetHwnd()) != 0);
371 bool wxFrame::IsMaximized() const
375 return (::IsZoomed(GetHwnd()) != 0);
380 void wxFrame::SetIcon(const wxIcon
& icon
)
382 wxFrameBase::SetIcon(icon
);
388 SendMessage(GetHwnd(), WM_SETICON,
389 (WPARAM)TRUE, (LPARAM)(HICON) m_icon.GetHICON());
395 wxStatusBar
*wxFrame::OnCreateStatusBar(int number
,
398 const wxString
& name
)
400 wxStatusBar
*statusBar
= NULL
;
402 statusBar
= wxFrameBase::OnCreateStatusBar(number
, style
, id
, name
);
407 void wxFrame::PositionStatusBar()
411 // native status bar positions itself
412 if ( m_frameStatusBar )
415 GetClientSize(&w, &h);
417 m_frameStatusBar->GetSize(&sw, &sh);
419 // Since we wish the status bar to be directly under the client area,
420 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
421 m_frameStatusBar->SetSize(0, h, w, sh);
425 #endif // wxUSE_STATUSBAR
427 void wxFrame::DetachMenuBar()
431 m_frameMenuBar
->Detach();
432 m_frameMenuBar
= NULL
;
436 void wxFrame::SetMenuBar(wxMenuBar
*menu_bar
)
444 wxCHECK_RET( !menu_bar
->GetFrame(), wxT("this menubar is already attached") );
447 delete m_frameMenuBar
;
449 m_hMenu
= menu_bar
->Create();
454 InternalSetMenuBar();
456 m_frameMenuBar
= menu_bar
;
457 menu_bar
->Attach(this);
460 void wxFrame::InternalSetMenuBar()
464 if ( !::SetMenu(GetHwnd(), (HMENU)m_hMenu) )
466 wxLogLastError("SetMenu");
471 // Responds to colour changes, and passes event on to children.
472 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
476 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
479 if ( m_frameStatusBar )
481 wxSysColourChangedEvent event2;
482 event2.SetEventObject( m_frameStatusBar );
483 m_frameStatusBar->GetEventHandler()->ProcessEvent(event2);
486 // Propagate the event to the non-top-level children
487 wxWindow::OnSysColourChanged(event);
496 bool wxFrame::OS2Create(int id
, wxWindow
*parent
, const wxChar
*wclass
, wxWindow
*wx_win
, const wxChar
*title
,
497 int x
, int y
, int width
, int height
, long style
)
500 m_defaultIcon
= (WXHICON
) (wxSTD_FRAME_ICON
? wxSTD_FRAME_ICON
: wxDEFAULT_FRAME_ICON
);
502 // If child windows aren't properly drawn initially, WS_CLIPCHILDREN
503 // could be the culprit. But without it, you can get a lot of flicker.
508 if ((style & wxCAPTION) == wxCAPTION)
509 msflags = WS_OVERLAPPED;
513 if (style & wxMINIMIZE_BOX)
514 msflags |= WS_MINIMIZEBOX;
515 if (style & wxMAXIMIZE_BOX)
516 msflags |= WS_MAXIMIZEBOX;
517 if (style & wxTHICK_FRAME)
518 msflags |= WS_THICKFRAME;
519 if (style & wxSYSTEM_MENU)
520 msflags |= WS_SYSMENU;
521 if ((style & wxMINIMIZE) || (style & wxICONIZE))
522 msflags |= WS_MINIMIZE;
523 if (style & wxMAXIMIZE)
524 msflags |= WS_MAXIMIZE;
525 if (style & wxCAPTION)
526 msflags |= WS_CAPTION;
527 if (style & wxCLIP_CHILDREN)
528 msflags |= WS_CLIPCHILDREN;
530 // Keep this in wxFrame because it saves recoding this function
533 if (style & wxTINY_CAPTION_VERT)
534 msflags |= IBS_VERTCAPTION;
535 if (style & wxTINY_CAPTION_HORIZ)
536 msflags |= IBS_HORZCAPTION;
538 if (style & wxTINY_CAPTION_VERT)
539 msflags |= WS_CAPTION;
540 if (style & wxTINY_CAPTION_HORIZ)
541 msflags |= WS_CAPTION;
543 if ((style & wxTHICK_FRAME) == 0)
544 msflags |= WS_BORDER;
546 WXDWORD extendedStyle = MakeExtendedStyle(style);
548 #if !defined(__WIN16__) && !defined(__SC__)
549 if (style & wxFRAME_TOOL_WINDOW)
550 extendedStyle |= WS_EX_TOOLWINDOW;
553 if (style & wxSTAY_ON_TOP)
554 extendedStyle |= WS_EX_TOPMOST;
557 if ( !wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height,
558 msflags, NULL, extendedStyle) )
561 // Seems to be necessary if we use WS_POPUP
562 // style instead of WS_OVERLAPPED
563 if (width > -1 && height > -1)
564 ::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height));
569 // Default activation behaviour - set the focus for the first child
571 void wxFrame::OnActivate(wxActivateEvent
& event
)
573 for ( wxWindowList::Node
*node
= GetChildren().GetFirst();
575 node
= node
->GetNext() )
577 // FIXME all this is totally bogus - we need to do the same as wxPanel,
578 // but how to do it without duplicating the code?
581 wxWindow
*child
= node
->GetData();
583 if ( !child
->IsTopLevel()
585 && !wxDynamicCast(child
, wxToolBar
)
586 #endif // wxUSE_TOOLBAR
588 && !wxDynamicCast(child
, wxStatusBar
)
589 #endif // wxUSE_STATUSBAR
598 // ----------------------------------------------------------------------------
599 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
600 // from the client area, so the client area is what's really available for the
602 // ----------------------------------------------------------------------------
604 // Checks if there is a toolbar, and returns the first free client position
605 wxPoint
wxFrame::GetClientAreaOrigin() const
611 GetToolBar()->GetSize(& w
, & h
);
613 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL
)
625 void wxFrame::DoScreenToClient(int *x
, int *y
) const
627 wxWindow::DoScreenToClient(x
, y
);
629 // We may be faking the client origin.
630 // So a window that's really at (0, 30) may appear
631 // (to wxWin apps) to be at (0, 0).
632 wxPoint
pt(GetClientAreaOrigin());
637 void wxFrame::DoClientToScreen(int *x
, int *y
) const
639 // We may be faking the client origin.
640 // So a window that's really at (0, 30) may appear
641 // (to wxWin apps) to be at (0, 0).
642 wxPoint
pt1(GetClientAreaOrigin());
646 wxWindow::DoClientToScreen(x
, y
);
649 // ----------------------------------------------------------------------------
650 // tool/status bar stuff
651 // ----------------------------------------------------------------------------
655 wxToolBar
* wxFrame::CreateToolBar(long style
, wxWindowID id
, const wxString
& name
)
657 if ( wxFrameBase::CreateToolBar(style
, id
, name
) )
662 return m_frameToolBar
;
665 void wxFrame::PositionToolBar()
670 ::GetClientRect(GetHwnd(), &rect);
673 if ( GetStatusBar() )
675 int statusX, statusY;
676 GetStatusBar()->GetClientSize(&statusX, &statusY);
677 rect.bottom -= statusY;
679 #endif // wxUSE_STATUSBAR
684 GetToolBar()->GetSize(&tw, &th);
686 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
695 // Use the 'real' MSW position here
696 GetToolBar()->SetSize(0, 0, tw, th, wxSIZE_NO_ADJUSTMENTS);
700 #endif // wxUSE_TOOLBAR
702 // ----------------------------------------------------------------------------
703 // frame state (iconized/maximized/...)
704 // ----------------------------------------------------------------------------
706 // propagate our state change to all child frames: this allows us to emulate X
707 // Windows behaviour where child frames float independently of the parent one
708 // on the desktop, but are iconized/restored with it
709 void wxFrame::IconizeChildFrames(bool bIconize
)
711 for ( wxWindowList::Node
*node
= GetChildren().GetFirst();
713 node
= node
->GetNext() )
715 wxWindow
*win
= node
->GetData();
717 if ( win
->IsKindOf(CLASSINFO(wxFrame
)) )
719 ((wxFrame
*)win
)->Iconize(bIconize
);
724 // ===========================================================================
725 // message processing
726 // ===========================================================================
728 // ---------------------------------------------------------------------------
730 // ---------------------------------------------------------------------------
732 bool wxFrame::OS2TranslateMessage(WXMSG
* pMsg
)
736 if ( wxWindow::OS2TranslateMessage(pMsg) )
739 // try the menu bar accels
740 wxMenuBar
*menuBar
= GetMenuBar();
744 const wxAcceleratorTable
& acceleratorTable
= menuBar
->GetAccelTable();
745 return acceleratorTable
.Translate(this, pMsg
);
748 // ---------------------------------------------------------------------------
749 // our private (non virtual) message handlers
750 // ---------------------------------------------------------------------------
752 bool wxFrame::HandlePaint()
757 if ( GetUpdateRect(GetHwnd(), &rect, FALSE) )
761 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
762 : (HICON)m_defaultIcon;
764 // Hold a pointer to the dc so long as the OnPaint() message
765 // is being processed
767 HDC hdc = ::BeginPaint(GetHwnd(), &ps);
769 // Erase background before painting or we get white background
770 MSWDefWindowProc(WM_ICONERASEBKGND, (WORD)(LONG)ps.hdc, 0L);
775 ::GetClientRect(GetHwnd(), &rect);
777 // FIXME: why hardcoded?
778 static const int icon_width = 32;
779 static const int icon_height = 32;
781 int icon_x = (int)((rect.right - icon_width)/2);
782 int icon_y = (int)((rect.bottom - icon_height)/2);
784 ::DrawIcon(hdc, icon_x, icon_y, hIcon);
787 ::EndPaint(GetHwnd(), &ps);
793 return wxWindow::HandlePaint();
798 // nothing to paint - processed
805 bool wxFrame::HandleSize(int x
, int y
, WXUINT id
)
807 bool processed
= FALSE
;
814 // only do it it if we were iconized before, otherwise resizing the
815 // parent frame has a curious side effect of bringing it under it's
820 // restore all child frames too
821 IconizeChildFrames(FALSE);
830 // iconize all child frames too
831 IconizeChildFrames(TRUE);
839 // forward WM_SIZE to status bar control
840 #if wxUSE_NATIVE_STATUSBAR
841 if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
843 wxSizeEvent event(wxSize(x, y), m_frameStatusBar->GetId());
844 event.SetEventObject( m_frameStatusBar );
846 ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event);
848 #endif // wxUSE_NATIVE_STATUSBAR
853 wxSizeEvent event(wxSize(x, y), m_windowId);
854 event.SetEventObject( this );
855 processed = GetEventHandler()->ProcessEvent(event);
861 bool wxFrame::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
867 // In case it's e.g. a toolbar.
868 wxWindow *win = wxFindWinFromHandle(control);
870 return win->MSWCommand(cmd, id);
873 // handle here commands from menus and accelerators
874 if ( cmd == 0 || cmd == 1 )
876 if ( wxCurrentPopupMenu )
878 wxMenu *popupMenu = wxCurrentPopupMenu;
879 wxCurrentPopupMenu = NULL;
881 return popupMenu->MSWCommand(cmd, id);
884 if ( ProcessCommand(id) )
893 bool wxFrame::HandleMenuSelect(WXWORD nItem
, WXWORD flags
, WXHMENU hMenu
)
896 if ( flags
== 0xFFFF && hMenu
== 0 )
898 // menu was removed from screen
903 else if ( !(flags & MF_POPUP) && !(flags & MF_SEPARATOR) )
909 // don't give hints for separators (doesn't make sense) nor for the
910 // items opening popup menus (they don't have them anyhow)
914 wxMenuEvent
event(wxEVT_MENU_HIGHLIGHT
, item
);
915 event
.SetEventObject( this );
917 return GetEventHandler()->ProcessEvent(event
);
920 // ---------------------------------------------------------------------------
921 // the window proc for wxFrame
922 // ---------------------------------------------------------------------------
924 MRESULT
wxFrame::OS2WindowProc(HWND hwnd
, WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
927 bool processed
= FALSE
;
934 // if we can't close, tell the system that we processed the
935 // message - otherwise it would close us
936 processed = !Close();
943 UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam,
946 processed = HandleCommand(id, cmd, (WXHWND)hwnd);
954 UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
956 processed = HandleMenuSelect(item, flags, hmenu);
961 processed = HandlePaint();
964 case WM_QUERYDRAGICON:
966 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
967 : (HICON)(m_defaultIcon);
974 processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
979 rc = wxWindow::MSWWindowProc(message, wParam, lParam);