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