1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/toplevel.cpp
3 // Purpose: implements wxTopLevelWindow for MSW
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
9 // License: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "toplevel.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
33 #include "wx/toplevel.h"
34 #include "wx/string.h"
40 #include "wx/msw/private.h"
42 // ----------------------------------------------------------------------------
43 // stubs for missing functions under MicroWindows
44 // ----------------------------------------------------------------------------
48 static inline bool IsIconic(HWND
WXUNUSED(hwnd
)) { return FALSE
; }
49 static inline bool IsZoomed(HWND
WXUNUSED(hwnd
)) { return FALSE
; }
51 #endif // __WXMICROWIN__
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 // list of all frames and modeless dialogs
58 wxWindowList wxModelessWindows
;
60 // the name of the default wxWindows class
61 extern const wxChar
*wxCanvasClassName
;
63 // ============================================================================
64 // wxTopLevelWindowMSW implementation
65 // ============================================================================
69 wxDlgProc(HWND
WXUNUSED(hWnd
), UINT message
, WPARAM
WXUNUSED(wParam
), LPARAM
WXUNUSED(lParam
))
71 if ( message
== WM_INITDIALOG
)
73 // for this message, returning TRUE tells system to set focus to the
74 // first control in the dialog box
79 // for all the other ones, FALSE means that we didn't process the
85 // ----------------------------------------------------------------------------
86 // wxTopLevelWindowMSW creation
87 // ----------------------------------------------------------------------------
89 void wxTopLevelWindowMSW::Init()
92 m_maximizeOnShow
= FALSE
;
94 // unlike (almost?) all other windows, frames are created hidden
98 long wxTopLevelWindowMSW::MSWGetCreateWindowFlags(long *exflags
) const
100 long style
= GetWindowStyle();
103 // first select the kind of window being created
104 if ( style
& wxCAPTION
)
106 if ( style
& wxFRAME_TOOL_WINDOW
)
107 msflags
|= WS_POPUPWINDOW
;
109 msflags
|= WS_OVERLAPPED
;
116 // next translate the individual flags
117 if ( style
& wxMINIMIZE_BOX
)
118 msflags
|= WS_MINIMIZEBOX
;
119 if ( style
& wxMAXIMIZE_BOX
)
120 msflags
|= WS_MAXIMIZEBOX
;
121 if ( style
& wxTHICK_FRAME
)
122 msflags
|= WS_THICKFRAME
;
123 if ( style
& wxSYSTEM_MENU
)
124 msflags
|= WS_SYSMENU
;
125 if ( style
& wxMINIMIZE
)
126 msflags
|= WS_MINIMIZE
;
127 if ( style
& wxMAXIMIZE
)
128 msflags
|= WS_MAXIMIZE
;
129 if ( style
& wxCAPTION
)
130 msflags
|= WS_CAPTION
;
131 if ( style
& wxCLIP_CHILDREN
)
132 msflags
|= WS_CLIPCHILDREN
;
134 // Keep this here because it saves recoding this function in wxTinyFrame
135 #if wxUSE_ITSY_BITSY && !defined(__WIN32__)
136 if ( style
& wxTINY_CAPTION_VERT
)
137 msflags
|= IBS_VERTCAPTION
;
138 if ( style
& wxTINY_CAPTION_HORIZ
)
139 msflags
|= IBS_HORZCAPTION
;
141 if ( style
& (wxTINY_CAPTION_VERT
| wxTINY_CAPTION_HORIZ
) )
142 msflags
|= WS_CAPTION
;
147 *exflags
= MakeExtendedStyle(style
);
149 // make all frames appear in the win9x shell taskbar unless
150 // wxFRAME_TOOL_WINDOW or wxFRAME_NO_TASKBAR is given - without giving
151 // them WS_EX_APPWINDOW style, the child (i.e. owned) frames wouldn't
153 #if !defined(__WIN16__) && !defined(__SC__)
154 if ( (style
& wxFRAME_TOOL_WINDOW
) || (style
& wxFRAME_NO_TASKBAR
) )
155 *exflags
|= WS_EX_TOOLWINDOW
;
156 else if ( !(style
& wxFRAME_NO_TASKBAR
) )
157 *exflags
|= WS_EX_APPWINDOW
;
160 if ( style
& wxSTAY_ON_TOP
)
161 *exflags
|= WS_EX_TOPMOST
;
164 if ( m_exStyle
& wxFRAME_EX_CONTEXTHELP
)
165 *exflags
|= WS_EX_CONTEXTHELP
;
172 bool wxTopLevelWindowMSW::CreateDialog(const wxChar
*dlgTemplate
,
173 const wxString
& title
,
177 #ifdef __WXMICROWIN__
178 // no dialogs support under MicroWin yet
179 return CreateFrame(title
, pos
, size
);
180 #else // !__WXMICROWIN__
181 wxWindow
*parent
= GetParent();
183 // for the dialogs without wxDIALOG_NO_PARENT style, use the top level
184 // app window as parent - this avoids creating modal dialogs without
186 if ( !parent
&& !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT
) )
188 parent
= wxTheApp
->GetTopWindow();
191 m_hWnd
= (WXHWND
)::CreateDialog(wxGetInstance(),
193 parent
? GetHwndOf(parent
) : NULL
,
198 wxFAIL_MSG(_("Did you forget to include wx/msw/wx.rc in your resources?"));
200 wxLogSysError(_("Can't create dialog using template '%s'"), dlgTemplate
);
206 (void)MSWGetCreateWindowFlags(&exflags
);
210 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exflags
);
211 ::SetWindowPos(GetHwnd(), NULL
, 0, 0, 0, 0,
218 #if defined(__WIN95__)
219 // For some reason, the system menu is activated when we use the
220 // WS_EX_CONTEXTHELP style, so let's set a reasonable icon
221 if ( exflags
& WS_EX_CONTEXTHELP
)
223 wxFrame
*winTop
= wxDynamicCast(wxTheApp
->GetTopWindow(), wxFrame
);
226 wxIcon icon
= winTop
->GetIcon();
229 ::SendMessage(GetHwnd(), WM_SETICON
,
231 (LPARAM
)GetHiconOf(icon
));
237 // move the dialog to its initial position without forcing repainting
239 if ( MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
) )
241 if ( !::MoveWindow(GetHwnd(), x
, y
, w
, h
, FALSE
) )
243 wxLogLastError(wxT("MoveWindow"));
246 //else: leave it at default position
248 if ( !title
.empty() )
250 ::SetWindowText(GetHwnd(), title
);
256 #endif // __WXMICROWIN__/!__WXMICROWIN__
259 bool wxTopLevelWindowMSW::CreateFrame(const wxString
& title
,
264 long flags
= MSWGetCreateWindowFlags(&exflags
);
266 return MSWCreate(wxCanvasClassName
, title
, pos
, size
, flags
, exflags
);
269 bool wxTopLevelWindowMSW::Create(wxWindow
*parent
,
271 const wxString
& title
,
275 const wxString
& name
)
280 m_windowStyle
= style
;
284 m_windowId
= id
== -1 ? NewControlId() : id
;
286 wxTopLevelWindows
.Append(this);
289 parent
->AddChild(this);
291 if ( GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
293 // TODO: it would be better to construct the dialog template in memory
294 // during run-time than to rely on the limited number of
295 // templates in wx.rc because:
296 // a) you wouldn't have to include wx.rc in all wxWin programs
297 // (and the number of complaints about it would dtop)
298 // b) we'd be able to provide more templates simply, i.e.
299 // we could generate the templates for all style
302 // we have different dialog templates to allows creation of dialogs
303 // with & without captions under MSWindows, resizeable or not (but a
304 // resizeable dialog always has caption - otherwise it would look too
306 const wxChar
*dlgTemplate
;
307 if ( style
& wxRESIZE_BORDER
)
308 dlgTemplate
= wxT("wxResizeableDialog");
309 else if ( style
& wxCAPTION
)
310 dlgTemplate
= wxT("wxCaptionDialog");
312 dlgTemplate
= wxT("wxNoCaptionDialog");
314 return CreateDialog(dlgTemplate
, title
, pos
, size
);
318 return CreateFrame(title
, pos
, size
);
322 wxTopLevelWindowMSW::~wxTopLevelWindowMSW()
324 wxTopLevelWindows
.DeleteObject(this);
326 if ( wxModelessWindows
.Find(this) )
327 wxModelessWindows
.DeleteObject(this);
329 // If this is the last top-level window, exit.
330 if ( wxTheApp
&& (wxTopLevelWindows
.Number() == 0) )
332 wxTheApp
->SetTopWindow(NULL
);
334 if ( wxTheApp
->GetExitOnFrameDelete() )
336 ::PostQuitMessage(0);
341 // ----------------------------------------------------------------------------
342 // wxTopLevelWindowMSW geometry
343 // ----------------------------------------------------------------------------
345 void wxTopLevelWindowMSW::DoSetClientSize(int width
, int height
)
347 HWND hWnd
= GetHwnd();
350 ::GetClientRect(hWnd
, &rectClient
);
353 ::GetWindowRect(hWnd
, &rectTotal
);
355 // Find the difference between the entire window (title bar and all)
356 // and the client area; add this to the new client size to move the
358 width
+= rectTotal
.right
- rectTotal
.left
- rectClient
.right
;
359 height
+= rectTotal
.bottom
- rectTotal
.top
- rectClient
.bottom
;
361 // note that calling GetClientAreaOrigin() takes the toolbar into account
362 wxPoint pt
= GetClientAreaOrigin();
366 if ( !::MoveWindow(hWnd
, rectTotal
.left
, rectTotal
.top
,
367 width
, height
, TRUE
/* redraw */) )
369 wxLogLastError(_T("MoveWindow"));
372 wxSizeEvent
event(wxSize(width
, height
), m_windowId
);
373 event
.SetEventObject(this);
374 (void)GetEventHandler()->ProcessEvent(event
);
377 // ----------------------------------------------------------------------------
378 // wxTopLevelWindowMSW showing
379 // ----------------------------------------------------------------------------
381 void wxTopLevelWindowMSW::DoShowWindow(int nShowCmd
)
383 ::ShowWindow(GetHwnd(), nShowCmd
);
385 m_iconized
= nShowCmd
== SW_MINIMIZE
;
388 bool wxTopLevelWindowMSW::Show(bool show
)
390 // don't use wxWindow version as we want to call DoShowWindow() ourselves
391 if ( !wxWindowBase::Show(show
) )
397 if ( m_maximizeOnShow
)
400 nShowCmd
= SW_MAXIMIZE
;
402 m_maximizeOnShow
= FALSE
;
414 DoShowWindow(nShowCmd
);
418 ::BringWindowToTop(GetHwnd());
420 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, m_windowId
);
421 event
.SetEventObject( this );
422 GetEventHandler()->ProcessEvent(event
);
426 // Try to highlight the correct window (the parent)
429 HWND hWndParent
= GetHwndOf(GetParent());
431 ::BringWindowToTop(hWndParent
);
438 // ----------------------------------------------------------------------------
439 // wxTopLevelWindowMSW maximize/minimize
440 // ----------------------------------------------------------------------------
442 void wxTopLevelWindowMSW::Maximize(bool maximize
)
446 // just maximize it directly
447 DoShowWindow(maximize
? SW_MAXIMIZE
: SW_RESTORE
);
451 // we can't maximize the hidden frame because it shows it as well, so
452 // just remember that we should do it later in this case
453 m_maximizeOnShow
= TRUE
;
457 bool wxTopLevelWindowMSW::IsMaximized() const
459 return ::IsZoomed(GetHwnd()) != 0;
462 void wxTopLevelWindowMSW::Iconize(bool iconize
)
464 DoShowWindow(iconize
? SW_MINIMIZE
: SW_RESTORE
);
467 bool wxTopLevelWindowMSW::IsIconized() const
469 // also update the current state
470 ((wxTopLevelWindowMSW
*)this)->m_iconized
= ::IsIconic(GetHwnd()) != 0;
475 void wxTopLevelWindowMSW::Restore()
477 DoShowWindow(SW_RESTORE
);
480 // ----------------------------------------------------------------------------
481 // wxTopLevelWindowMSW misc
482 // ----------------------------------------------------------------------------
484 void wxTopLevelWindowMSW::SetIcon(const wxIcon
& icon
)
487 wxTopLevelWindowBase::SetIcon(icon
);
489 #if defined(__WIN95__) && !defined(__WXMICROWIN__)
492 ::SendMessage(GetHwnd(), WM_SETICON
,
493 (WPARAM
)TRUE
, (LPARAM
)GetHiconOf(m_icon
));