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