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