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