]> git.saurik.com Git - wxWidgets.git/blob - src/os2/frame.cpp
dumb fix for wxDC::Clear() crash
[wxWidgets.git] / src / os2 / frame.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: frame.cpp
3 // Purpose: wxFrame
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/27/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/defs.h"
17 #include "wx/object.h"
18 #include "wx/dynarray.h"
19 #include "wx/list.h"
20 #include "wx/hash.h"
21 #include "wx/string.h"
22 #include "wx/intl.h"
23 #include "wx/log.h"
24 #include "wx/event.h"
25 #include "wx/setup.h"
26 #include "wx/frame.h"
27 #include "wx/menu.h"
28 #include "wx/app.h"
29 #include "wx/utils.h"
30 #include "wx/dialog.h"
31 #include "wx/settings.h"
32 #include "wx/dcclient.h"
33 #include "wx/mdi.h"
34 #endif // WX_PRECOMP
35
36 #include "wx/os2/private.h"
37
38 #if wxUSE_STATUSBAR
39 #include "wx/statusbr.h"
40 #include "wx/generic/statusbr.h"
41 #endif // wxUSE_STATUSBAR
42
43 #if wxUSE_TOOLBAR
44 #include "wx/toolbar.h"
45 #endif // wxUSE_TOOLBAR
46
47 #include "wx/menuitem.h"
48 #include "wx/log.h"
49
50 // ----------------------------------------------------------------------------
51 // globals
52 // ----------------------------------------------------------------------------
53
54 extern wxWindowList wxModelessWindows;
55 extern wxList WXDLLEXPORT wxPendingDelete;
56
57 #if wxUSE_MENUS_NATIVE
58 extern wxMenu *wxCurrentPopupMenu;
59 #endif
60
61 extern void wxAssociateWinWithHandle( HWND hWnd
62 ,wxWindowOS2* pWin
63 );
64
65 // ----------------------------------------------------------------------------
66 // event tables
67 // ----------------------------------------------------------------------------
68
69 BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
70 EVT_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 wxModelessWindows.Append(this);
148 return TRUE;
149 } // end of wxFrame::Create
150
151 wxFrame::~wxFrame()
152 {
153 m_isBeingDeleted = TRUE;
154 DeleteAllBars();
155 } // end of wxFrame::~wxFrame
156
157 //
158 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
159 //
160 void wxFrame::DoGetClientSize(
161 int* pX
162 , int* pY
163 ) const
164 {
165 wxTopLevelWindow::DoGetClientSize( pX
166 ,pY
167 );
168 //
169 // No need to use statusbar code as in WIN32 as the FORMATFRAME
170 // window procedure ensures PM knows about the new frame client
171 // size internally. A ::WinQueryWindowRect (that is called in
172 // wxWindow's GetClient size from above) is all that is needed!
173 //
174 } // end of wxFrame::DoGetClientSize
175
176 //
177 // Set the client size (i.e. leave the calculation of borders etc.
178 // to wxWindows)
179 //
180 void wxFrame::DoSetClientSize(
181 int nWidth
182 , int nHeight
183 )
184 {
185 wxStatusBar* pStatusBar = GetStatusBar();
186
187 //
188 // Statusbars are not part of the OS/2 Client but parent frame
189 // so no statusbar consideration
190 //
191 wxTopLevelWindow::DoSetClientSize( nWidth
192 ,nHeight
193 );
194 } // end of wxFrame::DoSetClientSize
195
196 // ----------------------------------------------------------------------------
197 // wxFrame: various geometry-related functions
198 // ----------------------------------------------------------------------------
199
200 void wxFrame::Raise()
201 {
202 wxFrameBase::Raise();
203 ::WinSetWindowPos( (HWND) GetParent()->GetHWND()
204 ,HWND_TOP
205 ,0
206 ,0
207 ,0
208 ,0
209 ,SWP_ZORDER
210 );
211 }
212
213 #if wxUSE_STATUSBAR
214 wxStatusBar* wxFrame::OnCreateStatusBar(
215 int nNumber
216 , long lulStyle
217 , wxWindowID vId
218 , const wxString& rName
219 )
220 {
221 wxStatusBar* pStatusBar = NULL;
222 SWP vSwp;
223 ERRORID vError;
224 wxString sError;
225
226 pStatusBar = wxFrameBase::OnCreateStatusBar( nNumber
227 ,lulStyle
228 ,vId
229 ,rName
230 );
231
232 if( !pStatusBar )
233 return NULL;
234
235 wxClientDC vDC(pStatusBar);
236 int nY;
237
238 //
239 // Set the height according to the font and the border size
240 //
241 vDC.SetFont(pStatusBar->GetFont()); // Screws up the menues for some reason
242 vDC.GetTextExtent( "X"
243 ,NULL
244 ,&nY
245 );
246
247 int nHeight = ((11 * nY) / 10 + 2 * pStatusBar->GetBorderY());
248
249 pStatusBar->SetSize( -1
250 ,-1
251 ,-1
252 ,nHeight
253 );
254
255 ::WinSetParent( pStatusBar->GetHWND()
256 ,m_hFrame
257 ,FALSE
258 );
259 ::WinSetOwner( pStatusBar->GetHWND()
260 ,m_hFrame
261 );
262 //
263 // to show statusbar
264 //
265 if(::WinIsWindowShowing(m_hFrame))
266 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
267
268 return pStatusBar;
269 } // end of wxFrame::OnCreateStatusBar
270
271 void wxFrame::PositionStatusBar()
272 {
273 SWP vSwp;
274 ERRORID vError;
275 wxString sError;
276
277 //
278 // Native status bar positions itself
279 //
280 if (m_frameStatusBar)
281 {
282 int nWidth;
283 int nY;
284 int nStatbarWidth;
285 int nStatbarHeight;
286 HWND hWndClient;
287 RECTL vRect;
288 RECTL vFRect;
289
290 ::WinQueryWindowRect(m_hFrame, &vRect);
291 nY = vRect.yTop;
292 ::WinMapWindowPoints(m_hFrame, HWND_DESKTOP, (PPOINTL)&vRect, 2);
293 vFRect = vRect;
294 ::WinCalcFrameRect(m_hFrame, &vRect, TRUE);
295 nWidth = vRect.xRight - vRect.xLeft;
296 nY = nY - (vRect.yBottom - vFRect.yBottom);
297
298 m_frameStatusBar->GetSize( &nStatbarWidth
299 ,&nStatbarHeight
300 );
301
302 nY= nY - nStatbarHeight;
303 //
304 // Since we wish the status bar to be directly under the client area,
305 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
306 //
307 m_frameStatusBar->SetSize( vRect.xLeft - vFRect.xLeft
308 ,nY
309 ,nWidth
310 ,nStatbarHeight
311 );
312 if (!::WinQueryWindowPos(m_frameStatusBar->GetHWND(), &vSwp))
313 {
314 vError = ::WinGetLastError(vHabmain);
315 sError = wxPMErrorToStr(vError);
316 wxLogError("Error setting parent for StautsBar. Error: %s\n", sError);
317 return;
318 }
319 }
320 } // end of wxFrame::PositionStatusBar
321 #endif // wxUSE_STATUSBAR
322
323 #if wxUSE_MENUS_NATIVE
324 void wxFrame::DetachMenuBar()
325 {
326 if (m_frameMenuBar)
327 {
328 m_frameMenuBar->Detach();
329 m_frameMenuBar = NULL;
330 }
331 } // end of wxFrame::DetachMenuBar
332
333 void wxFrame::SetMenuBar(
334 wxMenuBar* pMenuBar
335 )
336 {
337 ERRORID vError;
338 wxString sError;
339 HWND hTitlebar = NULLHANDLE;
340 HWND hHScroll = NULLHANDLE;
341 HWND hVScroll = NULLHANDLE;
342 HWND hMenuBar = NULLHANDLE;
343 SWP vSwp;
344 SWP vSwpTitlebar;
345 SWP vSwpVScroll;
346 SWP vSwpHScroll;
347 SWP vSwpMenu;
348
349 if (!pMenuBar)
350 {
351 DetachMenuBar();
352
353 //
354 // Actually remove the menu from the frame
355 //
356 m_hMenu = (WXHMENU)0;
357 InternalSetMenuBar();
358 }
359 else // set new non NULL menu bar
360 {
361 m_frameMenuBar = NULL;
362
363 //
364 // Can set a menubar several times.
365 // TODO: how to prevent a memory leak if you have a currently-unattached
366 // menubar? wxWindows assumes that the frame will delete the menu (otherwise
367 // there are problems for MDI).
368 //
369 if (pMenuBar->GetHMenu())
370 {
371 m_hMenu = pMenuBar->GetHMenu();
372 }
373 else
374 {
375 pMenuBar->Detach();
376 m_hMenu = pMenuBar->Create();
377 if (!m_hMenu)
378 return;
379 }
380 InternalSetMenuBar();
381 m_frameMenuBar = pMenuBar;
382 pMenuBar->Attach((wxFrame*)this);
383 }
384 } // end of wxFrame::SetMenuBar
385
386 void wxFrame::AttachMenuBar(
387 wxMenuBar* pMenubar
388 )
389 {
390 wxFrameBase::AttachMenuBar(pMenubar);
391
392 m_frameMenuBar = pMenubar;
393
394 if (!pMenubar)
395 {
396 //
397 // Actually remove the menu from the frame
398 //
399 m_hMenu = (WXHMENU)0;
400 InternalSetMenuBar();
401 }
402 else // Set new non NULL menu bar
403 {
404 //
405 // Can set a menubar several times.
406 //
407 if (pMenubar->GetHMenu())
408 {
409 m_hMenu = pMenubar->GetHMenu();
410 }
411 else
412 {
413 if (pMenubar->IsAttached())
414 pMenubar->Detach();
415
416 m_hMenu = pMenubar->Create();
417
418 if (!m_hMenu)
419 return;
420 }
421 InternalSetMenuBar();
422 }
423 } // end of wxFrame::AttachMenuBar
424
425 void wxFrame::InternalSetMenuBar()
426 {
427 ERRORID vError;
428 wxString sError;
429 //
430 // Set the parent and owner of the menubar to be the frame
431 //
432 if (!::WinSetParent(m_hMenu, m_hFrame, FALSE))
433 {
434 vError = ::WinGetLastError(vHabmain);
435 sError = wxPMErrorToStr(vError);
436 wxLogError("Error setting parent for submenu. Error: %s\n", sError);
437 }
438
439 if (!::WinSetOwner(m_hMenu, m_hFrame))
440 {
441 vError = ::WinGetLastError(vHabmain);
442 sError = wxPMErrorToStr(vError);
443 wxLogError("Error setting parent for submenu. Error: %s\n", sError);
444 }
445 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)FCF_MENU, (MPARAM)0);
446 } // end of wxFrame::InternalSetMenuBar
447 #endif // wxUSE_MENUS_NATIVE
448
449 //
450 // Responds to colour changes, and passes event on to children
451 //
452 void wxFrame::OnSysColourChanged(
453 wxSysColourChangedEvent& rEvent
454 )
455 {
456 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
457 Refresh();
458
459 #if wxUSE_STATUSBAR
460 if (m_frameStatusBar)
461 {
462 wxSysColourChangedEvent vEvent2;
463
464 vEvent2.SetEventObject(m_frameStatusBar);
465 m_frameStatusBar->GetEventHandler()->ProcessEvent(vEvent2);
466 }
467 #endif //wxUSE_STATUSBAR
468
469 //
470 // Propagate the event to the non-top-level children
471 //
472 wxWindow::OnSysColourChanged(rEvent);
473 } // end of wxFrame::OnSysColourChanged
474
475 // Pass TRUE to show full screen, FALSE to restore.
476 bool wxFrame::ShowFullScreen(
477 bool bShow
478 , long lStyle
479 )
480 {
481 if (bShow)
482 {
483 if (IsFullScreen())
484 return FALSE;
485
486 m_bFsIsShowing = TRUE;
487 m_lFsStyle = lStyle;
488
489 #if wxUSE_TOOLBAR
490 wxToolBar* pTheToolBar = GetToolBar();
491 #endif //wxUSE_TOOLBAR
492
493 #if wxUSE_STATUSBAR
494 wxStatusBar* pTheStatusBar = GetStatusBar();
495 #endif //wxUSE_STATUSBAR
496
497 int nDummyWidth;
498
499 #if wxUSE_TOOLBAR
500 if (pTheToolBar)
501 pTheToolBar->GetSize(&nDummyWidth, &m_nFsToolBarHeight);
502 #endif //wxUSE_TOOLBAR
503
504 #if wxUSE_STATUSBAR
505 if (pTheStatusBar)
506 pTheStatusBar->GetSize(&nDummyWidth, &m_nFsStatusBarHeight);
507 #endif //wxUSE_STATUSBAR
508
509 #if wxUSE_TOOLBAR
510 //
511 // Zap the toolbar, menubar, and statusbar
512 //
513 if ((lStyle & wxFULLSCREEN_NOTOOLBAR) && pTheToolBar)
514 {
515 pTheToolBar->SetSize(-1,0);
516 pTheToolBar->Show(FALSE);
517 }
518 #endif //wxUSE_TOOLBAR
519
520 if (lStyle & wxFULLSCREEN_NOMENUBAR)
521 {
522 ::WinSetParent(m_hMenu, m_hFrame, FALSE);
523 ::WinSetOwner(m_hMenu, m_hFrame);
524 ::WinSendMsg((HWND)m_hFrame, WM_UPDATEFRAME, (MPARAM)FCF_MENU, (MPARAM)0);
525 }
526
527 #if wxUSE_STATUSBAR
528 //
529 // Save the number of fields in the statusbar
530 //
531 if ((lStyle & wxFULLSCREEN_NOSTATUSBAR) && pTheStatusBar)
532 {
533 m_nFsStatusBarFields = pTheStatusBar->GetFieldsCount();
534 SetStatusBar((wxStatusBar*) NULL);
535 delete pTheStatusBar;
536 }
537 else
538 m_nFsStatusBarFields = 0;
539 #endif //wxUSE_STATUSBAR
540
541 //
542 // Zap the frame borders
543 //
544
545 //
546 // Save the 'normal' window style
547 //
548 m_lFsOldWindowStyle = ::WinQueryWindowULong(m_hFrame, QWL_STYLE);
549
550 //
551 // Save the old position, width & height, maximize state
552 //
553 m_vFsOldSize = GetRect();
554 m_bFsIsMaximized = IsMaximized();
555
556 //
557 // Decide which window style flags to turn off
558 //
559 LONG lNewStyle = m_lFsOldWindowStyle;
560 LONG lOffFlags = 0;
561
562 if (lStyle & wxFULLSCREEN_NOBORDER)
563 lOffFlags |= FCF_BORDER;
564 if (lStyle & wxFULLSCREEN_NOCAPTION)
565 lOffFlags |= (FCF_TASKLIST | FCF_SYSMENU);
566
567 lNewStyle &= (~lOffFlags);
568
569 //
570 // Change our window style to be compatible with full-screen mode
571 //
572 ::WinSetWindowULong((HWND)m_hFrame, QWL_STYLE, (ULONG)lNewStyle);
573
574 //
575 // Resize to the size of the desktop
576 int nWidth;
577 int nHeight;
578
579 RECTL vRect;
580
581 ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
582 nWidth = vRect.xRight - vRect.xLeft;
583 //
584 // Rmember OS/2 is backwards!
585 //
586 nHeight = vRect.yTop - vRect.yBottom;
587
588 SetSize( nWidth
589 ,nHeight
590 );
591
592 //
593 // Now flush the window style cache and actually go full-screen
594 //
595 ::WinSetWindowPos( (HWND) GetParent()->GetHWND()
596 ,HWND_TOP
597 ,0
598 ,0
599 ,nWidth
600 ,nHeight
601 ,SWP_SIZE | SWP_SHOW
602 );
603
604 wxSizeEvent vEvent( wxSize( nWidth
605 ,nHeight
606 )
607 ,GetId()
608 );
609
610 GetEventHandler()->ProcessEvent(vEvent);
611 return TRUE;
612 }
613 else
614 {
615 if (!IsFullScreen())
616 return FALSE;
617
618 m_bFsIsShowing = FALSE;
619
620 #if wxUSE_TOOLBAR
621 wxToolBar* pTheToolBar = GetToolBar();
622
623 //
624 // Restore the toolbar, menubar, and statusbar
625 //
626 if (pTheToolBar && (m_lFsStyle & wxFULLSCREEN_NOTOOLBAR))
627 {
628 pTheToolBar->SetSize(-1, m_nFsToolBarHeight);
629 pTheToolBar->Show(TRUE);
630 }
631 #endif //wxUSE_TOOLBAR
632
633 #if wxUSE_STATUSBAR
634 if ((m_lFsStyle & wxFULLSCREEN_NOSTATUSBAR) && (m_nFsStatusBarFields > 0))
635 {
636 CreateStatusBar(m_nFsStatusBarFields);
637 // PositionStatusBar();
638 }
639 #endif //wxUSE_STATUSBAR
640
641 if ((m_lFsStyle & wxFULLSCREEN_NOMENUBAR) && (m_hMenu != 0))
642 {
643 ::WinSetParent(m_hMenu, m_hFrame, FALSE);
644 ::WinSetOwner(m_hMenu, m_hFrame);
645 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)FCF_MENU, (MPARAM)0);
646 }
647 Maximize(m_bFsIsMaximized);
648
649 ::WinSetWindowULong( m_hFrame
650 ,QWL_STYLE
651 ,(ULONG)m_lFsOldWindowStyle
652 );
653 ::WinSetWindowPos( (HWND) GetParent()->GetHWND()
654 ,HWND_TOP
655 ,m_vFsOldSize.x
656 ,m_vFsOldSize.y
657 ,m_vFsOldSize.width
658 ,m_vFsOldSize.height
659 ,SWP_SIZE | SWP_SHOW
660 );
661 return TRUE;
662 }
663 } // end of wxFrame::ShowFullScreen
664
665 //
666 // Frame window
667 //
668 //
669 // Default activation behaviour - set the focus for the first child
670 // subwindow found.
671 //
672 void wxFrame::OnActivate(
673 wxActivateEvent& rEvent
674 )
675 {
676 if ( rEvent.GetActive() )
677 {
678 // restore focus to the child which was last focused
679 wxLogTrace(_T("focus"), _T("wxFrame %08x activated."), m_hWnd);
680
681 wxWindow* pParent = m_pWinLastFocused ? m_pWinLastFocused->GetParent()
682 : NULL;
683 if (!pParent)
684 {
685 pParent = this;
686 }
687
688 wxSetFocusToChild( pParent
689 ,&m_pWinLastFocused
690 );
691 }
692 else // deactivating
693 {
694 //
695 // Remember the last focused child if it is our child
696 //
697 m_pWinLastFocused = FindFocus();
698
699 for (wxWindowList::Node* pNode = GetChildren().GetFirst();
700 pNode;
701 pNode = pNode->GetNext())
702 {
703 // FIXME all this is totally bogus - we need to do the same as wxPanel,
704 // but how to do it without duplicating the code?
705
706 // restore focus
707 wxWindow* pChild = pNode->GetData();
708
709 if (!pChild->IsTopLevel()
710 #if wxUSE_TOOLBAR
711 && !wxDynamicCast(pChild, wxToolBar)
712 #endif // wxUSE_TOOLBAR
713 #if wxUSE_STATUSBAR
714 && !wxDynamicCast(pChild, wxStatusBar)
715 #endif // wxUSE_STATUSBAR
716 )
717 {
718 pChild->SetFocus();
719 return;
720 }
721 }
722 }
723 } // end of wxFrame::OnActivate
724
725 // ----------------------------------------------------------------------------
726 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
727 // from the client area, so the client area is what's really available for the
728 // frame contents
729 // ----------------------------------------------------------------------------
730
731 // Checks if there is a toolbar, and returns the first free client position
732 wxPoint wxFrame::GetClientAreaOrigin() const
733 {
734 wxPoint vPoint(0, 0);
735
736 #if wxUSE_TOOLBAR
737 if (GetToolBar())
738 {
739 int nWidth;
740 int nHeight;
741
742 GetToolBar()->GetSize( &nWidth
743 ,&nHeight
744 );
745
746 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
747 {
748 vPoint.x += nWidth;
749 }
750 else
751 {
752 // PM is backwards from windows
753 vPoint.y += nHeight;
754 }
755 }
756 #endif //wxUSE_TOOLBAR
757 return vPoint;
758 } // end of wxFrame::GetClientAreaOrigin
759
760 // ----------------------------------------------------------------------------
761 // tool/status bar stuff
762 // ----------------------------------------------------------------------------
763
764 #if wxUSE_TOOLBAR
765
766 wxToolBar* wxFrame::CreateToolBar(
767 long lStyle
768 , wxWindowID vId
769 , const wxString& rName
770 )
771 {
772 if (wxFrameBase::CreateToolBar( lStyle
773 ,vId
774 ,rName
775 ))
776 {
777 PositionToolBar();
778 }
779 return m_frameToolBar;
780 } // end of wxFrame::CreateToolBar
781
782 void wxFrame::PositionToolBar()
783 {
784 HWND hWndClient;
785 RECTL vRect;
786
787 ::WinQueryWindowRect(GetHwnd(), &vRect);
788
789 #if wxUSE_STATUSBAR
790 if (GetStatusBar())
791 {
792 int nStatusX;
793 int nStatusY;
794
795 GetStatusBar()->GetClientSize( &nStatusX
796 ,&nStatusY
797 );
798 // PM is backwards from windows
799 vRect.yBottom += nStatusY;
800 }
801 #endif // wxUSE_STATUSBAR
802
803 if ( m_frameToolBar )
804 {
805 int nToolbarWidth;
806 int nToolbarHeight;
807
808 m_frameToolBar->GetSize( &nToolbarWidth
809 ,&nToolbarHeight
810 );
811
812 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
813 {
814 nToolbarHeight = vRect.yBottom;
815 }
816 else
817 {
818 nToolbarWidth = vRect.xRight;
819 }
820
821 //
822 // Use the 'real' PM position here
823 //
824 GetToolBar()->SetSize( 0
825 ,0
826 ,nToolbarWidth
827 ,nToolbarHeight
828 ,wxSIZE_NO_ADJUSTMENTS
829 );
830 }
831 } // end of wxFrame::PositionToolBar
832 #endif // wxUSE_TOOLBAR
833
834 // ----------------------------------------------------------------------------
835 // frame state (iconized/maximized/...)
836 // ----------------------------------------------------------------------------
837
838 //
839 // propagate our state change to all child frames: this allows us to emulate X
840 // Windows behaviour where child frames float independently of the parent one
841 // on the desktop, but are iconized/restored with it
842 //
843 void wxFrame::IconizeChildFrames(
844 bool bIconize
845 )
846 {
847 for (wxWindowList::Node* pNode = GetChildren().GetFirst();
848 pNode;
849 pNode = pNode->GetNext() )
850 {
851 wxWindow* pWin = pNode->GetData();
852 wxFrame* pFrame = wxDynamicCast(pWin, wxFrame);
853
854 if ( pFrame
855 #if wxUSE_MDI_ARCHITECTURE
856 && !wxDynamicCast(pFrame, wxMDIChildFrame)
857 #endif // wxUSE_MDI_ARCHITECTURE
858 )
859 {
860 //
861 // We don't want to restore the child frames which had been
862 // iconized even before we were iconized, so save the child frame
863 // status when iconizing the parent frame and check it when
864 // restoring it.
865 //
866 if (bIconize)
867 {
868 pFrame->m_bWasMinimized = pFrame->IsIconized();
869 }
870
871 //
872 // This test works for both iconizing and restoring
873 //
874 if (!pFrame->m_bWasMinimized)
875 pFrame->Iconize(bIconize);
876 }
877 }
878 } // end of wxFrame::IconizeChildFrames
879
880 WXHICON wxFrame::GetDefaultIcon() const
881 {
882 return (WXHICON)(wxSTD_FRAME_ICON ? wxSTD_FRAME_ICON
883 : wxDEFAULT_FRAME_ICON);
884 }
885 // ===========================================================================
886 // message processing
887 // ===========================================================================
888
889 // ---------------------------------------------------------------------------
890 // preprocessing
891 // ---------------------------------------------------------------------------
892 bool wxFrame::OS2TranslateMessage(
893 WXMSG* pMsg
894 )
895 {
896 //
897 // try the menu bar accels
898 //
899 wxMenuBar* pMenuBar = GetMenuBar();
900
901 if (!pMenuBar)
902 return FALSE;
903
904 #if wxUSE_ACCEL && wxUSE_MENUS_NATIVE
905 const wxAcceleratorTable& rAcceleratorTable = pMenuBar->GetAccelTable();
906 return rAcceleratorTable.Translate(GetHWND(), pMsg);
907 #else
908 return FALSE;
909 #endif //wxUSE_ACCEL
910 } // end of wxFrame::OS2TranslateMessage
911
912 // ---------------------------------------------------------------------------
913 // our private (non virtual) message handlers
914 // ---------------------------------------------------------------------------
915 bool wxFrame::HandlePaint()
916 {
917 RECTL vRect;
918
919 if (::WinQueryUpdateRect(GetHWND(), &vRect))
920 {
921 if (m_bIconized)
922 {
923 //
924 // Icons in PM are the same as "pointers"
925 //
926 const wxIcon& vIcon = GetIcon();
927 HPOINTER hIcon;
928
929 if (vIcon.Ok())
930 hIcon = (HPOINTER)::WinSendMsg(m_hFrame, WM_QUERYICON, 0L, 0L);
931 else
932 hIcon = (HPOINTER)m_hDefaultIcon;
933
934 //
935 // Hold a pointer to the dc so long as the OnPaint() message
936 // is being processed
937 //
938 RECTL vRect2;
939 HPS hPs = ::WinBeginPaint(GetHwnd(), NULLHANDLE, &vRect2);
940
941 //
942 // Erase background before painting or we get white background
943 //
944 OS2DefWindowProc(WM_ERASEBACKGROUND, (MPARAM)hPs, (MPARAM)&vRect2);
945
946 if (hIcon)
947 {
948 HWND hWndClient;
949 RECTL vRect3;
950
951 ::WinQueryWindowRect(GetHwnd(), &vRect3);
952
953 static const int nIconWidth = 32;
954 static const int nIconHeight = 32;
955 int nIconX = (int)((vRect3.xRight - nIconWidth)/2);
956 int nIconY = (int)((vRect3.yBottom + nIconHeight)/2);
957
958 ::WinDrawPointer(hPs, nIconX, nIconY, hIcon, DP_NORMAL);
959 }
960 ::WinEndPaint(hPs);
961 return TRUE;
962 }
963 else
964 {
965 if (!wxWindow::HandlePaint())
966 {
967 HPS hPS;
968 RECTL vRect;
969
970 hPS = ::WinBeginPaint( GetHwnd()
971 ,NULLHANDLE
972 ,&vRect
973 );
974 if(hPS)
975 {
976 ::GpiCreateLogColorTable( hPS
977 ,0L
978 ,LCOLF_CONSECRGB
979 ,0L
980 ,(LONG)wxTheColourDatabase->m_nSize
981 ,(PLONG)wxTheColourDatabase->m_palTable
982 );
983 ::GpiCreateLogColorTable( hPS
984 ,0L
985 ,LCOLF_RGB
986 ,0L
987 ,0L
988 ,NULL
989 );
990
991 ::WinFillRect( hPS
992 ,&vRect
993 ,GetBackgroundColour().GetPixel()
994 );
995 ::WinEndPaint(hPS);
996 }
997 }
998 return TRUE;
999 }
1000 }
1001 else
1002 {
1003 // nothing to paint - processed
1004 return TRUE;
1005 }
1006 return FALSE;
1007 } // end of wxFrame::HandlePaint
1008
1009 bool wxFrame::HandleSize(
1010 int nX
1011 , int nY
1012 , WXUINT nId
1013 )
1014 {
1015 bool bProcessed = FALSE;
1016
1017 switch (nId)
1018 {
1019 case kSizeNormal:
1020 //
1021 // Only do it it if we were iconized before, otherwise resizing the
1022 // parent frame has a curious side effect of bringing it under it's
1023 // children
1024 if (!m_bIconized )
1025 break;
1026
1027 //
1028 // restore all child frames too
1029 //
1030 IconizeChildFrames(FALSE);
1031 (void)SendIconizeEvent(FALSE);
1032
1033 //
1034 // fall through
1035 //
1036
1037 case kSizeMax:
1038 m_bIconized = FALSE;
1039 break;
1040
1041 case kSizeMin:
1042 //
1043 // Iconize all child frames too
1044 //
1045 IconizeChildFrames(TRUE);
1046 (void)SendIconizeEvent();
1047 m_bIconized = TRUE;
1048 break;
1049 }
1050
1051 if (!m_bIconized)
1052 {
1053 //
1054 // forward WM_SIZE to status bar control
1055 //
1056 #if wxUSE_NATIVE_STATUSBAR
1057 if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
1058 {
1059 wxSizeEvent vEvent( wxSize( nX
1060 ,nY
1061 )
1062 ,m_frameStatusBar->GetId()
1063 );
1064
1065 vEvent.SetEventObject(m_frameStatusBar);
1066 m_frameStatusBar->OnSize(vEvent);
1067 }
1068 #endif // wxUSE_NATIVE_STATUSBAR
1069
1070 PositionStatusBar();
1071 #if wxUSE_TOOLBAR
1072 PositionToolBar();
1073 #endif // wxUSE_TOOLBAR
1074
1075 bProcessed = wxWindow::HandleSize( nX
1076 ,nY
1077 ,nId
1078 );
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 const wxIcon& vIcon = GetIcon();
1380 HPOINTER hIcon;
1381
1382 if (vIcon.Ok())
1383 hIcon = (HPOINTER)::WinSendMsg(GetHWND(), WM_QUERYICON, 0L, 0L);
1384 else
1385 hIcon = (HPOINTER)m_hDefaultIcon;
1386 mRc = (MRESULT)hIcon;
1387 bProcessed = mRc != 0;
1388 }
1389 break;
1390 }
1391
1392 if (!bProcessed )
1393 mRc = wxWindow::OS2WindowProc( uMessage
1394 ,wParam
1395 ,lParam
1396 );
1397 return (MRESULT)mRc;
1398 } // wxFrame::OS2WindowProc
1399
1400 void wxFrame::SetClient(WXHWND c_Hwnd)
1401 {
1402 // Duh...nothing to do under OS/2
1403 }
1404
1405 void wxFrame::SetClient(
1406 wxWindow* pWindow
1407 )
1408 {
1409 wxWindow* pOldClient = this->GetClient();
1410 bool bClientHasFocus = pOldClient && (pOldClient == wxWindow::FindFocus());
1411
1412 if(pOldClient == pWindow) // nothing to do
1413 return;
1414 if(pWindow == NULL) // just need to remove old client
1415 {
1416 if(pOldClient == NULL) // nothing to do
1417 return;
1418
1419 if(bClientHasFocus )
1420 this->SetFocus();
1421
1422 pOldClient->Enable( FALSE );
1423 pOldClient->Show( FALSE );
1424 ::WinSetWindowUShort(pOldClient->GetHWND(), QWS_ID, (USHORT)pOldClient->GetId());
1425 // to avoid OS/2 bug need to update frame
1426 ::WinSendMsg((HWND)this->GetFrame(), WM_UPDATEFRAME, (MPARAM)~0, 0);
1427 return;
1428 }
1429
1430 //
1431 // Else need to change client
1432 //
1433 if(bClientHasFocus)
1434 this->SetFocus();
1435
1436 ::WinEnableWindowUpdate((HWND)GetHWND(), FALSE);
1437 if(pOldClient)
1438 {
1439 pOldClient->Enable(FALSE);
1440 pOldClient->Show(FALSE);
1441 ::WinSetWindowUShort(pOldClient->GetHWND(), QWS_ID, (USHORT)pOldClient->GetId());
1442 }
1443 pWindow->Reparent(this);
1444 ::WinSetWindowUShort(pWindow->GetHWND(), QWS_ID, FID_CLIENT);
1445 ::WinEnableWindowUpdate((HWND)GetHWND(), TRUE);
1446 pWindow->Enable();
1447 pWindow->Show(); // ensure client is showing
1448 if( this->IsShown() )
1449 {
1450 this->Show();
1451 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
1452 }
1453 }
1454
1455 wxWindow* wxFrame::GetClient()
1456 {
1457 return wxFindWinFromHandle((WXHWND)::WinWindowFromID(m_hFrame, FID_CLIENT));
1458 }