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