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