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