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