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"
17 #include "wx/object.h"
18 #include "wx/dynarray.h"
21 #include "wx/string.h"
30 #include "wx/dialog.h"
31 #include "wx/settings.h"
32 #include "wx/dcclient.h"
35 #include "wx/os2/private.h"
38 #include "wx/statusbr.h"
39 #include "wx/generic/statusbr.h"
40 #endif // wxUSE_STATUSBAR
43 #include "wx/toolbar.h"
44 #endif // wxUSE_TOOLBAR
46 #include "wx/menuitem.h"
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 extern wxWindowList wxModelessWindows
;
54 extern wxList WXDLLEXPORT wxPendingDelete
;
55 extern wxChar wxFrameClassName
[];
57 #if wxUSE_MENUS_NATIVE
58 extern wxMenu
*wxCurrentPopupMenu
;
61 extern void wxAssociateWinWithHandle( HWND hWnd
65 // ----------------------------------------------------------------------------
67 // ----------------------------------------------------------------------------
69 BEGIN_EVENT_TABLE(wxFrame
, wxFrameBase
)
70 EVT_ACTIVATE(wxFrame::OnActivate
)
71 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged
)
74 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxWindow
)
76 // ============================================================================
78 // ============================================================================
80 // ----------------------------------------------------------------------------
81 // static class members
82 // ----------------------------------------------------------------------------
85 #if wxUSE_NATIVE_STATUSBAR
86 bool wxFrame::m_bUseNativeStatusBar
= TRUE
;
88 bool wxFrame::m_bUseNativeStatusBar
= FALSE
;
91 #endif //wxUSE_STATUSBAR
93 // ----------------------------------------------------------------------------
94 // creation/destruction
95 // ----------------------------------------------------------------------------
104 // Data to save/restore when calling ShowFullScreen
106 m_lFsOldWindowStyle
= 0L;
107 m_nFsStatusBarFields
= 0;
108 m_nFsStatusBarHeight
= 0;
109 m_nFsToolBarHeight
= 0;
110 m_bFsIsMaximized
= FALSE
;
111 m_bWasMinimized
= FALSE
;
112 m_bFsIsShowing
= FALSE
;
114 m_pWinLastFocused
= (wxWindow
*)NULL
;
124 memset(&m_vSwp
, 0, sizeof(SWP
));
125 memset(&m_vSwpClient
, 0, sizeof(SWP
));
126 memset(&m_vSwpTitleBar
, 0, sizeof(SWP
));
127 memset(&m_vSwpMenuBar
, 0, sizeof(SWP
));
128 memset(&m_vSwpHScroll
, 0, sizeof(SWP
));
129 memset(&m_vSwpVScroll
, 0, sizeof(SWP
));
130 memset(&m_vSwpStatusBar
, 0, sizeof(SWP
));
131 memset(&m_vSwpToolBar
, 0, sizeof(SWP
));
132 } // end of wxFrame::Init
134 bool wxFrame::Create(
137 , const wxString
& rsTitle
138 , const wxPoint
& rPos
139 , const wxSize
& rSize
141 , const wxString
& rsName
146 int nWidth
= rSize
.x
;
147 int nHeight
= rSize
.y
;
151 m_windowStyle
= lulStyle
;
152 m_frameMenuBar
= NULL
;
154 m_frameToolBar
= NULL
;
155 #endif //wxUSE_TOOLBAR
158 m_frameStatusBar
= NULL
;
159 #endif //wxUSE_STATUSBAR
161 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
166 m_windowId
= (int)NewControlId();
169 pParent
->AddChild(this);
173 if ((m_windowStyle
& wxFRAME_FLOAT_ON_PARENT
) == 0)
176 bOk
= OS2Create( m_windowId
190 wxTopLevelWindows
.Append(this);
191 wxModelessWindows
.Append(this);
194 } // end of wxFrame::Create
198 m_isBeingDeleted
= TRUE
;
200 wxTopLevelWindows
.DeleteObject(this);
204 if (wxTheApp
&& (wxTopLevelWindows
.Number() == 0))
206 wxTheApp
->SetTopWindow(NULL
);
208 if (wxTheApp
->GetExitOnFrameDelete())
210 ::WinPostMsg(NULL
, WM_QUIT
, 0, 0);
214 wxModelessWindows
.DeleteObject(this);
217 // For some reason, wxWindows can activate another task altogether
218 // when a frame is destroyed after a modal dialog has been invoked.
219 // Try to bring the parent to the top.
221 // MT:Only do this if this frame is currently the active window, else weird
222 // things start to happen.
224 if (wxGetActiveWindow() == this)
226 if (GetParent() && GetParent()->GetHWND())
228 ::WinSetWindowPos( (HWND
) GetParent()->GetHWND()
238 } // end of wxFrame::~wxFrame
241 // IF we have child controls in the Frame's client we need to alter
242 // the y position, because, OS/2 controls are positioned relative to
243 // wxWindows orgin (top left) not the OS/2 origin (bottom left)
244 void wxFrame::AlterChildPos()
247 // OS/2 is the only OS concerned about this
249 wxWindow
* pChild
= NULL
;
250 wxControl
* pCtrl
= NULL
;
254 ::WinQueryWindowRect(GetHwnd(), &vRect
);
255 for (wxWindowList::Node
* pNode
= GetChildren().GetFirst();
257 pNode
= pNode
->GetNext())
259 wxWindow
* pChild
= pNode
->GetData();
261 ::WinQueryWindowPos(pChild
->GetHWND(), &vSwp
);
262 vSwp
.y
+= (vRect
.yTop
- m_vSwpClient
.cy
);
263 if (pChild
->IsKindOf(CLASSINFO(wxControl
)))
265 pCtrl
= wxDynamicCast(pChild
, wxControl
);
267 // Must deal with controls that have margins like ENTRYFIELD. The SWP
268 // struct of such a control will have and origin offset from its intended
269 // position by the width of the margins.
271 vSwp
.y
-= pCtrl
->GetYComp();
272 vSwp
.x
-= pCtrl
->GetXComp();
274 ::WinSetWindowPos( pChild
->GetHWND()
282 ::WinQueryWindowPos(pChild
->GetHWND(), &vSwp
);
285 } // end of wxFrame::AlterChildPos
288 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
290 void wxFrame::DoGetClientSize(
296 ::WinQueryWindowRect(GetHwnd(), &vRect
);
299 // No need to use statusbar code as in WIN32 as the FORMATFRAME
300 // window procedure ensures PM knows about the new frame client
301 // size internally. A ::WinQueryWindowRect is all that is needed!
305 *pX
= vRect
.xRight
- vRect
.xLeft
;
307 *pY
= vRect
.yTop
- vRect
.yBottom
;
308 } // end of wxFrame::DoGetClientSize
311 // Set the client size (i.e. leave the calculation of borders etc.
314 void wxFrame::DoSetClientSize(
319 HWND hWnd
= GetHwnd();
323 ::WinQueryWindowRect(GetHwnd(), &vRect
);
324 ::WinQueryWindowRect(GetHwnd(), &vRect2
);
327 // Find the difference between the entire window (title bar and all)
328 // and the client area; add this to the new client size to move the
329 // window. Remember OS/2's backwards y coord system!
331 int nActualWidth
= vRect2
.xRight
- vRect2
.xLeft
- vRect
.xRight
;
332 int nActualHeight
= vRect2
.yTop
+ vRect2
.yTop
- vRect
.yTop
;
335 wxStatusBar
* pStatusBar
= GetStatusBar();
337 if (pStatusBar
&& pStatusBar
->IsShown())
339 nActualHeight
+= pStatusBar
->GetSize().y
;
342 #endif // wxUSE_STATUSBAR
344 wxPoint
vPoint(GetClientAreaOrigin());
346 nActualWidth
+= vPoint
.x
;
347 nActualHeight
+= vPoint
.y
;
351 vPointl
.x
= vRect2
.xLeft
;
352 vPointl
.y
= vRect2
.yTop
;
354 ::WinSetWindowPos( hWnd
360 ,SWP_MOVE
| SWP_SIZE
| SWP_SHOW
363 wxSizeEvent
vEvent( wxSize( nWidth
368 vEvent
.SetEventObject(this);
369 GetEventHandler()->ProcessEvent(vEvent
);
370 } // end of wxFrame::DoSetClientSize
372 void wxFrame::DoGetSize(
379 ::WinQueryWindowRect(m_hFrame
, &vRect
);
380 *pWidth
= vRect
.xRight
- vRect
.xLeft
;
381 *pHeight
= vRect
.yTop
- vRect
.yBottom
;
382 } // end of wxFrame::DoGetSize
384 void wxFrame::DoGetPosition(
392 ::WinQueryWindowRect(m_hFrame
, &vRect
);
394 *pX
= vRect
.xRight
- vRect
.xLeft
;
395 *pY
= vRect
.yTop
- vRect
.yBottom
;
396 } // end of wxFrame::DoGetPosition
398 // ----------------------------------------------------------------------------
399 // variations around ::ShowWindow()
400 // ----------------------------------------------------------------------------
402 void wxFrame::DoShowWindow(
406 ::WinShowWindow(m_hFrame
, (BOOL
)bShowCmd
);
407 m_bIconized
= bShowCmd
== SWP_MINIMIZE
;
408 } // end of wxFrame::DoShowWindow
426 DoShowWindow(nShowCmd
);
430 wxActivateEvent
vEvent(wxEVT_ACTIVATE
, TRUE
, m_windowId
);
432 ::WinQueryWindowPos(m_hFrame
, &vSwp
);
433 m_bIconized
= vSwp
.fl
& SWP_MINIMIZE
;
434 ::WinQueryWindowPos(m_hWnd
, &m_vSwpClient
);
435 ::WinSendMsg(m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)~0, 0);
436 ::WinEnableWindow(m_hFrame
, TRUE
);
437 vEvent
.SetEventObject(this);
438 GetEventHandler()->ProcessEvent(vEvent
);
443 // Try to highlight the correct window (the parent)
447 HWND hWndParent
= GetHwndOf(GetParent());
449 ::WinQueryWindowPos(hWndParent
, &vSwp
);
450 m_bIconized
= vSwp
.fl
& SWP_MINIMIZE
;
452 ::WinSetWindowPos( hWndParent
458 ,SWP_ZORDER
| SWP_ACTIVATE
| SWP_SHOW
| SWP_MOVE
460 ::WinEnableWindow(hWndParent
, TRUE
);
464 } // end of wxFrame::Show
466 void wxFrame::Iconize(
470 DoShowWindow(bIconize
? SWP_MINIMIZE
: SWP_RESTORE
);
471 } // end of wxFrame::Iconize
473 void wxFrame::Maximize(
476 DoShowWindow(bMaximize
? SWP_MAXIMIZE
: SWP_RESTORE
);
477 } // end of wxFrame::Maximize
479 void wxFrame::Restore()
481 DoShowWindow(SWP_RESTORE
);
482 } // end of wxFrame::Restore
484 bool wxFrame::IsIconized() const
488 ::WinQueryWindowPos(m_hFrame
, &vSwp
);
490 if (vSwp
.fl
& SWP_MINIMIZE
)
491 ((wxFrame
*)this)->m_bIconized
= TRUE
;
493 ((wxFrame
*)this)->m_bIconized
= FALSE
;
495 } // end of wxFrame::IsIconized
498 bool wxFrame::IsMaximized() const
503 ::WinQueryWindowPos(m_hFrame
, &vSwp
);
504 return (vSwp
.fl
& SWP_MAXIMIZE
);
505 } // end of wxFrame::IsMaximized
507 void wxFrame::SetIcon(
511 wxFrameBase::SetIcon(rIcon
);
513 if ((m_icon
.GetHICON()) != NULLHANDLE
)
515 ::WinSendMsg( m_hFrame
517 ,(MPARAM
)((HPOINTER
)m_icon
.GetHICON())
520 ::WinSendMsg( m_hFrame
526 } // end of wxFrame::SetIcon
529 wxStatusBar
* wxFrame::OnCreateStatusBar(
533 , const wxString
& rName
536 wxStatusBar
* pStatusBar
= NULL
;
541 pStatusBar
= wxFrameBase::OnCreateStatusBar( nNumber
550 ::WinSetParent( pStatusBar
->GetHWND()
554 ::WinSetOwner( pStatusBar
->GetHWND()
560 if(::WinIsWindowShowing(m_hFrame
))
561 ::WinSendMsg(m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)~0, 0);
564 } // end of wxFrame::OnCreateStatusBar
566 void wxFrame::PositionStatusBar()
573 // Native status bar positions itself
575 if (m_frameStatusBar
)
585 ::WinQueryWindowRect(m_hFrame
, &vRect
);
587 ::WinMapWindowPoints(m_hFrame
, HWND_DESKTOP
, (PPOINTL
)&vRect
, 2);
589 ::WinCalcFrameRect(m_hFrame
, &vRect
, TRUE
);
590 nWidth
= vRect
.xRight
- vRect
.xLeft
;
591 nY
= nY
- (vRect
.yBottom
- vFRect
.yBottom
);
593 m_frameStatusBar
->GetSize( &nStatbarWidth
597 nY
= nY
- nStatbarHeight
;
599 // Since we wish the status bar to be directly under the client area,
600 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
602 m_frameStatusBar
->SetSize( vRect
.xLeft
- vFRect
.xLeft
607 if (!::WinQueryWindowPos(m_frameStatusBar
->GetHWND(), &vSwp
))
609 vError
= ::WinGetLastError(vHabmain
);
610 sError
= wxPMErrorToStr(vError
);
611 wxLogError("Error setting parent for StautsBar. Error: %s\n", sError
);
615 } // end of wxFrame::PositionStatusBar
616 #endif // wxUSE_STATUSBAR
618 #if wxUSE_MENUS_NATIVE
619 void wxFrame::DetachMenuBar()
623 m_frameMenuBar
->Detach();
624 m_frameMenuBar
= NULL
;
626 } // end of wxFrame::DetachMenuBar
628 void wxFrame::SetMenuBar(
634 HWND hTitlebar
= NULLHANDLE
;
635 HWND hHScroll
= NULLHANDLE
;
636 HWND hVScroll
= NULLHANDLE
;
637 HWND hMenuBar
= NULLHANDLE
;
649 // Actually remove the menu from the frame
651 m_hMenu
= (WXHMENU
)0;
652 InternalSetMenuBar();
654 else // set new non NULL menu bar
656 m_frameMenuBar
= NULL
;
659 // Can set a menubar several times.
660 // TODO: how to prevent a memory leak if you have a currently-unattached
661 // menubar? wxWindows assumes that the frame will delete the menu (otherwise
662 // there are problems for MDI).
664 if (pMenuBar
->GetHMenu())
666 m_hMenu
= pMenuBar
->GetHMenu();
671 m_hMenu
= pMenuBar
->Create();
675 InternalSetMenuBar();
676 m_frameMenuBar
= pMenuBar
;
677 pMenuBar
->Attach((wxFrame
*)this);
679 } // end of wxFrame::SetMenuBar
681 void wxFrame::AttachMenuBar(
685 wxFrameBase::AttachMenuBar(pMenubar
);
687 m_frameMenuBar
= pMenubar
;
692 // Actually remove the menu from the frame
694 m_hMenu
= (WXHMENU
)0;
695 InternalSetMenuBar();
697 else // Set new non NULL menu bar
700 // Can set a menubar several times.
702 if (pMenubar
->GetHMenu())
704 m_hMenu
= pMenubar
->GetHMenu();
708 if (pMenubar
->IsAttached())
711 m_hMenu
= pMenubar
->Create();
716 InternalSetMenuBar();
718 } // end of wxFrame::AttachMenuBar
720 void wxFrame::InternalSetMenuBar()
725 // Set the parent and owner of the menubar to be the frame
727 if (!::WinSetParent(m_hMenu
, m_hFrame
, FALSE
))
729 vError
= ::WinGetLastError(vHabmain
);
730 sError
= wxPMErrorToStr(vError
);
731 wxLogError("Error setting parent for submenu. Error: %s\n", sError
);
734 if (!::WinSetOwner(m_hMenu
, m_hFrame
))
736 vError
= ::WinGetLastError(vHabmain
);
737 sError
= wxPMErrorToStr(vError
);
738 wxLogError("Error setting parent for submenu. Error: %s\n", sError
);
740 ::WinSendMsg(m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)FCF_MENU
, (MPARAM
)0);
741 } // end of wxFrame::InternalSetMenuBar
742 #endif // wxUSE_MENUS_NATIVE
745 // Responds to colour changes, and passes event on to children
747 void wxFrame::OnSysColourChanged(
748 wxSysColourChangedEvent
& rEvent
751 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
755 if (m_frameStatusBar
)
757 wxSysColourChangedEvent vEvent2
;
759 vEvent2
.SetEventObject(m_frameStatusBar
);
760 m_frameStatusBar
->GetEventHandler()->ProcessEvent(vEvent2
);
762 #endif //wxUSE_STATUSBAR
765 // Propagate the event to the non-top-level children
767 wxWindow::OnSysColourChanged(rEvent
);
768 } // end of wxFrame::OnSysColourChanged
770 // Pass TRUE to show full screen, FALSE to restore.
771 bool wxFrame::ShowFullScreen(
781 m_bFsIsShowing
= TRUE
;
785 wxToolBar
* pTheToolBar
= GetToolBar();
786 #endif //wxUSE_TOOLBAR
789 wxStatusBar
* pTheStatusBar
= GetStatusBar();
790 #endif //wxUSE_STATUSBAR
796 pTheToolBar
->GetSize(&nDummyWidth
, &m_nFsToolBarHeight
);
797 #endif //wxUSE_TOOLBAR
801 pTheStatusBar
->GetSize(&nDummyWidth
, &m_nFsStatusBarHeight
);
802 #endif //wxUSE_STATUSBAR
806 // Zap the toolbar, menubar, and statusbar
808 if ((lStyle
& wxFULLSCREEN_NOTOOLBAR
) && pTheToolBar
)
810 pTheToolBar
->SetSize(-1,0);
811 pTheToolBar
->Show(FALSE
);
813 #endif //wxUSE_TOOLBAR
815 if (lStyle
& wxFULLSCREEN_NOMENUBAR
)
817 ::WinSetParent(m_hMenu
, m_hFrame
, FALSE
);
818 ::WinSetOwner(m_hMenu
, m_hFrame
);
819 ::WinSendMsg((HWND
)m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)FCF_MENU
, (MPARAM
)0);
824 // Save the number of fields in the statusbar
826 if ((lStyle
& wxFULLSCREEN_NOSTATUSBAR
) && pTheStatusBar
)
828 m_nFsStatusBarFields
= pTheStatusBar
->GetFieldsCount();
829 SetStatusBar((wxStatusBar
*) NULL
);
830 delete pTheStatusBar
;
833 m_nFsStatusBarFields
= 0;
834 #endif //wxUSE_STATUSBAR
837 // Zap the frame borders
841 // Save the 'normal' window style
843 m_lFsOldWindowStyle
= ::WinQueryWindowULong(m_hFrame
, QWL_STYLE
);
846 // Save the old position, width & height, maximize state
848 m_vFsOldSize
= GetRect();
849 m_bFsIsMaximized
= IsMaximized();
852 // Decide which window style flags to turn off
854 LONG lNewStyle
= m_lFsOldWindowStyle
;
857 if (lStyle
& wxFULLSCREEN_NOBORDER
)
858 lOffFlags
|= FCF_BORDER
;
859 if (lStyle
& wxFULLSCREEN_NOCAPTION
)
860 lOffFlags
|= (FCF_TASKLIST
| FCF_SYSMENU
);
862 lNewStyle
&= (~lOffFlags
);
865 // Change our window style to be compatible with full-screen mode
867 ::WinSetWindowULong((HWND
)m_hFrame
, QWL_STYLE
, (ULONG
)lNewStyle
);
870 // Resize to the size of the desktop
876 ::WinQueryWindowRect(HWND_DESKTOP
, &vRect
);
877 nWidth
= vRect
.xRight
- vRect
.xLeft
;
879 // Rmember OS/2 is backwards!
881 nHeight
= vRect
.yTop
- vRect
.yBottom
;
888 // Now flush the window style cache and actually go full-screen
890 ::WinSetWindowPos( (HWND
) GetParent()->GetHWND()
899 wxSizeEvent
vEvent( wxSize( nWidth
905 GetEventHandler()->ProcessEvent(vEvent
);
913 m_bFsIsShowing
= FALSE
;
916 wxToolBar
* pTheToolBar
= GetToolBar();
919 // Restore the toolbar, menubar, and statusbar
921 if (pTheToolBar
&& (m_lFsStyle
& wxFULLSCREEN_NOTOOLBAR
))
923 pTheToolBar
->SetSize(-1, m_nFsToolBarHeight
);
924 pTheToolBar
->Show(TRUE
);
926 #endif //wxUSE_TOOLBAR
929 if ((m_lFsStyle
& wxFULLSCREEN_NOSTATUSBAR
) && (m_nFsStatusBarFields
> 0))
931 CreateStatusBar(m_nFsStatusBarFields
);
932 // PositionStatusBar();
934 #endif //wxUSE_STATUSBAR
936 if ((m_lFsStyle
& wxFULLSCREEN_NOMENUBAR
) && (m_hMenu
!= 0))
938 ::WinSetParent(m_hMenu
, m_hFrame
, FALSE
);
939 ::WinSetOwner(m_hMenu
, m_hFrame
);
940 ::WinSendMsg(m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)FCF_MENU
, (MPARAM
)0);
942 Maximize(m_bFsIsMaximized
);
944 ::WinSetWindowULong( m_hFrame
946 ,(ULONG
)m_lFsOldWindowStyle
948 ::WinSetWindowPos( (HWND
) GetParent()->GetHWND()
958 } // end of wxFrame::ShowFullScreen
963 bool wxFrame::OS2Create(
966 , const wxChar
* zWclass
968 , const wxChar
* zTitle
976 ULONG ulCreateFlags
= 0L;
977 ULONG ulStyleFlags
= 0L;
978 ULONG ulExtraFlags
= 0L;
979 FRAMECDATA vFrameCtlData
;
980 HWND hParent
= NULLHANDLE
;
981 HWND hTitlebar
= NULLHANDLE
;
982 HWND hHScroll
= NULLHANDLE
;
983 HWND hVScroll
= NULLHANDLE
;
984 HWND hFrame
= NULLHANDLE
;
985 HWND hClient
= NULLHANDLE
;
992 m_hDefaultIcon
= (WXHICON
) (wxSTD_FRAME_ICON
? wxSTD_FRAME_ICON
: wxDEFAULT_FRAME_ICON
);
995 hParent
= GetWinHwnd(pParent
);
997 hParent
= HWND_DESKTOP
;
999 if (ulStyle
== wxDEFAULT_FRAME_STYLE
)
1000 ulCreateFlags
= FCF_SIZEBORDER
| FCF_TITLEBAR
| FCF_SYSMENU
|
1001 FCF_MINMAX
| FCF_TASKLIST
;
1004 if ((ulStyle
& wxCAPTION
) == wxCAPTION
)
1005 ulCreateFlags
= FCF_TASKLIST
;
1007 ulCreateFlags
= FCF_NOMOVEWITHOWNER
;
1009 if ((ulStyle
& wxVSCROLL
) == wxVSCROLL
)
1010 ulCreateFlags
|= FCF_VERTSCROLL
;
1011 if ((ulStyle
& wxHSCROLL
) == wxHSCROLL
)
1012 ulCreateFlags
|= FCF_HORZSCROLL
;
1013 if (ulStyle
& wxMINIMIZE_BOX
)
1014 ulCreateFlags
|= FCF_MINBUTTON
;
1015 if (ulStyle
& wxMAXIMIZE_BOX
)
1016 ulCreateFlags
|= FCF_MAXBUTTON
;
1017 if (ulStyle
& wxTHICK_FRAME
)
1018 ulCreateFlags
|= FCF_DLGBORDER
;
1019 if (ulStyle
& wxSYSTEM_MENU
)
1020 ulCreateFlags
|= FCF_SYSMENU
;
1021 if (ulStyle
& wxCAPTION
)
1022 ulCreateFlags
|= FCF_TASKLIST
;
1023 if (ulStyle
& wxCLIP_CHILDREN
)
1025 // Invalid for frame windows under PM
1028 if (ulStyle
& wxTINY_CAPTION_VERT
)
1029 ulCreateFlags
|= FCF_TASKLIST
;
1030 if (ulStyle
& wxTINY_CAPTION_HORIZ
)
1031 ulCreateFlags
|= FCF_TASKLIST
;
1033 if ((ulStyle
& wxTHICK_FRAME
) == 0)
1034 ulCreateFlags
|= FCF_BORDER
;
1035 if (ulStyle
& wxFRAME_TOOL_WINDOW
)
1036 ulExtraFlags
= kFrameToolWindow
;
1038 if (ulStyle
& wxSTAY_ON_TOP
)
1039 ulCreateFlags
|= FCF_SYSMODAL
;
1041 if ((ulStyle
& wxMINIMIZE
) || (ulStyle
& wxICONIZE
))
1042 ulStyleFlags
|= WS_MINIMIZED
;
1043 if (ulStyle
& wxMAXIMIZE
)
1044 ulStyleFlags
|= WS_MAXIMIZED
;
1047 // Clear the visible flag, we always call show
1049 ulStyleFlags
&= (unsigned long)~WS_VISIBLE
;
1050 m_bIconized
= FALSE
;
1053 // Set the frame control block
1055 vFrameCtlData
.cb
= sizeof(vFrameCtlData
);
1056 vFrameCtlData
.flCreateFlags
= ulCreateFlags
;
1057 vFrameCtlData
.hmodResources
= 0L;
1058 vFrameCtlData
.idResources
= 0;
1061 // Create the frame window: We break ranks with other ports now
1062 // and instead of calling down into the base wxWindow class' OS2Create
1063 // we do all our own stuff here. We will set the needed pieces
1064 // of wxWindow manually, here.
1067 hFrame
= ::WinCreateStdWindow( hParent
1068 ,ulStyleFlags
// frame-window style
1069 ,&ulCreateFlags
// window style
1070 ,(PSZ
)zWclass
// class name
1071 ,(PSZ
)zTitle
// window title
1072 ,0L // default client style
1073 ,NULLHANDLE
// resource in executable file
1075 ,&hClient
// receives client window handle
1079 vError
= ::WinGetLastError(vHabmain
);
1080 sError
= wxPMErrorToStr(vError
);
1081 wxLogError("Error creating frame. Error: %s\n", sError
);
1086 // wxWindow class' m_hWnd set here and needed associations
1090 wxAssociateWinWithHandle(m_hWnd
, this);
1091 wxAssociateWinWithHandle(m_hFrame
, this);
1093 m_backgroundColour
.Set(wxString("GREY"));
1095 LONG lColor
= (LONG
)m_backgroundColour
.GetPixel();
1097 if (!::WinSetPresParam( m_hWnd
1103 vError
= ::WinGetLastError(vHabmain
);
1104 sError
= wxPMErrorToStr(vError
);
1105 wxLogError("Error creating frame. Error: %s\n", sError
);
1110 // Now need to subclass window. Instead of calling the SubClassWin in wxWindow
1111 // we manually subclass here because we don't want to use the main wxWndProc
1114 m_fnOldWndProc
= (WXFARPROC
) ::WinSubclassWindow(m_hFrame
, (PFNWP
)wxFrameMainWndProc
);
1117 // Now size everything. If adding a menu the client will need to be resized.
1122 nY
= pParent
->GetSize().y
- (nY
+ nHeight
);
1128 ::WinQueryWindowRect(HWND_DESKTOP
, &vRect
);
1129 nY
= vRect
.yTop
- (nY
+ nHeight
);
1131 if (!::WinSetWindowPos( m_hFrame
1137 ,SWP_SIZE
| SWP_MOVE
| SWP_ACTIVATE
| SWP_ZORDER
1140 vError
= ::WinGetLastError(vHabmain
);
1141 sError
= wxPMErrorToStr(vError
);
1142 wxLogError("Error sizing frame. Error: %s\n", sError
);
1146 } // end of wxFrame::OS2Create
1149 // Default activation behaviour - set the focus for the first child
1152 void wxFrame::OnActivate(
1153 wxActivateEvent
& rEvent
1156 if ( rEvent
.GetActive() )
1158 // restore focus to the child which was last focused
1159 wxLogTrace(_T("focus"), _T("wxFrame %08x activated."), m_hWnd
);
1161 wxWindow
* pParent
= m_pWinLastFocused
? m_pWinLastFocused
->GetParent()
1168 wxSetFocusToChild( pParent
1172 else // deactivating
1175 // Remember the last focused child if it is our child
1177 m_pWinLastFocused
= FindFocus();
1179 for (wxWindowList::Node
* pNode
= GetChildren().GetFirst();
1181 pNode
= pNode
->GetNext())
1183 // FIXME all this is totally bogus - we need to do the same as wxPanel,
1184 // but how to do it without duplicating the code?
1187 wxWindow
* pChild
= pNode
->GetData();
1189 if (!pChild
->IsTopLevel()
1191 && !wxDynamicCast(pChild
, wxToolBar
)
1192 #endif // wxUSE_TOOLBAR
1194 && !wxDynamicCast(pChild
, wxStatusBar
)
1195 #endif // wxUSE_STATUSBAR
1203 } // end of wxFrame::OnActivate
1205 // ----------------------------------------------------------------------------
1206 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
1207 // from the client area, so the client area is what's really available for the
1209 // ----------------------------------------------------------------------------
1211 // Checks if there is a toolbar, and returns the first free client position
1212 wxPoint
wxFrame::GetClientAreaOrigin() const
1214 wxPoint
vPoint(0, 0);
1222 GetToolBar()->GetSize( &nWidth
1226 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL
)
1232 // PM is backwards from windows
1233 vPoint
.y
+= nHeight
;
1236 #endif //wxUSE_TOOLBAR
1238 } // end of wxFrame::GetClientAreaOrigin
1240 // ----------------------------------------------------------------------------
1241 // tool/status bar stuff
1242 // ----------------------------------------------------------------------------
1246 wxToolBar
* wxFrame::CreateToolBar(
1249 , const wxString
& rName
1252 if (wxFrameBase::CreateToolBar( lStyle
1259 return m_frameToolBar
;
1260 } // end of wxFrame::CreateToolBar
1262 void wxFrame::PositionToolBar()
1267 ::WinQueryWindowRect(GetHwnd(), &vRect
);
1275 GetStatusBar()->GetClientSize( &nStatusX
1278 // PM is backwards from windows
1279 vRect
.yBottom
+= nStatusY
;
1281 #endif // wxUSE_STATUSBAR
1283 if ( m_frameToolBar
)
1288 m_frameToolBar
->GetSize( &nToolbarWidth
1292 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL
)
1294 nToolbarHeight
= vRect
.yBottom
;
1298 nToolbarWidth
= vRect
.xRight
;
1302 // Use the 'real' PM position here
1304 GetToolBar()->SetSize( 0
1308 ,wxSIZE_NO_ADJUSTMENTS
1311 } // end of wxFrame::PositionToolBar
1312 #endif // wxUSE_TOOLBAR
1314 // ----------------------------------------------------------------------------
1315 // frame state (iconized/maximized/...)
1316 // ----------------------------------------------------------------------------
1319 // propagate our state change to all child frames: this allows us to emulate X
1320 // Windows behaviour where child frames float independently of the parent one
1321 // on the desktop, but are iconized/restored with it
1323 void wxFrame::IconizeChildFrames(
1327 for (wxWindowList::Node
* pNode
= GetChildren().GetFirst();
1329 pNode
= pNode
->GetNext() )
1331 wxWindow
* pWin
= pNode
->GetData();
1332 wxFrame
* pFrame
= wxDynamicCast(pWin
, wxFrame
);
1335 #if wxUSE_MDI_ARCHITECTURE
1336 && !wxDynamicCast(pFrame
, wxMDIChildFrame
)
1337 #endif // wxUSE_MDI_ARCHITECTURE
1341 // We don't want to restore the child frames which had been
1342 // iconized even before we were iconized, so save the child frame
1343 // status when iconizing the parent frame and check it when
1348 pFrame
->m_bWasMinimized
= pFrame
->IsIconized();
1352 // This test works for both iconizing and restoring
1354 if (!pFrame
->m_bWasMinimized
)
1355 pFrame
->Iconize(bIconize
);
1358 } // end of wxFrame::IconizeChildFrames
1360 // ===========================================================================
1361 // message processing
1362 // ===========================================================================
1364 // ---------------------------------------------------------------------------
1366 // ---------------------------------------------------------------------------
1367 bool wxFrame::OS2TranslateMessage(
1372 // try the menu bar accels
1374 wxMenuBar
* pMenuBar
= GetMenuBar();
1379 #if wxUSE_ACCEL && wxUSE_MENUS_NATIVE
1380 const wxAcceleratorTable
& rAcceleratorTable
= pMenuBar
->GetAccelTable();
1381 return rAcceleratorTable
.Translate(GetHWND(), pMsg
);
1384 #endif //wxUSE_ACCEL
1385 } // end of wxFrame::OS2TranslateMessage
1387 // ---------------------------------------------------------------------------
1388 // our private (non virtual) message handlers
1389 // ---------------------------------------------------------------------------
1390 bool wxFrame::HandlePaint()
1394 if (::WinQueryUpdateRect(GetHWND(), &vRect
))
1399 // Icons in PM are the same as "pointers"
1404 hIcon
= (HPOINTER
)::WinSendMsg(m_hFrame
, WM_QUERYICON
, 0L, 0L);
1406 hIcon
= (HPOINTER
)m_hDefaultIcon
;
1409 // Hold a pointer to the dc so long as the OnPaint() message
1410 // is being processed
1413 HPS hPs
= ::WinBeginPaint(GetHwnd(), NULLHANDLE
, &vRect2
);
1416 // Erase background before painting or we get white background
1418 OS2DefWindowProc(WM_ERASEBACKGROUND
, (MPARAM
)hPs
, (MPARAM
)&vRect2
);
1425 ::WinQueryWindowRect(GetHwnd(), &vRect3
);
1427 static const int nIconWidth
= 32;
1428 static const int nIconHeight
= 32;
1429 int nIconX
= (int)((vRect3
.xRight
- nIconWidth
)/2);
1430 int nIconY
= (int)((vRect3
.yBottom
+ nIconHeight
)/2);
1432 ::WinDrawPointer(hPs
, nIconX
, nIconY
, hIcon
, DP_NORMAL
);
1439 if (!wxWindow::HandlePaint())
1444 hPS
= ::WinBeginPaint( GetHwnd()
1450 ::GpiCreateLogColorTable( hPS
1454 ,(LONG
)wxTheColourDatabase
->m_nSize
1455 ,(PLONG
)wxTheColourDatabase
->m_palTable
1457 ::GpiCreateLogColorTable( hPS
1467 ,GetBackgroundColour().GetPixel()
1477 // nothing to paint - processed
1481 } // end of wxFrame::HandlePaint
1483 bool wxFrame::HandleSize(
1489 bool bProcessed
= FALSE
;
1495 // Only do it it if we were iconized before, otherwise resizing the
1496 // parent frame has a curious side effect of bringing it under it's
1502 // restore all child frames too
1504 IconizeChildFrames(FALSE
);
1505 (void)SendIconizeEvent(FALSE
);
1512 m_bIconized
= FALSE
;
1517 // Iconize all child frames too
1519 IconizeChildFrames(TRUE
);
1520 (void)SendIconizeEvent();
1528 // forward WM_SIZE to status bar control
1530 #if wxUSE_NATIVE_STATUSBAR
1531 if (m_frameStatusBar
&& m_frameStatusBar
->IsKindOf(CLASSINFO(wxStatusBar95
)))
1533 wxSizeEvent
vEvent( wxSize( nX
1536 ,m_frameStatusBar
->GetId()
1539 vEvent
.SetEventObject(m_frameStatusBar
);
1540 m_frameStatusBar
->OnSize(vEvent
);
1542 #endif // wxUSE_NATIVE_STATUSBAR
1544 PositionStatusBar();
1547 #endif // wxUSE_TOOLBAR
1549 wxSizeEvent
vEvent( wxSize( nX
1555 vEvent
.SetEventObject(this);
1556 bProcessed
= GetEventHandler()->ProcessEvent(vEvent
);
1560 } // end of wxFrame::HandleSize
1562 bool wxFrame::HandleCommand(
1571 // In case it's e.g. a toolbar.
1573 wxWindow
* pWin
= wxFindWinFromHandle(hControl
);
1576 return pWin
->OS2Command( nCmd
1582 // Handle here commands from menus and accelerators
1584 if (nCmd
== CMDSRC_MENU
|| nCmd
== CMDSRC_ACCELERATOR
)
1586 #if wxUSE_MENUS_NATIVE
1587 if (wxCurrentPopupMenu
)
1589 wxMenu
* pPopupMenu
= wxCurrentPopupMenu
;
1591 wxCurrentPopupMenu
= NULL
;
1593 return pPopupMenu
->OS2Command( nCmd
1600 if (ProcessCommand(nId
))
1606 } // end of wxFrame::HandleCommand
1608 bool wxFrame::HandleMenuSelect(
1619 rc
= ::WinSendMsg(hMenu
, MM_QUERYITEM
, MPFROM2SHORT(nItem
, TRUE
), (MPARAM
)&mItem
);
1621 if(rc
&& !(mItem
.afStyle
& (MIS_SUBMENU
| MIS_SEPARATOR
)))
1623 wxMenuEvent
vEvent(wxEVT_MENU_HIGHLIGHT
, nItem
);
1625 vEvent
.SetEventObject(this);
1626 GetEventHandler()->ProcessEvent(vEvent
); // return value would be ignored by PM
1630 } // end of wxFrame::HandleMenuSelect
1632 // ---------------------------------------------------------------------------
1633 // Main Frame window proc
1634 // ---------------------------------------------------------------------------
1635 MRESULT EXPENTRY
wxFrameMainWndProc(
1642 MRESULT rc
= (MRESULT
)0;
1643 bool bProcessed
= FALSE
;
1644 wxFrame
* pWnd
= NULL
;
1646 pWnd
= (wxFrame
*) wxFindWinFromHandle((WXHWND
) hWnd
);
1649 case WM_QUERYFRAMECTLCOUNT
:
1650 if(pWnd
&& pWnd
->m_fnOldWndProc
)
1652 USHORT uItemCount
= SHORT1FROMMR(pWnd
->m_fnOldWndProc(hWnd
, ulMsg
, wParam
, lParam
));
1654 rc
= MRFROMSHORT(uItemCount
);
1658 case WM_FORMATFRAME
:
1659 /////////////////////////////////////////////////////////////////////////////////
1660 // Applications that subclass frame controls may find that the frame is already
1661 // subclassed the number of frame controls is variable.
1662 // The WM_FORMATFRAME and WM_QUERYFRAMECTLCOUNT messages must always be
1663 // subclassed by calling the previous window procedure and modifying its result.
1664 ////////////////////////////////////////////////////////////////////////////////
1674 pSWP
= (PSWP
)PVOIDFROMMP(wParam
);
1675 nItemCount
= SHORT1FROMMR(pWnd
->m_fnOldWndProc(hWnd
, ulMsg
, wParam
, lParam
));
1676 if(pWnd
->m_frameStatusBar
)
1678 ::WinQueryWindowRect(pWnd
->m_frameStatusBar
->GetHWND(), &vRstb
);
1679 pWnd
->m_frameStatusBar
->GetSize(NULL
, &nHeight
);
1680 ::WinQueryWindowRect(pWnd
->m_hFrame
, &vRectl
);
1681 ::WinMapWindowPoints(pWnd
->m_hFrame
, HWND_DESKTOP
, (PPOINTL
)&vRectl
, 2);
1683 ::WinCalcFrameRect(pWnd
->m_hFrame
, &vRectl
, TRUE
);
1685 vSwpStb
.x
= vRectl
.xLeft
- vRstb
.xLeft
;
1686 vSwpStb
.y
= vRectl
.yBottom
- vRstb
.yBottom
;
1687 vSwpStb
.cx
= vRectl
.xRight
- vRectl
.xLeft
- 1; //?? -1 ??
1688 vSwpStb
.cy
= nHeight
;
1689 vSwpStb
.fl
= SWP_SIZE
|SWP_MOVE
| SWP_SHOW
;
1690 vSwpStb
.hwnd
= pWnd
->m_frameStatusBar
->GetHWND();
1691 vSwpStb
.hwndInsertBehind
= HWND_TOP
;
1693 ::WinQueryWindowRect(pWnd
->m_hFrame
, &vRectl
);
1694 ::WinMapWindowPoints(pWnd
->m_hFrame
, HWND_DESKTOP
, (PPOINTL
)&vRectl
, 2);
1695 ::WinCalcFrameRect(pWnd
->m_hFrame
, &vRectl
, TRUE
);
1696 ::WinMapWindowPoints(HWND_DESKTOP
, pWnd
->m_hFrame
, (PPOINTL
)&vRectl
, 2);
1697 for(i
= 0; i
< nItemCount
; i
++)
1699 if(pWnd
->m_hWnd
&& pSWP
[i
].hwnd
== pWnd
->m_hWnd
)
1701 pSWP
[i
].x
= vRectl
.xLeft
;
1702 pSWP
[i
].y
= vRectl
.yBottom
+ nHeight
;
1703 pSWP
[i
].cx
= vRectl
.xRight
- vRectl
.xLeft
;
1704 pSWP
[i
].cy
= vRectl
.yTop
- vRectl
.yBottom
- nHeight
;
1705 pSWP
[i
].fl
= SWP_SIZE
| SWP_MOVE
| SWP_SHOW
;
1706 pSWP
[i
].hwndInsertBehind
= HWND_TOP
;
1710 rc
= MRFROMSHORT(nItemCount
);
1715 if(pWnd
&& pWnd
->m_fnOldWndProc
)
1716 rc
= pWnd
->m_fnOldWndProc(hWnd
, ulMsg
, wParam
, lParam
);
1718 rc
= ::WinDefWindowProc(hWnd
, ulMsg
, wParam
, lParam
);
1721 } // end of wxFrameMainWndProc
1723 MRESULT EXPENTRY
wxFrameWndProc(
1731 // Trace all ulMsgs - useful for the debugging
1734 wxFrame
* pWnd
= NULL
;
1736 parentHwnd
= WinQueryWindow(hWnd
,QW_PARENT
);
1737 pWnd
= (wxFrame
*) wxFindWinFromHandle((WXHWND
) hWnd
);
1740 // When we get the first message for the HWND we just created, we associate
1741 // it with wxWindow stored in wxWndHook
1744 MRESULT rc
= (MRESULT
)0;
1745 bool bProcessed
= FALSE
;
1748 // Stop right here if we don't have a valid handle in our wxWindow object.
1750 if (pWnd
&& !pWnd
->GetHWND())
1752 pWnd
->SetHWND((WXHWND
) hWnd
);
1753 rc
= pWnd
->OS2DefWindowProc(ulMsg
, wParam
, lParam
);
1759 rc
= pWnd
->OS2WindowProc(ulMsg
, wParam
, lParam
);
1761 rc
= ::WinDefWindowProc(hWnd
, ulMsg
, wParam
, lParam
);
1764 } // end of wxFrameWndProc
1766 MRESULT
wxFrame::OS2WindowProc(
1773 bool bProcessed
= FALSE
;
1779 // If we can't close, tell the system that we processed the
1780 // message - otherwise it would close us
1782 bProcessed
= !Close();
1786 bProcessed
= HandlePaint();
1787 mRc
= (MRESULT
)FALSE
;
1790 case WM_ERASEBACKGROUND
:
1792 // Returning TRUE to requests PM to paint the window background
1793 // in SYSCLR_WINDOW. We capture this here because the PS returned
1794 // in Frames is the PS for the whole frame, which we can't really
1795 // use at all. If you want to paint a different background, do it
1796 // in an OnPaint using a wxPaintDC.
1798 mRc
= (MRESULT
)(TRUE
);
1807 UnpackCommand( (WXWPARAM
)wParam
1814 bProcessed
= HandleCommand( wId
1827 UnpackMenuSelect( wParam
1833 bProcessed
= HandleMenuSelect( wItem
1837 mRc
= (MRESULT
)TRUE
;
1843 SHORT nScxold
= SHORT1FROMMP(wParam
); // Old horizontal size.
1844 SHORT nScyold
= SHORT2FROMMP(wParam
); // Old vertical size.
1845 SHORT nScxnew
= SHORT1FROMMP(lParam
); // New horizontal size.
1846 SHORT nScynew
= SHORT2FROMMP(lParam
); // New vertical size.
1848 lParam
= MRFROM2SHORT( nScxnew
- 20
1852 bProcessed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), (WXUINT
)wParam
);
1853 mRc
= (MRESULT
)FALSE
;
1856 case CM_QUERYDRAGIMAGE
:
1861 hIcon
= (HPOINTER
)::WinSendMsg(GetHWND(), WM_QUERYICON
, 0L, 0L);
1863 hIcon
= (HPOINTER
)m_hDefaultIcon
;
1864 mRc
= (MRESULT
)hIcon
;
1865 bProcessed
= mRc
!= 0;
1871 mRc
= wxWindow::OS2WindowProc( uMessage
1875 return (MRESULT
)mRc
;
1876 } // wxFrame::OS2WindowProc
1878 void wxFrame::SetClient(WXHWND c_Hwnd
)
1880 // Duh...nothing to do under OS/2
1883 void wxFrame::SetClient(
1887 wxWindow
* pOldClient
= this->GetClient();
1888 bool bClientHasFocus
= pOldClient
&& (pOldClient
== wxWindow::FindFocus());
1890 if(pOldClient
== pWindow
) // nothing to do
1892 if(pWindow
== NULL
) // just need to remove old client
1894 if(pOldClient
== NULL
) // nothing to do
1897 if(bClientHasFocus
)
1900 pOldClient
->Enable( FALSE
);
1901 pOldClient
->Show( FALSE
);
1902 ::WinSetWindowUShort(pOldClient
->GetHWND(), QWS_ID
, (USHORT
)pOldClient
->GetId());
1903 // to avoid OS/2 bug need to update frame
1904 ::WinSendMsg((HWND
)this->GetFrame(), WM_UPDATEFRAME
, (MPARAM
)~0, 0);
1909 // Else need to change client
1914 ::WinEnableWindowUpdate((HWND
)GetHWND(), FALSE
);
1917 pOldClient
->Enable(FALSE
);
1918 pOldClient
->Show(FALSE
);
1919 ::WinSetWindowUShort(pOldClient
->GetHWND(), QWS_ID
, (USHORT
)pOldClient
->GetId());
1921 pWindow
->Reparent(this);
1922 ::WinSetWindowUShort(pWindow
->GetHWND(), QWS_ID
, FID_CLIENT
);
1923 ::WinEnableWindowUpdate((HWND
)GetHWND(), TRUE
);
1925 pWindow
->Show(); // ensure client is showing
1926 if( this->IsShown() )
1929 ::WinSendMsg(m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)~0, 0);
1933 wxWindow
* wxFrame::GetClient()
1935 return wxFindWinFromHandle((WXHWND
)::WinWindowFromID(m_hFrame
, FID_CLIENT
));