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