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