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