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