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
;
111 m_windowStyle
= lStyle
;
112 m_frameMenuBar
= NULL
;
113 m_frameToolBar
= NULL
;
114 m_frameStatusBar
= NULL
;
116 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
121 m_windowId
= (int)NewControlId();
124 pParent
->AddChild(this);
129 // We pass NULL as parent to MSWCreate because frames with parents behave
130 // very strangely under Win95 shell.
131 // Alteration by JACS: keep normal Windows behaviour (float on top of parent)
134 if ((m_windowStyle
& wxFRAME_FLOAT_ON_PARENT
) == 0)
138 wxTopLevelWindows
.Append(this);
140 OS2Create( m_windowId
152 wxModelessWindows
.Append(this);
154 } // end of wxFrame::Create
158 m_isBeingDeleted
= TRUE
;
159 wxTopLevelWindows
.DeleteObject(this);
163 if (wxTheApp
&& (wxTopLevelWindows
.Number() == 0))
165 wxTheApp
->SetTopWindow(NULL
);
167 if (wxTheApp
->GetExitOnFrameDelete())
169 ::WinPostMsg(GetHwnd(), WM_QUIT
, 0, 0);
172 wxModelessWindows
.DeleteObject(this);
175 // For some reason, wxWindows can activate another task altogether
176 // when a frame is destroyed after a modal dialog has been invoked.
177 // Try to bring the parent to the top.
179 // MT:Only do this if this frame is currently the active window, else weird
180 // things start to happen.
182 if (wxGetActiveWindow() == this)
184 if (GetParent() && GetParent()->GetHWND())
186 ::WinSetWindowPos( (HWND
) GetParent()->GetHWND()
196 } // end of wxFrame::~wxFrame
199 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
201 void wxFrame::DoGetClientSize(
207 // OS/2 PM's coordinates go from bottom-left not
208 // top-left thus the += instead of the -=
214 // PM has no GetClientRect that inherantly knows about the client window
215 // We have to explicitly go fetch it!
217 hWndClient
= ::WinWindowFromId(GetHwnd(), FID_CLIENT
);
218 ::WinQueryWindowRect(hWndClient
, &vRect
);
221 if ( GetStatusBar() )
226 GetStatusBar()->GetClientSize( &nStatusX
229 vRect
.yBottom
+= nStatusY
;
231 #endif // wxUSE_STATUSBAR
233 wxPoint
vPoint(GetClientAreaOrigin());
235 vRect
.bottom
+= pt
.y
;
242 } // end of wxFrame::DoGetClientSize
245 // Set the client size (i.e. leave the calculation of borders etc.
248 void wxFrame::DoSetClientSize(
253 HWND hWnd
= GetHwnd();
258 hWndClient
= ::WinWindowFromId(GetHwnd(), FID_CLIENT
);
259 ::WinQueryWindowRect(hWndClient
, &vRect
);
261 ::WinQueryWindowRect(hWnd
, &vRect2
);
264 // Find the difference between the entire window (title bar and all)
265 // and the client area; add this to the new client size to move the
266 // window. Remember OS/2's backwards y coord system!
268 int nActualWidth
= vRect2
.xRight
- vRect2
.xLeft
- vRect
.xRight
+ nWidth
;
269 int nActualHeight
= vRect2
.yTop
+ vRect2
.yTop
- vRect
.yTop
+ nHeight
;
272 if ( GetStatusBar() )
277 GetStatusBar()->GetClientSize( &nStatusX
280 nActualHeight
+= nStatusY
;
282 #endif // wxUSE_STATUSBAR
284 wxPoint
vPoint(GetClientAreaOrigin());
285 nActualWidth
+= vPoint
.y
;
286 nActualHeight
+= vPoint
.x
;
290 vPointl
.x
= vRect2
.xLeft
;
291 vPoint
.y
= vRect2
.yTop
;
293 ::WinSetWindowPos( hWnd
299 ,SWP_MOVE
| SWP_SIZE
| SWP_SHOW
302 wxSizeEvent
vEvent( wxSize( nWidth
307 vEvent
.SetEventObject(this);
308 GetEventHandler()->ProcessEvent(vEvent
);
309 } // end of wxFrame::DoSetClientSize
311 void wxFrame::DoGetSize(
318 ::WinQueryWindowRect(GetHwnd(), &vRect
);
319 *pWidth
= vRect
.xRight
- vRect
.xLeft
;
320 *pHeight
= vRect
.yTop
- vRect
.yBottom
;
321 } // end of wxFrame::DoGetSize
323 void wxFrame::DoGetPosition(
331 ::WinQueryWindowRect(GetHwnd(), &vRect
);
332 vPoint
.x
= vRect
.xLeft
;
335 // OS/2 is backwards [WIN32 it is vRect.yTop]
337 vPoint
.y
= vRect
.yBottom
;
341 } // end of wxFrame::DoGetPosition
343 // ----------------------------------------------------------------------------
344 // variations around ::ShowWindow()
345 // ----------------------------------------------------------------------------
347 void wxFrame::DoShowWindow(
351 ::WinShowWindow(GetHwnd(), nShowCmd
);
352 m_bIconized
= nShowCmd
== SWP_MINIMIZE
;
353 } // end of wxFrame::DoShowWindow
359 DoShowWindow(show
? SWP_SHOW
: SW_HIDE
);
363 wxActivateEvent
vEvent(wxEVT_ACTIVATE
, TRUE
, m_windowId
);
365 ::WinSetWindowPos( (HWND
) GetHWND()
373 vEvent
.SetEventObject(this);
374 GetEventHandler()->ProcessEvent(vEvent
);
379 // Try to highlight the correct window (the parent)
383 HWND hWndParent
= GetHwndOf(GetParent());
386 ::WinSetWindowPos( hWndParent
397 } // end of wxFrame::Show
399 void wxFrame::Iconize(
403 DoShowWindow(bIconize
? SWP_MINIMIZE
: SWP_RESTORE
);
404 } // end of wxFrame::Iconize
406 void wxFrame::Maximize(
409 DoShowWindow(bMaximize
? SWP_MAXIMIZE
: SWP_RESTORE
);
410 } // end of wxFrame::Maximize
412 void wxFrame::Restore()
414 DoShowWindow(SWP_RESTORE
);
415 } // end of wxFrame::Restore
417 bool wxFrame::IsIconized() const
422 ::WinQueryWindowPos(GetHwnd(), &vSwp
)
424 if (vSwp
.fl
& SWP_MINIMIZE
)
425 ((wxFrame
*)this)->m_bIconized
= TRUE
;
427 ((wxFrame
*)this)->m_bIconized
= FALSE
;
429 } // end of wxFrame::IsIconized
432 bool wxFrame::IsMaximized() const
437 ::WinQueryWindowPos(GetHwnd(), &vSwp
)
438 return (vSwp
.fl
& SWP_MAXIMIZE
);
439 } // end of wxFrame::IsMaximized
441 void wxFrame::SetIcon(
445 wxFrameBase::SetIcon(rIcon
);
449 WinSendMessage( GetHwnd()
451 ,(HICON
) m_icon
.GetHICON()
455 } // end of wxFrame::SetIcon
458 wxStatusBar
* wxFrame::OnCreateStatusBar(
462 , const wxString
& rName
465 wxStatusBar
* pStatusBar
= NULL
;
467 pStatusBar
= wxFrameBase::OnCreateStatusBar( nNumber
473 } // end of wxFrame::OnCreateStatusBar
475 void wxFrame::PositionStatusBar()
478 // Native status bar positions itself
480 if (m_frameStatusBar
)
489 hWndClient
= ::WinWindowFromId(GetHwnd(), FID_CLIENT
);
490 ::WinQueryWindowRect(hWndClient
, &vRect
);
491 nWidth
= vRect
.xRight
- vRect
.xLeft
;
492 nHeight
= vRect
.xTop
- vRect
.xBottom
;
494 m_frameStatusBar
->GetSize( &nStatbarWidth
499 // Since we wish the status bar to be directly under the client area,
500 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
502 m_frameStatusBar
->SetSize( 0
508 } // end of wxFrame::PositionStatusBar
509 #endif // wxUSE_STATUSBAR
511 void wxFrame::DetachMenuBar()
515 m_frameMenuBar
->Detach();
516 m_frameMenuBar
= NULL
;
518 } // end of wxFrame::DetachMenuBar
520 void wxFrame::SetMenuBar(
530 wxCHECK_RET(!pMenuBar
->GetFrame(), wxT("this menubar is already attached"));
533 delete m_frameMenuBar
;
535 m_hMenu
= pMenuBbar
->Create();
536 m_ulMenubarId
= pMenubar
->GetMenubarId();
537 if (m_ulMenubarId
!= FID_MENU
)
539 ::WinSetWIndowUShort( m_hMenu
541 ,(unsigned short(m_ulMenubarId
)
548 InternalSetMenuBar();
550 m_frameMenuBar
= menu_bar
;
551 menu_bar
->Attach(this);
552 } // end of wxFrame::SetMenuBar
554 void wxFrame::InternalSetMenuBar()
557 ::WinPostMsg( GetHwnd()
562 } // end of wxFrame::InternalSetMenuBar
564 // Responds to colour changes, and passes event on to children.
565 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
569 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
572 if ( m_frameStatusBar )
574 wxSysColourChangedEvent event2;
575 event2.SetEventObject( m_frameStatusBar );
576 m_frameStatusBar->GetEventHandler()->ProcessEvent(event2);
579 // Propagate the event to the non-top-level children
580 wxWindow::OnSysColourChanged(event);
589 bool wxFrame::OS2Create(int id
, wxWindow
*parent
, const wxChar
*wclass
, wxWindow
*wx_win
, const wxChar
*title
,
590 int x
, int y
, int width
, int height
, long style
)
593 m_hDefaultIcon
= (WXHICON
) (wxSTD_FRAME_ICON
? wxSTD_FRAME_ICON
: wxDEFAULT_FRAME_ICON
);
595 // If child windows aren't properly drawn initially, WS_CLIPCHILDREN
596 // could be the culprit. But without it, you can get a lot of flicker.
601 if ((style & wxCAPTION) == wxCAPTION)
602 msflags = WS_OVERLAPPED;
606 if (style & wxMINIMIZE_BOX)
607 msflags |= WS_MINIMIZEBOX;
608 if (style & wxMAXIMIZE_BOX)
609 msflags |= WS_MAXIMIZEBOX;
610 if (style & wxTHICK_FRAME)
611 msflags |= WS_THICKFRAME;
612 if (style & wxSYSTEM_MENU)
613 msflags |= WS_SYSMENU;
614 if ((style & wxMINIMIZE) || (style & wxICONIZE))
615 msflags |= WS_MINIMIZE;
616 if (style & wxMAXIMIZE)
617 msflags |= WS_MAXIMIZE;
618 if (style & wxCAPTION)
619 msflags |= WS_CAPTION;
620 if (style & wxCLIP_CHILDREN)
621 msflags |= WS_CLIPCHILDREN;
623 // Keep this in wxFrame because it saves recoding this function
626 if (style & wxTINY_CAPTION_VERT)
627 msflags |= IBS_VERTCAPTION;
628 if (style & wxTINY_CAPTION_HORIZ)
629 msflags |= IBS_HORZCAPTION;
631 if (style & wxTINY_CAPTION_VERT)
632 msflags |= WS_CAPTION;
633 if (style & wxTINY_CAPTION_HORIZ)
634 msflags |= WS_CAPTION;
636 if ((style & wxTHICK_FRAME) == 0)
637 msflags |= WS_BORDER;
639 WXDWORD extendedStyle = MakeExtendedStyle(style);
641 #if !defined(__WIN16__) && !defined(__SC__)
642 if (style & wxFRAME_TOOL_WINDOW)
643 extendedStyle |= WS_EX_TOOLWINDOW;
646 if (style & wxSTAY_ON_TOP)
647 extendedStyle |= WS_EX_TOPMOST;
650 if ( !wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height,
651 msflags, NULL, extendedStyle) )
654 // Seems to be necessary if we use WS_POPUP
655 // style instead of WS_OVERLAPPED
656 if (width > -1 && height > -1)
657 ::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height));
662 // Default activation behaviour - set the focus for the first child
664 void wxFrame::OnActivate(wxActivateEvent
& event
)
666 for ( wxWindowList::Node
*node
= GetChildren().GetFirst();
668 node
= node
->GetNext() )
670 // FIXME all this is totally bogus - we need to do the same as wxPanel,
671 // but how to do it without duplicating the code?
674 wxWindow
*child
= node
->GetData();
676 if ( !child
->IsTopLevel()
678 && !wxDynamicCast(child
, wxToolBar
)
679 #endif // wxUSE_TOOLBAR
681 && !wxDynamicCast(child
, wxStatusBar
)
682 #endif // wxUSE_STATUSBAR
691 // ----------------------------------------------------------------------------
692 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
693 // from the client area, so the client area is what's really available for the
695 // ----------------------------------------------------------------------------
697 // Checks if there is a toolbar, and returns the first free client position
698 wxPoint
wxFrame::GetClientAreaOrigin() const
704 GetToolBar()->GetSize(& w
, & h
);
706 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL
)
718 void wxFrame::DoScreenToClient(int *x
, int *y
) const
720 wxWindow::DoScreenToClient(x
, y
);
722 // We may be faking the client origin.
723 // So a window that's really at (0, 30) may appear
724 // (to wxWin apps) to be at (0, 0).
725 wxPoint
pt(GetClientAreaOrigin());
730 void wxFrame::DoClientToScreen(int *x
, int *y
) const
732 // We may be faking the client origin.
733 // So a window that's really at (0, 30) may appear
734 // (to wxWin apps) to be at (0, 0).
735 wxPoint
pt1(GetClientAreaOrigin());
739 wxWindow::DoClientToScreen(x
, y
);
742 // ----------------------------------------------------------------------------
743 // tool/status bar stuff
744 // ----------------------------------------------------------------------------
748 wxToolBar
* wxFrame::CreateToolBar(long style
, wxWindowID id
, const wxString
& name
)
750 if ( wxFrameBase::CreateToolBar(style
, id
, name
) )
755 return m_frameToolBar
;
758 void wxFrame::PositionToolBar()
763 ::GetClientRect(GetHwnd(), &rect);
766 if ( GetStatusBar() )
768 int statusX, statusY;
769 GetStatusBar()->GetClientSize(&statusX, &statusY);
770 rect.bottom -= statusY;
772 #endif // wxUSE_STATUSBAR
777 GetToolBar()->GetSize(&tw, &th);
779 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
788 // Use the 'real' MSW position here
789 GetToolBar()->SetSize(0, 0, tw, th, wxSIZE_NO_ADJUSTMENTS);
793 #endif // wxUSE_TOOLBAR
795 // ----------------------------------------------------------------------------
796 // frame state (iconized/maximized/...)
797 // ----------------------------------------------------------------------------
799 // propagate our state change to all child frames: this allows us to emulate X
800 // Windows behaviour where child frames float independently of the parent one
801 // on the desktop, but are iconized/restored with it
802 void wxFrame::IconizeChildFrames(bool bIconize
)
804 for ( wxWindowList::Node
*node
= GetChildren().GetFirst();
806 node
= node
->GetNext() )
808 wxWindow
*win
= node
->GetData();
810 if ( win
->IsKindOf(CLASSINFO(wxFrame
)) )
812 ((wxFrame
*)win
)->Iconize(bIconize
);
817 // ===========================================================================
818 // message processing
819 // ===========================================================================
821 // ---------------------------------------------------------------------------
823 // ---------------------------------------------------------------------------
825 bool wxFrame::OS2TranslateMessage(WXMSG
* pMsg
)
829 if ( wxWindow::OS2TranslateMessage(pMsg) )
832 // try the menu bar accels
833 wxMenuBar
*menuBar
= GetMenuBar();
837 const wxAcceleratorTable
& acceleratorTable
= menuBar
->GetAccelTable();
838 return acceleratorTable
.Translate(this, pMsg
);
841 // ---------------------------------------------------------------------------
842 // our private (non virtual) message handlers
843 // ---------------------------------------------------------------------------
845 bool wxFrame::HandlePaint()
850 if ( GetUpdateRect(GetHwnd(), &rect, FALSE) )
854 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
855 : (HICON)m_defaultIcon;
857 // Hold a pointer to the dc so long as the OnPaint() message
858 // is being processed
860 HDC hdc = ::BeginPaint(GetHwnd(), &ps);
862 // Erase background before painting or we get white background
863 MSWDefWindowProc(WM_ICONERASEBKGND, (WORD)(LONG)ps.hdc, 0L);
868 ::GetClientRect(GetHwnd(), &rect);
870 // FIXME: why hardcoded?
871 static const int icon_width = 32;
872 static const int icon_height = 32;
874 int icon_x = (int)((rect.right - icon_width)/2);
875 int icon_y = (int)((rect.bottom - icon_height)/2);
877 ::DrawIcon(hdc, icon_x, icon_y, hIcon);
880 ::EndPaint(GetHwnd(), &ps);
886 return wxWindow::HandlePaint();
891 // nothing to paint - processed
898 bool wxFrame::HandleSize(int x
, int y
, WXUINT id
)
900 bool processed
= FALSE
;
907 // only do it it if we were iconized before, otherwise resizing the
908 // parent frame has a curious side effect of bringing it under it's
913 // restore all child frames too
914 IconizeChildFrames(FALSE);
923 // iconize all child frames too
924 IconizeChildFrames(TRUE);
932 // forward WM_SIZE to status bar control
933 #if wxUSE_NATIVE_STATUSBAR
934 if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
936 wxSizeEvent event(wxSize(x, y), m_frameStatusBar->GetId());
937 event.SetEventObject( m_frameStatusBar );
939 ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event);
941 #endif // wxUSE_NATIVE_STATUSBAR
946 wxSizeEvent event(wxSize(x, y), m_windowId);
947 event.SetEventObject( this );
948 processed = GetEventHandler()->ProcessEvent(event);
954 bool wxFrame::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
960 // In case it's e.g. a toolbar.
961 wxWindow *win = wxFindWinFromHandle(control);
963 return win->MSWCommand(cmd, id);
966 // handle here commands from menus and accelerators
967 if ( cmd == 0 || cmd == 1 )
969 if ( wxCurrentPopupMenu )
971 wxMenu *popupMenu = wxCurrentPopupMenu;
972 wxCurrentPopupMenu = NULL;
974 return popupMenu->MSWCommand(cmd, id);
977 if ( ProcessCommand(id) )
986 bool wxFrame::HandleMenuSelect(WXWORD nItem
, WXWORD flags
, WXHMENU hMenu
)
989 if ( flags
== 0xFFFF && hMenu
== 0 )
991 // menu was removed from screen
996 else if ( !(flags & MF_POPUP) && !(flags & MF_SEPARATOR) )
1002 // don't give hints for separators (doesn't make sense) nor for the
1003 // items opening popup menus (they don't have them anyhow)
1007 wxMenuEvent
event(wxEVT_MENU_HIGHLIGHT
, item
);
1008 event
.SetEventObject( this );
1010 return GetEventHandler()->ProcessEvent(event
);
1013 // ---------------------------------------------------------------------------
1014 // the window proc for wxFrame
1015 // ---------------------------------------------------------------------------
1017 MRESULT
wxFrame::OS2WindowProc(HWND hwnd
, WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
1020 bool processed
= FALSE
;
1027 // if we can't close, tell the system that we processed the
1028 // message - otherwise it would close us
1029 processed = !Close();
1036 UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam,
1039 processed = HandleCommand(id, cmd, (WXHWND)hwnd);
1047 UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
1049 processed = HandleMenuSelect(item, flags, hmenu);
1054 processed = HandlePaint();
1057 case WM_QUERYDRAGICON:
1059 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
1060 : (HICON)(m_defaultIcon);
1062 processed = rc != 0;
1067 processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
1072 rc = wxWindow::MSWWindowProc(message, wParam, lParam);