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(const wxIcon
& icon
)
443 wxFrameBase::SetIcon(icon
);
449 SendMessage(GetHwnd(), WM_SETICON,
450 (WPARAM)TRUE, (LPARAM)(HICON) m_icon.GetHICON());
456 wxStatusBar
*wxFrame::OnCreateStatusBar(int number
,
459 const wxString
& name
)
461 wxStatusBar
*statusBar
= NULL
;
463 statusBar
= wxFrameBase::OnCreateStatusBar(number
, style
, id
, name
);
468 void wxFrame::PositionStatusBar()
472 // native status bar positions itself
473 if ( m_frameStatusBar )
476 GetClientSize(&w, &h);
478 m_frameStatusBar->GetSize(&sw, &sh);
480 // Since we wish the status bar to be directly under the client area,
481 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
482 m_frameStatusBar->SetSize(0, h, w, sh);
486 #endif // wxUSE_STATUSBAR
488 void wxFrame::DetachMenuBar()
492 m_frameMenuBar
->Detach();
493 m_frameMenuBar
= NULL
;
497 void wxFrame::SetMenuBar(wxMenuBar
*menu_bar
)
505 wxCHECK_RET( !menu_bar
->GetFrame(), wxT("this menubar is already attached") );
508 delete m_frameMenuBar
;
510 m_hMenu
= menu_bar
->Create();
515 InternalSetMenuBar();
517 m_frameMenuBar
= menu_bar
;
518 menu_bar
->Attach(this);
521 void wxFrame::InternalSetMenuBar()
525 if ( !::SetMenu(GetHwnd(), (HMENU)m_hMenu) )
527 wxLogLastError("SetMenu");
532 // Responds to colour changes, and passes event on to children.
533 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
537 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
540 if ( m_frameStatusBar )
542 wxSysColourChangedEvent event2;
543 event2.SetEventObject( m_frameStatusBar );
544 m_frameStatusBar->GetEventHandler()->ProcessEvent(event2);
547 // Propagate the event to the non-top-level children
548 wxWindow::OnSysColourChanged(event);
557 bool wxFrame::OS2Create(int id
, wxWindow
*parent
, const wxChar
*wclass
, wxWindow
*wx_win
, const wxChar
*title
,
558 int x
, int y
, int width
, int height
, long style
)
561 m_hDefaultIcon
= (WXHICON
) (wxSTD_FRAME_ICON
? wxSTD_FRAME_ICON
: wxDEFAULT_FRAME_ICON
);
563 // If child windows aren't properly drawn initially, WS_CLIPCHILDREN
564 // could be the culprit. But without it, you can get a lot of flicker.
569 if ((style & wxCAPTION) == wxCAPTION)
570 msflags = WS_OVERLAPPED;
574 if (style & wxMINIMIZE_BOX)
575 msflags |= WS_MINIMIZEBOX;
576 if (style & wxMAXIMIZE_BOX)
577 msflags |= WS_MAXIMIZEBOX;
578 if (style & wxTHICK_FRAME)
579 msflags |= WS_THICKFRAME;
580 if (style & wxSYSTEM_MENU)
581 msflags |= WS_SYSMENU;
582 if ((style & wxMINIMIZE) || (style & wxICONIZE))
583 msflags |= WS_MINIMIZE;
584 if (style & wxMAXIMIZE)
585 msflags |= WS_MAXIMIZE;
586 if (style & wxCAPTION)
587 msflags |= WS_CAPTION;
588 if (style & wxCLIP_CHILDREN)
589 msflags |= WS_CLIPCHILDREN;
591 // Keep this in wxFrame because it saves recoding this function
594 if (style & wxTINY_CAPTION_VERT)
595 msflags |= IBS_VERTCAPTION;
596 if (style & wxTINY_CAPTION_HORIZ)
597 msflags |= IBS_HORZCAPTION;
599 if (style & wxTINY_CAPTION_VERT)
600 msflags |= WS_CAPTION;
601 if (style & wxTINY_CAPTION_HORIZ)
602 msflags |= WS_CAPTION;
604 if ((style & wxTHICK_FRAME) == 0)
605 msflags |= WS_BORDER;
607 WXDWORD extendedStyle = MakeExtendedStyle(style);
609 #if !defined(__WIN16__) && !defined(__SC__)
610 if (style & wxFRAME_TOOL_WINDOW)
611 extendedStyle |= WS_EX_TOOLWINDOW;
614 if (style & wxSTAY_ON_TOP)
615 extendedStyle |= WS_EX_TOPMOST;
618 if ( !wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height,
619 msflags, NULL, extendedStyle) )
622 // Seems to be necessary if we use WS_POPUP
623 // style instead of WS_OVERLAPPED
624 if (width > -1 && height > -1)
625 ::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height));
630 // Default activation behaviour - set the focus for the first child
632 void wxFrame::OnActivate(wxActivateEvent
& event
)
634 for ( wxWindowList::Node
*node
= GetChildren().GetFirst();
636 node
= node
->GetNext() )
638 // FIXME all this is totally bogus - we need to do the same as wxPanel,
639 // but how to do it without duplicating the code?
642 wxWindow
*child
= node
->GetData();
644 if ( !child
->IsTopLevel()
646 && !wxDynamicCast(child
, wxToolBar
)
647 #endif // wxUSE_TOOLBAR
649 && !wxDynamicCast(child
, wxStatusBar
)
650 #endif // wxUSE_STATUSBAR
659 // ----------------------------------------------------------------------------
660 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
661 // from the client area, so the client area is what's really available for the
663 // ----------------------------------------------------------------------------
665 // Checks if there is a toolbar, and returns the first free client position
666 wxPoint
wxFrame::GetClientAreaOrigin() const
672 GetToolBar()->GetSize(& w
, & h
);
674 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL
)
686 void wxFrame::DoScreenToClient(int *x
, int *y
) const
688 wxWindow::DoScreenToClient(x
, y
);
690 // We may be faking the client origin.
691 // So a window that's really at (0, 30) may appear
692 // (to wxWin apps) to be at (0, 0).
693 wxPoint
pt(GetClientAreaOrigin());
698 void wxFrame::DoClientToScreen(int *x
, int *y
) const
700 // We may be faking the client origin.
701 // So a window that's really at (0, 30) may appear
702 // (to wxWin apps) to be at (0, 0).
703 wxPoint
pt1(GetClientAreaOrigin());
707 wxWindow::DoClientToScreen(x
, y
);
710 // ----------------------------------------------------------------------------
711 // tool/status bar stuff
712 // ----------------------------------------------------------------------------
716 wxToolBar
* wxFrame::CreateToolBar(long style
, wxWindowID id
, const wxString
& name
)
718 if ( wxFrameBase::CreateToolBar(style
, id
, name
) )
723 return m_frameToolBar
;
726 void wxFrame::PositionToolBar()
731 ::GetClientRect(GetHwnd(), &rect);
734 if ( GetStatusBar() )
736 int statusX, statusY;
737 GetStatusBar()->GetClientSize(&statusX, &statusY);
738 rect.bottom -= statusY;
740 #endif // wxUSE_STATUSBAR
745 GetToolBar()->GetSize(&tw, &th);
747 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
756 // Use the 'real' MSW position here
757 GetToolBar()->SetSize(0, 0, tw, th, wxSIZE_NO_ADJUSTMENTS);
761 #endif // wxUSE_TOOLBAR
763 // ----------------------------------------------------------------------------
764 // frame state (iconized/maximized/...)
765 // ----------------------------------------------------------------------------
767 // propagate our state change to all child frames: this allows us to emulate X
768 // Windows behaviour where child frames float independently of the parent one
769 // on the desktop, but are iconized/restored with it
770 void wxFrame::IconizeChildFrames(bool bIconize
)
772 for ( wxWindowList::Node
*node
= GetChildren().GetFirst();
774 node
= node
->GetNext() )
776 wxWindow
*win
= node
->GetData();
778 if ( win
->IsKindOf(CLASSINFO(wxFrame
)) )
780 ((wxFrame
*)win
)->Iconize(bIconize
);
785 // ===========================================================================
786 // message processing
787 // ===========================================================================
789 // ---------------------------------------------------------------------------
791 // ---------------------------------------------------------------------------
793 bool wxFrame::OS2TranslateMessage(WXMSG
* pMsg
)
797 if ( wxWindow::OS2TranslateMessage(pMsg) )
800 // try the menu bar accels
801 wxMenuBar
*menuBar
= GetMenuBar();
805 const wxAcceleratorTable
& acceleratorTable
= menuBar
->GetAccelTable();
806 return acceleratorTable
.Translate(this, pMsg
);
809 // ---------------------------------------------------------------------------
810 // our private (non virtual) message handlers
811 // ---------------------------------------------------------------------------
813 bool wxFrame::HandlePaint()
818 if ( GetUpdateRect(GetHwnd(), &rect, FALSE) )
822 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
823 : (HICON)m_defaultIcon;
825 // Hold a pointer to the dc so long as the OnPaint() message
826 // is being processed
828 HDC hdc = ::BeginPaint(GetHwnd(), &ps);
830 // Erase background before painting or we get white background
831 MSWDefWindowProc(WM_ICONERASEBKGND, (WORD)(LONG)ps.hdc, 0L);
836 ::GetClientRect(GetHwnd(), &rect);
838 // FIXME: why hardcoded?
839 static const int icon_width = 32;
840 static const int icon_height = 32;
842 int icon_x = (int)((rect.right - icon_width)/2);
843 int icon_y = (int)((rect.bottom - icon_height)/2);
845 ::DrawIcon(hdc, icon_x, icon_y, hIcon);
848 ::EndPaint(GetHwnd(), &ps);
854 return wxWindow::HandlePaint();
859 // nothing to paint - processed
866 bool wxFrame::HandleSize(int x
, int y
, WXUINT id
)
868 bool processed
= FALSE
;
875 // only do it it if we were iconized before, otherwise resizing the
876 // parent frame has a curious side effect of bringing it under it's
881 // restore all child frames too
882 IconizeChildFrames(FALSE);
891 // iconize all child frames too
892 IconizeChildFrames(TRUE);
900 // forward WM_SIZE to status bar control
901 #if wxUSE_NATIVE_STATUSBAR
902 if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
904 wxSizeEvent event(wxSize(x, y), m_frameStatusBar->GetId());
905 event.SetEventObject( m_frameStatusBar );
907 ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event);
909 #endif // wxUSE_NATIVE_STATUSBAR
914 wxSizeEvent event(wxSize(x, y), m_windowId);
915 event.SetEventObject( this );
916 processed = GetEventHandler()->ProcessEvent(event);
922 bool wxFrame::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
928 // In case it's e.g. a toolbar.
929 wxWindow *win = wxFindWinFromHandle(control);
931 return win->MSWCommand(cmd, id);
934 // handle here commands from menus and accelerators
935 if ( cmd == 0 || cmd == 1 )
937 if ( wxCurrentPopupMenu )
939 wxMenu *popupMenu = wxCurrentPopupMenu;
940 wxCurrentPopupMenu = NULL;
942 return popupMenu->MSWCommand(cmd, id);
945 if ( ProcessCommand(id) )
954 bool wxFrame::HandleMenuSelect(WXWORD nItem
, WXWORD flags
, WXHMENU hMenu
)
957 if ( flags
== 0xFFFF && hMenu
== 0 )
959 // menu was removed from screen
964 else if ( !(flags & MF_POPUP) && !(flags & MF_SEPARATOR) )
970 // don't give hints for separators (doesn't make sense) nor for the
971 // items opening popup menus (they don't have them anyhow)
975 wxMenuEvent
event(wxEVT_MENU_HIGHLIGHT
, item
);
976 event
.SetEventObject( this );
978 return GetEventHandler()->ProcessEvent(event
);
981 // ---------------------------------------------------------------------------
982 // the window proc for wxFrame
983 // ---------------------------------------------------------------------------
985 MRESULT
wxFrame::OS2WindowProc(HWND hwnd
, WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
988 bool processed
= FALSE
;
995 // if we can't close, tell the system that we processed the
996 // message - otherwise it would close us
997 processed = !Close();
1004 UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam,
1007 processed = HandleCommand(id, cmd, (WXHWND)hwnd);
1015 UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
1017 processed = HandleMenuSelect(item, flags, hmenu);
1022 processed = HandlePaint();
1025 case WM_QUERYDRAGICON:
1027 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
1028 : (HICON)(m_defaultIcon);
1030 processed = rc != 0;
1035 processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
1040 rc = wxWindow::MSWWindowProc(message, wParam, lParam);