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