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_bFsIsShowing
= FALSE
;
113 m_pWinLastFocused
= (wxWindow
*)NULL
;
123 memset(&m_vSwp
, 0, sizeof(SWP
));
124 memset(&m_vSwpClient
, 0, sizeof(SWP
));
125 memset(&m_vSwpTitleBar
, 0, sizeof(SWP
));
126 memset(&m_vSwpMenuBar
, 0, sizeof(SWP
));
127 memset(&m_vSwpHScroll
, 0, sizeof(SWP
));
128 memset(&m_vSwpVScroll
, 0, sizeof(SWP
));
129 memset(&m_vSwpStatusBar
, 0, sizeof(SWP
));
130 memset(&m_vSwpToolBar
, 0, sizeof(SWP
));
131 } // end of wxFrame::Init
133 bool wxFrame::Create(
136 , const wxString
& rsTitle
137 , const wxPoint
& rPos
138 , const wxSize
& rSize
140 , const wxString
& rsName
145 int nWidth
= rSize
.x
;
146 int nHeight
= rSize
.y
;
150 m_windowStyle
= lulStyle
;
151 m_frameMenuBar
= NULL
;
153 m_frameToolBar
= NULL
;
154 #endif //wxUSE_TOOLBAR
157 m_frameStatusBar
= NULL
;
158 #endif //wxUSE_STATUSBAR
160 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
165 m_windowId
= (int)NewControlId();
168 pParent
->AddChild(this);
172 if ((m_windowStyle
& wxFRAME_FLOAT_ON_PARENT
) == 0)
175 bOk
= OS2Create( m_windowId
189 wxTopLevelWindows
.Append(this);
190 wxModelessWindows
.Append(this);
193 } // end of wxFrame::Create
197 m_isBeingDeleted
= TRUE
;
199 wxTopLevelWindows
.DeleteObject(this);
203 if (wxTheApp
&& (wxTopLevelWindows
.Number() == 0))
205 wxTheApp
->SetTopWindow(NULL
);
207 if (wxTheApp
->GetExitOnFrameDelete())
209 ::WinPostMsg(NULL
, WM_QUIT
, 0, 0);
213 wxModelessWindows
.DeleteObject(this);
216 // For some reason, wxWindows can activate another task altogether
217 // when a frame is destroyed after a modal dialog has been invoked.
218 // Try to bring the parent to the top.
220 // MT:Only do this if this frame is currently the active window, else weird
221 // things start to happen.
223 if (wxGetActiveWindow() == this)
225 if (GetParent() && GetParent()->GetHWND())
227 ::WinSetWindowPos( (HWND
) GetParent()->GetHWND()
237 } // end of wxFrame::~wxFrame
240 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
242 void wxFrame::DoGetClientSize(
248 ::WinQueryWindowRect(GetHwnd(), &vRect
);
251 // No need to use statusbar code as in WIN32 as the FORMATFRAME
252 // window procedure ensures PM knows about the new frame client
253 // size internally. A ::WinQueryWindowRect is all that is needed!
257 *pX
= vRect
.xRight
- vRect
.xLeft
;
259 *pY
= vRect
.yTop
- vRect
.yBottom
;
260 } // end of wxFrame::DoGetClientSize
263 // Set the client size (i.e. leave the calculation of borders etc.
266 void wxFrame::DoSetClientSize(
271 HWND hWnd
= GetHwnd();
275 ::WinQueryWindowRect(GetHwnd(), &vRect
);
276 ::WinQueryWindowRect(GetHwnd(), &vRect2
);
279 // Find the difference between the entire window (title bar and all)
280 // and the client area; add this to the new client size to move the
281 // window. Remember OS/2's backwards y coord system!
283 int nActualWidth
= vRect2
.xRight
- vRect2
.xLeft
- vRect
.xRight
+ nWidth
;
284 int nActualHeight
= vRect2
.yTop
+ vRect2
.yTop
- vRect
.yTop
+ nHeight
;
287 if ( GetStatusBar() )
292 GetStatusBar()->GetClientSize( &nStatusX
295 nActualHeight
+= nStatusY
;
297 #endif // wxUSE_STATUSBAR
299 wxPoint
vPoint(GetClientAreaOrigin());
300 nActualWidth
+= vPoint
.y
;
301 nActualHeight
+= vPoint
.x
;
305 vPointl
.x
= vRect2
.xLeft
;
306 vPointl
.y
= vRect2
.yTop
;
308 ::WinSetWindowPos( hWnd
314 ,SWP_MOVE
| SWP_SIZE
| SWP_SHOW
317 wxSizeEvent
vEvent( wxSize( nWidth
322 vEvent
.SetEventObject(this);
323 GetEventHandler()->ProcessEvent(vEvent
);
324 } // end of wxFrame::DoSetClientSize
326 void wxFrame::DoGetSize(
333 ::WinQueryWindowRect(m_hFrame
, &vRect
);
334 *pWidth
= vRect
.xRight
- vRect
.xLeft
;
335 *pHeight
= vRect
.yTop
- vRect
.yBottom
;
336 } // end of wxFrame::DoGetSize
338 void wxFrame::DoGetPosition(
346 ::WinQueryWindowRect(m_hFrame
, &vRect
);
348 *pX
= vRect
.xRight
- vRect
.xLeft
;
349 *pY
= vRect
.yTop
- vRect
.yBottom
;
350 } // end of wxFrame::DoGetPosition
352 // ----------------------------------------------------------------------------
353 // variations around ::ShowWindow()
354 // ----------------------------------------------------------------------------
356 void wxFrame::DoShowWindow(
360 ::WinShowWindow(m_hFrame
, (BOOL
)bShowCmd
);
361 m_bIconized
= bShowCmd
== SWP_MINIMIZE
;
362 } // end of wxFrame::DoShowWindow
370 DoShowWindow((int)bShow
);
374 wxActivateEvent
vEvent(wxEVT_ACTIVATE
, TRUE
, m_windowId
);
376 ::WinQueryWindowPos(m_hFrame
, &vSwp
);
377 m_bIconized
= vSwp
.fl
& SWP_MINIMIZE
;
378 ::WinSendMsg(m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)~0, 0);
379 ::WinEnableWindow(m_hFrame
, TRUE
);
380 vEvent
.SetEventObject(this);
381 GetEventHandler()->ProcessEvent(vEvent
);
386 // Try to highlight the correct window (the parent)
390 HWND hWndParent
= GetHwndOf(GetParent());
392 ::WinQueryWindowPos(hWndParent
, &vSwp
);
393 m_bIconized
= vSwp
.fl
& SWP_MINIMIZE
;
395 ::WinSetWindowPos( hWndParent
401 ,SWP_ZORDER
| SWP_ACTIVATE
| SWP_SHOW
| SWP_MOVE
403 ::WinEnableWindow(hWndParent
, TRUE
);
407 } // end of wxFrame::Show
409 void wxFrame::Iconize(
413 DoShowWindow(bIconize
? SWP_MINIMIZE
: SWP_RESTORE
);
414 } // end of wxFrame::Iconize
416 void wxFrame::Maximize(
419 DoShowWindow(bMaximize
? SWP_MAXIMIZE
: SWP_RESTORE
);
420 } // end of wxFrame::Maximize
422 void wxFrame::Restore()
424 DoShowWindow(SWP_RESTORE
);
425 } // end of wxFrame::Restore
427 bool wxFrame::IsIconized() const
431 ::WinQueryWindowPos(m_hFrame
, &vSwp
);
433 if (vSwp
.fl
& SWP_MINIMIZE
)
434 ((wxFrame
*)this)->m_bIconized
= TRUE
;
436 ((wxFrame
*)this)->m_bIconized
= FALSE
;
438 } // end of wxFrame::IsIconized
441 bool wxFrame::IsMaximized() const
446 ::WinQueryWindowPos(m_hFrame
, &vSwp
);
447 return (vSwp
.fl
& SWP_MAXIMIZE
);
448 } // end of wxFrame::IsMaximized
450 void wxFrame::SetIcon(
454 wxFrameBase::SetIcon(rIcon
);
456 if ((m_icon
.GetHICON()) != NULLHANDLE
)
458 ::WinSendMsg( m_hFrame
460 ,(MPARAM
)((HPOINTER
)m_icon
.GetHICON())
463 ::WinSendMsg( m_hFrame
469 } // end of wxFrame::SetIcon
472 wxStatusBar
* wxFrame::OnCreateStatusBar(
476 , const wxString
& rName
479 wxStatusBar
* pStatusBar
= NULL
;
484 pStatusBar
= wxFrameBase::OnCreateStatusBar( nNumber
493 ::WinSetParent( pStatusBar
->GetHWND()
497 ::WinSetOwner( pStatusBar
->GetHWND()
503 if(::WinIsWindowShowing(m_hFrame
))
504 ::WinSendMsg(m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)~0, 0);
507 } // end of wxFrame::OnCreateStatusBar
509 void wxFrame::PositionStatusBar()
516 // Native status bar positions itself
518 if (m_frameStatusBar
)
527 ::WinQueryWindowRect(m_hFrame
, &vRect
);
528 ::WinMapWindowPoints(m_hFrame
, HWND_DESKTOP
, (PPOINTL
)&vRect
, 2);
530 ::WinCalcFrameRect(m_hFrame
, &vRect
, TRUE
);
531 nWidth
= vRect
.xRight
- vRect
.xLeft
;
533 m_frameStatusBar
->GetSize( &nStatbarWidth
538 // Since we wish the status bar to be directly under the client area,
539 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
541 m_frameStatusBar
->SetSize( vRect
.xLeft
- vFRect
.xLeft
542 ,vRect
.yBottom
- vFRect
.yBottom
546 if (!::WinQueryWindowPos(m_frameStatusBar
->GetHWND(), &vSwp
))
548 vError
= ::WinGetLastError(vHabmain
);
549 sError
= wxPMErrorToStr(vError
);
550 wxLogError("Error setting parent for StautsBar. Error: %s\n", sError
);
554 } // end of wxFrame::PositionStatusBar
555 #endif // wxUSE_STATUSBAR
557 #if wxUSE_MENUS_NATIVE
558 void wxFrame::DetachMenuBar()
562 m_frameMenuBar
->Detach();
563 m_frameMenuBar
= NULL
;
565 } // end of wxFrame::DetachMenuBar
567 void wxFrame::SetMenuBar(
573 HWND hTitlebar
= NULLHANDLE
;
574 HWND hHScroll
= NULLHANDLE
;
575 HWND hVScroll
= NULLHANDLE
;
576 HWND hMenuBar
= NULLHANDLE
;
588 // Actually remove the menu from the frame
590 m_hMenu
= (WXHMENU
)0;
591 InternalSetMenuBar();
593 else // set new non NULL menu bar
595 m_frameMenuBar
= NULL
;
598 // Can set a menubar several times.
599 // TODO: how to prevent a memory leak if you have a currently-unattached
600 // menubar? wxWindows assumes that the frame will delete the menu (otherwise
601 // there are problems for MDI).
603 if (pMenuBar
->GetHMenu())
605 m_hMenu
= pMenuBar
->GetHMenu();
610 m_hMenu
= pMenuBar
->Create();
614 InternalSetMenuBar();
615 m_frameMenuBar
= pMenuBar
;
616 pMenuBar
->Attach((wxFrame
*)this);
618 } // end of wxFrame::SetMenuBar
620 void wxFrame::AttachMenuBar(
624 wxFrameBase::AttachMenuBar(pMenubar
);
626 m_frameMenuBar
= pMenubar
;
631 // Actually remove the menu from the frame
633 m_hMenu
= (WXHMENU
)0;
634 InternalSetMenuBar();
636 else // Set new non NULL menu bar
639 // Can set a menubar several times.
641 if (pMenubar
->GetHMenu())
643 m_hMenu
= pMenubar
->GetHMenu();
647 if (pMenubar
->IsAttached())
650 m_hMenu
= pMenubar
->Create();
655 InternalSetMenuBar();
657 } // end of wxFrame::AttachMenuBar
659 void wxFrame::InternalSetMenuBar()
664 // Set the parent and owner of the menubar to be the frame
666 if (!::WinSetParent(m_hMenu
, m_hFrame
, FALSE
))
668 vError
= ::WinGetLastError(vHabmain
);
669 sError
= wxPMErrorToStr(vError
);
670 wxLogError("Error setting parent for submenu. Error: %s\n", sError
);
673 if (!::WinSetOwner(m_hMenu
, m_hFrame
))
675 vError
= ::WinGetLastError(vHabmain
);
676 sError
= wxPMErrorToStr(vError
);
677 wxLogError("Error setting parent for submenu. Error: %s\n", sError
);
679 ::WinSendMsg(m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)FCF_MENU
, (MPARAM
)0);
680 } // end of wxFrame::InternalSetMenuBar
681 #endif // wxUSE_MENUS_NATIVE
684 // Responds to colour changes, and passes event on to children
686 void wxFrame::OnSysColourChanged(
687 wxSysColourChangedEvent
& rEvent
690 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
694 if (m_frameStatusBar
)
696 wxSysColourChangedEvent vEvent2
;
698 vEvent2
.SetEventObject(m_frameStatusBar
);
699 m_frameStatusBar
->GetEventHandler()->ProcessEvent(vEvent2
);
701 #endif //wxUSE_STATUSBAR
704 // Propagate the event to the non-top-level children
706 wxWindow::OnSysColourChanged(rEvent
);
707 } // end of wxFrame::OnSysColourChanged
709 // Pass TRUE to show full screen, FALSE to restore.
710 bool wxFrame::ShowFullScreen(
720 m_bFsIsShowing
= TRUE
;
724 wxToolBar
* pTheToolBar
= GetToolBar();
725 #endif //wxUSE_TOOLBAR
728 wxStatusBar
* pTheStatusBar
= GetStatusBar();
729 #endif //wxUSE_STATUSBAR
735 pTheToolBar
->GetSize(&nDummyWidth
, &m_nFsToolBarHeight
);
736 #endif //wxUSE_TOOLBAR
740 pTheStatusBar
->GetSize(&nDummyWidth
, &m_nFsStatusBarHeight
);
741 #endif //wxUSE_STATUSBAR
745 // Zap the toolbar, menubar, and statusbar
747 if ((lStyle
& wxFULLSCREEN_NOTOOLBAR
) && pTheToolBar
)
749 pTheToolBar
->SetSize(-1,0);
750 pTheToolBar
->Show(FALSE
);
752 #endif //wxUSE_TOOLBAR
754 if (lStyle
& wxFULLSCREEN_NOMENUBAR
)
756 ::WinSetParent(m_hMenu
, m_hFrame
, FALSE
);
757 ::WinSetOwner(m_hMenu
, m_hFrame
);
758 ::WinSendMsg((HWND
)m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)FCF_MENU
, (MPARAM
)0);
763 // Save the number of fields in the statusbar
765 if ((lStyle
& wxFULLSCREEN_NOSTATUSBAR
) && pTheStatusBar
)
767 m_nFsStatusBarFields
= pTheStatusBar
->GetFieldsCount();
768 SetStatusBar((wxStatusBar
*) NULL
);
769 delete pTheStatusBar
;
772 m_nFsStatusBarFields
= 0;
773 #endif //wxUSE_STATUSBAR
776 // Zap the frame borders
780 // Save the 'normal' window style
782 m_lFsOldWindowStyle
= ::WinQueryWindowULong(m_hFrame
, QWL_STYLE
);
785 // Save the old position, width & height, maximize state
787 m_vFsOldSize
= GetRect();
788 m_bFsIsMaximized
= IsMaximized();
791 // Decide which window style flags to turn off
793 LONG lNewStyle
= m_lFsOldWindowStyle
;
796 if (lStyle
& wxFULLSCREEN_NOBORDER
)
797 lOffFlags
|= FCF_BORDER
;
798 if (lStyle
& wxFULLSCREEN_NOCAPTION
)
799 lOffFlags
|= (FCF_TASKLIST
| FCF_SYSMENU
);
801 lNewStyle
&= (~lOffFlags
);
804 // Change our window style to be compatible with full-screen mode
806 ::WinSetWindowULong((HWND
)m_hFrame
, QWL_STYLE
, (ULONG
)lNewStyle
);
809 // Resize to the size of the desktop
815 ::WinQueryWindowRect(HWND_DESKTOP
, &vRect
);
816 nWidth
= vRect
.xRight
- vRect
.xLeft
;
818 // Rmember OS/2 is backwards!
820 nHeight
= vRect
.yTop
- vRect
.yBottom
;
827 // Now flush the window style cache and actually go full-screen
829 ::WinSetWindowPos( (HWND
) GetParent()->GetHWND()
838 wxSizeEvent
vEvent( wxSize( nWidth
844 GetEventHandler()->ProcessEvent(vEvent
);
852 m_bFsIsShowing
= FALSE
;
855 wxToolBar
* pTheToolBar
= GetToolBar();
858 // Restore the toolbar, menubar, and statusbar
860 if (pTheToolBar
&& (m_lFsStyle
& wxFULLSCREEN_NOTOOLBAR
))
862 pTheToolBar
->SetSize(-1, m_nFsToolBarHeight
);
863 pTheToolBar
->Show(TRUE
);
865 #endif //wxUSE_TOOLBAR
868 if ((m_lFsStyle
& wxFULLSCREEN_NOSTATUSBAR
) && (m_nFsStatusBarFields
> 0))
870 CreateStatusBar(m_nFsStatusBarFields
);
871 // PositionStatusBar();
873 #endif //wxUSE_STATUSBAR
875 if ((m_lFsStyle
& wxFULLSCREEN_NOMENUBAR
) && (m_hMenu
!= 0))
877 ::WinSetParent(m_hMenu
, m_hFrame
, FALSE
);
878 ::WinSetOwner(m_hMenu
, m_hFrame
);
879 ::WinSendMsg(m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)FCF_MENU
, (MPARAM
)0);
881 Maximize(m_bFsIsMaximized
);
883 ::WinSetWindowULong( m_hFrame
885 ,(ULONG
)m_lFsOldWindowStyle
887 ::WinSetWindowPos( (HWND
) GetParent()->GetHWND()
897 } // end of wxFrame::ShowFullScreen
902 bool wxFrame::OS2Create(
905 , const wxChar
* zWclass
907 , const wxChar
* zTitle
915 ULONG ulCreateFlags
= 0L;
916 ULONG ulStyleFlags
= 0L;
917 ULONG ulExtraFlags
= 0L;
918 FRAMECDATA vFrameCtlData
;
919 HWND hParent
= NULLHANDLE
;
920 HWND hTitlebar
= NULLHANDLE
;
921 HWND hHScroll
= NULLHANDLE
;
922 HWND hVScroll
= NULLHANDLE
;
923 HWND hFrame
= NULLHANDLE
;
924 HWND hClient
= NULLHANDLE
;
931 m_hDefaultIcon
= (WXHICON
) (wxSTD_FRAME_ICON
? wxSTD_FRAME_ICON
: wxDEFAULT_FRAME_ICON
);
934 hParent
= GetWinHwnd(pParent
);
936 hParent
= HWND_DESKTOP
;
938 if (ulStyle
== wxDEFAULT_FRAME_STYLE
)
939 ulCreateFlags
= FCF_SIZEBORDER
| FCF_TITLEBAR
| FCF_SYSMENU
|
940 FCF_MINMAX
| FCF_TASKLIST
;
943 if ((ulStyle
& wxCAPTION
) == wxCAPTION
)
944 ulCreateFlags
= FCF_TASKLIST
;
946 ulCreateFlags
= FCF_NOMOVEWITHOWNER
;
948 if ((ulStyle
& wxVSCROLL
) == wxVSCROLL
)
949 ulCreateFlags
|= FCF_VERTSCROLL
;
950 if ((ulStyle
& wxHSCROLL
) == wxHSCROLL
)
951 ulCreateFlags
|= FCF_HORZSCROLL
;
952 if (ulStyle
& wxMINIMIZE_BOX
)
953 ulCreateFlags
|= FCF_MINBUTTON
;
954 if (ulStyle
& wxMAXIMIZE_BOX
)
955 ulCreateFlags
|= FCF_MAXBUTTON
;
956 if (ulStyle
& wxTHICK_FRAME
)
957 ulCreateFlags
|= FCF_DLGBORDER
;
958 if (ulStyle
& wxSYSTEM_MENU
)
959 ulCreateFlags
|= FCF_SYSMENU
;
960 if (ulStyle
& wxCAPTION
)
961 ulCreateFlags
|= FCF_TASKLIST
;
962 if (ulStyle
& wxCLIP_CHILDREN
)
964 // Invalid for frame windows under PM
967 if (ulStyle
& wxTINY_CAPTION_VERT
)
968 ulCreateFlags
|= FCF_TASKLIST
;
969 if (ulStyle
& wxTINY_CAPTION_HORIZ
)
970 ulCreateFlags
|= FCF_TASKLIST
;
972 if ((ulStyle
& wxTHICK_FRAME
) == 0)
973 ulCreateFlags
|= FCF_BORDER
;
974 if (ulStyle
& wxFRAME_TOOL_WINDOW
)
975 ulExtraFlags
= kFrameToolWindow
;
977 if (ulStyle
& wxSTAY_ON_TOP
)
978 ulCreateFlags
|= FCF_SYSMODAL
;
980 if ((ulStyle
& wxMINIMIZE
) || (ulStyle
& wxICONIZE
))
981 ulStyleFlags
|= WS_MINIMIZED
;
982 if (ulStyle
& wxMAXIMIZE
)
983 ulStyleFlags
|= WS_MAXIMIZED
;
986 // Clear the visible flag, we always call show
988 ulStyleFlags
&= (unsigned long)~WS_VISIBLE
;
992 // Set the frame control block
994 vFrameCtlData
.cb
= sizeof(vFrameCtlData
);
995 vFrameCtlData
.flCreateFlags
= ulCreateFlags
;
996 vFrameCtlData
.hmodResources
= 0L;
997 vFrameCtlData
.idResources
= 0;
1000 // Create the frame window: We break ranks with other ports now
1001 // and instead of calling down into the base wxWindow class' OS2Create
1002 // we do all our own stuff here. We will set the needed pieces
1003 // of wxWindow manually, here.
1006 hFrame
= ::WinCreateStdWindow( hParent
1007 ,ulStyleFlags
// frame-window style
1008 ,&ulCreateFlags
// window style
1009 ,(PSZ
)zWclass
// class name
1010 ,(PSZ
)zTitle
// window title
1011 ,0L // default client style
1012 ,NULLHANDLE
// resource in executable file
1014 ,&hClient
// receives client window handle
1018 vError
= ::WinGetLastError(vHabmain
);
1019 sError
= wxPMErrorToStr(vError
);
1020 wxLogError("Error creating frame. Error: %s\n", sError
);
1025 // wxWindow class' m_hWnd set here and needed associations
1029 wxAssociateWinWithHandle(m_hWnd
, this);
1030 wxAssociateWinWithHandle(m_hFrame
, this);
1032 m_backgroundColour
.Set(wxString("GREY"));
1034 LONG lColor
= (LONG
)m_backgroundColour
.GetPixel();
1036 if (!::WinSetPresParam( m_hWnd
1042 vError
= ::WinGetLastError(vHabmain
);
1043 sError
= wxPMErrorToStr(vError
);
1044 wxLogError("Error creating frame. Error: %s\n", sError
);
1049 // Now need to subclass window. Instead of calling the SubClassWin in wxWindow
1050 // we manually subclass here because we don't want to use the main wxWndProc
1053 m_fnOldWndProc
= (WXFARPROC
) ::WinSubclassWindow(m_hFrame
, (PFNWP
)wxFrameMainWndProc
);
1056 // Now size everything. If adding a menu the client will need to be resized.
1059 if (!::WinSetWindowPos( m_hFrame
1065 ,SWP_SIZE
| SWP_MOVE
| SWP_ACTIVATE
| SWP_ZORDER
1068 vError
= ::WinGetLastError(vHabmain
);
1069 sError
= wxPMErrorToStr(vError
);
1070 wxLogError("Error sizing frame. Error: %s\n", sError
);
1074 // We may have to be smarter here when variable sized toolbars are added!
1076 if (!::WinSetWindowPos( m_hWnd
1082 ,SWP_SIZE
| SWP_MOVE
| SWP_ACTIVATE
| SWP_ZORDER
1085 vError
= ::WinGetLastError(vHabmain
);
1086 sError
= wxPMErrorToStr(vError
);
1087 wxLogError("Error sizing client. Error: %s\n", sError
);
1091 } // end of wxFrame::OS2Create
1094 // Default activation behaviour - set the focus for the first child
1097 void wxFrame::OnActivate(
1098 wxActivateEvent
& rEvent
1101 if ( rEvent
.GetActive() )
1103 // restore focus to the child which was last focused
1104 wxLogTrace(_T("focus"), _T("wxFrame %08x activated."), m_hWnd
);
1106 wxWindow
* pParent
= m_pWinLastFocused
? m_pWinLastFocused
->GetParent()
1113 wxSetFocusToChild( pParent
1117 else // deactivating
1120 // Remember the last focused child if it is our child
1122 m_pWinLastFocused
= FindFocus();
1124 for (wxWindowList::Node
* pNode
= GetChildren().GetFirst();
1126 pNode
= pNode
->GetNext())
1128 // FIXME all this is totally bogus - we need to do the same as wxPanel,
1129 // but how to do it without duplicating the code?
1132 wxWindow
* pChild
= pNode
->GetData();
1134 if (!pChild
->IsTopLevel()
1136 && !wxDynamicCast(pChild
, wxToolBar
)
1137 #endif // wxUSE_TOOLBAR
1139 && !wxDynamicCast(pChild
, wxStatusBar
)
1140 #endif // wxUSE_STATUSBAR
1148 } // end of wxFrame::OnActivate
1150 // ----------------------------------------------------------------------------
1151 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
1152 // from the client area, so the client area is what's really available for the
1154 // ----------------------------------------------------------------------------
1156 // Checks if there is a toolbar, and returns the first free client position
1157 wxPoint
wxFrame::GetClientAreaOrigin() const
1159 wxPoint
vPoint(0, 0);
1167 GetToolBar()->GetSize( &nWidth
1171 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL
)
1177 // PM is backwards from windows
1178 vPoint
.y
+= nHeight
;
1181 #endif //wxUSE_TOOLBAR
1183 } // end of wxFrame::GetClientAreaOrigin
1185 // ----------------------------------------------------------------------------
1186 // tool/status bar stuff
1187 // ----------------------------------------------------------------------------
1191 wxToolBar
* wxFrame::CreateToolBar(
1194 , const wxString
& rName
1197 if (wxFrameBase::CreateToolBar( lStyle
1204 return m_frameToolBar
;
1205 } // end of wxFrame::CreateToolBar
1207 void wxFrame::PositionToolBar()
1212 ::WinQueryWindowRect(GetHwnd(), &vRect
);
1220 GetStatusBar()->GetClientSize( &nStatusX
1223 // PM is backwards from windows
1224 vRect
.yBottom
+= nStatusY
;
1226 #endif // wxUSE_STATUSBAR
1228 if ( m_frameToolBar
)
1233 m_frameToolBar
->GetSize( &nToolbarWidth
1237 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL
)
1239 nToolbarHeight
= vRect
.yBottom
;
1243 nToolbarWidth
= vRect
.xRight
;
1247 // Use the 'real' PM position here
1249 GetToolBar()->SetSize( 0
1253 ,wxSIZE_NO_ADJUSTMENTS
1256 } // end of wxFrame::PositionToolBar
1257 #endif // wxUSE_TOOLBAR
1259 // ----------------------------------------------------------------------------
1260 // frame state (iconized/maximized/...)
1261 // ----------------------------------------------------------------------------
1264 // propagate our state change to all child frames: this allows us to emulate X
1265 // Windows behaviour where child frames float independently of the parent one
1266 // on the desktop, but are iconized/restored with it
1268 void wxFrame::IconizeChildFrames(
1272 for (wxWindowList::Node
* pNode
= GetChildren().GetFirst();
1274 pNode
= pNode
->GetNext() )
1276 wxWindow
* pWin
= pNode
->GetData();
1278 if (pWin
->IsKindOf(CLASSINFO(wxFrame
)) )
1280 ((wxFrame
*)pWin
)->Iconize(bIconize
);
1283 } // end of wxFrame::IconizeChildFrames
1285 // ===========================================================================
1286 // message processing
1287 // ===========================================================================
1289 // ---------------------------------------------------------------------------
1291 // ---------------------------------------------------------------------------
1292 bool wxFrame::OS2TranslateMessage(
1297 // try the menu bar accels
1299 wxMenuBar
* pMenuBar
= GetMenuBar();
1304 #if wxUSE_ACCEL && wxUSE_MENUS_NATIVE
1305 const wxAcceleratorTable
& rAcceleratorTable
= pMenuBar
->GetAccelTable();
1306 return rAcceleratorTable
.Translate(GetHWND(), pMsg
);
1309 #endif //wxUSE_ACCEL
1310 } // end of wxFrame::OS2TranslateMessage
1312 // ---------------------------------------------------------------------------
1313 // our private (non virtual) message handlers
1314 // ---------------------------------------------------------------------------
1315 bool wxFrame::HandlePaint()
1319 if (::WinQueryUpdateRect(GetHWND(), &vRect
))
1324 // Icons in PM are the same as "pointers"
1329 hIcon
= (HPOINTER
)::WinSendMsg(m_hFrame
, WM_QUERYICON
, 0L, 0L);
1331 hIcon
= (HPOINTER
)m_hDefaultIcon
;
1334 // Hold a pointer to the dc so long as the OnPaint() message
1335 // is being processed
1338 HPS hPs
= ::WinBeginPaint(GetHwnd(), NULLHANDLE
, &vRect2
);
1341 // Erase background before painting or we get white background
1343 OS2DefWindowProc(WM_ERASEBACKGROUND
, (MPARAM
)hPs
, (MPARAM
)&vRect2
);
1350 ::WinQueryWindowRect(GetHwnd(), &vRect3
);
1352 static const int nIconWidth
= 32;
1353 static const int nIconHeight
= 32;
1354 int nIconX
= (int)((vRect3
.xRight
- nIconWidth
)/2);
1355 int nIconY
= (int)((vRect3
.yBottom
+ nIconHeight
)/2);
1357 ::WinDrawPointer(hPs
, nIconX
, nIconY
, hIcon
, DP_NORMAL
);
1364 return(wxWindow::HandlePaint());
1369 // nothing to paint - processed
1373 } // end of wxFrame::HandlePaint
1375 bool wxFrame::HandleSize(
1381 bool bProcessed
= FALSE
;
1387 // Only do it it if we were iconized before, otherwise resizing the
1388 // parent frame has a curious side effect of bringing it under it's
1394 // restore all child frames too
1396 IconizeChildFrames(FALSE
);
1397 (void)SendIconizeEvent(FALSE
);
1404 m_bIconized
= FALSE
;
1409 // Iconize all child frames too
1411 IconizeChildFrames(TRUE
);
1412 (void)SendIconizeEvent();
1420 // forward WM_SIZE to status bar control
1422 #if wxUSE_NATIVE_STATUSBAR
1423 if (m_frameStatusBar
&& m_frameStatusBar
->IsKindOf(CLASSINFO(wxStatusBar95
)))
1425 wxSizeEvent
vEvent( wxSize( nX
1428 ,m_frameStatusBar
->GetId()
1431 vEvent
.SetEventObject(m_frameStatusBar
);
1432 m_frameStatusBar
->OnSize(vEvent
);
1434 #endif // wxUSE_NATIVE_STATUSBAR
1436 PositionStatusBar();
1439 #endif // wxUSE_TOOLBAR
1441 wxSizeEvent
vEvent( wxSize( nX
1447 vEvent
.SetEventObject(this);
1448 bProcessed
= GetEventHandler()->ProcessEvent(vEvent
);
1451 } // end of wxFrame::HandleSize
1453 bool wxFrame::HandleCommand(
1462 // In case it's e.g. a toolbar.
1464 wxWindow
* pWin
= wxFindWinFromHandle(hControl
);
1467 return pWin
->OS2Command( nCmd
1473 // Handle here commands from menus and accelerators
1475 if (nCmd
== CMDSRC_MENU
|| nCmd
== CMDSRC_ACCELERATOR
)
1477 #if wxUSE_MENUS_NATIVE
1478 if (wxCurrentPopupMenu
)
1480 wxMenu
* pPopupMenu
= wxCurrentPopupMenu
;
1482 wxCurrentPopupMenu
= NULL
;
1484 return pPopupMenu
->OS2Command( nCmd
1491 if (ProcessCommand(nId
))
1497 } // end of wxFrame::HandleCommand
1499 bool wxFrame::HandleMenuSelect(
1510 rc
= ::WinSendMsg(hMenu
, MM_QUERYITEM
, MPFROM2SHORT(nItem
, TRUE
), (MPARAM
)&mItem
);
1512 if(rc
&& !(mItem
.afStyle
& (MIS_SUBMENU
| MIS_SEPARATOR
)))
1514 wxMenuEvent
vEvent(wxEVT_MENU_HIGHLIGHT
, nItem
);
1516 vEvent
.SetEventObject(this);
1517 GetEventHandler()->ProcessEvent(vEvent
); // return value would be ignored by PM
1521 } // end of wxFrame::HandleMenuSelect
1523 // ---------------------------------------------------------------------------
1524 // Main Frame window proc
1525 // ---------------------------------------------------------------------------
1526 MRESULT EXPENTRY
wxFrameMainWndProc(
1533 MRESULT rc
= (MRESULT
)0;
1534 bool bProcessed
= FALSE
;
1535 wxFrame
* pWnd
= NULL
;
1537 pWnd
= (wxFrame
*) wxFindWinFromHandle((WXHWND
) hWnd
);
1540 case WM_QUERYFRAMECTLCOUNT
:
1541 if(pWnd
&& pWnd
->m_fnOldWndProc
)
1543 USHORT uItemCount
= SHORT1FROMMR(pWnd
->m_fnOldWndProc(hWnd
, ulMsg
, wParam
, lParam
));
1545 rc
= MRFROMSHORT(uItemCount
);
1549 case WM_FORMATFRAME
:
1550 /////////////////////////////////////////////////////////////////////////////////
1551 // Applications that subclass frame controls may find that the frame is already
1552 // subclassed the number of frame controls is variable.
1553 // The WM_FORMATFRAME and WM_QUERYFRAMECTLCOUNT messages must always be
1554 // subclassed by calling the previous window procedure and modifying its result.
1555 ////////////////////////////////////////////////////////////////////////////////
1565 pSWP
= (PSWP
)PVOIDFROMMP(wParam
);
1566 nItemCount
= SHORT1FROMMR(pWnd
->m_fnOldWndProc(hWnd
, ulMsg
, wParam
, lParam
));
1567 if(pWnd
->m_frameStatusBar
)
1569 ::WinQueryWindowRect(pWnd
->m_frameStatusBar
->GetHWND(), &vRstb
);
1570 pWnd
->m_frameStatusBar
->GetSize(NULL
, &nHeight
);
1571 ::WinQueryWindowRect(pWnd
->m_hFrame
, &vRectl
);
1572 ::WinMapWindowPoints(pWnd
->m_hFrame
, HWND_DESKTOP
, (PPOINTL
)&vRectl
, 2);
1574 ::WinCalcFrameRect(pWnd
->m_hFrame
, &vRectl
, TRUE
);
1576 vSwpStb
.x
= vRectl
.xLeft
- vRstb
.xLeft
;
1577 vSwpStb
.y
= vRectl
.yBottom
- vRstb
.yBottom
;
1578 vSwpStb
.cx
= vRectl
.xRight
- vRectl
.xLeft
- 1; //?? -1 ??
1579 vSwpStb
.cy
= nHeight
;
1580 vSwpStb
.fl
= SWP_SIZE
|SWP_MOVE
| SWP_SHOW
;
1581 vSwpStb
.hwnd
= pWnd
->m_frameStatusBar
->GetHWND();
1582 vSwpStb
.hwndInsertBehind
= HWND_TOP
;
1584 ::WinQueryWindowRect(pWnd
->m_hFrame
, &vRectl
);
1585 ::WinMapWindowPoints(pWnd
->m_hFrame
, HWND_DESKTOP
, (PPOINTL
)&vRectl
, 2);
1586 ::WinCalcFrameRect(pWnd
->m_hFrame
, &vRectl
, TRUE
);
1587 ::WinMapWindowPoints(HWND_DESKTOP
, pWnd
->m_hFrame
, (PPOINTL
)&vRectl
, 2);
1588 for(i
= 0; i
< nItemCount
; i
++)
1590 if(pWnd
->m_hWnd
&& pSWP
[i
].hwnd
== pWnd
->m_hWnd
)
1592 pSWP
[i
].x
= vRectl
.xLeft
;
1593 pSWP
[i
].y
= vRectl
.yBottom
+ nHeight
;
1594 pSWP
[i
].cx
= vRectl
.xRight
- vRectl
.xLeft
;
1595 pSWP
[i
].cy
= vRectl
.yTop
- vRectl
.yBottom
- nHeight
;
1596 pSWP
[i
].fl
= SWP_SIZE
| SWP_MOVE
| SWP_SHOW
;
1597 pSWP
[i
].hwndInsertBehind
= HWND_TOP
;
1601 rc
= MRFROMSHORT(nItemCount
);
1606 if(pWnd
&& pWnd
->m_fnOldWndProc
)
1607 rc
= pWnd
->m_fnOldWndProc(hWnd
, ulMsg
, wParam
, lParam
);
1609 rc
= ::WinDefWindowProc(hWnd
, ulMsg
, wParam
, lParam
);
1612 } // end of wxFrameMainWndProc
1614 MRESULT EXPENTRY
wxFrameWndProc(
1622 // Trace all ulMsgs - useful for the debugging
1625 wxFrame
* pWnd
= NULL
;
1627 parentHwnd
= WinQueryWindow(hWnd
,QW_PARENT
);
1628 pWnd
= (wxFrame
*) wxFindWinFromHandle((WXHWND
) hWnd
);
1631 // When we get the first message for the HWND we just created, we associate
1632 // it with wxWindow stored in wxWndHook
1635 MRESULT rc
= (MRESULT
)0;
1636 bool bProcessed
= FALSE
;
1639 // Stop right here if we don't have a valid handle in our wxWindow object.
1641 if (pWnd
&& !pWnd
->GetHWND())
1643 pWnd
->SetHWND((WXHWND
) hWnd
);
1644 rc
= pWnd
->OS2DefWindowProc(ulMsg
, wParam
, lParam
);
1650 rc
= pWnd
->OS2WindowProc(ulMsg
, wParam
, lParam
);
1652 rc
= ::WinDefWindowProc(hWnd
, ulMsg
, wParam
, lParam
);
1655 } // end of wxFrameWndProc
1657 MRESULT
wxFrame::OS2WindowProc(
1664 bool bProcessed
= FALSE
;
1670 // If we can't close, tell the system that we processed the
1671 // message - otherwise it would close us
1673 bProcessed
= !Close();
1677 bProcessed
= HandlePaint();
1678 mRc
= (MRESULT
)FALSE
;
1681 case WM_ERASEBACKGROUND
:
1683 // Returning TRUE to requests PM to paint the window background
1684 // in SYSCLR_WINDOW. We capture this here because the PS returned
1685 // in Frames is the PS for the whole frame, which we can't really
1686 // use at all. If you want to paint a different background, do it
1687 // in an OnPaint using a wxPaintDC.
1689 mRc
= (MRESULT
)(TRUE
);
1698 UnpackCommand( (WXWPARAM
)wParam
1705 bProcessed
= HandleCommand( wId
1718 UnpackMenuSelect( wParam
1724 bProcessed
= HandleMenuSelect( wItem
1728 mRc
= (MRESULT
)TRUE
;
1734 SHORT nScxold
= SHORT1FROMMP(wParam
); // Old horizontal size.
1735 SHORT nScyold
= SHORT2FROMMP(wParam
); // Old vertical size.
1736 SHORT nScxnew
= SHORT1FROMMP(lParam
); // New horizontal size.
1737 SHORT nScynew
= SHORT2FROMMP(lParam
); // New vertical size.
1739 lParam
= MRFROM2SHORT( nScxnew
- 20
1743 bProcessed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), (WXUINT
)wParam
);
1744 mRc
= (MRESULT
)FALSE
;
1747 case CM_QUERYDRAGIMAGE
:
1752 hIcon
= (HPOINTER
)::WinSendMsg(GetHWND(), WM_QUERYICON
, 0L, 0L);
1754 hIcon
= (HPOINTER
)m_hDefaultIcon
;
1755 mRc
= (MRESULT
)hIcon
;
1756 bProcessed
= mRc
!= 0;
1762 mRc
= wxWindow::OS2WindowProc( uMessage
1766 return (MRESULT
)mRc
;
1767 } // wxFrame::OS2WindowProc
1769 void wxFrame::SetClient(WXHWND c_Hwnd
)
1771 // Duh...nothing to do under OS/2
1774 void wxFrame::SetClient(
1778 wxWindow
* pOldClient
= this->GetClient();
1779 bool bClientHasFocus
= pOldClient
&& (pOldClient
== wxWindow::FindFocus());
1781 if(pOldClient
== pWindow
) // nothing to do
1783 if(pWindow
== NULL
) // just need to remove old client
1785 if(pOldClient
== NULL
) // nothing to do
1788 if(bClientHasFocus
)
1791 pOldClient
->Enable( FALSE
);
1792 pOldClient
->Show( FALSE
);
1793 ::WinSetWindowUShort(pOldClient
->GetHWND(), QWS_ID
, (USHORT
)pOldClient
->GetId());
1794 // to avoid OS/2 bug need to update frame
1795 ::WinSendMsg((HWND
)this->GetFrame(), WM_UPDATEFRAME
, (MPARAM
)~0, 0);
1800 // Else need to change client
1805 ::WinEnableWindowUpdate((HWND
)GetHWND(), FALSE
);
1808 pOldClient
->Enable(FALSE
);
1809 pOldClient
->Show(FALSE
);
1810 ::WinSetWindowUShort(pOldClient
->GetHWND(), QWS_ID
, (USHORT
)pOldClient
->GetId());
1812 pWindow
->Reparent(this);
1813 ::WinSetWindowUShort(pWindow
->GetHWND(), QWS_ID
, FID_CLIENT
);
1814 ::WinEnableWindowUpdate((HWND
)GetHWND(), TRUE
);
1816 pWindow
->Show(); // ensure client is showing
1817 if( this->IsShown() )
1820 ::WinSendMsg(m_hFrame
, WM_UPDATEFRAME
, (MPARAM
)~0, 0);
1824 wxWindow
* wxFrame::GetClient()
1826 return wxFindWinFromHandle((WXHWND
)::WinWindowFromID(m_hFrame
, FID_CLIENT
));