]> git.saurik.com Git - wxWidgets.git/blame - src/msw/toplevel.cpp
mention wx[Flex]GridSizer too
[wxWidgets.git] / src / msw / toplevel.cpp
CommitLineData
82c9f85c
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: msw/toplevel.cpp
3// Purpose: implements wxTopLevelWindow for MSW
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 24.09.01
7// RCS-ID: $Id$
8// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
9// License: wxWindows license
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
3a922bb4
RL
32 #include "wx/app.h"
33 #include "wx/toplevel.h"
82c9f85c
VZ
34 #include "wx/string.h"
35 #include "wx/log.h"
36 #include "wx/intl.h"
37#endif //WX_PRECOMP
38
39#include "wx/msw/private.h"
40
41// ----------------------------------------------------------------------------
42// stubs for missing functions under MicroWindows
43// ----------------------------------------------------------------------------
44
45#ifdef __WXMICROWIN__
46
47static inline bool IsIconic(HWND WXUNUSED(hwnd)) { return FALSE; }
48static inline bool IsZoomed(HWND WXUNUSED(hwnd)) { return FALSE; }
49
50#endif // __WXMICROWIN__
51
52// ----------------------------------------------------------------------------
53// globals
54// ----------------------------------------------------------------------------
55
56// list of all frames and modeless dialogs
57wxWindowList wxModelessWindows;
58
b225f659
VZ
59// the name of the default wxWindows class
60extern const wxChar *wxCanvasClassName;
61
82c9f85c
VZ
62// ============================================================================
63// wxTopLevelWindowMSW implementation
64// ============================================================================
65
b225f659
VZ
66// Dialog window proc
67LONG APIENTRY _EXPORT
68wxDlgProc(HWND WXUNUSED(hWnd), UINT message, WPARAM WXUNUSED(wParam), LPARAM WXUNUSED(lParam))
69{
70 if ( message == WM_INITDIALOG )
71 {
72 // for this message, returning TRUE tells system to set focus to the
73 // first control in the dialog box
74 return TRUE;
75 }
76 else
77 {
78 // for all the other ones, FALSE means that we didn't process the
79 // message
80 return FALSE;
81 }
82}
83
82c9f85c
VZ
84// ----------------------------------------------------------------------------
85// wxTopLevelWindowMSW creation
86// ----------------------------------------------------------------------------
87
88void wxTopLevelWindowMSW::Init()
89{
90 m_iconized =
91 m_maximizeOnShow = FALSE;
b225f659
VZ
92
93 // unlike (almost?) all other windows, frames are created hidden
94 m_isShown = FALSE;
95}
96
97long wxTopLevelWindowMSW::MSWGetCreateWindowFlags(long *exflags) const
98{
99 long style = GetWindowStyle();
100 long msflags = 0;
101
102 // first select the kind of window being created
103 if ( style & wxCAPTION )
104 {
105 if ( style & wxFRAME_TOOL_WINDOW )
106 msflags |= WS_POPUPWINDOW;
107 else
108 msflags |= WS_OVERLAPPED;
109 }
110 else
111 {
112 msflags |= WS_POPUP;
113 }
114
115 // next translate the individual flags
116 if ( style & wxMINIMIZE_BOX )
117 msflags |= WS_MINIMIZEBOX;
118 if ( style & wxMAXIMIZE_BOX )
119 msflags |= WS_MAXIMIZEBOX;
120 if ( style & wxTHICK_FRAME )
121 msflags |= WS_THICKFRAME;
122 if ( style & wxSYSTEM_MENU )
123 msflags |= WS_SYSMENU;
124 if ( style & wxMINIMIZE )
125 msflags |= WS_MINIMIZE;
126 if ( style & wxMAXIMIZE )
127 msflags |= WS_MAXIMIZE;
128 if ( style & wxCAPTION )
129 msflags |= WS_CAPTION;
130 if ( style & wxCLIP_CHILDREN )
131 msflags |= WS_CLIPCHILDREN;
132
133 // Keep this here because it saves recoding this function in wxTinyFrame
134#if wxUSE_ITSY_BITSY && !defined(__WIN32__)
135 if ( style & wxTINY_CAPTION_VERT )
136 msflags |= IBS_VERTCAPTION;
137 if ( style & wxTINY_CAPTION_HORIZ )
138 msflags |= IBS_HORZCAPTION;
139#else
140 if ( style & (wxTINY_CAPTION_VERT | wxTINY_CAPTION_HORIZ) )
141 msflags |= WS_CAPTION;
142#endif
143
144 if ( exflags )
145 {
146 *exflags = MakeExtendedStyle(style);
147
148 // make all frames appear in the win9x shell taskbar unless
149 // wxFRAME_TOOL_WINDOW or wxFRAME_NO_TASKBAR is given - without giving
150 // them WS_EX_APPWINDOW style, the child (i.e. owned) frames wouldn't
151 // appear in it
152#if !defined(__WIN16__) && !defined(__SC__)
153 if ( (style & wxFRAME_TOOL_WINDOW) || (style & wxFRAME_NO_TASKBAR) )
154 *exflags |= WS_EX_TOOLWINDOW;
155 else if ( !(style & wxFRAME_NO_TASKBAR) )
156 *exflags |= WS_EX_APPWINDOW;
157#endif
158
159 if ( style & wxSTAY_ON_TOP )
160 *exflags |= WS_EX_TOPMOST;
161
162#ifdef __WIN32__
163 if ( m_exStyle & wxFRAME_EX_CONTEXTHELP )
164 *exflags |= WS_EX_CONTEXTHELP;
165#endif // __WIN32__
166 }
167
168 return msflags;
169}
170
171bool wxTopLevelWindowMSW::CreateDialog(const wxChar *dlgTemplate,
172 const wxString& title,
173 const wxPoint& pos,
174 const wxSize& size)
175{
176#ifdef __WXMICROWIN__
177 // no dialogs support under MicroWin yet
178 return CreateFrame(title, pos, size);
179#else // !__WXMICROWIN__
180 wxWindow *parent = GetParent();
181
182 // for the dialogs without wxDIALOG_NO_PARENT style, use the top level
183 // app window as parent - this avoids creating modal dialogs without
184 // parent
185 if ( !parent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) )
186 {
187 parent = wxTheApp->GetTopWindow();
188 }
189
190 m_hWnd = (WXHWND)::CreateDialog(wxGetInstance(),
191 dlgTemplate,
192 parent ? GetHwndOf(parent) : NULL,
193 (DLGPROC)wxDlgProc);
194
195 if ( !m_hWnd )
196 {
197 wxFAIL_MSG(_("Did you forget to include wx/msw/wx.rc in your resources?"));
198
199 wxLogSysError(_("Can't create dialog using template '%s'"), dlgTemplate);
200
201 return FALSE;
202 }
203
204 long exflags;
205 (void)MSWGetCreateWindowFlags(&exflags);
206
207 if ( exflags )
208 {
209 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exflags);
210 ::SetWindowPos(GetHwnd(), NULL, 0, 0, 0, 0,
211 SWP_NOSIZE |
212 SWP_NOMOVE |
213 SWP_NOZORDER |
214 SWP_NOACTIVATE);
215 }
216
217#if defined(__WIN95__)
218 // For some reason, the system menu is activated when we use the
219 // WS_EX_CONTEXTHELP style, so let's set a reasonable icon
220 if ( exflags & WS_EX_CONTEXTHELP )
221 {
222 wxFrame *winTop = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
223 if ( winTop )
224 {
225 wxIcon icon = winTop->GetIcon();
226 if ( icon.Ok() )
227 {
228 ::SendMessage(GetHwnd(), WM_SETICON,
229 (WPARAM)TRUE,
230 (LPARAM)GetHiconOf(icon));
231 }
232 }
233 }
234#endif // __WIN95__
235
236 // move the dialog to its initial position without forcing repainting
237 int x, y, w, h;
238 if ( MSWGetCreateWindowCoords(pos, size, x, y, w, h) )
239 {
240 if ( !::MoveWindow(GetHwnd(), x, y, w, h, FALSE) )
241 {
242 wxLogLastError(wxT("MoveWindow"));
243 }
244 }
245 //else: leave it at default position
246
247 if ( !title.empty() )
248 {
249 ::SetWindowText(GetHwnd(), title);
250 }
251
252 SubclassWin(m_hWnd);
253
254 return TRUE;
255#endif // __WXMICROWIN__/!__WXMICROWIN__
256}
257
258bool wxTopLevelWindowMSW::CreateFrame(const wxString& title,
259 const wxPoint& pos,
260 const wxSize& size)
261{
262 long exflags;
263 long flags = MSWGetCreateWindowFlags(&exflags);
264
265 return MSWCreate(wxCanvasClassName, title, pos, size, flags, exflags);
82c9f85c
VZ
266}
267
268bool wxTopLevelWindowMSW::Create(wxWindow *parent,
269 wxWindowID id,
270 const wxString& title,
271 const wxPoint& pos,
272 const wxSize& size,
273 long style,
274 const wxString& name)
275{
276 // init our fields
277 Init();
278
279 m_windowStyle = style;
280
281 SetName(name);
282
283 m_windowId = id == -1 ? NewControlId() : id;
284
285 wxTopLevelWindows.Append(this);
286
287 if ( parent )
288 parent->AddChild(this);
289
b225f659
VZ
290 if ( GetExtraStyle() & wxTOPLEVEL_EX_DIALOG )
291 {
292 // TODO: it would be better to construct the dialog template in memory
293 // during run-time than to rely on the limited number of
294 // templates in wx.rc because:
295 // a) you wouldn't have to include wx.rc in all wxWin programs
296 // (and the number of complaints about it would dtop)
297 // b) we'd be able to provide more templates simply, i.e.
298 // we could generate the templates for all style
299 // combinations
300
301 // we have different dialog templates to allows creation of dialogs
302 // with & without captions under MSWindows, resizeable or not (but a
303 // resizeable dialog always has caption - otherwise it would look too
304 // strange)
305 const wxChar *dlgTemplate;
306 if ( style & wxRESIZE_BORDER )
307 dlgTemplate = wxT("wxResizeableDialog");
308 else if ( style & wxCAPTION )
309 dlgTemplate = wxT("wxCaptionDialog");
310 else
311 dlgTemplate = wxT("wxNoCaptionDialog");
312
313 return CreateDialog(dlgTemplate, title, pos, size);
314 }
315 else // !dialog
316 {
317 return CreateFrame(title, pos, size);
318 }
82c9f85c
VZ
319}
320
321wxTopLevelWindowMSW::~wxTopLevelWindowMSW()
322{
323 wxTopLevelWindows.DeleteObject(this);
324
325 if ( wxModelessWindows.Find(this) )
326 wxModelessWindows.DeleteObject(this);
327
328 // If this is the last top-level window, exit.
329 if ( wxTheApp && (wxTopLevelWindows.Number() == 0) )
330 {
331 wxTheApp->SetTopWindow(NULL);
332
333 if ( wxTheApp->GetExitOnFrameDelete() )
334 {
335 ::PostQuitMessage(0);
336 }
337 }
338}
339
340// ----------------------------------------------------------------------------
341// wxTopLevelWindowMSW geometry
342// ----------------------------------------------------------------------------
343
344void wxTopLevelWindowMSW::DoSetClientSize(int width, int height)
345{
346 HWND hWnd = GetHwnd();
347
348 RECT rectClient;
349 ::GetClientRect(hWnd, &rectClient);
350
351 RECT rectTotal;
352 ::GetWindowRect(hWnd, &rectTotal);
353
354 // Find the difference between the entire window (title bar and all)
355 // and the client area; add this to the new client size to move the
356 // window
357 width += rectTotal.right - rectTotal.left - rectClient.right;
358 height += rectTotal.bottom - rectTotal.top - rectClient.bottom;
359
360 // note that calling GetClientAreaOrigin() takes the toolbar into account
361 wxPoint pt = GetClientAreaOrigin();
362 width += pt.x;
363 height += pt.y;
364
365 if ( !::MoveWindow(hWnd, rectTotal.left, rectTotal.top,
366 width, height, TRUE /* redraw */) )
367 {
368 wxLogLastError(_T("MoveWindow"));
369 }
370
371 wxSizeEvent event(wxSize(width, height), m_windowId);
372 event.SetEventObject(this);
373 (void)GetEventHandler()->ProcessEvent(event);
374}
375
376// ----------------------------------------------------------------------------
377// wxTopLevelWindowMSW showing
378// ----------------------------------------------------------------------------
379
380void wxTopLevelWindowMSW::DoShowWindow(int nShowCmd)
381{
382 ::ShowWindow(GetHwnd(), nShowCmd);
383
384 m_iconized = nShowCmd == SW_MINIMIZE;
385}
386
387bool wxTopLevelWindowMSW::Show(bool show)
388{
389 // don't use wxWindow version as we want to call DoShowWindow() ourselves
390 if ( !wxWindowBase::Show(show) )
391 return FALSE;
392
393 int nShowCmd;
394 if ( show )
395 {
396 if ( m_maximizeOnShow )
397 {
398 // show and maximize
399 nShowCmd = SW_MAXIMIZE;
400
401 m_maximizeOnShow = FALSE;
402 }
403 else // just show
404 {
405 nShowCmd = SW_SHOW;
406 }
407 }
408 else // hide
409 {
410 nShowCmd = SW_HIDE;
411 }
412
413 DoShowWindow(nShowCmd);
414
415 if ( show )
416 {
417 ::BringWindowToTop(GetHwnd());
418
419 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_windowId);
420 event.SetEventObject( this );
421 GetEventHandler()->ProcessEvent(event);
422 }
423 else // hide
424 {
425 // Try to highlight the correct window (the parent)
426 if ( GetParent() )
427 {
428 HWND hWndParent = GetHwndOf(GetParent());
429 if (hWndParent)
430 ::BringWindowToTop(hWndParent);
431 }
432 }
433
434 return TRUE;
435}
436
437// ----------------------------------------------------------------------------
438// wxTopLevelWindowMSW maximize/minimize
439// ----------------------------------------------------------------------------
440
441void wxTopLevelWindowMSW::Maximize(bool maximize)
442{
443 if ( IsShown() )
444 {
445 // just maximize it directly
446 DoShowWindow(maximize ? SW_MAXIMIZE : SW_RESTORE);
447 }
448 else // hidden
449 {
450 // we can't maximize the hidden frame because it shows it as well, so
451 // just remember that we should do it later in this case
452 m_maximizeOnShow = TRUE;
453 }
454}
455
456bool wxTopLevelWindowMSW::IsMaximized() const
457{
458 return ::IsZoomed(GetHwnd()) != 0;
459}
460
461void wxTopLevelWindowMSW::Iconize(bool iconize)
462{
463 DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE);
464}
465
466bool wxTopLevelWindowMSW::IsIconized() const
467{
468 // also update the current state
469 ((wxTopLevelWindowMSW *)this)->m_iconized = ::IsIconic(GetHwnd()) != 0;
470
471 return m_iconized;
472}
473
474void wxTopLevelWindowMSW::Restore()
475{
476 DoShowWindow(SW_RESTORE);
477}
478
479// ----------------------------------------------------------------------------
480// wxTopLevelWindowMSW misc
481// ----------------------------------------------------------------------------
482
483void wxTopLevelWindowMSW::SetIcon(const wxIcon& icon)
484{
485 // this sets m_icon
486 wxTopLevelWindowBase::SetIcon(icon);
487
488#if defined(__WIN95__) && !defined(__WXMICROWIN__)
489 if ( m_icon.Ok() )
490 {
491 ::SendMessage(GetHwnd(), WM_SETICON,
492 (WPARAM)TRUE, (LPARAM)GetHiconOf(m_icon));
493 }
494#endif // __WIN95__
495}