]> git.saurik.com Git - wxWidgets.git/blame - src/os2/toplevel.cpp
Blind fix for bug #1209944, wxFileConfig constructor corrupts the stack
[wxWidgets.git] / src / os2 / toplevel.cpp
CommitLineData
f45e4fad 1///////////////////////////////////////////////////////////////////////////////
76d81b4d
SN
2// Name: os2/toplevel.cpp
3// Purpose: implements wxTopLevelWindow for OS/2
f45e4fad
DW
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)
65571936 9// License: wxWindows licence
f45e4fad
DW
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"
7b048ef6 34 #include "wx/dialog.h"
f45e4fad
DW
35 #include "wx/string.h"
36 #include "wx/log.h"
37 #include "wx/intl.h"
38 #include "wx/frame.h"
a4a16252 39 #include "wx/control.h"
272ebf16 40 #include "wx/containr.h" // wxSetFocusToChild()
f45e4fad
DW
41#endif //WX_PRECOMP
42
542e68c7 43#include "wx/module.h" // wxSetFocusToChild()
f45e4fad
DW
44#include "wx/os2/private.h"
45
46// ----------------------------------------------------------------------------
47// stubs for missing functions under MicroWindows
48// ----------------------------------------------------------------------------
49
50
51// ----------------------------------------------------------------------------
52// globals
53// ----------------------------------------------------------------------------
54
77ffb593 55// the name of the default wxWidgets class
793c7f9b
DW
56extern void wxAssociateWinWithHandle( HWND hWnd
57 ,wxWindowOS2* pWin
58 );
45e0dc94 59bool wxTopLevelWindowOS2::m_sbInitialized = FALSE;
6ed98c6a 60wxWindow* wxTopLevelWindowOS2::m_spHiddenParent = NULL;
f45e4fad 61
47df2b8c
DW
62// ============================================================================
63// wxTopLevelWindowOS2 implementation
64// ============================================================================
65
66BEGIN_EVENT_TABLE(wxTopLevelWindowOS2, wxTopLevelWindowBase)
67 EVT_ACTIVATE(wxTopLevelWindowOS2::OnActivate)
68END_EVENT_TABLE()
69
f45e4fad
DW
70// ============================================================================
71// wxTopLevelWindowMSW implementation
72// ============================================================================
73
74// Dialog window proc
75MRESULT EXPENTRY wxDlgProc( HWND WXUNUSED(hWnd)
76 ,UINT uMessage
9923c37d
DW
77 ,void * WXUNUSED(wParam)
78 ,void * WXUNUSED(lParam)
f45e4fad
DW
79 )
80{
47df2b8c 81 switch(uMessage)
f45e4fad 82 {
47df2b8c
DW
83 case WM_INITDLG:
84 //
85 // For this message, returning TRUE tells system to set focus to
0256cfeb
DW
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
47df2b8c 88 //
0256cfeb 89 return (MRESULT)TRUE;
47df2b8c
DW
90 default:
91 //
92 // For all the other ones, FALSE means that we didn't process the
93 // message
94 //
95 return (MRESULT)FALSE;
f45e4fad
DW
96 }
97} // end of wxDlgProc
98
376ef4a1
DW
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
104class wxTLWHiddenParentModule : public wxModule
105{
106public:
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
118private:
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
131IMPLEMENT_DYNAMIC_CLASS(wxTLWHiddenParentModule, wxModule)
132
f45e4fad
DW
133// ----------------------------------------------------------------------------
134// wxTopLevelWindowOS2 creation
135// ----------------------------------------------------------------------------
136
137void 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));
47df2b8c 156 m_pWinLastFocused = (wxWindow *)NULL;
f45e4fad
DW
157} // end of wxTopLevelWindowIOS2::Init
158
47df2b8c
DW
159void wxTopLevelWindowOS2::OnActivate(
160 wxActivateEvent& rEvent
161)
162{
163 if (rEvent.GetActive())
164 {
165 //
166 // Restore focus to the child which was last focused
167 //
9923c37d 168 wxLogTrace(_T("focus"), _T("wxTLW %08lx activated."), m_hWnd);
47df2b8c
DW
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"),
9923c37d 207 _T("wxTLW %08lx deactivated, last focused: %08lx."),
47df2b8c
DW
208 m_hWnd,
209 m_pWinLastFocused ? GetHwndOf(m_pWinLastFocused)
210 : NULL);
211 rEvent.Skip();
212 }
213} // end of wxTopLevelWindowOS2::OnActivate
214
b9b1d6c8
DW
215WXDWORD wxTopLevelWindowOS2::OS2GetStyle(
216 long lStyle
217, WXDWORD* pdwExflags
f45e4fad
DW
218) const
219{
b9b1d6c8
DW
220 long lMsflags = wxWindow::OS2GetStyle( (lStyle & ~wxBORDER_MASK) | wxBORDER_NONE
221 ,pdwExflags
222 );
f45e4fad 223
76d81b4d 224 if ((lStyle & wxDEFAULT_FRAME_STYLE) == wxDEFAULT_FRAME_STYLE)
b9b1d6c8
DW
225 lMsflags |= FCF_SIZEBORDER | FCF_TITLEBAR | FCF_SYSMENU |
226 FCF_MINMAX | FCF_TASKLIST;
76d81b4d
SN
227
228 if ((lStyle & wxCAPTION) == wxCAPTION)
229 lMsflags |= FCF_TASKLIST;
f45e4fad 230 else
76d81b4d
SN
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)
f45e4fad 248 {
76d81b4d
SN
249 // Invalid for frame windows under PM
250 }
f45e4fad 251
76d81b4d
SN
252 if (lStyle & wxTINY_CAPTION_VERT)
253 lMsflags |= FCF_TASKLIST;
254 if (lStyle & wxTINY_CAPTION_HORIZ)
255 lMsflags |= FCF_TASKLIST;
f45e4fad 256
76d81b4d
SN
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;
f45e4fad 264
f45e4fad
DW
265 return lMsflags;
266} // end of wxTopLevelWindowOS2::OS2GetCreateWindowFlags
267
6ed98c6a
DW
268WXHWND wxTopLevelWindowOS2::OS2GetParent() const
269{
376ef4a1
DW
270 HWND hWndParent = NULL;
271
6ed98c6a
DW
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 //
6ed98c6a
DW
278 if (HasFlag(wxFRAME_FLOAT_ON_PARENT) )
279 {
376ef4a1 280 const wxWindow* pParent = GetParent();
6ed98c6a 281
376ef4a1 282 if (!pParent)
6ed98c6a 283 {
6ed98c6a 284 //
376ef4a1 285 // This flag doesn't make sense then and will be ignored
6ed98c6a 286 //
376ef4a1 287 wxFAIL_MSG( _T("wxFRAME_FLOAT_ON_PARENT but no parent?") );
6ed98c6a 288 }
376ef4a1
DW
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();
6ed98c6a 306 }
376ef4a1 307 return (WXHWND)hWndParent;
6ed98c6a
DW
308} // end of wxTopLevelWindowOS2::OS2GetParent
309
f45e4fad
DW
310bool 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;
1b086de1 345 HWND hWndOwner;
f45e4fad
DW
346
347 if (pParent)
1b086de1 348 hWndOwner = GetHwndOf(pParent);
f45e4fad 349 else
1b086de1 350 hWndOwner = HWND_DESKTOP;
f45e4fad 351
1b086de1
DW
352 hWndDlg = ::WinLoadDlg( HWND_DESKTOP
353 ,hWndOwner
f45e4fad
DW
354 ,(PFNWP)wxDlgProc
355 ,NULL
356 ,(ULONG)ulDlgTemplate
357 ,(PVOID)this
358 );
359
360 m_hWnd = (WXHWND) hWndDlg;
361
362 if ( !m_hWnd )
363 {
7e99eddf 364 wxFAIL_MSG(wxT("Did you forget to include wx/os2/wx.rc in your resources?"));
f45e4fad 365
9923c37d 366 wxLogSysError(wxT("Can't create dialog using template '%ld'"), ulDlgTemplate);
f45e4fad
DW
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 }
0fba44b4 416 m_backgroundColour.Set(wxString(wxT("LIGHT GREY")));
626af800
DW
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 }
b3260bce 428
f45e4fad
DW
429 ::WinSetWindowPos( GetHwnd()
430 ,HWND_TOP
431 ,nX
432 ,nY
433 ,nWidth
434 ,nHeight
0256cfeb 435 ,SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE
f45e4fad 436 );
859e65de 437 ::WinQueryWindowPos(GetHwnd(), GetSwp());
626af800 438 m_hFrame = m_hWnd;
f45e4fad
DW
439 SubclassWin(m_hWnd);
440 return TRUE;
441} // end of wxTopLevelWindowOS2::CreateDialog
442
443bool wxTopLevelWindowOS2::CreateFrame(
444 const wxString& rsTitle
445, const wxPoint& rPos
446, const wxSize& rSize
447)
448{
b9b1d6c8
DW
449 WXDWORD lExflags;
450 WXDWORD lFlags = OS2GetCreateWindowFlags(&lExflags);
f45e4fad
DW
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);
0fba44b4 501 wxLogError(_T("Error creating frame. Error: %s\n"), sError.c_str());
f45e4fad
DW
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
0fba44b4 513 m_backgroundColour.Set(wxString(wxT("MEDIUM GREY")));
f45e4fad
DW
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);
0fba44b4 525 wxLogError(_T("Error creating frame. Error: %s\n"), sError.c_str());
f45e4fad
DW
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);
0fba44b4 562 wxLogError(_T("Error sizing frame. Error: %s\n"), sError.c_str());
f45e4fad
DW
563 return FALSE;
564 }
54ffa107
DW
565 lStyle = ::WinQueryWindowULong( m_hWnd
566 ,QWL_STYLE
567 );
568 lStyle |= WS_CLIPCHILDREN;
569 ::WinSetWindowULong( m_hWnd
570 ,QWL_STYLE
571 ,lStyle
572 );
f45e4fad
DW
573 return TRUE;
574} // end of wxTopLevelWindowOS2::CreateFrame
575
576bool wxTopLevelWindowOS2::Create(
577 wxWindow* pParent
578, wxWindowID vId
579, const wxString& rsTitle
580, const wxPoint& rPos
2d28c41c 581, const wxSize& rSizeOrig
f45e4fad
DW
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;
2d28c41c
SN
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
f45e4fad
DW
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
641wxTopLevelWindowOS2::~wxTopLevelWindowOS2()
642{
f45e4fad 643 //
a23692f0
DW
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 }
f45e4fad
DW
662} // end of wxTopLevelWindowOS2::~wxTopLevelWindowOS2
663
f45e4fad
DW
664// ----------------------------------------------------------------------------
665// wxTopLevelWindowOS2 client size
666// ----------------------------------------------------------------------------
667
668void 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
686void 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
708void wxTopLevelWindowOS2::DoShowWindow(
709 int nShowCmd
710)
711{
54ffa107 712 ::WinShowWindow(m_hFrame, (BOOL)(nShowCmd & SWP_SHOW));
239c2e96
DW
713
714 //
715 // Need to artificially send a size event as wxApps often expect to do some
716 // final child control sizing
717 SendSizeEvent();
f45e4fad
DW
718 m_bIconized = nShowCmd == SWP_MINIMIZE;
719} // end of wxTopLevelWindowOS2::DoShowWindow
720
721bool wxTopLevelWindowOS2::Show(
722 bool bShow
723)
724{
725 int nShowCmd;
726 SWP vSwp;
f45e4fad 727
376ef4a1
DW
728 if (bShow != IsShown() )
729 {
730 m_isShown = bShow;
731 }
732 else
733 {
734 return FALSE;
735 }
f45e4fad
DW
736 if (bShow)
737 {
738 if (m_bMaximizeOnShow)
739 {
54ffa107 740 nShowCmd = SWP_MAXIMIZE;
f45e4fad
DW
741 m_bMaximizeOnShow = FALSE;
742 }
743 else
744 {
54ffa107 745 nShowCmd = SWP_SHOW;
f45e4fad
DW
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);
4a46a5df 762 ::WinQueryWindowPos(m_hWnd, &vSwp);
f45e4fad 763 ::WinEnableWindow(m_hFrame, TRUE);
859e65de
DW
764
765 //
766 // Deal with children
767 //
768 MoveChildren(m_vSwpClient.cy - vSwp.cy);
f45e4fad
DW
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;
f45e4fad
DW
783 ::WinEnableWindow(hWndParent, TRUE);
784 }
785 }
786 return TRUE;
787} // end of wxTopLevelWindowOS2::Show
788
789// ----------------------------------------------------------------------------
790// wxTopLevelWindowOS2 maximize/minimize
791// ----------------------------------------------------------------------------
792
793void 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 //
6e348b12 810 m_bMaximizeOnShow = bMaximize;
f45e4fad
DW
811 }
812} // end of wxTopLevelWindowOS2::Maximize
813
814bool wxTopLevelWindowOS2::IsMaximized() const
815{
f45e4fad
DW
816
817 ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp);
818 return (m_vSwp.fl & SWP_MAXIMIZE);
819} // end of wxTopLevelWindowOS2::IsMaximized
820
821void wxTopLevelWindowOS2::Iconize(
822 bool bIconize
823)
824{
825 DoShowWindow(bIconize ? SWP_MINIMIZE : SWP_RESTORE);
826} // end of wxTopLevelWindowOS2::Iconize
827
828bool 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
839void wxTopLevelWindowOS2::Restore()
840{
841 DoShowWindow(SWP_RESTORE);
842} // end of wxTopLevelWindowOS2::Restore
843
239c2e96
DW
844// generate an artificial resize event
845void 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
f45e4fad
DW
859// ----------------------------------------------------------------------------
860// wxTopLevelWindowOS2 fullscreen
861// ----------------------------------------------------------------------------
862
863bool 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
976void wxTopLevelWindowOS2::SetIcon(
977 const wxIcon& rIcon
978)
3437f881
DW
979{
980 SetIcons(wxIconBundle(rIcon));
981} // end of wxTopLevelWindowOS2::SetIcon
982
983void wxTopLevelWindowOS2::SetIcons(
984 const wxIconBundle& rIcons
985)
f45e4fad
DW
986{
987 //
988 // This sets m_icon
989 //
3437f881
DW
990 wxTopLevelWindowBase::SetIcons(rIcons);
991
992 const wxIcon& vIcon = rIcons.GetIcon(wxSize(32, 32));
f45e4fad 993
3437f881 994 if (vIcon.Ok() && vIcon.GetWidth() == 32 && vIcon.GetHeight() == 32)
f45e4fad
DW
995 {
996 ::WinSendMsg( m_hFrame
997 ,WM_SETICON
3437f881 998 ,(MPARAM)((HPOINTER)vIcon.GetHICON())
f45e4fad
DW
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
1009bool 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
376ef4a1
DW
1052// ============================================================================
1053// wxTLWHiddenParentModule implementation
1054// ============================================================================
1055
1056HWND wxTLWHiddenParentModule::m_shWnd = NULL;
1057const wxChar* wxTLWHiddenParentModule::m_szClassName = NULL;
1058
1059bool wxTLWHiddenParentModule::OnInit()
1060{
1061 m_shWnd = NULL;
1062 m_szClassName = NULL;
1063 return TRUE;
1064} // end of wxTLWHiddenParentModule::OnInit
1065
1066void 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 */
1081HWND 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()
0fba44b4 1090 ,(PSZ)zHIDDEN_PARENT_CLASS
376ef4a1
DW
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
0fba44b4 1104 ,(PSZ)m_szClassName
376ef4a1
DW
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