OS/2 scrolling support
[wxWidgets.git] / src / os2 / toplevel.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/toplevel.cpp
3 // Purpose: implements wxTopLevelWindow for MSW
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 30.12.01
7 // RCS-ID: $Id$
8 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
9 // License: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "toplevel.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/app.h"
33 #include "wx/toplevel.h"
34 #include "wx/string.h"
35 #include "wx/log.h"
36 #include "wx/intl.h"
37 #include "wx/frame.h"
38 #include "wx/control.h"
39 #endif //WX_PRECOMP
40
41 #include "wx/os2/private.h"
42
43 // ----------------------------------------------------------------------------
44 // stubs for missing functions under MicroWindows
45 // ----------------------------------------------------------------------------
46
47
48 // ----------------------------------------------------------------------------
49 // globals
50 // ----------------------------------------------------------------------------
51
52 // list of all frames and modeless dialogs
53 wxWindowList wxModelessWindows;
54
55 // the name of the default wxWindows class
56 extern void wxAssociateWinWithHandle( HWND hWnd
57 ,wxWindowOS2* pWin
58 );
59 bool wxTopLevelWindowOS2::m_sbInitialized = FALSE;
60
61 // ============================================================================
62 // wxTopLevelWindowMSW implementation
63 // ============================================================================
64
65 // Dialog window proc
66 MRESULT EXPENTRY wxDlgProc( HWND WXUNUSED(hWnd)
67 ,UINT uMessage
68 ,MPARAM WXUNUSED(wParam)
69 ,MPARAM WXUNUSED(lParam)
70 )
71 {
72 if (uMessage == WM_INITDLG)
73 {
74 //
75 // For this message, returning TRUE tells system to set focus to the
76 // first control in the dialog box.
77 //
78 return (MRESULT)TRUE;
79 }
80 else
81 {
82 //
83 // For all the other ones, FALSE means that we didn't process the
84 // message
85 //
86 return (MRESULT)FALSE;
87 }
88 } // end of wxDlgProc
89
90 // ----------------------------------------------------------------------------
91 // wxTopLevelWindowOS2 creation
92 // ----------------------------------------------------------------------------
93
94 void wxTopLevelWindowOS2::Init()
95 {
96 m_bIconized = m_bMaximizeOnShow = FALSE;
97
98 //
99 // Unlike (almost?) all other windows, frames are created hidden
100 //
101 m_isShown = FALSE;
102
103 //
104 // Data to save/restore when calling ShowFullScreen
105 m_lFsStyle = 0;
106 m_lFsOldWindowStyle = 0;
107 m_bFsIsMaximized = FALSE;
108 m_bFsIsShowing = FALSE;
109
110 m_hFrame = NULLHANDLE;
111 memset(&m_vSwp, 0, sizeof(SWP));
112 memset(&m_vSwpClient, 0, sizeof(SWP));
113 } // end of wxTopLevelWindowIOS2::Init
114
115 long wxTopLevelWindowOS2::OS2GetCreateWindowFlags(
116 long* plExflags
117 ) const
118 {
119 long lStyle = GetWindowStyle();
120 long lMsflags = 0;
121
122 if (lStyle == wxDEFAULT_FRAME_STYLE)
123 lMsflags = FCF_SIZEBORDER | FCF_TITLEBAR | FCF_SYSMENU |
124 FCF_MINMAX | FCF_TASKLIST;
125 else
126 {
127 if ((lStyle & wxCAPTION) == wxCAPTION)
128 lMsflags = FCF_TASKLIST;
129 else
130 lMsflags = FCF_NOMOVEWITHOWNER;
131
132 if ((lStyle & wxVSCROLL) == wxVSCROLL)
133 lMsflags |= FCF_VERTSCROLL;
134 if ((lStyle & wxHSCROLL) == wxHSCROLL)
135 lMsflags |= FCF_HORZSCROLL;
136 if (lStyle & wxMINIMIZE_BOX)
137 lMsflags |= FCF_MINBUTTON;
138 if (lStyle & wxMAXIMIZE_BOX)
139 lMsflags |= FCF_MAXBUTTON;
140 if (lStyle & wxTHICK_FRAME)
141 lMsflags |= FCF_DLGBORDER;
142 if (lStyle & wxSYSTEM_MENU)
143 lMsflags |= FCF_SYSMENU;
144 if (lStyle & wxCAPTION)
145 lMsflags |= FCF_TASKLIST;
146 if (lStyle & wxCLIP_CHILDREN)
147 {
148 // Invalid for frame windows under PM
149 }
150
151 if (lStyle & wxTINY_CAPTION_VERT)
152 lMsflags |= FCF_TASKLIST;
153 if (lStyle & wxTINY_CAPTION_HORIZ)
154 lMsflags |= FCF_TASKLIST;
155
156 if ((lStyle & wxTHICK_FRAME) == 0)
157 lMsflags |= FCF_BORDER;
158 if (lStyle & wxFRAME_TOOL_WINDOW)
159 *plExflags = kFrameToolWindow;
160
161 if (lStyle & wxSTAY_ON_TOP)
162 lMsflags |= FCF_SYSMODAL;
163 }
164 return lMsflags;
165 } // end of wxTopLevelWindowOS2::OS2GetCreateWindowFlags
166
167 bool wxTopLevelWindowOS2::CreateDialog(
168 ULONG ulDlgTemplate
169 , const wxString& rsTitle
170 , const wxPoint& rPos
171 , const wxSize& rSize
172 )
173 {
174 wxWindow* pParent = GetParent();
175
176 //
177 // For the dialogs without wxDIALOG_NO_PARENT style, use the top level
178 // app window as parent - this avoids creating modal dialogs without
179 // parent
180 //
181 if (!pParent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT))
182 {
183 pParent = wxTheApp->GetTopWindow();
184
185 if (pParent)
186 {
187 //
188 // Don't use transient windows as parents, this is dangerous as it
189 // can lead to a crash if the parent is destroyed before the child
190 //
191 // also don't use the window which is currently hidden as then the
192 // dialog would be hidden as well
193 if ((pParent->GetExtraStyle() & wxWS_EX_TRANSIENT) ||
194 !pParent->IsShown())
195 {
196 pParent = NULL;
197 }
198 }
199 }
200
201 HWND hWndDlg;
202 HWND hWndOwner;
203
204 if (pParent)
205 hWndOwner = GetHwndOf(pParent);
206 else
207 hWndOwner = HWND_DESKTOP;
208
209 hWndDlg = ::WinLoadDlg( HWND_DESKTOP
210 ,hWndOwner
211 ,(PFNWP)wxDlgProc
212 ,NULL
213 ,(ULONG)ulDlgTemplate
214 ,(PVOID)this
215 );
216
217 m_hWnd = (WXHWND) hWndDlg;
218
219 if ( !m_hWnd )
220 {
221 wxFAIL_MSG(_("Did you forget to include wx/os2/wx.rc in your resources?"));
222
223 wxLogSysError(_("Can't create dialog using template '%ul'"), ulDlgTemplate);
224
225 return FALSE;
226 }
227
228 //
229 // Move the dialog to its initial position without forcing repainting
230 //
231 int nX;
232 int nY;
233 int nWidth;
234 int nHeight;
235
236 if (!OS2GetCreateWindowCoords( rPos
237 ,rSize
238 ,nX
239 ,nY
240 ,nWidth
241 ,nHeight
242 ))
243 {
244 nX = nWidth = (int)CW_USEDEFAULT;
245 }
246
247 //
248 // We can't use CW_USEDEFAULT here as we're not calling CreateWindow()
249 // and passing CW_USEDEFAULT to MoveWindow() results in resizing the
250 // window to (0, 0) size which breaks quite a lot of things, e.g. the
251 // sizer calculation in wxSizer::Fit()
252 //
253 if (nWidth == (int)CW_USEDEFAULT)
254 {
255 //
256 // The exact number doesn't matter, the dialog will be resized
257 // again soon anyhow but it should be big enough to allow
258 // calculation relying on "totalSize - clientSize > 0" work, i.e.
259 // at least greater than the title bar height
260 //
261 nWidth = nHeight = 100;
262 }
263 if (nX == (int)CW_USEDEFAULT)
264 {
265 //
266 // Centre it on the screen - what else can we do?
267 //
268 wxSize vSizeDpy = wxGetDisplaySize();
269
270 nX = (vSizeDpy.x - nWidth) / 2;
271 nY = (vSizeDpy.y - nHeight) / 2;
272 }
273 m_backgroundColour.Set(wxString("LIGHT GREY"));
274
275 LONG lColor = (LONG)m_backgroundColour.GetPixel();
276
277 if (!::WinSetPresParam( m_hWnd
278 ,PP_BACKGROUNDCOLOR
279 ,sizeof(LONG)
280 ,(PVOID)&lColor
281 ))
282 {
283 return FALSE;
284 }
285
286 ::WinSetWindowPos( GetHwnd()
287 ,HWND_TOP
288 ,nX
289 ,nY
290 ,nWidth
291 ,nHeight
292 ,SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW
293 );
294 m_hFrame = m_hWnd;
295 SubclassWin(m_hWnd);
296 return TRUE;
297 } // end of wxTopLevelWindowOS2::CreateDialog
298
299 bool wxTopLevelWindowOS2::CreateFrame(
300 const wxString& rsTitle
301 , const wxPoint& rPos
302 , const wxSize& rSize
303 )
304 {
305 long lExflags;
306 long lFlags = OS2GetCreateWindowFlags(&lExflags);
307 long lStyle = GetWindowStyleFlag();
308 int nX = rPos.x;
309 int nY = rPos.y;
310 int nWidth = rSize.x;
311 int nHeight = rSize.y;
312 ULONG ulStyleFlags = 0L;
313 ERRORID vError;
314 wxString sError;
315 wxWindow* pParent = GetParent();
316 HWND hParent;
317 HWND hFrame;
318 HWND hClient;
319
320 if (pParent)
321 hParent = GetHwndOf(pParent);
322 else
323 hParent = HWND_DESKTOP;
324
325 if ((lStyle & wxMINIMIZE) || (lStyle & wxICONIZE))
326 ulStyleFlags |= WS_MINIMIZED;
327 if (lStyle & wxMAXIMIZE)
328 ulStyleFlags |= WS_MAXIMIZED;
329
330 //
331 // Clear the visible flag, we always call show
332 //
333 ulStyleFlags &= (unsigned long)~WS_VISIBLE;
334 m_bIconized = FALSE;
335
336 //
337 // Create the frame window: We break ranks with other ports now
338 // and instead of calling down into the base wxWindow class' OS2Create
339 // we do all our own stuff here. We will set the needed pieces
340 // of wxWindow manually, here.
341 //
342
343 hFrame = ::WinCreateStdWindow( hParent
344 ,ulStyleFlags // frame-window style
345 ,(PULONG)&lFlags // window style
346 ,(PSZ)wxFrameClassName // class name
347 ,(PSZ)rsTitle.c_str() // window title
348 ,0L // default client style
349 ,NULLHANDLE // resource in executable file
350 ,0 // resource id
351 ,&hClient // receives client window handle
352 );
353 if (!hFrame)
354 {
355 vError = ::WinGetLastError(vHabmain);
356 sError = wxPMErrorToStr(vError);
357 wxLogError("Error creating frame. Error: %s\n", sError);
358 return FALSE;
359 }
360
361 //
362 // wxWindow class' m_hWnd set here and needed associations
363 //
364 m_hFrame = hFrame;
365 m_hWnd = hClient;
366 wxAssociateWinWithHandle(m_hWnd, this);
367 wxAssociateWinWithHandle(m_hFrame, this);
368
369 m_backgroundColour.Set(wxString("MEDIUM GREY"));
370
371 LONG lColor = (LONG)m_backgroundColour.GetPixel();
372
373 if (!::WinSetPresParam( m_hWnd
374 ,PP_BACKGROUNDCOLOR
375 ,sizeof(LONG)
376 ,(PVOID)&lColor
377 ))
378 {
379 vError = ::WinGetLastError(vHabmain);
380 sError = wxPMErrorToStr(vError);
381 wxLogError("Error creating frame. Error: %s\n", sError);
382 return FALSE;
383 }
384
385 //
386 // Now need to subclass window. Instead of calling the SubClassWin in wxWindow
387 // we manually subclass here because we don't want to use the main wxWndProc
388 // by default
389 //
390 m_fnOldWndProc = (WXFARPROC) ::WinSubclassWindow(m_hFrame, (PFNWP)wxFrameMainWndProc);
391
392 //
393 // Now size everything. If adding a menu the client will need to be resized.
394 //
395
396 if (pParent)
397 {
398 nY = pParent->GetSize().y - (nY + nHeight);
399 }
400 else
401 {
402 RECTL vRect;
403
404 ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
405 nY = vRect.yTop - (nY + nHeight);
406 }
407 if (!::WinSetWindowPos( m_hFrame
408 ,HWND_TOP
409 ,nX
410 ,nY
411 ,nWidth
412 ,nHeight
413 ,SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_ZORDER
414 ))
415 {
416 vError = ::WinGetLastError(vHabmain);
417 sError = wxPMErrorToStr(vError);
418 wxLogError("Error sizing frame. Error: %s\n", sError);
419 return FALSE;
420 }
421 lStyle = ::WinQueryWindowULong( m_hWnd
422 ,QWL_STYLE
423 );
424 lStyle |= WS_CLIPCHILDREN;
425 ::WinSetWindowULong( m_hWnd
426 ,QWL_STYLE
427 ,lStyle
428 );
429 return TRUE;
430 } // end of wxTopLevelWindowOS2::CreateFrame
431
432 bool wxTopLevelWindowOS2::Create(
433 wxWindow* pParent
434 , wxWindowID vId
435 , const wxString& rsTitle
436 , const wxPoint& rPos
437 , const wxSize& rSize
438 , long lStyle
439 , const wxString& rsName
440 )
441 {
442 //
443 // Init our fields
444 //
445 Init();
446 m_windowStyle = lStyle;
447 SetName(rsName);
448 m_windowId = vId == -1 ? NewControlId() : vId;
449 wxTopLevelWindows.Append(this);
450 if (pParent)
451 pParent->AddChild(this);
452
453 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
454 {
455 //
456 // We have different dialog templates to allows creation of dialogs
457 // with & without captions under OS2indows, resizeable or not (but a
458 // resizeable dialog always has caption - otherwise it would look too
459 // strange)
460 //
461 ULONG ulDlgTemplate;
462
463 if (lStyle & wxRESIZE_BORDER)
464 ulDlgTemplate = (ULONG)kResizeableDialog;
465 else if (lStyle & wxCAPTION)
466 ulDlgTemplate = (ULONG)kCaptionDialog;
467 else
468 ulDlgTemplate = (ULONG)kNoCaptionDialog;
469 return CreateDialog( ulDlgTemplate
470 ,rsTitle
471 ,rPos
472 ,rSize
473 );
474 }
475 else // !dialog
476 {
477 return CreateFrame( rsTitle
478 ,rPos
479 ,rSize
480 );
481 }
482 } // end of wxTopLevelWindowOS2::Create
483
484 wxTopLevelWindowOS2::~wxTopLevelWindowOS2()
485 {
486 wxTopLevelWindows.DeleteObject(this);
487
488 if (wxModelessWindows.Find(this))
489 wxModelessWindows.DeleteObject(this);
490
491 //
492 // If this is the last top-level window, exit.
493 //
494 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
495 {
496 wxTheApp->SetTopWindow(NULL);
497 if ( wxTheApp->GetExitOnFrameDelete() )
498 {
499 ::WinPostMsg(NULL, WM_QUIT, 0, 0);
500 }
501 }
502 } // end of wxTopLevelWindowOS2::~wxTopLevelWindowOS2
503
504 //
505 // IF we have child controls in the Frame's client we need to alter
506 // the y position, because, OS/2 controls are positioned relative to
507 // wxWindows orgin (top left) not the OS/2 origin (bottom left)
508 //
509 void wxTopLevelWindowOS2::AlterChildPos()
510 {
511 //
512 // OS/2 is the only OS concerned about this
513 //
514 wxWindow* pChild = NULL;
515 wxControl* pCtrl = NULL;
516 RECTL vRect;
517 SWP vSwp;
518
519 if (GetAutoLayout)
520 //
521 // Auto layouts taken care of elsewhere
522 //
523 return;
524
525 ::WinQueryWindowRect(GetHwnd(), &vRect);
526 for (wxWindowList::Node* pNode = GetChildren().GetFirst();
527 pNode;
528 pNode = pNode->GetNext())
529 {
530 wxWindow* pChild = pNode->GetData();
531
532 ::WinQueryWindowPos(pChild->GetHWND(), &vSwp);
533 vSwp.y += (vRect.yTop - m_vSwpClient.cy);
534 if (pChild->IsKindOf(CLASSINFO(wxControl)))
535 {
536 pCtrl = wxDynamicCast(pChild, wxControl);
537 //
538 // Must deal with controls that have margins like ENTRYFIELD. The SWP
539 // struct of such a control will have and origin offset from its intended
540 // position by the width of the margins.
541 //
542 vSwp.y -= pCtrl->GetYComp();
543 vSwp.x -= pCtrl->GetXComp();
544 }
545 ::WinSetWindowPos( pChild->GetHWND()
546 ,HWND_TOP
547 ,vSwp.x
548 ,vSwp.y
549 ,vSwp.cx
550 ,vSwp.cy
551 ,SWP_MOVE
552 );
553 ::WinQueryWindowPos(pChild->GetHWND(), &vSwp);
554 pChild = NULL;
555 }
556 ::WinQueryWindowPos(GetHwnd(), &m_vSwpClient);
557 } // end of wxTopLevelWindowOS2::AlterChildPos
558
559 void wxTopLevelWindowOS2::UpdateInternalSize(
560 wxWindow* pChild
561 , int nChildWidth
562 , int nChildHeight
563 )
564 {
565 int nWidthAdjust = 0;
566 int nHeightAdjust = 0;
567 int nPosX;
568 int nPosY;
569 bool bNewYSize = FALSE;
570 bool bNewXSize = FALSE;
571
572 //
573 // Under OS/2, if we have a srolled window as the child, the
574 // scrollbars will be SIBLINGS of the scrolled window. So, in
575 // order to be able to display the scrollbars properly we have to
576 // resize the scrolled window. Of course, that means dealing with
577 // child windows of that window as well, because OS/2 does not
578 // tend to put them in the right place.
579 //
580 if (nChildHeight != m_vSwpClient.cy)
581 bNewYSize = TRUE;
582 if (nChildWidth != m_vSwpClient.cx)
583 bNewXSize = TRUE;
584 if (bNewXSize || bNewYSize)
585 pChild->SetSize( 0
586 ,0
587 ,nChildWidth
588 ,nChildHeight
589 );
590 if(bNewYSize)
591 {
592 //
593 // This is needed SetSize will mess up the OS/2 child window
594 // positioning because we position in wxWindows coordinates,
595 // not OS/2 coordinates.
596 //
597 pChild->MoveChildren(m_vSwpClient.cy - nChildHeight);
598 pChild->Refresh();
599 }
600
601 if (pChild->GetScrollBarHorz() != NULLHANDLE ||
602 pChild->GetScrollBarVert() != NULLHANDLE)
603 {
604 if (bNewXSize || bNewYSize)
605 {
606 pChild->GetSize( &nChildWidth
607 ,&nChildHeight
608 );
609 if (pChild->GetScrollBarHorz() != NULLHANDLE)
610 nHeightAdjust = 20;
611 if (pChild->GetScrollBarVert() != NULLHANDLE)
612 nWidthAdjust = 20;
613 pChild->GetPosition( &nPosX
614 ,&nPosY
615 );
616 ::WinSetWindowPos( pChild->GetHWND()
617 ,HWND_TOP
618 ,nPosX
619 ,nPosY + nHeightAdjust
620 ,nChildWidth - nWidthAdjust
621 ,nChildHeight - nHeightAdjust
622 ,SWP_MOVE | SWP_SIZE
623 );
624 }
625 if (bNewYSize && !m_sbInitialized)
626 {
627 //
628 // Only need to readjust child control positions of
629 // scrolled windows once on initialization. After that
630 // the sizing takes care of things itself.
631 //
632 pChild->MoveChildren(nHeightAdjust);
633 m_sbInitialized = TRUE;
634 }
635 if (bNewXSize || bNewYSize)
636 {
637 //
638 // Always refresh to keep scollbars visible. They are
639 // children of the Toplevel window, not the child panel.
640 //
641 pChild->Refresh();
642 }
643 }
644 //
645 // This brings the internal "last size" up to date.
646 //
647 ::WinQueryWindowPos(GetHwnd(), &m_vSwpClient);
648 } // end of wxTopLevelWindowOS2::UpdateInternalSize
649
650 // ----------------------------------------------------------------------------
651 // wxTopLevelWindowOS2 client size
652 // ----------------------------------------------------------------------------
653
654 void wxTopLevelWindowOS2::DoSetClientSize(
655 int nWidth
656 , int nHeight
657 )
658 {
659 //
660 // Call GetClientAreaOrigin() to take the toolbar into account
661 //
662 wxPoint vPt = GetClientAreaOrigin();
663
664 nWidth += vPt.x;
665 nHeight += vPt.y;
666
667 wxWindow::DoSetClientSize( nWidth
668 ,nHeight
669 );
670 } // end of wxTopLevelWindowOS2::DoSetClientSize
671
672 void wxTopLevelWindowOS2::DoGetClientSize(
673 int* pnX
674 , int* pnY
675 ) const
676 {
677 wxWindow::DoGetClientSize( pnX
678 ,pnY
679 );
680
681 wxPoint vPt = GetClientAreaOrigin();
682
683 if (pnX)
684 *pnX -= vPt.x;
685
686 if (pnY)
687 *pnY += vPt.y;
688 } // end of wxTopLevelWindowOS2::DoGetClientSize
689
690 // ----------------------------------------------------------------------------
691 // wxTopLevelWindowOS2 showing
692 // ----------------------------------------------------------------------------
693
694 void wxTopLevelWindowOS2::DoShowWindow(
695 int nShowCmd
696 )
697 {
698 ::WinShowWindow(m_hFrame, (BOOL)(nShowCmd & SWP_SHOW));
699
700 //
701 // Need to artificially send a size event as wxApps often expect to do some
702 // final child control sizing
703 SendSizeEvent();
704 m_bIconized = nShowCmd == SWP_MINIMIZE;
705 } // end of wxTopLevelWindowOS2::DoShowWindow
706
707 bool wxTopLevelWindowOS2::Show(
708 bool bShow
709 )
710 {
711 int nShowCmd;
712 SWP vSwp;
713 RECTL vRect;
714
715 if (bShow)
716 {
717 if (m_bMaximizeOnShow)
718 {
719 nShowCmd = SWP_MAXIMIZE;
720 m_bMaximizeOnShow = FALSE;
721 }
722 else
723 {
724 nShowCmd = SWP_SHOW;
725 }
726 }
727 else // hide
728 {
729 nShowCmd = SWP_HIDE;
730 }
731 DoShowWindow(nShowCmd);
732
733 if (bShow)
734 {
735 wxActivateEvent vEvent(wxEVT_ACTIVATE, TRUE, m_windowId);
736
737 ::WinQueryWindowPos(m_hFrame, &vSwp);
738 m_bIconized = vSwp.fl & SWP_MINIMIZE;
739 ::WinQueryWindowPos(m_hWnd, &m_vSwpClient);
740 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
741 ::WinEnableWindow(m_hFrame, TRUE);
742 vEvent.SetEventObject(this);
743 GetEventHandler()->ProcessEvent(vEvent);
744 }
745 else
746 {
747 //
748 // Try to highlight the correct window (the parent)
749 //
750 if (GetParent())
751 {
752 HWND hWndParent = GetHwndOf(GetParent());
753
754 ::WinQueryWindowPos(hWndParent, &vSwp);
755 m_bIconized = vSwp.fl & SWP_MINIMIZE;
756 if (hWndParent)
757 ::WinSetWindowPos( hWndParent
758 ,HWND_TOP
759 ,vSwp.x
760 ,vSwp.y
761 ,vSwp.cx
762 ,vSwp.cy
763 ,SWP_ZORDER | SWP_ACTIVATE | SWP_SHOW | SWP_MOVE
764 );
765 ::WinEnableWindow(hWndParent, TRUE);
766 }
767 }
768 return TRUE;
769 } // end of wxTopLevelWindowOS2::Show
770
771 // ----------------------------------------------------------------------------
772 // wxTopLevelWindowOS2 maximize/minimize
773 // ----------------------------------------------------------------------------
774
775 void wxTopLevelWindowOS2::Maximize(
776 bool bMaximize
777 )
778 {
779 if (IsShown())
780 {
781 //
782 // Just maximize it directly
783 //
784 DoShowWindow(bMaximize ? SWP_MAXIMIZE : SWP_RESTORE);
785 }
786 else // hidden
787 {
788 //
789 // We can't maximize the hidden frame because it shows it as well, so
790 // just remember that we should do it later in this case
791 //
792 m_bMaximizeOnShow = TRUE;
793 }
794 } // end of wxTopLevelWindowOS2::Maximize
795
796 bool wxTopLevelWindowOS2::IsMaximized() const
797 {
798 bool bIconic;
799
800 ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp);
801 return (m_vSwp.fl & SWP_MAXIMIZE);
802 } // end of wxTopLevelWindowOS2::IsMaximized
803
804 void wxTopLevelWindowOS2::Iconize(
805 bool bIconize
806 )
807 {
808 DoShowWindow(bIconize ? SWP_MINIMIZE : SWP_RESTORE);
809 } // end of wxTopLevelWindowOS2::Iconize
810
811 bool wxTopLevelWindowOS2::IsIconized() const
812 {
813 // also update the current state
814 ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp);
815 if (m_vSwp.fl & SWP_MINIMIZE)
816 ((wxTopLevelWindow*)this)->m_bIconized = TRUE;
817 else
818 ((wxTopLevelWindow*)this)->m_bIconized = FALSE;
819 return m_bIconized;
820 } // end of wxTopLevelWindowOS2::IsIconized
821
822 void wxTopLevelWindowOS2::Restore()
823 {
824 DoShowWindow(SWP_RESTORE);
825 } // end of wxTopLevelWindowOS2::Restore
826
827 // generate an artificial resize event
828 void wxTopLevelWindowOS2::SendSizeEvent()
829 {
830 if (!m_bIconized)
831 {
832 RECTL vRect = wxGetWindowRect(GetHwnd());
833
834 (void)::WinPostMsg( m_hFrame
835 ,WM_SIZE
836 ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom)
837 ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom)
838 );
839 }
840 } // end of wxTopLevelWindowOS2::SendSizeEvent
841
842 // ----------------------------------------------------------------------------
843 // wxTopLevelWindowOS2 fullscreen
844 // ----------------------------------------------------------------------------
845
846 bool wxTopLevelWindowOS2::ShowFullScreen(
847 bool bShow
848 , long lStyle
849 )
850 {
851 if (bShow)
852 {
853 if (IsFullScreen())
854 return FALSE;
855
856 m_bFsIsShowing = TRUE;
857 m_lFsStyle = lStyle;
858
859 //
860 // Zap the frame borders
861 //
862
863 //
864 // Save the 'normal' window lStyle
865 //
866 m_lFsOldWindowStyle = ::WinQueryWindowULong( (HWND)GetHWND()
867 ,QWL_STYLE
868 );
869
870 //
871 // Save the old position, width & height, maximize state
872 //
873 m_vFsOldSize = GetRect();
874 m_bFsIsMaximized = IsMaximized();
875
876 //
877 // Decide which window lStyle flags to turn off
878 //
879 LONG lNewStyle = m_lFsOldWindowStyle;
880 LONG lOffFlags = 0;
881
882 if (lStyle & wxFULLSCREEN_NOBORDER)
883 lOffFlags |= FCF_BORDER;
884 if (lStyle & wxFULLSCREEN_NOCAPTION)
885 lOffFlags |= (FCF_TASKLIST | FCF_SYSMENU);
886
887 lNewStyle &= (~lOffFlags);
888
889 //
890 // Change our window style to be compatible with full-screen mode
891 //
892 ::WinSetWindowULong( (HWND)GetHWND()
893 ,QWL_STYLE
894 ,lNewStyle
895 );
896
897 //
898 // Resize to the size of the desktop
899 //
900 int nWidth;
901 int nHeight;
902 RECTL vRect = wxGetWindowRect(HWND_DESKTOP);
903
904 nWidth = vRect.xRight - vRect.xLeft;
905 nHeight = vRect.yTop - vRect.yBottom;
906
907 SetSize( nWidth
908 ,nHeight
909 );
910
911 //
912 // Now flush the window style cache and actually go full-screen
913 //
914 ::WinSetWindowPos( m_hFrame
915 ,HWND_TOP
916 ,0
917 ,0
918 ,nWidth
919 ,nHeight
920 ,SWP_SIZE | SWP_MOVE
921 );
922
923 wxSizeEvent vEvent( wxSize( nWidth
924 ,nHeight
925 )
926 ,GetId()
927 );
928
929 GetEventHandler()->ProcessEvent(vEvent);
930 return TRUE;
931 }
932 else
933 {
934 if (!IsFullScreen())
935 return FALSE;
936
937 m_bFsIsShowing = FALSE;
938 Maximize(m_bFsIsMaximized);
939 ::WinSetWindowULong( (HWND)GetHWND()
940 ,QWL_STYLE
941 ,m_lFsOldWindowStyle
942 );
943 ::WinSetWindowPos( m_hFrame
944 ,HWND_TOP
945 ,m_vFsOldSize.x
946 ,m_vFsOldSize.y
947 ,m_vFsOldSize.width
948 ,m_vFsOldSize.height
949 ,SWP_SIZE | SWP_MOVE
950 );
951 return TRUE;
952 }
953 } // end of wxTopLevelWindowOS2::ShowFullScreen
954
955 // ----------------------------------------------------------------------------
956 // wxTopLevelWindowOS2 misc
957 // ----------------------------------------------------------------------------
958
959 void wxTopLevelWindowOS2::SetIcon(
960 const wxIcon& rIcon
961 )
962 {
963 //
964 // This sets m_icon
965 //
966 wxTopLevelWindowBase::SetIcon(rIcon);
967
968 if (m_icon.Ok())
969 {
970 ::WinSendMsg( m_hFrame
971 ,WM_SETICON
972 ,(MPARAM)((HPOINTER)m_icon.GetHICON())
973 ,NULL
974 );
975 ::WinSendMsg( m_hFrame
976 ,WM_UPDATEFRAME
977 ,(MPARAM)FCF_ICON
978 ,(MPARAM)0
979 );
980 }
981 } // end of wxTopLevelWindowOS2::SetIcon
982
983 bool wxTopLevelWindowOS2::EnableCloseButton(
984 bool bEnable
985 )
986 {
987 //
988 // Get system (a.k.a. window) menu
989 //
990 HMENU hMenu = ::WinWindowFromID(m_hFrame, FID_SYSMENU);
991
992 if (!hMenu)
993 {
994 wxLogLastError(_T("GetSystemMenu"));
995 return FALSE;
996 }
997
998 //
999 // Enabling/disabling the close item from it also automatically
1000 // disables/enables the close title bar button
1001 //
1002 if (bEnable)
1003 (void)::WinSendMsg( hMenu
1004 ,MM_SETITEMATTR
1005 ,MPFROM2SHORT(SC_CLOSE, FALSE)
1006 ,MPFROM2SHORT(MIA_DISABLED, FALSE)
1007 );
1008 else
1009 (void)::WinSendMsg( hMenu
1010 ,MM_SETITEMATTR
1011 ,MPFROM2SHORT(SC_CLOSE, FALSE)
1012 ,MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)
1013 );
1014
1015 //
1016 // Update appearance immediately
1017 //
1018 ::WinSendMsg( m_hFrame
1019 ,WM_UPDATEFRAME
1020 ,(MPARAM)FCF_MENU
1021 ,(MPARAM)0
1022 );
1023 return TRUE;
1024 } // end of wxTopLevelWindowOS2::EnableCloseButton
1025