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