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