]> git.saurik.com Git - wxWidgets.git/blob - src/os2/toplevel.cpp
generate key events for Space/Enter in addition to the activate events, as wxMSW...
[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 #include "wx/containr.h" // wxSetFocusToChild()
40 #endif //WX_PRECOMP
41
42 #include "wx/os2/private.h"
43
44 // ----------------------------------------------------------------------------
45 // stubs for missing functions under MicroWindows
46 // ----------------------------------------------------------------------------
47
48
49 // ----------------------------------------------------------------------------
50 // globals
51 // ----------------------------------------------------------------------------
52
53 // list of all frames and modeless dialogs
54 wxWindowList wxModelessWindows;
55
56 // the name of the default wxWindows class
57 extern void wxAssociateWinWithHandle( HWND hWnd
58 ,wxWindowOS2* pWin
59 );
60 bool wxTopLevelWindowOS2::m_sbInitialized = FALSE;
61 wxWindow* wxTopLevelWindowOS2::m_spHiddenParent = NULL;
62
63 // ============================================================================
64 // wxTopLevelWindowOS2 implementation
65 // ============================================================================
66
67 BEGIN_EVENT_TABLE(wxTopLevelWindowOS2, wxTopLevelWindowBase)
68 EVT_ACTIVATE(wxTopLevelWindowOS2::OnActivate)
69 END_EVENT_TABLE()
70
71 // ============================================================================
72 // wxTopLevelWindowMSW implementation
73 // ============================================================================
74
75 // Dialog window proc
76 MRESULT EXPENTRY wxDlgProc( HWND WXUNUSED(hWnd)
77 ,UINT uMessage
78 ,MPARAM WXUNUSED(wParam)
79 ,MPARAM WXUNUSED(lParam)
80 )
81 {
82 switch(uMessage)
83 {
84 case WM_INITDLG:
85 //
86 // For this message, returning TRUE tells system to set focus to
87 // the first control in the dialog box, but we set the focus
88 // ourselves, however in OS/2 we must return true to enable the dialog
89 //
90 return (MRESULT)TRUE;
91 default:
92 //
93 // For all the other ones, FALSE means that we didn't process the
94 // message
95 //
96 return (MRESULT)FALSE;
97 }
98 } // end of wxDlgProc
99
100 // ----------------------------------------------------------------------------
101 // wxTopLevelWindowOS2 creation
102 // ----------------------------------------------------------------------------
103
104 void wxTopLevelWindowOS2::Init()
105 {
106 m_bIconized = m_bMaximizeOnShow = FALSE;
107
108 //
109 // Unlike (almost?) all other windows, frames are created hidden
110 //
111 m_isShown = FALSE;
112
113 //
114 // Data to save/restore when calling ShowFullScreen
115 m_lFsStyle = 0;
116 m_lFsOldWindowStyle = 0;
117 m_bFsIsMaximized = FALSE;
118 m_bFsIsShowing = FALSE;
119
120 m_hFrame = NULLHANDLE;
121 memset(&m_vSwp, 0, sizeof(SWP));
122 memset(&m_vSwpClient, 0, sizeof(SWP));
123 m_pWinLastFocused = (wxWindow *)NULL;
124 } // end of wxTopLevelWindowIOS2::Init
125
126 void wxTopLevelWindowOS2::OnActivate(
127 wxActivateEvent& rEvent
128 )
129 {
130 if (rEvent.GetActive())
131 {
132 //
133 // Restore focus to the child which was last focused
134 //
135 wxLogTrace(_T("focus"), _T("wxTLW %08x activated."), m_hWnd);
136
137 wxWindow* pParent = m_pWinLastFocused ? m_pWinLastFocused->GetParent()
138 : NULL;
139 if (!pParent)
140 {
141 pParent = this;
142 }
143
144 wxSetFocusToChild( pParent
145 ,&m_pWinLastFocused
146 );
147 }
148 else // deactivating
149 {
150 //
151 // Remember the last focused child if it is our child
152 //
153 m_pWinLastFocused = FindFocus();
154
155 //
156 // So we NULL it out if it's a child from some other frame
157 //
158 wxWindow* pWin = m_pWinLastFocused;
159
160 while (pWin)
161 {
162 if (pWin->IsTopLevel())
163 {
164 if (pWin != this)
165 {
166 m_pWinLastFocused = NULL;
167 }
168 break;
169 }
170 pWin = pWin->GetParent();
171 }
172
173 wxLogTrace(_T("focus"),
174 _T("wxTLW %08x deactivated, last focused: %08x."),
175 m_hWnd,
176 m_pWinLastFocused ? GetHwndOf(m_pWinLastFocused)
177 : NULL);
178 rEvent.Skip();
179 }
180 } // end of wxTopLevelWindowOS2::OnActivate
181
182 WXDWORD wxTopLevelWindowOS2::OS2GetStyle(
183 long lStyle
184 , WXDWORD* pdwExflags
185 ) const
186 {
187 long lMsflags = wxWindow::OS2GetStyle( (lStyle & ~wxBORDER_MASK) | wxBORDER_NONE
188 ,pdwExflags
189 );
190
191 if (lStyle == wxDEFAULT_FRAME_STYLE)
192 lMsflags |= FCF_SIZEBORDER | FCF_TITLEBAR | FCF_SYSMENU |
193 FCF_MINMAX | FCF_TASKLIST;
194 else
195 {
196 if ((lStyle & wxCAPTION) == wxCAPTION)
197 lMsflags |= FCF_TASKLIST;
198 else
199 lMsflags |= FCF_NOMOVEWITHOWNER;
200
201 if ((lStyle & wxVSCROLL) == wxVSCROLL)
202 lMsflags |= FCF_VERTSCROLL;
203 if ((lStyle & wxHSCROLL) == wxHSCROLL)
204 lMsflags |= FCF_HORZSCROLL;
205 if (lStyle & wxMINIMIZE_BOX)
206 lMsflags |= FCF_MINBUTTON;
207 if (lStyle & wxMAXIMIZE_BOX)
208 lMsflags |= FCF_MAXBUTTON;
209 if (lStyle & wxTHICK_FRAME)
210 lMsflags |= FCF_DLGBORDER;
211 if (lStyle & wxSYSTEM_MENU)
212 lMsflags |= FCF_SYSMENU;
213 if (lStyle & wxCAPTION)
214 lMsflags |= FCF_TASKLIST;
215 if (lStyle & wxCLIP_CHILDREN)
216 {
217 // Invalid for frame windows under PM
218 }
219
220 if (lStyle & wxTINY_CAPTION_VERT)
221 lMsflags |= FCF_TASKLIST;
222 if (lStyle & wxTINY_CAPTION_HORIZ)
223 lMsflags |= FCF_TASKLIST;
224
225 if ((lStyle & wxTHICK_FRAME) == 0)
226 lMsflags |= FCF_BORDER;
227 if (lStyle & wxFRAME_TOOL_WINDOW)
228 *pdwExflags = kFrameToolWindow;
229
230 if (lStyle & wxSTAY_ON_TOP)
231 lMsflags |= FCF_SYSMODAL;
232 }
233 return lMsflags;
234 } // end of wxTopLevelWindowOS2::OS2GetCreateWindowFlags
235
236 WXHWND wxTopLevelWindowOS2::OS2GetParent() const
237 {
238 //
239 // For the frames without wxFRAME_FLOAT_ON_PARENT style we should use NULL
240 // parent HWND or it would be always on top of its parent which is not what
241 // we usually want (in fact, we only want it for frames with the
242 // wxFRAME_FLOAT_ON_PARENT flag)
243 //
244 wxWindow* pParent;
245
246 if (HasFlag(wxFRAME_FLOAT_ON_PARENT) )
247 {
248 pParent = GetParent();
249
250 // this flag doesn't make sense then and will be ignored
251 wxASSERT_MSG( pParent,
252 _T("wxFRAME_FLOAT_ON_PARENT but no parent?") );
253 }
254 else // don't float on parent, must not be owned
255 {
256 pParent = NULL;
257 }
258 if (HasFlag(wxFRAME_NO_TASKBAR) && !pParent)
259 {
260 if (!m_spHiddenParent)
261 {
262 m_spHiddenParent = new wxTopLevelWindowOS2(NULL, -1, _T(""));
263
264 //
265 // We shouldn't leave it in wxTopLevelWindows or we wouldn't
266 // terminate the app when the last user-created frame is deleted --
267 // see ~wxTopLevelWindowMSW
268 //
269 wxTopLevelWindows.DeleteObject(m_spHiddenParent);
270 }
271 pParent = m_spHiddenParent;
272 }
273 return pParent ? pParent->GetHWND() : NULL;
274 } // end of wxTopLevelWindowOS2::OS2GetParent
275
276 bool wxTopLevelWindowOS2::CreateDialog(
277 ULONG ulDlgTemplate
278 , const wxString& rsTitle
279 , const wxPoint& rPos
280 , const wxSize& rSize
281 )
282 {
283 wxWindow* pParent = GetParent();
284
285 //
286 // For the dialogs without wxDIALOG_NO_PARENT style, use the top level
287 // app window as parent - this avoids creating modal dialogs without
288 // parent
289 //
290 if (!pParent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT))
291 {
292 pParent = wxTheApp->GetTopWindow();
293
294 if (pParent)
295 {
296 //
297 // Don't use transient windows as parents, this is dangerous as it
298 // can lead to a crash if the parent is destroyed before the child
299 //
300 // also don't use the window which is currently hidden as then the
301 // dialog would be hidden as well
302 if ((pParent->GetExtraStyle() & wxWS_EX_TRANSIENT) ||
303 !pParent->IsShown())
304 {
305 pParent = NULL;
306 }
307 }
308 }
309
310 HWND hWndDlg;
311 HWND hWndOwner;
312
313 if (pParent)
314 hWndOwner = GetHwndOf(pParent);
315 else
316 hWndOwner = HWND_DESKTOP;
317
318 hWndDlg = ::WinLoadDlg( HWND_DESKTOP
319 ,hWndOwner
320 ,(PFNWP)wxDlgProc
321 ,NULL
322 ,(ULONG)ulDlgTemplate
323 ,(PVOID)this
324 );
325
326 m_hWnd = (WXHWND) hWndDlg;
327
328 if ( !m_hWnd )
329 {
330 wxFAIL_MSG(_("Did you forget to include wx/os2/wx.rc in your resources?"));
331
332 wxLogSysError(_("Can't create dialog using template '%ul'"), ulDlgTemplate);
333
334 return FALSE;
335 }
336
337 //
338 // Move the dialog to its initial position without forcing repainting
339 //
340 int nX;
341 int nY;
342 int nWidth;
343 int nHeight;
344
345 if (!OS2GetCreateWindowCoords( rPos
346 ,rSize
347 ,nX
348 ,nY
349 ,nWidth
350 ,nHeight
351 ))
352 {
353 nX = nWidth = (int)CW_USEDEFAULT;
354 }
355
356 //
357 // We can't use CW_USEDEFAULT here as we're not calling CreateWindow()
358 // and passing CW_USEDEFAULT to MoveWindow() results in resizing the
359 // window to (0, 0) size which breaks quite a lot of things, e.g. the
360 // sizer calculation in wxSizer::Fit()
361 //
362 if (nWidth == (int)CW_USEDEFAULT)
363 {
364 //
365 // The exact number doesn't matter, the dialog will be resized
366 // again soon anyhow but it should be big enough to allow
367 // calculation relying on "totalSize - clientSize > 0" work, i.e.
368 // at least greater than the title bar height
369 //
370 nWidth = nHeight = 100;
371 }
372 if (nX == (int)CW_USEDEFAULT)
373 {
374 //
375 // Centre it on the screen - what else can we do?
376 //
377 wxSize vSizeDpy = wxGetDisplaySize();
378
379 nX = (vSizeDpy.x - nWidth) / 2;
380 nY = (vSizeDpy.y - nHeight) / 2;
381 }
382 m_backgroundColour.Set(wxString("LIGHT GREY"));
383
384 LONG lColor = (LONG)m_backgroundColour.GetPixel();
385
386 if (!::WinSetPresParam( m_hWnd
387 ,PP_BACKGROUNDCOLOR
388 ,sizeof(LONG)
389 ,(PVOID)&lColor
390 ))
391 {
392 return FALSE;
393 }
394
395 ::WinSetWindowPos( GetHwnd()
396 ,HWND_TOP
397 ,nX
398 ,nY
399 ,nWidth
400 ,nHeight
401 ,SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE
402 );
403 ::WinQueryWindowPos(GetHwnd(), GetSwp());
404 m_hFrame = m_hWnd;
405 SubclassWin(m_hWnd);
406 return TRUE;
407 } // end of wxTopLevelWindowOS2::CreateDialog
408
409 bool wxTopLevelWindowOS2::CreateFrame(
410 const wxString& rsTitle
411 , const wxPoint& rPos
412 , const wxSize& rSize
413 )
414 {
415 WXDWORD lExflags;
416 WXDWORD lFlags = OS2GetCreateWindowFlags(&lExflags);
417 long lStyle = GetWindowStyleFlag();
418 int nX = rPos.x;
419 int nY = rPos.y;
420 int nWidth = rSize.x;
421 int nHeight = rSize.y;
422 ULONG ulStyleFlags = 0L;
423 ERRORID vError;
424 wxString sError;
425 wxWindow* pParent = GetParent();
426 HWND hParent;
427 HWND hFrame;
428 HWND hClient;
429
430 if (pParent)
431 hParent = GetHwndOf(pParent);
432 else
433 hParent = HWND_DESKTOP;
434
435 if ((lStyle & wxMINIMIZE) || (lStyle & wxICONIZE))
436 ulStyleFlags |= WS_MINIMIZED;
437 if (lStyle & wxMAXIMIZE)
438 ulStyleFlags |= WS_MAXIMIZED;
439
440 //
441 // Clear the visible flag, we always call show
442 //
443 ulStyleFlags &= (unsigned long)~WS_VISIBLE;
444 m_bIconized = FALSE;
445
446 //
447 // Create the frame window: We break ranks with other ports now
448 // and instead of calling down into the base wxWindow class' OS2Create
449 // we do all our own stuff here. We will set the needed pieces
450 // of wxWindow manually, here.
451 //
452
453 hFrame = ::WinCreateStdWindow( hParent
454 ,ulStyleFlags // frame-window style
455 ,(PULONG)&lFlags // window style
456 ,(PSZ)wxFrameClassName // class name
457 ,(PSZ)rsTitle.c_str() // window title
458 ,0L // default client style
459 ,NULLHANDLE // resource in executable file
460 ,0 // resource id
461 ,&hClient // receives client window handle
462 );
463 if (!hFrame)
464 {
465 vError = ::WinGetLastError(vHabmain);
466 sError = wxPMErrorToStr(vError);
467 wxLogError("Error creating frame. Error: %s\n", sError);
468 return FALSE;
469 }
470
471 //
472 // wxWindow class' m_hWnd set here and needed associations
473 //
474 m_hFrame = hFrame;
475 m_hWnd = hClient;
476 wxAssociateWinWithHandle(m_hWnd, this);
477 wxAssociateWinWithHandle(m_hFrame, this);
478
479 m_backgroundColour.Set(wxString("MEDIUM GREY"));
480
481 LONG lColor = (LONG)m_backgroundColour.GetPixel();
482
483 if (!::WinSetPresParam( m_hWnd
484 ,PP_BACKGROUNDCOLOR
485 ,sizeof(LONG)
486 ,(PVOID)&lColor
487 ))
488 {
489 vError = ::WinGetLastError(vHabmain);
490 sError = wxPMErrorToStr(vError);
491 wxLogError("Error creating frame. Error: %s\n", sError);
492 return FALSE;
493 }
494
495 //
496 // Now need to subclass window. Instead of calling the SubClassWin in wxWindow
497 // we manually subclass here because we don't want to use the main wxWndProc
498 // by default
499 //
500 m_fnOldWndProc = (WXFARPROC) ::WinSubclassWindow(m_hFrame, (PFNWP)wxFrameMainWndProc);
501
502 //
503 // Now size everything. If adding a menu the client will need to be resized.
504 //
505
506 if (pParent)
507 {
508 nY = pParent->GetSize().y - (nY + nHeight);
509 }
510 else
511 {
512 RECTL vRect;
513
514 ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
515 nY = vRect.yTop - (nY + nHeight);
516 }
517 if (!::WinSetWindowPos( m_hFrame
518 ,HWND_TOP
519 ,nX
520 ,nY
521 ,nWidth
522 ,nHeight
523 ,SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_ZORDER
524 ))
525 {
526 vError = ::WinGetLastError(vHabmain);
527 sError = wxPMErrorToStr(vError);
528 wxLogError("Error sizing frame. Error: %s\n", sError);
529 return FALSE;
530 }
531 lStyle = ::WinQueryWindowULong( m_hWnd
532 ,QWL_STYLE
533 );
534 lStyle |= WS_CLIPCHILDREN;
535 ::WinSetWindowULong( m_hWnd
536 ,QWL_STYLE
537 ,lStyle
538 );
539 return TRUE;
540 } // end of wxTopLevelWindowOS2::CreateFrame
541
542 bool wxTopLevelWindowOS2::Create(
543 wxWindow* pParent
544 , wxWindowID vId
545 , const wxString& rsTitle
546 , const wxPoint& rPos
547 , const wxSize& rSize
548 , long lStyle
549 , const wxString& rsName
550 )
551 {
552 //
553 // Init our fields
554 //
555 Init();
556 m_windowStyle = lStyle;
557 SetName(rsName);
558 m_windowId = vId == -1 ? NewControlId() : vId;
559 wxTopLevelWindows.Append(this);
560 if (pParent)
561 pParent->AddChild(this);
562
563 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
564 {
565 //
566 // We have different dialog templates to allows creation of dialogs
567 // with & without captions under OS2indows, resizeable or not (but a
568 // resizeable dialog always has caption - otherwise it would look too
569 // strange)
570 //
571 ULONG ulDlgTemplate;
572
573 if (lStyle & wxRESIZE_BORDER)
574 ulDlgTemplate = (ULONG)kResizeableDialog;
575 else if (lStyle & wxCAPTION)
576 ulDlgTemplate = (ULONG)kCaptionDialog;
577 else
578 ulDlgTemplate = (ULONG)kNoCaptionDialog;
579 return CreateDialog( ulDlgTemplate
580 ,rsTitle
581 ,rPos
582 ,rSize
583 );
584 }
585 else // !dialog
586 {
587 return CreateFrame( rsTitle
588 ,rPos
589 ,rSize
590 );
591 }
592 } // end of wxTopLevelWindowOS2::Create
593
594 wxTopLevelWindowOS2::~wxTopLevelWindowOS2()
595 {
596 if (this == m_spHiddenParent)
597 {
598 //
599 // Stop [infinite] recursion which would otherwise happen when we do
600 // "delete ms_hiddenParent" below -- and we're not interested in doing
601 // anything of the rest below for that window because the rest of
602 // wxWindows doesn't even know about it
603 //
604 return;
605 }
606
607 if (wxModelessWindows.Find(this))
608 wxModelessWindows.DeleteObject(this);
609
610 //
611 // After destroying an owned window, Windows activates the next top level
612 // window in Z order but it may be different from our owner (to reproduce
613 // this simply Alt-TAB to another application and back before closing the
614 // owned frame) whereas we always want to yield activation to our parent
615 //
616 if (HasFlag(wxFRAME_FLOAT_ON_PARENT))
617 {
618 wxWindow* pParent = GetParent();
619
620 if (pParent)
621 {
622 ::WinSetWindowPos( GetHwndOf(pParent)
623 ,HWND_TOP
624 ,0, 0, 0, 0
625 ,SWP_ZORDER
626 );
627 }
628 }
629
630 //
631 // If this is the last top-level window, we're going to exit and we should
632 // delete ms_hiddenParent now to avoid leaking it
633 //
634 if (IsLastBeforeExit())
635 {
636 if (m_spHiddenParent)
637 {
638 delete m_spHiddenParent;
639 m_spHiddenParent = NULL;
640 }
641 }
642 } // end of wxTopLevelWindowOS2::~wxTopLevelWindowOS2
643
644 // ----------------------------------------------------------------------------
645 // wxTopLevelWindowOS2 client size
646 // ----------------------------------------------------------------------------
647
648 void wxTopLevelWindowOS2::DoSetClientSize(
649 int nWidth
650 , int nHeight
651 )
652 {
653 //
654 // Call GetClientAreaOrigin() to take the toolbar into account
655 //
656 wxPoint vPt = GetClientAreaOrigin();
657
658 nWidth += vPt.x;
659 nHeight += vPt.y;
660
661 wxWindow::DoSetClientSize( nWidth
662 ,nHeight
663 );
664 } // end of wxTopLevelWindowOS2::DoSetClientSize
665
666 void wxTopLevelWindowOS2::DoGetClientSize(
667 int* pnX
668 , int* pnY
669 ) const
670 {
671 wxWindow::DoGetClientSize( pnX
672 ,pnY
673 );
674
675 wxPoint vPt = GetClientAreaOrigin();
676
677 if (pnX)
678 *pnX -= vPt.x;
679
680 if (pnY)
681 *pnY += vPt.y;
682 } // end of wxTopLevelWindowOS2::DoGetClientSize
683
684 // ----------------------------------------------------------------------------
685 // wxTopLevelWindowOS2 showing
686 // ----------------------------------------------------------------------------
687
688 void wxTopLevelWindowOS2::DoShowWindow(
689 int nShowCmd
690 )
691 {
692 ::WinShowWindow(m_hFrame, (BOOL)(nShowCmd & SWP_SHOW));
693
694 //
695 // Need to artificially send a size event as wxApps often expect to do some
696 // final child control sizing
697 SendSizeEvent();
698 m_bIconized = nShowCmd == SWP_MINIMIZE;
699 } // end of wxTopLevelWindowOS2::DoShowWindow
700
701 bool wxTopLevelWindowOS2::Show(
702 bool bShow
703 )
704 {
705 int nShowCmd;
706 SWP vSwp;
707 RECTL vRect;
708
709 if (bShow)
710 {
711 if (m_bMaximizeOnShow)
712 {
713 nShowCmd = SWP_MAXIMIZE;
714 m_bMaximizeOnShow = FALSE;
715 }
716 else
717 {
718 nShowCmd = SWP_SHOW;
719 }
720 }
721 else // hide
722 {
723 nShowCmd = SWP_HIDE;
724 }
725 DoShowWindow(nShowCmd);
726
727 if (bShow)
728 {
729 wxActivateEvent vEvent(wxEVT_ACTIVATE, TRUE, m_windowId);
730
731 ::WinQueryWindowPos(m_hFrame, &vSwp);
732 m_bIconized = vSwp.fl & SWP_MINIMIZE;
733 ::WinQueryWindowPos(m_hWnd, &m_vSwpClient);
734 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
735 ::WinQueryWindowPos(m_hWnd, &vSwp);
736 ::WinEnableWindow(m_hFrame, TRUE);
737
738 //
739 // Deal with children
740 //
741 MoveChildren(m_vSwpClient.cy - vSwp.cy);
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 ::WinEnableWindow(hWndParent, TRUE);
757 }
758 }
759 return TRUE;
760 } // end of wxTopLevelWindowOS2::Show
761
762 // ----------------------------------------------------------------------------
763 // wxTopLevelWindowOS2 maximize/minimize
764 // ----------------------------------------------------------------------------
765
766 void wxTopLevelWindowOS2::Maximize(
767 bool bMaximize
768 )
769 {
770 if (IsShown())
771 {
772 //
773 // Just maximize it directly
774 //
775 DoShowWindow(bMaximize ? SWP_MAXIMIZE : SWP_RESTORE);
776 }
777 else // hidden
778 {
779 //
780 // We can't maximize the hidden frame because it shows it as well, so
781 // just remember that we should do it later in this case
782 //
783 m_bMaximizeOnShow = TRUE;
784 }
785 } // end of wxTopLevelWindowOS2::Maximize
786
787 bool wxTopLevelWindowOS2::IsMaximized() const
788 {
789 bool bIconic;
790
791 ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp);
792 return (m_vSwp.fl & SWP_MAXIMIZE);
793 } // end of wxTopLevelWindowOS2::IsMaximized
794
795 void wxTopLevelWindowOS2::Iconize(
796 bool bIconize
797 )
798 {
799 DoShowWindow(bIconize ? SWP_MINIMIZE : SWP_RESTORE);
800 } // end of wxTopLevelWindowOS2::Iconize
801
802 bool wxTopLevelWindowOS2::IsIconized() const
803 {
804 // also update the current state
805 ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp);
806 if (m_vSwp.fl & SWP_MINIMIZE)
807 ((wxTopLevelWindow*)this)->m_bIconized = TRUE;
808 else
809 ((wxTopLevelWindow*)this)->m_bIconized = FALSE;
810 return m_bIconized;
811 } // end of wxTopLevelWindowOS2::IsIconized
812
813 void wxTopLevelWindowOS2::Restore()
814 {
815 DoShowWindow(SWP_RESTORE);
816 } // end of wxTopLevelWindowOS2::Restore
817
818 // generate an artificial resize event
819 void wxTopLevelWindowOS2::SendSizeEvent()
820 {
821 if (!m_bIconized)
822 {
823 RECTL vRect = wxGetWindowRect(GetHwnd());
824
825 (void)::WinPostMsg( m_hFrame
826 ,WM_SIZE
827 ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom)
828 ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom)
829 );
830 }
831 } // end of wxTopLevelWindowOS2::SendSizeEvent
832
833 // ----------------------------------------------------------------------------
834 // wxTopLevelWindowOS2 fullscreen
835 // ----------------------------------------------------------------------------
836
837 bool wxTopLevelWindowOS2::ShowFullScreen(
838 bool bShow
839 , long lStyle
840 )
841 {
842 if (bShow)
843 {
844 if (IsFullScreen())
845 return FALSE;
846
847 m_bFsIsShowing = TRUE;
848 m_lFsStyle = lStyle;
849
850 //
851 // Zap the frame borders
852 //
853
854 //
855 // Save the 'normal' window lStyle
856 //
857 m_lFsOldWindowStyle = ::WinQueryWindowULong( (HWND)GetHWND()
858 ,QWL_STYLE
859 );
860
861 //
862 // Save the old position, width & height, maximize state
863 //
864 m_vFsOldSize = GetRect();
865 m_bFsIsMaximized = IsMaximized();
866
867 //
868 // Decide which window lStyle flags to turn off
869 //
870 LONG lNewStyle = m_lFsOldWindowStyle;
871 LONG lOffFlags = 0;
872
873 if (lStyle & wxFULLSCREEN_NOBORDER)
874 lOffFlags |= FCF_BORDER;
875 if (lStyle & wxFULLSCREEN_NOCAPTION)
876 lOffFlags |= (FCF_TASKLIST | FCF_SYSMENU);
877
878 lNewStyle &= (~lOffFlags);
879
880 //
881 // Change our window style to be compatible with full-screen mode
882 //
883 ::WinSetWindowULong( (HWND)GetHWND()
884 ,QWL_STYLE
885 ,lNewStyle
886 );
887
888 //
889 // Resize to the size of the desktop
890 //
891 int nWidth;
892 int nHeight;
893 RECTL vRect = wxGetWindowRect(HWND_DESKTOP);
894
895 nWidth = vRect.xRight - vRect.xLeft;
896 nHeight = vRect.yTop - vRect.yBottom;
897
898 SetSize( nWidth
899 ,nHeight
900 );
901
902 //
903 // Now flush the window style cache and actually go full-screen
904 //
905 ::WinSetWindowPos( m_hFrame
906 ,HWND_TOP
907 ,0
908 ,0
909 ,nWidth
910 ,nHeight
911 ,SWP_SIZE | SWP_MOVE
912 );
913
914 wxSizeEvent vEvent( wxSize( nWidth
915 ,nHeight
916 )
917 ,GetId()
918 );
919
920 GetEventHandler()->ProcessEvent(vEvent);
921 return TRUE;
922 }
923 else
924 {
925 if (!IsFullScreen())
926 return FALSE;
927
928 m_bFsIsShowing = FALSE;
929 Maximize(m_bFsIsMaximized);
930 ::WinSetWindowULong( (HWND)GetHWND()
931 ,QWL_STYLE
932 ,m_lFsOldWindowStyle
933 );
934 ::WinSetWindowPos( m_hFrame
935 ,HWND_TOP
936 ,m_vFsOldSize.x
937 ,m_vFsOldSize.y
938 ,m_vFsOldSize.width
939 ,m_vFsOldSize.height
940 ,SWP_SIZE | SWP_MOVE
941 );
942 return TRUE;
943 }
944 } // end of wxTopLevelWindowOS2::ShowFullScreen
945
946 // ----------------------------------------------------------------------------
947 // wxTopLevelWindowOS2 misc
948 // ----------------------------------------------------------------------------
949
950 void wxTopLevelWindowOS2::SetIcon(
951 const wxIcon& rIcon
952 )
953 {
954 SetIcons(wxIconBundle(rIcon));
955 } // end of wxTopLevelWindowOS2::SetIcon
956
957 void wxTopLevelWindowOS2::SetIcons(
958 const wxIconBundle& rIcons
959 )
960 {
961 //
962 // This sets m_icon
963 //
964 wxTopLevelWindowBase::SetIcons(rIcons);
965
966 const wxIcon& vIcon = rIcons.GetIcon(wxSize(32, 32));
967
968 if (vIcon.Ok() && vIcon.GetWidth() == 32 && vIcon.GetHeight() == 32)
969 {
970 ::WinSendMsg( m_hFrame
971 ,WM_SETICON
972 ,(MPARAM)((HPOINTER)vIcon.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