]> git.saurik.com Git - wxWidgets.git/blame - src/os2/toplevel.cpp
Fix referencing of cairo_t returned from wxDCImpl::GetCairoContext().
[wxWidgets.git] / src / os2 / toplevel.cpp
CommitLineData
f45e4fad 1///////////////////////////////////////////////////////////////////////////////
743e24aa 2// Name: src/os2/toplevel.cpp
76d81b4d 3// Purpose: implements wxTopLevelWindow for OS/2
f45e4fad
DW
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 30.12.01
f45e4fad 7// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
526954c5 8// Licence: wxWindows licence
f45e4fad
DW
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
f45e4fad
DW
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
1832043f
WS
26#include "wx/toplevel.h"
27
f45e4fad
DW
28#ifndef WX_PRECOMP
29 #include "wx/app.h"
7b048ef6 30 #include "wx/dialog.h"
f45e4fad
DW
31 #include "wx/string.h"
32 #include "wx/log.h"
33 #include "wx/intl.h"
34 #include "wx/frame.h"
a4a16252 35 #include "wx/control.h"
272ebf16 36 #include "wx/containr.h" // wxSetFocusToChild()
ad4e3f7b 37 #include "wx/settings.h"
02761f6c 38 #include "wx/module.h" // wxSetFocusToChild()
f45e4fad
DW
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
77ffb593 52// the name of the default wxWidgets class
743e24aa
WS
53extern void wxAssociateWinWithHandle( HWND hWnd, wxWindowOS2* pWin );
54
55bool wxTopLevelWindowOS2::m_sbInitialized = false;
56wxWindow* wxTopLevelWindowOS2::m_spHiddenParent = NULL;
f45e4fad 57
47df2b8c
DW
58// ============================================================================
59// wxTopLevelWindowOS2 implementation
60// ============================================================================
61
62BEGIN_EVENT_TABLE(wxTopLevelWindowOS2, wxTopLevelWindowBase)
63 EVT_ACTIVATE(wxTopLevelWindowOS2::OnActivate)
64END_EVENT_TABLE()
65
f45e4fad
DW
66// ============================================================================
67// wxTopLevelWindowMSW implementation
68// ============================================================================
69
70// Dialog window proc
71MRESULT EXPENTRY wxDlgProc( HWND WXUNUSED(hWnd)
72 ,UINT uMessage
9923c37d
DW
73 ,void * WXUNUSED(wParam)
74 ,void * WXUNUSED(lParam)
f45e4fad
DW
75 )
76{
47df2b8c 77 switch(uMessage)
f45e4fad 78 {
47df2b8c
DW
79 case WM_INITDLG:
80 //
81 // For this message, returning TRUE tells system to set focus to
0256cfeb
DW
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
47df2b8c 84 //
0256cfeb 85 return (MRESULT)TRUE;
47df2b8c
DW
86 default:
87 //
88 // For all the other ones, FALSE means that we didn't process the
89 // message
90 //
91 return (MRESULT)FALSE;
f45e4fad
DW
92 }
93} // end of wxDlgProc
94
376ef4a1
DW
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
100class wxTLWHiddenParentModule : public wxModule
101{
102public:
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
114private:
115 //
116 // The HWND of the hidden parent
117 //
743e24aa 118 static HWND m_shWnd;
376ef4a1
DW
119
120 //
121 // The class used to create it
122 //
743e24aa 123 static const wxChar* m_szClassName;
376ef4a1
DW
124 DECLARE_DYNAMIC_CLASS(wxTLWHiddenParentModule)
125}; // end of CLASS wxTLWHiddenParentModule
126
127IMPLEMENT_DYNAMIC_CLASS(wxTLWHiddenParentModule, wxModule)
128
f45e4fad
DW
129// ----------------------------------------------------------------------------
130// wxTopLevelWindowOS2 creation
131// ----------------------------------------------------------------------------
132
133void wxTopLevelWindowOS2::Init()
134{
743e24aa 135 m_bIconized = m_bMaximizeOnShow = false;
f45e4fad
DW
136
137 //
138 // Unlike (almost?) all other windows, frames are created hidden
139 //
743e24aa 140 m_isShown = false;
f45e4fad
DW
141
142 //
143 // Data to save/restore when calling ShowFullScreen
144 m_lFsStyle = 0;
145 m_lFsOldWindowStyle = 0;
743e24aa
WS
146 m_bFsIsMaximized = false;
147 m_bFsIsShowing = false;
f45e4fad
DW
148
149 m_hFrame = NULLHANDLE;
150 memset(&m_vSwp, 0, sizeof(SWP));
151 memset(&m_vSwpClient, 0, sizeof(SWP));
d3b9f782 152 m_pWinLastFocused = NULL;
f45e4fad
DW
153} // end of wxTopLevelWindowIOS2::Init
154
47df2b8c
DW
155void wxTopLevelWindowOS2::OnActivate(
156 wxActivateEvent& rEvent
157)
158{
159 if (rEvent.GetActive())
160 {
161 //
162 // Restore focus to the child which was last focused
163 //
9a83f860 164 wxLogTrace(wxT("focus"), wxT("wxTLW %08lx activated."), m_hWnd);
47df2b8c
DW
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
9a83f860
VZ
202 wxLogTrace(wxT("focus"),
203 wxT("wxTLW %08lx deactivated, last focused: %08lx."),
47df2b8c
DW
204 m_hWnd,
205 m_pWinLastFocused ? GetHwndOf(m_pWinLastFocused)
206 : NULL);
207 rEvent.Skip();
208 }
209} // end of wxTopLevelWindowOS2::OnActivate
210
b9b1d6c8
DW
211WXDWORD wxTopLevelWindowOS2::OS2GetStyle(
212 long lStyle
213, WXDWORD* pdwExflags
f45e4fad
DW
214) const
215{
b9b1d6c8
DW
216 long lMsflags = wxWindow::OS2GetStyle( (lStyle & ~wxBORDER_MASK) | wxBORDER_NONE
217 ,pdwExflags
218 );
f45e4fad 219
76d81b4d 220 if ((lStyle & wxDEFAULT_FRAME_STYLE) == wxDEFAULT_FRAME_STYLE)
b9b1d6c8
DW
221 lMsflags |= FCF_SIZEBORDER | FCF_TITLEBAR | FCF_SYSMENU |
222 FCF_MINMAX | FCF_TASKLIST;
76d81b4d
SN
223
224 if ((lStyle & wxCAPTION) == wxCAPTION)
225 lMsflags |= FCF_TASKLIST;
f45e4fad 226 else
76d81b4d
SN
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;
1c067fe3 237 if (lStyle & wxRESIZE_BORDER)
76d81b4d
SN
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)
f45e4fad 244 {
76d81b4d
SN
245 // Invalid for frame windows under PM
246 }
f45e4fad 247
7282b067 248 if (lStyle & wxTINY_CAPTION)
76d81b4d 249 lMsflags |= FCF_TASKLIST;
f45e4fad 250
1c067fe3 251 if ((lStyle & wxRESIZE_BORDER) == 0)
76d81b4d
SN
252 lMsflags |= FCF_BORDER;
253 if (lStyle & wxFRAME_TOOL_WINDOW)
254 *pdwExflags = kFrameToolWindow;
255
256 if (lStyle & wxSTAY_ON_TOP)
257 lMsflags |= FCF_SYSMODAL;
f45e4fad 258
f45e4fad
DW
259 return lMsflags;
260} // end of wxTopLevelWindowOS2::OS2GetCreateWindowFlags
261
6ed98c6a
DW
262WXHWND wxTopLevelWindowOS2::OS2GetParent() const
263{
376ef4a1
DW
264 HWND hWndParent = NULL;
265
6ed98c6a
DW
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 //
6ed98c6a
DW
272 if (HasFlag(wxFRAME_FLOAT_ON_PARENT) )
273 {
376ef4a1 274 const wxWindow* pParent = GetParent();
6ed98c6a 275
376ef4a1 276 if (!pParent)
6ed98c6a 277 {
6ed98c6a 278 //
376ef4a1 279 // This flag doesn't make sense then and will be ignored
6ed98c6a 280 //
9a83f860 281 wxFAIL_MSG( wxT("wxFRAME_FLOAT_ON_PARENT but no parent?") );
6ed98c6a 282 }
376ef4a1
DW
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();
6ed98c6a 300 }
376ef4a1 301 return (WXHWND)hWndParent;
6ed98c6a
DW
302} // end of wxTopLevelWindowOS2::OS2GetParent
303
6670f564
WS
304
305bool wxTopLevelWindowOS2::CreateDialog( ULONG ulDlgTemplate,
306 const wxString& WXUNUSED(rsTitle),
307 const wxPoint& rPos,
308 const wxSize& rSize )
f45e4fad
DW
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;
1b086de1 338 HWND hWndOwner;
f45e4fad
DW
339
340 if (pParent)
1b086de1 341 hWndOwner = GetHwndOf(pParent);
f45e4fad 342 else
1b086de1 343 hWndOwner = HWND_DESKTOP;
f45e4fad 344
1b086de1
DW
345 hWndDlg = ::WinLoadDlg( HWND_DESKTOP
346 ,hWndOwner
f45e4fad
DW
347 ,(PFNWP)wxDlgProc
348 ,NULL
349 ,(ULONG)ulDlgTemplate
350 ,(PVOID)this
351 );
352
353 m_hWnd = (WXHWND) hWndDlg;
354
355 if ( !m_hWnd )
356 {
7e99eddf 357 wxFAIL_MSG(wxT("Did you forget to include wx/os2/wx.rc in your resources?"));
f45e4fad 358
9923c37d 359 wxLogSysError(wxT("Can't create dialog using template '%ld'"), ulDlgTemplate);
f45e4fad 360
743e24aa 361 return false;
f45e4fad
DW
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 }
ad4e3f7b 409 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
626af800
DW
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 {
743e24aa 419 return false;
626af800 420 }
b3260bce 421
53758b0f
SN
422 // Convert to OS/2 coordinates
423 nY = GetOS2ParentHeight(pParent) - nY - nHeight;
424
f45e4fad
DW
425 ::WinSetWindowPos( GetHwnd()
426 ,HWND_TOP
427 ,nX
428 ,nY
429 ,nWidth
430 ,nHeight
0256cfeb 431 ,SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE
f45e4fad 432 );
859e65de 433 ::WinQueryWindowPos(GetHwnd(), GetSwp());
626af800 434 m_hFrame = m_hWnd;
f45e4fad 435 SubclassWin(m_hWnd);
743e24aa 436 return true;
f45e4fad
DW
437} // end of wxTopLevelWindowOS2::CreateDialog
438
743e24aa
WS
439bool wxTopLevelWindowOS2::CreateFrame( const wxString& rsTitle,
440 const wxPoint& rPos,
441 const wxSize& rSize )
f45e4fad 442{
743e24aa
WS
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;
f45e4fad
DW
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;
743e24aa 472 m_bIconized = false;
f45e4fad
DW
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
932762af
SN
484 ,wxString(wxFrameClassName).c_str() // class name
485 ,rsTitle.c_str() // window title
f45e4fad
DW
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);
9a83f860 495 wxLogError(wxT("Error creating frame. Error: %s\n"), sError.c_str());
743e24aa 496 return false;
f45e4fad
DW
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
ad4e3f7b 507 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
f45e4fad
DW
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);
9a83f860 519 wxLogError(wxT("Error creating frame. Error: %s\n"), sError.c_str());
743e24aa 520 return false;
f45e4fad
DW
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
53758b0f
SN
534 if (!OS2GetCreateWindowCoords( rPos
535 ,rSize
536 ,nX
537 ,nY
538 ,nWidth
539 ,nHeight
540 ))
f45e4fad 541 {
53758b0f 542 nX = nWidth = (int)CW_USEDEFAULT;
f45e4fad 543 }
53758b0f
SN
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)
f45e4fad 552 {
a8988cb3 553 //
53758b0f
SN
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();
f45e4fad 569
53758b0f
SN
570 nX = (vSizeDpy.x - nWidth) / 2;
571 nY = (vSizeDpy.y - nHeight) / 2;
f45e4fad 572 }
53758b0f
SN
573
574 // Convert to OS/2 coordinates
575 nY = GetOS2ParentHeight(pParent) - nY - nHeight;
576
f45e4fad
DW
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);
9a83f860 588 wxLogError(wxT("Error sizing frame. Error: %s\n"), sError.c_str());
743e24aa 589 return false;
f45e4fad 590 }
54ffa107
DW
591 lStyle = ::WinQueryWindowULong( m_hWnd
592 ,QWL_STYLE
593 );
594 lStyle |= WS_CLIPCHILDREN;
595 ::WinSetWindowULong( m_hWnd
596 ,QWL_STYLE
597 ,lStyle
598 );
743e24aa 599 return true;
f45e4fad
DW
600} // end of wxTopLevelWindowOS2::CreateFrame
601
602bool wxTopLevelWindowOS2::Create(
603 wxWindow* pParent
604, wxWindowID vId
605, const wxString& rsTitle
606, const wxPoint& rPos
2d28c41c 607, const wxSize& rSizeOrig
f45e4fad
DW
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;
2d28c41c
SN
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
f45e4fad
DW
632 wxTopLevelWindows.Append(this);
633 if (pParent)
634 pParent->AddChild(this);
635
636 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
637 {
638 //
90e572f1 639 // We have different dialog templates to allow creation of dialogs
d13b34d3
DS
640 // with & without captions under OS2indows, resizable or not (but a
641 // resizable dialog always has caption - otherwise it would look too
f45e4fad
DW
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
667wxTopLevelWindowOS2::~wxTopLevelWindowOS2()
668{
f45e4fad 669 //
a23692f0
DW
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 }
f45e4fad
DW
688} // end of wxTopLevelWindowOS2::~wxTopLevelWindowOS2
689
f45e4fad
DW
690// ----------------------------------------------------------------------------
691// wxTopLevelWindowOS2 client size
692// ----------------------------------------------------------------------------
693
694void 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
712void 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
734void wxTopLevelWindowOS2::DoShowWindow(
735 int nShowCmd
736)
737{
54ffa107 738 ::WinShowWindow(m_hFrame, (BOOL)(nShowCmd & SWP_SHOW));
239c2e96
DW
739
740 //
741 // Need to artificially send a size event as wxApps often expect to do some
742 // final child control sizing
743 SendSizeEvent();
f45e4fad
DW
744 m_bIconized = nShowCmd == SWP_MINIMIZE;
745} // end of wxTopLevelWindowOS2::DoShowWindow
746
743e24aa 747bool wxTopLevelWindowOS2::Show( bool bShow )
f45e4fad 748{
743e24aa
WS
749 int nShowCmd;
750 SWP vSwp;
f45e4fad 751
376ef4a1
DW
752 if (bShow != IsShown() )
753 {
754 m_isShown = bShow;
755 }
756 else
757 {
743e24aa 758 return false;
376ef4a1 759 }
f45e4fad
DW
760 if (bShow)
761 {
762 if (m_bMaximizeOnShow)
763 {
54ffa107 764 nShowCmd = SWP_MAXIMIZE;
743e24aa 765 m_bMaximizeOnShow = false;
f45e4fad
DW
766 }
767 else
768 {
54ffa107 769 nShowCmd = SWP_SHOW;
f45e4fad
DW
770 }
771 }
772 else // hide
773 {
774 nShowCmd = SWP_HIDE;
775 }
776 DoShowWindow(nShowCmd);
777
778 if (bShow)
779 {
743e24aa 780 wxActivateEvent vEvent(wxEVT_ACTIVATE, true, m_windowId);
f45e4fad
DW
781
782 ::WinQueryWindowPos(m_hFrame, &vSwp);
6670f564 783 m_bIconized = ( vSwp.fl & SWP_MINIMIZE ) == SWP_MINIMIZE ;
f45e4fad
DW
784 ::WinQueryWindowPos(m_hWnd, &m_vSwpClient);
785 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
4a46a5df 786 ::WinQueryWindowPos(m_hWnd, &vSwp);
f45e4fad 787 ::WinEnableWindow(m_hFrame, TRUE);
859e65de 788
f45e4fad 789 vEvent.SetEventObject(this);
937013e0 790 HandleWindowEvent(vEvent);
f45e4fad
DW
791 }
792 else
793 {
794 //
795 // Try to highlight the correct window (the parent)
796 //
797 if (GetParent())
798 {
743e24aa 799 HWND hWndParent = GetHwndOf(GetParent());
f45e4fad
DW
800
801 ::WinQueryWindowPos(hWndParent, &vSwp);
6670f564 802 m_bIconized = (vSwp.fl & SWP_MINIMIZE)==SWP_MINIMIZE;
f45e4fad
DW
803 ::WinEnableWindow(hWndParent, TRUE);
804 }
805 }
743e24aa 806 return true;
f45e4fad
DW
807} // end of wxTopLevelWindowOS2::Show
808
809// ----------------------------------------------------------------------------
810// wxTopLevelWindowOS2 maximize/minimize
811// ----------------------------------------------------------------------------
812
813void 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 //
6e348b12 830 m_bMaximizeOnShow = bMaximize;
f45e4fad
DW
831 }
832} // end of wxTopLevelWindowOS2::Maximize
833
834bool wxTopLevelWindowOS2::IsMaximized() const
835{
f45e4fad 836 ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp);
6670f564 837 return (m_vSwp.fl & SWP_MAXIMIZE) == SWP_MAXIMIZE;
f45e4fad
DW
838} // end of wxTopLevelWindowOS2::IsMaximized
839
743e24aa
WS
840void wxTopLevelWindowOS2::SetTitle( const wxString& title)
841{
842 SetLabel(title);
843}
844
845wxString wxTopLevelWindowOS2::GetTitle() const
846{
847 return GetLabel();
848}
849
850void wxTopLevelWindowOS2::Iconize( bool bIconize )
f45e4fad
DW
851{
852 DoShowWindow(bIconize ? SWP_MINIMIZE : SWP_RESTORE);
853} // end of wxTopLevelWindowOS2::Iconize
854
855bool wxTopLevelWindowOS2::IsIconized() const
856{
857 // also update the current state
858 ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp);
859 if (m_vSwp.fl & SWP_MINIMIZE)
743e24aa 860 ((wxTopLevelWindow*)this)->m_bIconized = true;
f45e4fad 861 else
743e24aa 862 ((wxTopLevelWindow*)this)->m_bIconized = false;
f45e4fad
DW
863 return m_bIconized;
864} // end of wxTopLevelWindowOS2::IsIconized
865
866void wxTopLevelWindowOS2::Restore()
867{
868 DoShowWindow(SWP_RESTORE);
869} // end of wxTopLevelWindowOS2::Restore
870
239c2e96 871// generate an artificial resize event
ecdc1183 872void wxTopLevelWindowOS2::SendSizeEvent(int flags)
239c2e96
DW
873{
874 if (!m_bIconized)
875 {
876 RECTL vRect = wxGetWindowRect(GetHwnd());
877
ecdc1183
VZ
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 }
239c2e96
DW
894 }
895} // end of wxTopLevelWindowOS2::SendSizeEvent
896
f45e4fad
DW
897// ----------------------------------------------------------------------------
898// wxTopLevelWindowOS2 fullscreen
899// ----------------------------------------------------------------------------
900
6670f564
WS
901bool wxTopLevelWindowOS2::ShowFullScreen( bool bShow,
902 long lStyle )
f45e4fad
DW
903{
904 if (bShow)
905 {
906 if (IsFullScreen())
6670f564 907 return false;
f45e4fad 908
6670f564 909 m_bFsIsShowing = true;
f45e4fad
DW
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 //
6670f564
WS
932 LONG lNewStyle = m_lFsOldWindowStyle;
933 LONG lOffFlags = 0;
f45e4fad
DW
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 //
6670f564
WS
953 int nWidth;
954 int nHeight;
955 RECTL vRect = wxGetWindowRect(HWND_DESKTOP);
f45e4fad
DW
956
957 nWidth = vRect.xRight - vRect.xLeft;
958 nHeight = vRect.yTop - vRect.yBottom;
959
6670f564 960 SetSize( nWidth, nHeight );
f45e4fad
DW
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
6670f564
WS
974 wxSize full( nWidth, nHeight );
975 wxSizeEvent vEvent( full, GetId() );
937013e0 976 HandleWindowEvent(vEvent);
6670f564 977 return true;
f45e4fad
DW
978 }
979 else
980 {
981 if (!IsFullScreen())
6670f564 982 return false;
f45e4fad 983
6670f564 984 m_bFsIsShowing = false;
f45e4fad
DW
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 );
6670f564 998 return true;
f45e4fad
DW
999 }
1000} // end of wxTopLevelWindowOS2::ShowFullScreen
1001
1002// ----------------------------------------------------------------------------
1003// wxTopLevelWindowOS2 misc
1004// ----------------------------------------------------------------------------
1005
3437f881
DW
1006void wxTopLevelWindowOS2::SetIcons(
1007 const wxIconBundle& rIcons
1008)
f45e4fad
DW
1009{
1010 //
1011 // This sets m_icon
1012 //
3437f881
DW
1013 wxTopLevelWindowBase::SetIcons(rIcons);
1014
f605c258 1015 const wxIcon& vIcon = rIcons.GetIconOfExactSize(32);
f45e4fad 1016
a1b806b9 1017 if (vIcon.IsOk())
f45e4fad
DW
1018 {
1019 ::WinSendMsg( m_hFrame
1020 ,WM_SETICON
3437f881 1021 ,(MPARAM)((HPOINTER)vIcon.GetHICON())
f45e4fad
DW
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
743e24aa 1032bool wxTopLevelWindowOS2::EnableCloseButton( bool bEnable )
f45e4fad
DW
1033{
1034 //
1035 // Get system (a.k.a. window) menu
1036 //
743e24aa 1037 HMENU hMenu = ::WinWindowFromID(m_hFrame, FID_SYSMENU);
f45e4fad
DW
1038
1039 if (!hMenu)
1040 {
9a83f860 1041 wxLogLastError(wxT("GetSystemMenu"));
743e24aa 1042 return false;
f45e4fad
DW
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 );
743e24aa 1070 return true;
f45e4fad
DW
1071} // end of wxTopLevelWindowOS2::EnableCloseButton
1072
376ef4a1
DW
1073// ============================================================================
1074// wxTLWHiddenParentModule implementation
1075// ============================================================================
1076
1077HWND wxTLWHiddenParentModule::m_shWnd = NULL;
1078const wxChar* wxTLWHiddenParentModule::m_szClassName = NULL;
1079
1080bool wxTLWHiddenParentModule::OnInit()
1081{
1082 m_shWnd = NULL;
1083 m_szClassName = NULL;
743e24aa 1084 return true;
376ef4a1
DW
1085} // end of wxTLWHiddenParentModule::OnInit
1086
1087void wxTLWHiddenParentModule::OnExit()
1088{
1089 if (m_shWnd)
1090 {
1091 if (!::WinDestroyWindow(m_shWnd))
1092 {
9a83f860 1093 wxLogLastError(wxT("DestroyWindow(hidden TLW parent)"));
376ef4a1
DW
1094 }
1095 m_shWnd = NULL;
1096 }
1097
1098 m_szClassName = NULL;
1099} // end of wxTLWHiddenParentModule::OnExit
1100
1101/* static */
1102HWND wxTLWHiddenParentModule::GetHWND()
1103{
1104 if (!m_shWnd)
1105 {
1106 if (!m_szClassName)
1107 {
9a83f860 1108 static const wxChar* zHIDDEN_PARENT_CLASS = wxT("wxTLWHiddenParent");
376ef4a1
DW
1109
1110 if (!::WinRegisterClass( wxGetInstance()
0fba44b4 1111 ,(PSZ)zHIDDEN_PARENT_CLASS
376ef4a1
DW
1112 ,NULL
1113 ,0
1114 ,sizeof(ULONG)
1115 ))
1116 {
9a83f860 1117 wxLogLastError(wxT("RegisterClass(\"wxTLWHiddenParent\")"));
376ef4a1
DW
1118 }
1119 else
1120 {
1121 m_szClassName = zHIDDEN_PARENT_CLASS;
1122 }
1123 }
743e24aa
WS
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 );
376ef4a1
DW
1137 if (!m_shWnd)
1138 {
9a83f860 1139 wxLogLastError(wxT("CreateWindow(hidden TLW parent)"));
376ef4a1
DW
1140 }
1141 }
1142 return m_shWnd;
1143} // end of wxTLWHiddenParentModule::GetHWND