OS/2 updates and initial toolbar implementation
[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(0, 0);
699
700 #if wxUSE_TOOLBAR
701 if (GetToolBar())
702 {
703 int nWidth;
704 int nHeight;
705
706 GetToolBar()->GetSize( &nWidth
707 ,&nHeight
708 );
709
710 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
711 {
712 vPoint.x += nWidth;
713 }
714 else
715 {
716 // PM is backwards from windows
717 vPoint.y += nHeight;
718 }
719 }
720 #endif //wxUSE_TOOLBAR
721 return vPoint;
722 } // end of wxFrame::GetClientAreaOrigin
723
724 // ----------------------------------------------------------------------------
725 // tool/status bar stuff
726 // ----------------------------------------------------------------------------
727
728 #if wxUSE_TOOLBAR
729
730 wxToolBar* wxFrame::CreateToolBar(
731 long lStyle
732 , wxWindowID vId
733 , const wxString& rName
734 )
735 {
736 if (wxFrameBase::CreateToolBar( lStyle
737 ,vId
738 ,rName
739 ))
740 {
741 PositionToolBar();
742 }
743 return m_frameToolBar;
744 } // end of wxFrame::CreateToolBar
745
746 void wxFrame::PositionToolBar()
747 {
748 wxToolBar* pToolBar = GetToolBar();
749 wxCoord vWidth;
750 wxCoord vHeight;
751 wxCoord vTWidth;
752 wxCoord vTHeight;
753
754 if (!pToolBar)
755 return;
756
757 HWND hWndClient;
758 RECTL vRect;
759 RECTL vFRect;
760 SWP vSwp;
761 wxPoint vPos;
762
763 ::WinQueryWindowRect(m_hFrame, &vRect);
764 vPos.y = (wxCoord)vRect.yTop;
765 ::WinMapWindowPoints(m_hFrame, HWND_DESKTOP, (PPOINTL)&vRect, 2);
766 vFRect = vRect;
767 ::WinCalcFrameRect(m_hFrame, &vRect, TRUE);
768
769 vPos.y = (wxCoord)(vFRect.yTop - vRect.yTop);
770 pToolBar->GetSize( &vTWidth
771 ,&vTHeight
772 );
773
774 if (pToolBar->GetWindowStyleFlag() & wxTB_HORIZONTAL)
775 {
776 vWidth = (wxCoord)(vRect.xRight - vRect.xLeft);
777 pToolBar->SetSize( vRect.xLeft - vFRect.xLeft
778 ,vPos.y
779 ,vWidth
780 ,vTHeight
781 );
782 }
783 else
784 {
785 wxCoord vSwidth = 0;
786 wxCoord vSheight = 0;
787
788 if (m_frameStatusBar)
789 m_frameStatusBar->GetSize( &vSwidth
790 ,&vSheight
791 );
792 vHeight = (wxCoord)(vRect.yTop - vRect.yBottom);
793 pToolBar->SetSize( vRect.xLeft - vFRect.xLeft
794 ,vPos.y
795 ,vTWidth
796 ,vHeight - vSheight
797 );
798 }
799 if( ::WinIsWindowShowing(m_hFrame) )
800 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
801 } // end of wxFrame::PositionToolBar
802 #endif // wxUSE_TOOLBAR
803
804 // ----------------------------------------------------------------------------
805 // frame state (iconized/maximized/...)
806 // ----------------------------------------------------------------------------
807
808 //
809 // propagate our state change to all child frames: this allows us to emulate X
810 // Windows behaviour where child frames float independently of the parent one
811 // on the desktop, but are iconized/restored with it
812 //
813 void wxFrame::IconizeChildFrames(
814 bool bIconize
815 )
816 {
817 for (wxWindowList::Node* pNode = GetChildren().GetFirst();
818 pNode;
819 pNode = pNode->GetNext() )
820 {
821 wxWindow* pWin = pNode->GetData();
822 wxFrame* pFrame = wxDynamicCast(pWin, wxFrame);
823
824 if ( pFrame
825 #if wxUSE_MDI_ARCHITECTURE
826 && !wxDynamicCast(pFrame, wxMDIChildFrame)
827 #endif // wxUSE_MDI_ARCHITECTURE
828 )
829 {
830 //
831 // We don't want to restore the child frames which had been
832 // iconized even before we were iconized, so save the child frame
833 // status when iconizing the parent frame and check it when
834 // restoring it.
835 //
836 if (bIconize)
837 {
838 pFrame->m_bWasMinimized = pFrame->IsIconized();
839 }
840
841 //
842 // This test works for both iconizing and restoring
843 //
844 if (!pFrame->m_bWasMinimized)
845 pFrame->Iconize(bIconize);
846 }
847 }
848 } // end of wxFrame::IconizeChildFrames
849
850 WXHICON wxFrame::GetDefaultIcon() const
851 {
852 return (WXHICON)(wxSTD_FRAME_ICON ? wxSTD_FRAME_ICON
853 : wxDEFAULT_FRAME_ICON);
854 }
855 // ===========================================================================
856 // message processing
857 // ===========================================================================
858
859 // ---------------------------------------------------------------------------
860 // preprocessing
861 // ---------------------------------------------------------------------------
862 bool wxFrame::OS2TranslateMessage(
863 WXMSG* pMsg
864 )
865 {
866 //
867 // try the menu bar accels
868 //
869 wxMenuBar* pMenuBar = GetMenuBar();
870
871 if (!pMenuBar)
872 return FALSE;
873
874 #if wxUSE_ACCEL && wxUSE_MENUS_NATIVE
875 const wxAcceleratorTable& rAcceleratorTable = pMenuBar->GetAccelTable();
876 return rAcceleratorTable.Translate(GetHWND(), pMsg);
877 #else
878 return FALSE;
879 #endif //wxUSE_ACCEL
880 } // end of wxFrame::OS2TranslateMessage
881
882 // ---------------------------------------------------------------------------
883 // our private (non virtual) message handlers
884 // ---------------------------------------------------------------------------
885 bool wxFrame::HandlePaint()
886 {
887 RECTL vRect;
888
889 if (::WinQueryUpdateRect(GetHWND(), &vRect))
890 {
891 if (m_bIconized)
892 {
893 //
894 // Icons in PM are the same as "pointers"
895 //
896 const wxIcon& vIcon = GetIcon();
897 HPOINTER hIcon;
898
899 if (vIcon.Ok())
900 hIcon = (HPOINTER)::WinSendMsg(m_hFrame, WM_QUERYICON, 0L, 0L);
901 else
902 hIcon = (HPOINTER)m_hDefaultIcon;
903
904 //
905 // Hold a pointer to the dc so long as the OnPaint() message
906 // is being processed
907 //
908 RECTL vRect2;
909 HPS hPs = ::WinBeginPaint(GetHwnd(), NULLHANDLE, &vRect2);
910
911 //
912 // Erase background before painting or we get white background
913 //
914 OS2DefWindowProc(WM_ERASEBACKGROUND, (MPARAM)hPs, (MPARAM)&vRect2);
915
916 if (hIcon)
917 {
918 HWND hWndClient;
919 RECTL vRect3;
920
921 ::WinQueryWindowRect(GetHwnd(), &vRect3);
922
923 static const int nIconWidth = 32;
924 static const int nIconHeight = 32;
925 int nIconX = (int)((vRect3.xRight - nIconWidth)/2);
926 int nIconY = (int)((vRect3.yBottom + nIconHeight)/2);
927
928 ::WinDrawPointer(hPs, nIconX, nIconY, hIcon, DP_NORMAL);
929 }
930 ::WinEndPaint(hPs);
931 return TRUE;
932 }
933 else
934 {
935 if (!wxWindow::HandlePaint())
936 {
937 HPS hPS;
938 RECTL vRect;
939
940 hPS = ::WinBeginPaint( GetHwnd()
941 ,NULLHANDLE
942 ,&vRect
943 );
944 if(hPS)
945 {
946 ::GpiCreateLogColorTable( hPS
947 ,0L
948 ,LCOLF_CONSECRGB
949 ,0L
950 ,(LONG)wxTheColourDatabase->m_nSize
951 ,(PLONG)wxTheColourDatabase->m_palTable
952 );
953 ::GpiCreateLogColorTable( hPS
954 ,0L
955 ,LCOLF_RGB
956 ,0L
957 ,0L
958 ,NULL
959 );
960
961 ::WinFillRect( hPS
962 ,&vRect
963 ,GetBackgroundColour().GetPixel()
964 );
965 ::WinEndPaint(hPS);
966 }
967 }
968 return TRUE;
969 }
970 }
971 else
972 {
973 // nothing to paint - processed
974 return TRUE;
975 }
976 return FALSE;
977 } // end of wxFrame::HandlePaint
978
979 bool wxFrame::HandleSize(
980 int nX
981 , int nY
982 , WXUINT nId
983 )
984 {
985 bool bProcessed = FALSE;
986
987 switch (nId)
988 {
989 case kSizeNormal:
990 //
991 // Only do it it if we were iconized before, otherwise resizing the
992 // parent frame has a curious side effect of bringing it under it's
993 // children
994 if (!m_bIconized )
995 break;
996
997 //
998 // restore all child frames too
999 //
1000 IconizeChildFrames(FALSE);
1001 (void)SendIconizeEvent(FALSE);
1002
1003 //
1004 // fall through
1005 //
1006
1007 case kSizeMax:
1008 m_bIconized = FALSE;
1009 break;
1010
1011 case kSizeMin:
1012 //
1013 // Iconize all child frames too
1014 //
1015 IconizeChildFrames(TRUE);
1016 (void)SendIconizeEvent();
1017 m_bIconized = TRUE;
1018 break;
1019 }
1020
1021 if (!m_bIconized)
1022 {
1023 //
1024 // forward WM_SIZE to status bar control
1025 //
1026 #if wxUSE_NATIVE_STATUSBAR
1027 if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
1028 {
1029 wxSizeEvent vEvent( wxSize( nX
1030 ,nY
1031 )
1032 ,m_frameStatusBar->GetId()
1033 );
1034
1035 vEvent.SetEventObject(m_frameStatusBar);
1036 m_frameStatusBar->OnSize(vEvent);
1037 }
1038 #endif // wxUSE_NATIVE_STATUSBAR
1039
1040 PositionStatusBar();
1041 #if wxUSE_TOOLBAR
1042 PositionToolBar();
1043 #endif // wxUSE_TOOLBAR
1044
1045 bProcessed = wxWindow::HandleSize( nX
1046 ,nY
1047 ,nId
1048 );
1049 }
1050 return bProcessed;
1051 } // end of wxFrame::HandleSize
1052
1053 bool wxFrame::HandleCommand(
1054 WXWORD nId
1055 , WXWORD nCmd
1056 , WXHWND hControl
1057 )
1058 {
1059 if (hControl)
1060 {
1061 //
1062 // In case it's e.g. a toolbar.
1063 //
1064 wxWindow* pWin = wxFindWinFromHandle(hControl);
1065
1066 if (pWin)
1067 return pWin->OS2Command( nCmd
1068 ,nId
1069 );
1070 }
1071
1072 //
1073 // Handle here commands from menus and accelerators
1074 //
1075 if (nCmd == CMDSRC_MENU || nCmd == CMDSRC_ACCELERATOR)
1076 {
1077 #if wxUSE_MENUS_NATIVE
1078 if (wxCurrentPopupMenu)
1079 {
1080 wxMenu* pPopupMenu = wxCurrentPopupMenu;
1081
1082 wxCurrentPopupMenu = NULL;
1083
1084 return pPopupMenu->OS2Command( nCmd
1085 ,nId
1086 );
1087 return TRUE;
1088 }
1089 #endif
1090
1091 if (ProcessCommand(nId))
1092 {
1093 return TRUE;
1094 }
1095 }
1096 return FALSE;
1097 } // end of wxFrame::HandleCommand
1098
1099 bool wxFrame::HandleMenuSelect(
1100 WXWORD nItem
1101 , WXWORD nFlags
1102 , WXHMENU hMenu
1103 )
1104 {
1105 if( !nFlags )
1106 {
1107 MENUITEM mItem;
1108 MRESULT rc;
1109
1110 rc = ::WinSendMsg(hMenu, MM_QUERYITEM, MPFROM2SHORT(nItem, TRUE), (MPARAM)&mItem);
1111
1112 if(rc && !(mItem.afStyle & (MIS_SUBMENU | MIS_SEPARATOR)))
1113 {
1114 wxMenuEvent vEvent(wxEVT_MENU_HIGHLIGHT, nItem);
1115
1116 vEvent.SetEventObject(this);
1117 GetEventHandler()->ProcessEvent(vEvent); // return value would be ignored by PM
1118 }
1119 else
1120 {
1121 DoGiveHelp(wxEmptyString, FALSE);
1122 return FALSE;
1123 }
1124 }
1125 return TRUE;
1126 } // end of wxFrame::HandleMenuSelect
1127
1128 // ---------------------------------------------------------------------------
1129 // Main Frame window proc
1130 // ---------------------------------------------------------------------------
1131 MRESULT EXPENTRY wxFrameMainWndProc(
1132 HWND hWnd
1133 , ULONG ulMsg
1134 , MPARAM wParam
1135 , MPARAM lParam
1136 )
1137 {
1138 MRESULT rc = (MRESULT)0;
1139 bool bProcessed = FALSE;
1140 wxFrame* pWnd = NULL;
1141
1142 pWnd = (wxFrame*) wxFindWinFromHandle((WXHWND) hWnd);
1143 switch (ulMsg)
1144 {
1145 case WM_QUERYFRAMECTLCOUNT:
1146 if(pWnd && pWnd->m_fnOldWndProc)
1147 {
1148 USHORT uItemCount = SHORT1FROMMR(pWnd->m_fnOldWndProc(hWnd, ulMsg, wParam, lParam));
1149
1150 rc = MRFROMSHORT(uItemCount);
1151 }
1152 break;
1153
1154 case WM_FORMATFRAME:
1155 /////////////////////////////////////////////////////////////////////////////////
1156 // Applications that subclass frame controls may find that the frame is already
1157 // subclassed the number of frame controls is variable.
1158 // The WM_FORMATFRAME and WM_QUERYFRAMECTLCOUNT messages must always be
1159 // subclassed by calling the previous window procedure and modifying its result.
1160 ////////////////////////////////////////////////////////////////////////////////
1161 {
1162 int nItemCount;
1163 int i;
1164 PSWP pSWP = NULL;
1165 RECTL vRectl;
1166 RECTL vRstb;
1167 RECTL vRtlb;
1168 int nHeight = 0;
1169 int nHeight2 = 0;
1170 int nWidth = 0;
1171
1172 pSWP = (PSWP)PVOIDFROMMP(wParam);
1173 nItemCount = SHORT1FROMMR(pWnd->m_fnOldWndProc(hWnd, ulMsg, wParam, lParam));
1174 if(pWnd->m_frameStatusBar)
1175 {
1176 ::WinQueryWindowRect(pWnd->m_frameStatusBar->GetHWND(), &vRstb);
1177 pWnd->m_frameStatusBar->GetSize(NULL, &nHeight);
1178 }
1179 if(pWnd->m_frameToolBar)
1180 {
1181 ::WinQueryWindowRect(pWnd->m_frameToolBar->GetHWND(), &vRtlb);
1182 pWnd->m_frameToolBar->GetSize(&nWidth, &nHeight2);
1183 }
1184 ::WinQueryWindowRect(pWnd->m_hFrame, &vRectl);
1185 ::WinMapWindowPoints(pWnd->m_hFrame, HWND_DESKTOP, (PPOINTL)&vRectl, 2);
1186 ::WinCalcFrameRect(pWnd->m_hFrame, &vRectl, TRUE);
1187 ::WinMapWindowPoints(HWND_DESKTOP, pWnd->m_hFrame, (PPOINTL)&vRectl, 2);
1188 for(i = 0; i < nItemCount; i++)
1189 {
1190 if(pWnd->m_hWnd && pSWP[i].hwnd == pWnd->m_hWnd)
1191 {
1192 if (pWnd->m_frameToolBar && pWnd->m_frameToolBar->GetWindowStyleFlag() & wxTB_HORIZONTAL)
1193 {
1194 pSWP[i].x = vRectl.xLeft;
1195 pSWP[i].y = vRectl.yBottom + nHeight;
1196 pSWP[i].cx = vRectl.xRight - vRectl.xLeft;
1197 pSWP[i].cy = vRectl.yTop - vRectl.yBottom - (nHeight + nHeight2);
1198 }
1199 else
1200 {
1201 pSWP[i].x = vRectl.xLeft;
1202 pSWP[i].y = vRectl.yBottom + nHeight;
1203 pSWP[i].cx = vRectl.xRight - (vRectl.xLeft + nWidth);
1204 pSWP[i].cy = vRectl.yTop - vRectl.yBottom - nHeight;
1205 }
1206 pSWP[i].fl = SWP_SIZE | SWP_MOVE | SWP_SHOW;
1207 pSWP[i].hwndInsertBehind = HWND_TOP;
1208 }
1209 }
1210 bProcessed = TRUE;
1211 rc = MRFROMSHORT(nItemCount);
1212 }
1213 break;
1214
1215 default:
1216 if(pWnd && pWnd->m_fnOldWndProc)
1217 rc = pWnd->m_fnOldWndProc(hWnd, ulMsg, wParam, lParam);
1218 else
1219 rc = ::WinDefWindowProc(hWnd, ulMsg, wParam, lParam);
1220 }
1221 return rc;
1222 } // end of wxFrameMainWndProc
1223
1224 MRESULT EXPENTRY wxFrameWndProc(
1225 HWND hWnd
1226 , ULONG ulMsg
1227 , MPARAM wParam
1228 , MPARAM lParam
1229 )
1230 {
1231 //
1232 // Trace all ulMsgs - useful for the debugging
1233 //
1234 HWND parentHwnd;
1235 wxFrame* pWnd = NULL;
1236
1237 parentHwnd = WinQueryWindow(hWnd,QW_PARENT);
1238 pWnd = (wxFrame*) wxFindWinFromHandle((WXHWND) hWnd);
1239
1240 //
1241 // When we get the first message for the HWND we just created, we associate
1242 // it with wxWindow stored in wxWndHook
1243 //
1244
1245 MRESULT rc = (MRESULT)0;
1246 bool bProcessed = FALSE;
1247
1248 //
1249 // Stop right here if we don't have a valid handle in our wxWindow object.
1250 //
1251 if (pWnd && !pWnd->GetHWND())
1252 {
1253 pWnd->SetHWND((WXHWND) hWnd);
1254 rc = pWnd->OS2DefWindowProc(ulMsg, wParam, lParam );
1255 pWnd->SetHWND(0);
1256 }
1257 else
1258 {
1259 if (pWnd)
1260 rc = pWnd->OS2WindowProc(ulMsg, wParam, lParam);
1261 else
1262 rc = ::WinDefWindowProc(hWnd, ulMsg, wParam, lParam);
1263 }
1264 return rc;
1265 } // end of wxFrameWndProc
1266
1267 MRESULT wxFrame::OS2WindowProc(
1268 WXUINT uMessage
1269 , WXWPARAM wParam
1270 , WXLPARAM lParam
1271 )
1272 {
1273 MRESULT mRc = 0L;
1274 bool bProcessed = FALSE;
1275
1276 switch (uMessage)
1277 {
1278 case WM_CLOSE:
1279 //
1280 // If we can't close, tell the system that we processed the
1281 // message - otherwise it would close us
1282 //
1283 bProcessed = !Close();
1284 break;
1285
1286 case WM_PAINT:
1287 bProcessed = HandlePaint();
1288 mRc = (MRESULT)FALSE;
1289 break;
1290
1291 case WM_ERASEBACKGROUND:
1292 //
1293 // Returning TRUE to requests PM to paint the window background
1294 // in SYSCLR_WINDOW. We capture this here because the PS returned
1295 // in Frames is the PS for the whole frame, which we can't really
1296 // use at all. If you want to paint a different background, do it
1297 // in an OnPaint using a wxPaintDC.
1298 //
1299 mRc = (MRESULT)(TRUE);
1300 break;
1301
1302 case WM_COMMAND:
1303 {
1304 WORD wId;
1305 WORD wCmd;
1306 WXHWND hWnd;
1307
1308 UnpackCommand( (WXWPARAM)wParam
1309 ,(WXLPARAM)lParam
1310 ,&wId
1311 ,&hWnd
1312 ,&wCmd
1313 );
1314
1315 bProcessed = HandleCommand( wId
1316 ,wCmd
1317 ,(WXHWND)hWnd
1318 );
1319 }
1320 break;
1321
1322 case WM_MENUSELECT:
1323 {
1324 WXWORD wItem;
1325 WXWORD wFlags;
1326 WXHMENU hMenu;
1327
1328 UnpackMenuSelect( wParam
1329 ,lParam
1330 ,&wItem
1331 ,&wFlags
1332 ,&hMenu
1333 );
1334 bProcessed = HandleMenuSelect( wItem
1335 ,wFlags
1336 ,hMenu
1337 );
1338 mRc = (MRESULT)TRUE;
1339 }
1340 break;
1341
1342 case WM_SIZE:
1343 {
1344 SHORT nScxold = SHORT1FROMMP(wParam); // Old horizontal size.
1345 SHORT nScyold = SHORT2FROMMP(wParam); // Old vertical size.
1346 SHORT nScxnew = SHORT1FROMMP(lParam); // New horizontal size.
1347 SHORT nScynew = SHORT2FROMMP(lParam); // New vertical size.
1348
1349 lParam = MRFROM2SHORT( nScxnew - 20
1350 ,nScynew - 30
1351 );
1352 }
1353 bProcessed = HandleSize(LOWORD(lParam), HIWORD(lParam), (WXUINT)wParam);
1354 mRc = (MRESULT)FALSE;
1355 break;
1356
1357 case CM_QUERYDRAGIMAGE:
1358 {
1359 const wxIcon& vIcon = GetIcon();
1360 HPOINTER hIcon;
1361
1362 if (vIcon.Ok())
1363 hIcon = (HPOINTER)::WinSendMsg(GetHWND(), WM_QUERYICON, 0L, 0L);
1364 else
1365 hIcon = (HPOINTER)m_hDefaultIcon;
1366 mRc = (MRESULT)hIcon;
1367 bProcessed = mRc != 0;
1368 }
1369 break;
1370 }
1371
1372 if (!bProcessed )
1373 mRc = wxWindow::OS2WindowProc( uMessage
1374 ,wParam
1375 ,lParam
1376 );
1377 return (MRESULT)mRc;
1378 } // wxFrame::OS2WindowProc
1379
1380 void wxFrame::SetClient(WXHWND c_Hwnd)
1381 {
1382 // Duh...nothing to do under OS/2
1383 }
1384
1385 void wxFrame::SetClient(
1386 wxWindow* pWindow
1387 )
1388 {
1389 wxWindow* pOldClient = this->GetClient();
1390 bool bClientHasFocus = pOldClient && (pOldClient == wxWindow::FindFocus());
1391
1392 if(pOldClient == pWindow) // nothing to do
1393 return;
1394 if(pWindow == NULL) // just need to remove old client
1395 {
1396 if(pOldClient == NULL) // nothing to do
1397 return;
1398
1399 if(bClientHasFocus )
1400 this->SetFocus();
1401
1402 pOldClient->Enable( FALSE );
1403 pOldClient->Show( FALSE );
1404 ::WinSetWindowUShort(pOldClient->GetHWND(), QWS_ID, (USHORT)pOldClient->GetId());
1405 // to avoid OS/2 bug need to update frame
1406 ::WinSendMsg((HWND)this->GetFrame(), WM_UPDATEFRAME, (MPARAM)~0, 0);
1407 return;
1408 }
1409
1410 //
1411 // Else need to change client
1412 //
1413 if(bClientHasFocus)
1414 this->SetFocus();
1415
1416 ::WinEnableWindowUpdate((HWND)GetHWND(), FALSE);
1417 if(pOldClient)
1418 {
1419 pOldClient->Enable(FALSE);
1420 pOldClient->Show(FALSE);
1421 ::WinSetWindowUShort(pOldClient->GetHWND(), QWS_ID, (USHORT)pOldClient->GetId());
1422 }
1423 pWindow->Reparent(this);
1424 ::WinSetWindowUShort(pWindow->GetHWND(), QWS_ID, FID_CLIENT);
1425 ::WinEnableWindowUpdate((HWND)GetHWND(), TRUE);
1426 pWindow->Enable();
1427 pWindow->Show(); // ensure client is showing
1428 if( this->IsShown() )
1429 {
1430 this->Show();
1431 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
1432 }
1433 }
1434
1435 wxWindow* wxFrame::GetClient()
1436 {
1437 return wxFindWinFromHandle((WXHWND)::WinWindowFromID(m_hFrame, FID_CLIENT));
1438 }