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