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