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