Toolbar fixes and weekly catch-up.
[wxWidgets.git] / src / os2 / frame.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: frame.cpp
3 // Purpose: wxFrame
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/27/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/defs.h"
17 #include "wx/object.h"
18 #include "wx/dynarray.h"
19 #include "wx/list.h"
20 #include "wx/hash.h"
21 #include "wx/string.h"
22 #include "wx/intl.h"
23 #include "wx/log.h"
24 #include "wx/event.h"
25 #include "wx/setup.h"
26 #include "wx/frame.h"
27 #include "wx/menu.h"
28 #include "wx/app.h"
29 #include "wx/utils.h"
30 #include "wx/dialog.h"
31 #include "wx/settings.h"
32 #include "wx/dcclient.h"
33 #include "wx/mdi.h"
34 #endif // WX_PRECOMP
35
36 #include "wx/os2/private.h"
37
38 #if wxUSE_STATUSBAR
39 #include "wx/statusbr.h"
40 #include "wx/generic/statusbr.h"
41 #endif // wxUSE_STATUSBAR
42
43 #if wxUSE_TOOLBAR
44 #include "wx/toolbar.h"
45 #endif // wxUSE_TOOLBAR
46
47 #include "wx/menuitem.h"
48 #include "wx/log.h"
49
50 // ----------------------------------------------------------------------------
51 // globals
52 // ----------------------------------------------------------------------------
53
54 extern wxWindowList wxModelessWindows;
55 extern wxList WXDLLEXPORT wxPendingDelete;
56
57 #if wxUSE_MENUS_NATIVE
58 extern wxMenu *wxCurrentPopupMenu;
59 #endif
60
61 extern void wxAssociateWinWithHandle( HWND hWnd
62 ,wxWindowOS2* pWin
63 );
64
65 // ----------------------------------------------------------------------------
66 // event tables
67 // ----------------------------------------------------------------------------
68
69 BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
70 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
71 END_EVENT_TABLE()
72
73 IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
74
75 // ============================================================================
76 // implementation
77 // ============================================================================
78
79 // ----------------------------------------------------------------------------
80 // static class members
81 // ----------------------------------------------------------------------------
82 #if wxUSE_STATUSBAR
83
84 #if wxUSE_NATIVE_STATUSBAR
85 bool wxFrame::m_bUseNativeStatusBar = TRUE;
86 #else
87 bool wxFrame::m_bUseNativeStatusBar = FALSE;
88 #endif
89
90 #endif //wxUSE_STATUSBAR
91
92 // ----------------------------------------------------------------------------
93 // creation/destruction
94 // ----------------------------------------------------------------------------
95
96 void wxFrame::Init()
97 {
98 m_nFsStatusBarFields = 0;
99 m_nFsStatusBarHeight = 0;
100 m_nFsToolBarHeight = 0;
101 m_hWndToolTip = 0L;
102 m_bWasMinimized = FALSE;
103
104
105 m_frameMenuBar = NULL;
106 m_frameToolBar = NULL;
107 m_frameStatusBar = NULL;
108
109 m_hTitleBar = NULLHANDLE;
110 m_hHScroll = NULLHANDLE;
111 m_hVScroll = NULLHANDLE;
112
113 //
114 // Initialize SWP's
115 //
116 memset(&m_vSwpTitleBar, 0, sizeof(SWP));
117 memset(&m_vSwpMenuBar, 0, sizeof(SWP));
118 memset(&m_vSwpHScroll, 0, sizeof(SWP));
119 memset(&m_vSwpVScroll, 0, sizeof(SWP));
120 memset(&m_vSwpStatusBar, 0, sizeof(SWP));
121 memset(&m_vSwpToolBar, 0, sizeof(SWP));
122 m_bIconized = FALSE;
123
124 } // end of wxFrame::Init
125
126 bool wxFrame::Create(
127 wxWindow* pParent
128 , wxWindowID vId
129 , const wxString& rsTitle
130 , const wxPoint& rPos
131 , const wxSize& rSize
132 , long lStyle
133 , const wxString& rsName
134 )
135 {
136 if (!wxTopLevelWindow::Create( pParent
137 ,vId
138 ,rsTitle
139 ,rPos
140 ,rSize
141 ,lStyle
142 ,rsName
143 ))
144 return FALSE;
145 wxModelessWindows.Append(this);
146 return TRUE;
147 } // end of wxFrame::Create
148
149 wxFrame::~wxFrame()
150 {
151 m_isBeingDeleted = TRUE;
152 DeleteAllBars();
153 } // end of wxFrame::~wxFrame
154
155 //
156 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
157 //
158 void wxFrame::DoGetClientSize(
159 int* pX
160 , int* pY
161 ) const
162 {
163 wxTopLevelWindow::DoGetClientSize( pX
164 ,pY
165 );
166 //
167 // No need to use statusbar code as in WIN32 as the FORMATFRAME
168 // window procedure ensures PM knows about the new frame client
169 // size internally. A ::WinQueryWindowRect (that is called in
170 // wxWindow's GetClient size from above) is all that is needed!
171 //
172 } // end of wxFrame::DoGetClientSize
173
174 //
175 // Set the client size (i.e. leave the calculation of borders etc.
176 // to wxWindows)
177 //
178 void wxFrame::DoSetClientSize(
179 int nWidth
180 , int nHeight
181 )
182 {
183 wxStatusBar* pStatusBar = GetStatusBar();
184
185 //
186 // Statusbars are not part of the OS/2 Client but parent frame
187 // so no statusbar consideration
188 //
189 wxTopLevelWindow::DoSetClientSize( nWidth
190 ,nHeight
191 );
192 } // end of wxFrame::DoSetClientSize
193
194 // ----------------------------------------------------------------------------
195 // wxFrame: various geometry-related functions
196 // ----------------------------------------------------------------------------
197
198 void wxFrame::Raise()
199 {
200 wxFrameBase::Raise();
201 ::WinSetWindowPos( (HWND) GetParent()->GetHWND()
202 ,HWND_TOP
203 ,0
204 ,0
205 ,0
206 ,0
207 ,SWP_ZORDER
208 );
209 }
210
211 #if wxUSE_STATUSBAR
212 wxStatusBar* wxFrame::OnCreateStatusBar(
213 int nNumber
214 , long lulStyle
215 , wxWindowID vId
216 , const wxString& rName
217 )
218 {
219 wxStatusBar* pStatusBar = NULL;
220 SWP vSwp;
221 ERRORID vError;
222 wxString sError;
223
224 pStatusBar = wxFrameBase::OnCreateStatusBar( nNumber
225 ,lulStyle
226 ,vId
227 ,rName
228 );
229
230 if( !pStatusBar )
231 return NULL;
232
233 wxClientDC vDC(pStatusBar);
234 int nY;
235
236 //
237 // Set the height according to the font and the border size
238 //
239 vDC.SetFont(pStatusBar->GetFont()); // Screws up the menues for some reason
240 vDC.GetTextExtent( "X"
241 ,NULL
242 ,&nY
243 );
244
245 int nHeight = ((11 * nY) / 10 + 2 * pStatusBar->GetBorderY());
246
247 pStatusBar->SetSize( -1
248 ,-1
249 ,-1
250 ,nHeight
251 );
252
253 ::WinSetParent( pStatusBar->GetHWND()
254 ,m_hFrame
255 ,FALSE
256 );
257 ::WinSetOwner( pStatusBar->GetHWND()
258 ,m_hFrame
259 );
260 //
261 // to show statusbar
262 //
263 if(::WinIsWindowShowing(m_hFrame))
264 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
265
266 return pStatusBar;
267 } // end of wxFrame::OnCreateStatusBar
268
269 void wxFrame::PositionStatusBar()
270 {
271 SWP vSwp;
272 ERRORID vError;
273 wxString sError;
274
275 //
276 // Native status bar positions itself
277 //
278 if (m_frameStatusBar)
279 {
280 int nWidth;
281 int nY;
282 int nStatbarWidth;
283 int nStatbarHeight;
284 HWND hWndClient;
285 RECTL vRect;
286 RECTL vFRect;
287
288 ::WinQueryWindowRect(m_hFrame, &vRect);
289 nY = vRect.yTop;
290 ::WinMapWindowPoints(m_hFrame, HWND_DESKTOP, (PPOINTL)&vRect, 2);
291 vFRect = vRect;
292 ::WinCalcFrameRect(m_hFrame, &vRect, TRUE);
293 nWidth = vRect.xRight - vRect.xLeft;
294 nY = nY - (vRect.yBottom - vFRect.yBottom);
295
296 m_frameStatusBar->GetSize( &nStatbarWidth
297 ,&nStatbarHeight
298 );
299
300 nY= nY - nStatbarHeight;
301 //
302 // Since we wish the status bar to be directly under the client area,
303 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
304 //
305 m_frameStatusBar->SetSize( vRect.xLeft - vFRect.xLeft
306 ,nY
307 ,nWidth
308 ,nStatbarHeight
309 );
310 if (!::WinQueryWindowPos(m_frameStatusBar->GetHWND(), &vSwp))
311 {
312 vError = ::WinGetLastError(vHabmain);
313 sError = wxPMErrorToStr(vError);
314 wxLogError("Error setting parent for StautsBar. Error: %s\n", sError);
315 return;
316 }
317 }
318 } // end of wxFrame::PositionStatusBar
319 #endif // wxUSE_STATUSBAR
320
321 #if wxUSE_TOOLBAR
322 wxToolBar* wxFrame::OnCreateToolBar(
323 long lStyle
324 , wxWindowID vId
325 , const wxString& rsName
326 )
327 {
328 wxToolBar* pToolBar = wxFrameBase::OnCreateToolBar( lStyle
329 ,vId
330 ,rsName
331 );
332
333 ::WinSetParent( pToolBar->GetHWND()
334 ,m_hFrame
335 ,FALSE
336 );
337 ::WinSetOwner( pToolBar->GetHWND()
338 ,m_hFrame
339 );
340 return pToolBar;
341 } // end of WinGuiBase_CFrame::OnCreateToolBar
342 #endif
343
344 #if wxUSE_MENUS_NATIVE
345 void wxFrame::DetachMenuBar()
346 {
347 if (m_frameMenuBar)
348 {
349 m_frameMenuBar->Detach();
350 m_frameMenuBar = NULL;
351 }
352 } // end of wxFrame::DetachMenuBar
353
354 void wxFrame::SetMenuBar(
355 wxMenuBar* pMenuBar
356 )
357 {
358 ERRORID vError;
359 wxString sError;
360 HWND hTitlebar = NULLHANDLE;
361 HWND hHScroll = NULLHANDLE;
362 HWND hVScroll = NULLHANDLE;
363 HWND hMenuBar = NULLHANDLE;
364 SWP vSwp;
365 SWP vSwpTitlebar;
366 SWP vSwpVScroll;
367 SWP vSwpHScroll;
368 SWP vSwpMenu;
369
370 if (!pMenuBar)
371 {
372 DetachMenuBar();
373
374 //
375 // Actually remove the menu from the frame
376 //
377 m_hMenu = (WXHMENU)0;
378 InternalSetMenuBar();
379 }
380 else // set new non NULL menu bar
381 {
382 m_frameMenuBar = NULL;
383
384 //
385 // Can set a menubar several times.
386 // TODO: how to prevent a memory leak if you have a currently-unattached
387 // menubar? wxWindows assumes that the frame will delete the menu (otherwise
388 // there are problems for MDI).
389 //
390 if (pMenuBar->GetHMenu())
391 {
392 m_hMenu = pMenuBar->GetHMenu();
393 }
394 else
395 {
396 pMenuBar->Detach();
397 m_hMenu = pMenuBar->Create();
398 if (!m_hMenu)
399 return;
400 }
401 InternalSetMenuBar();
402 m_frameMenuBar = pMenuBar;
403 pMenuBar->Attach((wxFrame*)this);
404 }
405 } // end of wxFrame::SetMenuBar
406
407 void wxFrame::AttachMenuBar(
408 wxMenuBar* pMenubar
409 )
410 {
411 wxFrameBase::AttachMenuBar(pMenubar);
412
413 m_frameMenuBar = pMenubar;
414
415 if (!pMenubar)
416 {
417 //
418 // Actually remove the menu from the frame
419 //
420 m_hMenu = (WXHMENU)0;
421 InternalSetMenuBar();
422 }
423 else // Set new non NULL menu bar
424 {
425 //
426 // Can set a menubar several times.
427 //
428 if (pMenubar->GetHMenu())
429 {
430 m_hMenu = pMenubar->GetHMenu();
431 }
432 else
433 {
434 if (pMenubar->IsAttached())
435 pMenubar->Detach();
436
437 m_hMenu = pMenubar->Create();
438
439 if (!m_hMenu)
440 return;
441 }
442 InternalSetMenuBar();
443 }
444 } // end of wxFrame::AttachMenuBar
445
446 void wxFrame::InternalSetMenuBar()
447 {
448 ERRORID vError;
449 wxString sError;
450 //
451 // Set the parent and owner of the menubar to be the frame
452 //
453 if (!::WinSetParent(m_hMenu, m_hFrame, FALSE))
454 {
455 vError = ::WinGetLastError(vHabmain);
456 sError = wxPMErrorToStr(vError);
457 wxLogError("Error setting parent for submenu. Error: %s\n", sError);
458 }
459
460 if (!::WinSetOwner(m_hMenu, m_hFrame))
461 {
462 vError = ::WinGetLastError(vHabmain);
463 sError = wxPMErrorToStr(vError);
464 wxLogError("Error setting parent for submenu. Error: %s\n", sError);
465 }
466 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)FCF_MENU, (MPARAM)0);
467 } // end of wxFrame::InternalSetMenuBar
468 #endif // wxUSE_MENUS_NATIVE
469
470 //
471 // Responds to colour changes, and passes event on to children
472 //
473 void wxFrame::OnSysColourChanged(
474 wxSysColourChangedEvent& rEvent
475 )
476 {
477 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
478 Refresh();
479
480 #if wxUSE_STATUSBAR
481 if (m_frameStatusBar)
482 {
483 wxSysColourChangedEvent vEvent2;
484
485 vEvent2.SetEventObject(m_frameStatusBar);
486 m_frameStatusBar->GetEventHandler()->ProcessEvent(vEvent2);
487 }
488 #endif //wxUSE_STATUSBAR
489
490 //
491 // Propagate the event to the non-top-level children
492 //
493 wxWindow::OnSysColourChanged(rEvent);
494 } // end of wxFrame::OnSysColourChanged
495
496 // Pass TRUE to show full screen, FALSE to restore.
497 bool wxFrame::ShowFullScreen(
498 bool bShow
499 , long lStyle
500 )
501 {
502 if (bShow)
503 {
504 if (IsFullScreen())
505 return FALSE;
506
507 m_bFsIsShowing = TRUE;
508 m_lFsStyle = lStyle;
509
510 #if wxUSE_TOOLBAR
511 wxToolBar* pTheToolBar = GetToolBar();
512 #endif //wxUSE_TOOLBAR
513
514 #if wxUSE_STATUSBAR
515 wxStatusBar* pTheStatusBar = GetStatusBar();
516 #endif //wxUSE_STATUSBAR
517
518 int nDummyWidth;
519
520 #if wxUSE_TOOLBAR
521 if (pTheToolBar)
522 pTheToolBar->GetSize(&nDummyWidth, &m_nFsToolBarHeight);
523 #endif //wxUSE_TOOLBAR
524
525 #if wxUSE_STATUSBAR
526 if (pTheStatusBar)
527 pTheStatusBar->GetSize(&nDummyWidth, &m_nFsStatusBarHeight);
528 #endif //wxUSE_STATUSBAR
529
530 #if wxUSE_TOOLBAR
531 //
532 // Zap the toolbar, menubar, and statusbar
533 //
534 if ((lStyle & wxFULLSCREEN_NOTOOLBAR) && pTheToolBar)
535 {
536 pTheToolBar->SetSize(-1,0);
537 pTheToolBar->Show(FALSE);
538 }
539 #endif //wxUSE_TOOLBAR
540
541 if (lStyle & wxFULLSCREEN_NOMENUBAR)
542 {
543 ::WinSetParent(m_hMenu, m_hFrame, FALSE);
544 ::WinSetOwner(m_hMenu, m_hFrame);
545 ::WinSendMsg((HWND)m_hFrame, WM_UPDATEFRAME, (MPARAM)FCF_MENU, (MPARAM)0);
546 }
547
548 #if wxUSE_STATUSBAR
549 //
550 // Save the number of fields in the statusbar
551 //
552 if ((lStyle & wxFULLSCREEN_NOSTATUSBAR) && pTheStatusBar)
553 {
554 m_nFsStatusBarFields = pTheStatusBar->GetFieldsCount();
555 SetStatusBar((wxStatusBar*) NULL);
556 delete pTheStatusBar;
557 }
558 else
559 m_nFsStatusBarFields = 0;
560 #endif //wxUSE_STATUSBAR
561
562 //
563 // Zap the frame borders
564 //
565
566 //
567 // Save the 'normal' window style
568 //
569 m_lFsOldWindowStyle = ::WinQueryWindowULong(m_hFrame, QWL_STYLE);
570
571 //
572 // Save the old position, width & height, maximize state
573 //
574 m_vFsOldSize = GetRect();
575 m_bFsIsMaximized = IsMaximized();
576
577 //
578 // Decide which window style flags to turn off
579 //
580 LONG lNewStyle = m_lFsOldWindowStyle;
581 LONG lOffFlags = 0;
582
583 if (lStyle & wxFULLSCREEN_NOBORDER)
584 lOffFlags |= FCF_BORDER;
585 if (lStyle & wxFULLSCREEN_NOCAPTION)
586 lOffFlags |= (FCF_TASKLIST | FCF_SYSMENU);
587
588 lNewStyle &= (~lOffFlags);
589
590 //
591 // Change our window style to be compatible with full-screen mode
592 //
593 ::WinSetWindowULong((HWND)m_hFrame, QWL_STYLE, (ULONG)lNewStyle);
594
595 //
596 // Resize to the size of the desktop
597 int nWidth;
598 int nHeight;
599
600 RECTL vRect;
601
602 ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
603 nWidth = vRect.xRight - vRect.xLeft;
604 //
605 // Rmember OS/2 is backwards!
606 //
607 nHeight = vRect.yTop - vRect.yBottom;
608
609 SetSize( nWidth
610 ,nHeight
611 );
612
613 //
614 // Now flush the window style cache and actually go full-screen
615 //
616 ::WinSetWindowPos( (HWND) GetParent()->GetHWND()
617 ,HWND_TOP
618 ,0
619 ,0
620 ,nWidth
621 ,nHeight
622 ,SWP_SIZE | SWP_SHOW
623 );
624
625 wxSizeEvent vEvent( wxSize( nWidth
626 ,nHeight
627 )
628 ,GetId()
629 );
630
631 GetEventHandler()->ProcessEvent(vEvent);
632 return TRUE;
633 }
634 else
635 {
636 if (!IsFullScreen())
637 return FALSE;
638
639 m_bFsIsShowing = FALSE;
640
641 #if wxUSE_TOOLBAR
642 wxToolBar* pTheToolBar = GetToolBar();
643
644 //
645 // Restore the toolbar, menubar, and statusbar
646 //
647 if (pTheToolBar && (m_lFsStyle & wxFULLSCREEN_NOTOOLBAR))
648 {
649 pTheToolBar->SetSize(-1, m_nFsToolBarHeight);
650 pTheToolBar->Show(TRUE);
651 }
652 #endif //wxUSE_TOOLBAR
653
654 #if wxUSE_STATUSBAR
655 if ((m_lFsStyle & wxFULLSCREEN_NOSTATUSBAR) && (m_nFsStatusBarFields > 0))
656 {
657 CreateStatusBar(m_nFsStatusBarFields);
658 // PositionStatusBar();
659 }
660 #endif //wxUSE_STATUSBAR
661
662 if ((m_lFsStyle & wxFULLSCREEN_NOMENUBAR) && (m_hMenu != 0))
663 {
664 ::WinSetParent(m_hMenu, m_hFrame, FALSE);
665 ::WinSetOwner(m_hMenu, m_hFrame);
666 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)FCF_MENU, (MPARAM)0);
667 }
668 Maximize(m_bFsIsMaximized);
669
670 ::WinSetWindowULong( m_hFrame
671 ,QWL_STYLE
672 ,(ULONG)m_lFsOldWindowStyle
673 );
674 ::WinSetWindowPos( (HWND) GetParent()->GetHWND()
675 ,HWND_TOP
676 ,m_vFsOldSize.x
677 ,m_vFsOldSize.y
678 ,m_vFsOldSize.width
679 ,m_vFsOldSize.height
680 ,SWP_SIZE | SWP_SHOW
681 );
682 }
683 return wxFrameBase::ShowFullScreen(bShow, lStyle);
684 } // end of wxFrame::ShowFullScreen
685
686 //
687 // Frame window
688 //
689 // ----------------------------------------------------------------------------
690 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
691 // from the client area, so the client area is what's really available for the
692 // frame contents
693 // ----------------------------------------------------------------------------
694
695 // Checks if there is a toolbar, and returns the first free client position
696 wxPoint wxFrame::GetClientAreaOrigin() const
697 {
698 wxPoint vPoint = wxTopLevelWindow::GetClientAreaOrigin();
699
700 //
701 // In OS/2 the toolbar and statusbar are frame extensions so there is no
702 // adjustment. The client is supposedly resized for a toolbar in OS/2
703 // as it is for the status bar.
704 //
705 return vPoint;
706 } // end of wxFrame::GetClientAreaOrigin
707
708 // ----------------------------------------------------------------------------
709 // tool/status bar stuff
710 // ----------------------------------------------------------------------------
711
712 #if wxUSE_TOOLBAR
713
714 wxToolBar* wxFrame::CreateToolBar(
715 long lStyle
716 , wxWindowID vId
717 , const wxString& rName
718 )
719 {
720 if (wxFrameBase::CreateToolBar( lStyle
721 ,vId
722 ,rName
723 ))
724 {
725 PositionToolBar();
726 }
727 return m_frameToolBar;
728 } // end of wxFrame::CreateToolBar
729
730 void wxFrame::PositionToolBar()
731 {
732 wxToolBar* pToolBar = GetToolBar();
733 wxCoord vWidth;
734 wxCoord vHeight;
735 wxCoord vTWidth;
736 wxCoord vTHeight;
737
738 if (!pToolBar)
739 return;
740
741 HWND hWndClient;
742 RECTL vRect;
743 RECTL vFRect;
744 SWP vSwp;
745 wxPoint vPos;
746
747 ::WinQueryWindowRect(m_hFrame, &vRect);
748 vPos.y = (wxCoord)vRect.yTop;
749 ::WinMapWindowPoints(m_hFrame, HWND_DESKTOP, (PPOINTL)&vRect, 2);
750 vFRect = vRect;
751 ::WinCalcFrameRect(m_hFrame, &vRect, TRUE);
752
753 vPos.y = (wxCoord)(vFRect.yTop - vRect.yTop);
754 pToolBar->GetSize( &vTWidth
755 ,&vTHeight
756 );
757
758 if (pToolBar->GetWindowStyleFlag() & wxTB_HORIZONTAL)
759 {
760 vWidth = (wxCoord)(vRect.xRight - vRect.xLeft);
761 pToolBar->SetSize( vRect.xLeft - vFRect.xLeft
762 ,vPos.y
763 ,vWidth
764 ,vTHeight
765 );
766 }
767 else
768 {
769 wxCoord vSwidth = 0;
770 wxCoord vSheight = 0;
771
772 if (m_frameStatusBar)
773 m_frameStatusBar->GetSize( &vSwidth
774 ,&vSheight
775 );
776 vHeight = (wxCoord)(vRect.yTop - vRect.yBottom);
777 pToolBar->SetSize( vRect.xLeft - vFRect.xLeft
778 ,vPos.y
779 ,vTWidth
780 ,vHeight - vSheight
781 );
782 }
783 if( ::WinIsWindowShowing(m_hFrame) )
784 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
785 } // end of wxFrame::PositionToolBar
786 #endif // wxUSE_TOOLBAR
787
788 // ----------------------------------------------------------------------------
789 // frame state (iconized/maximized/...)
790 // ----------------------------------------------------------------------------
791
792 //
793 // propagate our state change to all child frames: this allows us to emulate X
794 // Windows behaviour where child frames float independently of the parent one
795 // on the desktop, but are iconized/restored with it
796 //
797 void wxFrame::IconizeChildFrames(
798 bool bIconize
799 )
800 {
801 for (wxWindowList::Node* pNode = GetChildren().GetFirst();
802 pNode;
803 pNode = pNode->GetNext() )
804 {
805 wxWindow* pWin = pNode->GetData();
806 wxFrame* pFrame = wxDynamicCast(pWin, wxFrame);
807
808 if ( pFrame
809 #if wxUSE_MDI_ARCHITECTURE
810 && !wxDynamicCast(pFrame, wxMDIChildFrame)
811 #endif // wxUSE_MDI_ARCHITECTURE
812 )
813 {
814 //
815 // We don't want to restore the child frames which had been
816 // iconized even before we were iconized, so save the child frame
817 // status when iconizing the parent frame and check it when
818 // restoring it.
819 //
820 if (bIconize)
821 {
822 pFrame->m_bWasMinimized = pFrame->IsIconized();
823 }
824
825 //
826 // This test works for both iconizing and restoring
827 //
828 if (!pFrame->m_bWasMinimized)
829 pFrame->Iconize(bIconize);
830 }
831 }
832 } // end of wxFrame::IconizeChildFrames
833
834 WXHICON wxFrame::GetDefaultIcon() const
835 {
836 return (WXHICON)(wxSTD_FRAME_ICON ? wxSTD_FRAME_ICON
837 : wxDEFAULT_FRAME_ICON);
838 }
839 // ===========================================================================
840 // message processing
841 // ===========================================================================
842
843 // ---------------------------------------------------------------------------
844 // preprocessing
845 // ---------------------------------------------------------------------------
846 bool wxFrame::OS2TranslateMessage(
847 WXMSG* pMsg
848 )
849 {
850 //
851 // try the menu bar accels
852 //
853 wxMenuBar* pMenuBar = GetMenuBar();
854
855 if (!pMenuBar)
856 return FALSE;
857
858 #if wxUSE_ACCEL && wxUSE_MENUS_NATIVE
859 const wxAcceleratorTable& rAcceleratorTable = pMenuBar->GetAccelTable();
860 return rAcceleratorTable.Translate(GetHWND(), pMsg);
861 #else
862 return FALSE;
863 #endif //wxUSE_ACCEL
864 } // end of wxFrame::OS2TranslateMessage
865
866 // ---------------------------------------------------------------------------
867 // our private (non virtual) message handlers
868 // ---------------------------------------------------------------------------
869 bool wxFrame::HandlePaint()
870 {
871 RECTL vRect;
872
873 if (::WinQueryUpdateRect(GetHWND(), &vRect))
874 {
875 if (m_bIconized)
876 {
877 //
878 // Icons in PM are the same as "pointers"
879 //
880 const wxIcon& vIcon = GetIcon();
881 HPOINTER hIcon;
882
883 if (vIcon.Ok())
884 hIcon = (HPOINTER)::WinSendMsg(m_hFrame, WM_QUERYICON, 0L, 0L);
885 else
886 hIcon = (HPOINTER)m_hDefaultIcon;
887
888 //
889 // Hold a pointer to the dc so long as the OnPaint() message
890 // is being processed
891 //
892 RECTL vRect2;
893 HPS hPs = ::WinBeginPaint(GetHwnd(), NULLHANDLE, &vRect2);
894
895 //
896 // Erase background before painting or we get white background
897 //
898 OS2DefWindowProc(WM_ERASEBACKGROUND, (MPARAM)hPs, (MPARAM)&vRect2);
899
900 if (hIcon)
901 {
902 HWND hWndClient;
903 RECTL vRect3;
904
905 ::WinQueryWindowRect(GetHwnd(), &vRect3);
906
907 static const int nIconWidth = 32;
908 static const int nIconHeight = 32;
909 int nIconX = (int)((vRect3.xRight - nIconWidth)/2);
910 int nIconY = (int)((vRect3.yBottom + nIconHeight)/2);
911
912 ::WinDrawPointer(hPs, nIconX, nIconY, hIcon, DP_NORMAL);
913 }
914 ::WinEndPaint(hPs);
915 return TRUE;
916 }
917 else
918 {
919 if (!wxWindow::HandlePaint())
920 {
921 HPS hPS;
922 RECTL vRect;
923
924 hPS = ::WinBeginPaint( GetHwnd()
925 ,NULLHANDLE
926 ,&vRect
927 );
928 if(hPS)
929 {
930 ::GpiCreateLogColorTable( hPS
931 ,0L
932 ,LCOLF_CONSECRGB
933 ,0L
934 ,(LONG)wxTheColourDatabase->m_nSize
935 ,(PLONG)wxTheColourDatabase->m_palTable
936 );
937 ::GpiCreateLogColorTable( hPS
938 ,0L
939 ,LCOLF_RGB
940 ,0L
941 ,0L
942 ,NULL
943 );
944
945 ::WinFillRect( hPS
946 ,&vRect
947 ,GetBackgroundColour().GetPixel()
948 );
949 ::WinEndPaint(hPS);
950 }
951 }
952 return TRUE;
953 }
954 }
955 else
956 {
957 // nothing to paint - processed
958 return TRUE;
959 }
960 return FALSE;
961 } // end of wxFrame::HandlePaint
962
963 bool wxFrame::HandleSize(
964 int nX
965 , int nY
966 , WXUINT nId
967 )
968 {
969 bool bProcessed = FALSE;
970
971 switch (nId)
972 {
973 case kSizeNormal:
974 //
975 // Only do it it if we were iconized before, otherwise resizing the
976 // parent frame has a curious side effect of bringing it under it's
977 // children
978 if (!m_bIconized )
979 break;
980
981 //
982 // restore all child frames too
983 //
984 IconizeChildFrames(FALSE);
985 (void)SendIconizeEvent(FALSE);
986
987 //
988 // fall through
989 //
990
991 case kSizeMax:
992 m_bIconized = FALSE;
993 break;
994
995 case kSizeMin:
996 //
997 // Iconize all child frames too
998 //
999 IconizeChildFrames(TRUE);
1000 (void)SendIconizeEvent();
1001 m_bIconized = TRUE;
1002 break;
1003 }
1004
1005 if (!m_bIconized)
1006 {
1007 //
1008 // forward WM_SIZE to status bar control
1009 //
1010 #if wxUSE_NATIVE_STATUSBAR
1011 if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
1012 {
1013 wxSizeEvent vEvent( wxSize( nX
1014 ,nY
1015 )
1016 ,m_frameStatusBar->GetId()
1017 );
1018
1019 vEvent.SetEventObject(m_frameStatusBar);
1020 m_frameStatusBar->OnSize(vEvent);
1021 }
1022 #endif // wxUSE_NATIVE_STATUSBAR
1023
1024 PositionStatusBar();
1025 #if wxUSE_TOOLBAR
1026 PositionToolBar();
1027 #endif // wxUSE_TOOLBAR
1028
1029 bProcessed = wxWindow::HandleSize( nX
1030 ,nY
1031 ,nId
1032 );
1033 }
1034 return bProcessed;
1035 } // end of wxFrame::HandleSize
1036
1037 bool wxFrame::HandleCommand(
1038 WXWORD nId
1039 , WXWORD nCmd
1040 , WXHWND hControl
1041 )
1042 {
1043 if (hControl)
1044 {
1045 //
1046 // In case it's e.g. a toolbar.
1047 //
1048 wxWindow* pWin = wxFindWinFromHandle(hControl);
1049
1050 if (pWin)
1051 return pWin->OS2Command( nCmd
1052 ,nId
1053 );
1054 }
1055
1056 //
1057 // Handle here commands from menus and accelerators
1058 //
1059 if (nCmd == CMDSRC_MENU || nCmd == CMDSRC_ACCELERATOR)
1060 {
1061 #if wxUSE_MENUS_NATIVE
1062 if (wxCurrentPopupMenu)
1063 {
1064 wxMenu* pPopupMenu = wxCurrentPopupMenu;
1065
1066 wxCurrentPopupMenu = NULL;
1067
1068 return pPopupMenu->OS2Command( nCmd
1069 ,nId
1070 );
1071 return TRUE;
1072 }
1073 #endif
1074
1075 if (ProcessCommand(nId))
1076 {
1077 return TRUE;
1078 }
1079 }
1080 return FALSE;
1081 } // end of wxFrame::HandleCommand
1082
1083 bool wxFrame::HandleMenuSelect(
1084 WXWORD nItem
1085 , WXWORD nFlags
1086 , WXHMENU hMenu
1087 )
1088 {
1089 if( !nFlags )
1090 {
1091 MENUITEM mItem;
1092 MRESULT rc;
1093
1094 rc = ::WinSendMsg(hMenu, MM_QUERYITEM, MPFROM2SHORT(nItem, TRUE), (MPARAM)&mItem);
1095
1096 if(rc && !(mItem.afStyle & (MIS_SUBMENU | MIS_SEPARATOR)))
1097 {
1098 wxMenuEvent vEvent(wxEVT_MENU_HIGHLIGHT, nItem);
1099
1100 vEvent.SetEventObject(this);
1101 GetEventHandler()->ProcessEvent(vEvent); // return value would be ignored by PM
1102 }
1103 else
1104 {
1105 DoGiveHelp(wxEmptyString, FALSE);
1106 return FALSE;
1107 }
1108 }
1109 return TRUE;
1110 } // end of wxFrame::HandleMenuSelect
1111
1112 // ---------------------------------------------------------------------------
1113 // Main Frame window proc
1114 // ---------------------------------------------------------------------------
1115 MRESULT EXPENTRY wxFrameMainWndProc(
1116 HWND hWnd
1117 , ULONG ulMsg
1118 , MPARAM wParam
1119 , MPARAM lParam
1120 )
1121 {
1122 MRESULT rc = (MRESULT)0;
1123 bool bProcessed = FALSE;
1124 wxFrame* pWnd = NULL;
1125
1126 pWnd = (wxFrame*) wxFindWinFromHandle((WXHWND) hWnd);
1127 switch (ulMsg)
1128 {
1129 case WM_QUERYFRAMECTLCOUNT:
1130 if(pWnd && pWnd->m_fnOldWndProc)
1131 {
1132 USHORT uItemCount = SHORT1FROMMR(pWnd->m_fnOldWndProc(hWnd, ulMsg, wParam, lParam));
1133
1134 rc = MRFROMSHORT(uItemCount);
1135 }
1136 break;
1137
1138 case WM_FORMATFRAME:
1139 /////////////////////////////////////////////////////////////////////////////////
1140 // Applications that subclass frame controls may find that the frame is already
1141 // subclassed the number of frame controls is variable.
1142 // The WM_FORMATFRAME and WM_QUERYFRAMECTLCOUNT messages must always be
1143 // subclassed by calling the previous window procedure and modifying its result.
1144 ////////////////////////////////////////////////////////////////////////////////
1145 {
1146 int nItemCount;
1147 int i;
1148 PSWP pSWP = NULL;
1149 RECTL vRectl;
1150 RECTL vRstb;
1151 RECTL vRtlb;
1152 int nHeight = 0;
1153 int nHeight2 = 0;
1154 int nWidth = 0;
1155
1156 pSWP = (PSWP)PVOIDFROMMP(wParam);
1157 nItemCount = SHORT1FROMMR(pWnd->m_fnOldWndProc(hWnd, ulMsg, wParam, lParam));
1158 if(pWnd->m_frameStatusBar)
1159 {
1160 ::WinQueryWindowRect(pWnd->m_frameStatusBar->GetHWND(), &vRstb);
1161 pWnd->m_frameStatusBar->GetSize(NULL, &nHeight);
1162 }
1163 if(pWnd->m_frameToolBar)
1164 {
1165 ::WinQueryWindowRect(pWnd->m_frameToolBar->GetHWND(), &vRtlb);
1166 pWnd->m_frameToolBar->GetSize(&nWidth, &nHeight2);
1167 }
1168 ::WinQueryWindowRect(pWnd->m_hFrame, &vRectl);
1169 ::WinMapWindowPoints(pWnd->m_hFrame, HWND_DESKTOP, (PPOINTL)&vRectl, 2);
1170 ::WinCalcFrameRect(pWnd->m_hFrame, &vRectl, TRUE);
1171 ::WinMapWindowPoints(HWND_DESKTOP, pWnd->m_hFrame, (PPOINTL)&vRectl, 2);
1172 for(i = 0; i < nItemCount; i++)
1173 {
1174 if(pWnd->m_hWnd && pSWP[i].hwnd == pWnd->m_hWnd)
1175 {
1176 if (pWnd->m_frameToolBar && pWnd->m_frameToolBar->GetWindowStyleFlag() & wxTB_HORIZONTAL)
1177 {
1178 pSWP[i].x = vRectl.xLeft;
1179 pSWP[i].y = vRectl.yBottom + nHeight;
1180 pSWP[i].cx = vRectl.xRight - vRectl.xLeft;
1181 pSWP[i].cy = vRectl.yTop - vRectl.yBottom - (nHeight + nHeight2);
1182 }
1183 else
1184 {
1185 pSWP[i].x = vRectl.xLeft + nWidth;
1186 pSWP[i].y = vRectl.yBottom + nHeight;
1187 pSWP[i].cx = vRectl.xRight - (vRectl.xLeft + nWidth);
1188 pSWP[i].cy = vRectl.yTop - vRectl.yBottom - nHeight;
1189 }
1190 pSWP[i].fl = SWP_SIZE | SWP_MOVE | SWP_SHOW;
1191 pSWP[i].hwndInsertBehind = HWND_TOP;
1192 }
1193 }
1194 bProcessed = TRUE;
1195 rc = MRFROMSHORT(nItemCount);
1196 }
1197 break;
1198
1199 default:
1200 if(pWnd && pWnd->m_fnOldWndProc)
1201 rc = pWnd->m_fnOldWndProc(hWnd, ulMsg, wParam, lParam);
1202 else
1203 rc = ::WinDefWindowProc(hWnd, ulMsg, wParam, lParam);
1204 }
1205 return rc;
1206 } // end of wxFrameMainWndProc
1207
1208 MRESULT EXPENTRY wxFrameWndProc(
1209 HWND hWnd
1210 , ULONG ulMsg
1211 , MPARAM wParam
1212 , MPARAM lParam
1213 )
1214 {
1215 //
1216 // Trace all ulMsgs - useful for the debugging
1217 //
1218 HWND parentHwnd;
1219 wxFrame* pWnd = NULL;
1220
1221 parentHwnd = WinQueryWindow(hWnd,QW_PARENT);
1222 pWnd = (wxFrame*) wxFindWinFromHandle((WXHWND) hWnd);
1223
1224 //
1225 // When we get the first message for the HWND we just created, we associate
1226 // it with wxWindow stored in wxWndHook
1227 //
1228
1229 MRESULT rc = (MRESULT)0;
1230 bool bProcessed = FALSE;
1231
1232 //
1233 // Stop right here if we don't have a valid handle in our wxWindow object.
1234 //
1235 if (pWnd && !pWnd->GetHWND())
1236 {
1237 pWnd->SetHWND((WXHWND) hWnd);
1238 rc = pWnd->OS2DefWindowProc(ulMsg, wParam, lParam );
1239 pWnd->SetHWND(0);
1240 }
1241 else
1242 {
1243 if (pWnd)
1244 rc = pWnd->OS2WindowProc(ulMsg, wParam, lParam);
1245 else
1246 rc = ::WinDefWindowProc(hWnd, ulMsg, wParam, lParam);
1247 }
1248 return rc;
1249 } // end of wxFrameWndProc
1250
1251 MRESULT wxFrame::OS2WindowProc(
1252 WXUINT uMessage
1253 , WXWPARAM wParam
1254 , WXLPARAM lParam
1255 )
1256 {
1257 MRESULT mRc = 0L;
1258 bool bProcessed = FALSE;
1259
1260 switch (uMessage)
1261 {
1262 case WM_CLOSE:
1263 //
1264 // If we can't close, tell the system that we processed the
1265 // message - otherwise it would close us
1266 //
1267 bProcessed = !Close();
1268 break;
1269
1270 case WM_PAINT:
1271 bProcessed = HandlePaint();
1272 mRc = (MRESULT)FALSE;
1273 break;
1274
1275 case WM_ERASEBACKGROUND:
1276 //
1277 // Returning TRUE to requests PM to paint the window background
1278 // in SYSCLR_WINDOW. We capture this here because the PS returned
1279 // in Frames is the PS for the whole frame, which we can't really
1280 // use at all. If you want to paint a different background, do it
1281 // in an OnPaint using a wxPaintDC.
1282 //
1283 mRc = (MRESULT)(TRUE);
1284 break;
1285
1286 case WM_COMMAND:
1287 {
1288 WORD wId;
1289 WORD wCmd;
1290 WXHWND hWnd;
1291
1292 UnpackCommand( (WXWPARAM)wParam
1293 ,(WXLPARAM)lParam
1294 ,&wId
1295 ,&hWnd
1296 ,&wCmd
1297 );
1298
1299 bProcessed = HandleCommand( wId
1300 ,wCmd
1301 ,(WXHWND)hWnd
1302 );
1303 }
1304 break;
1305
1306 case WM_MENUSELECT:
1307 {
1308 WXWORD wItem;
1309 WXWORD wFlags;
1310 WXHMENU hMenu;
1311
1312 UnpackMenuSelect( wParam
1313 ,lParam
1314 ,&wItem
1315 ,&wFlags
1316 ,&hMenu
1317 );
1318 bProcessed = HandleMenuSelect( wItem
1319 ,wFlags
1320 ,hMenu
1321 );
1322 mRc = (MRESULT)TRUE;
1323 }
1324 break;
1325
1326 case WM_SIZE:
1327 {
1328 SHORT nScxold = SHORT1FROMMP(wParam); // Old horizontal size.
1329 SHORT nScyold = SHORT2FROMMP(wParam); // Old vertical size.
1330 SHORT nScxnew = SHORT1FROMMP(lParam); // New horizontal size.
1331 SHORT nScynew = SHORT2FROMMP(lParam); // New vertical size.
1332
1333 lParam = MRFROM2SHORT( nScxnew - 20
1334 ,nScynew - 30
1335 );
1336 }
1337 bProcessed = HandleSize(LOWORD(lParam), HIWORD(lParam), (WXUINT)wParam);
1338 mRc = (MRESULT)FALSE;
1339 break;
1340
1341 case CM_QUERYDRAGIMAGE:
1342 {
1343 const wxIcon& vIcon = GetIcon();
1344 HPOINTER hIcon;
1345
1346 if (vIcon.Ok())
1347 hIcon = (HPOINTER)::WinSendMsg(GetHWND(), WM_QUERYICON, 0L, 0L);
1348 else
1349 hIcon = (HPOINTER)m_hDefaultIcon;
1350 mRc = (MRESULT)hIcon;
1351 bProcessed = mRc != 0;
1352 }
1353 break;
1354 }
1355
1356 if (!bProcessed )
1357 mRc = wxWindow::OS2WindowProc( uMessage
1358 ,wParam
1359 ,lParam
1360 );
1361 return (MRESULT)mRc;
1362 } // wxFrame::OS2WindowProc
1363
1364 void wxFrame::SetClient(WXHWND c_Hwnd)
1365 {
1366 // Duh...nothing to do under OS/2
1367 }
1368
1369 void wxFrame::SetClient(
1370 wxWindow* pWindow
1371 )
1372 {
1373 wxWindow* pOldClient = this->GetClient();
1374 bool bClientHasFocus = pOldClient && (pOldClient == wxWindow::FindFocus());
1375
1376 if(pOldClient == pWindow) // nothing to do
1377 return;
1378 if(pWindow == NULL) // just need to remove old client
1379 {
1380 if(pOldClient == NULL) // nothing to do
1381 return;
1382
1383 if(bClientHasFocus )
1384 this->SetFocus();
1385
1386 pOldClient->Enable( FALSE );
1387 pOldClient->Show( FALSE );
1388 ::WinSetWindowUShort(pOldClient->GetHWND(), QWS_ID, (USHORT)pOldClient->GetId());
1389 // to avoid OS/2 bug need to update frame
1390 ::WinSendMsg((HWND)this->GetFrame(), WM_UPDATEFRAME, (MPARAM)~0, 0);
1391 return;
1392 }
1393
1394 //
1395 // Else need to change client
1396 //
1397 if(bClientHasFocus)
1398 this->SetFocus();
1399
1400 ::WinEnableWindowUpdate((HWND)GetHWND(), FALSE);
1401 if(pOldClient)
1402 {
1403 pOldClient->Enable(FALSE);
1404 pOldClient->Show(FALSE);
1405 ::WinSetWindowUShort(pOldClient->GetHWND(), QWS_ID, (USHORT)pOldClient->GetId());
1406 }
1407 pWindow->Reparent(this);
1408 ::WinSetWindowUShort(pWindow->GetHWND(), QWS_ID, FID_CLIENT);
1409 ::WinEnableWindowUpdate((HWND)GetHWND(), TRUE);
1410 pWindow->Enable();
1411 pWindow->Show(); // ensure client is showing
1412 if( this->IsShown() )
1413 {
1414 this->Show();
1415 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
1416 }
1417 }
1418
1419 wxWindow* wxFrame::GetClient()
1420 {
1421 return wxFindWinFromHandle((WXHWND)::WinWindowFromID(m_hFrame, FID_CLIENT));
1422 }