]> git.saurik.com Git - wxWidgets.git/blob - src/msw/toplevel.cpp
changed/centralized window creation code to allow wxTLW work in wxUniv
[wxWidgets.git] / src / msw / toplevel.cpp
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
32 #include "wx/app.h"
33 #include "wx/toplevel.h"
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
47 static inline bool IsIconic(HWND WXUNUSED(hwnd)) { return FALSE; }
48 static 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
57 wxWindowList wxModelessWindows;
58
59 // the name of the default wxWindows class
60 extern const wxChar *wxCanvasClassName;
61
62 // ============================================================================
63 // wxTopLevelWindowMSW implementation
64 // ============================================================================
65
66 // Dialog window proc
67 LONG APIENTRY _EXPORT
68 wxDlgProc(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
84 // ----------------------------------------------------------------------------
85 // wxTopLevelWindowMSW creation
86 // ----------------------------------------------------------------------------
87
88 void wxTopLevelWindowMSW::Init()
89 {
90 m_iconized =
91 m_maximizeOnShow = FALSE;
92
93 // unlike (almost?) all other windows, frames are created hidden
94 m_isShown = FALSE;
95 }
96
97 long 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
171 bool 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
258 bool 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);
266 }
267
268 bool 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
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 }
319 }
320
321 wxTopLevelWindowMSW::~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
344 void 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
380 void wxTopLevelWindowMSW::DoShowWindow(int nShowCmd)
381 {
382 ::ShowWindow(GetHwnd(), nShowCmd);
383
384 m_iconized = nShowCmd == SW_MINIMIZE;
385 }
386
387 bool 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
441 void 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
456 bool wxTopLevelWindowMSW::IsMaximized() const
457 {
458 return ::IsZoomed(GetHwnd()) != 0;
459 }
460
461 void wxTopLevelWindowMSW::Iconize(bool iconize)
462 {
463 DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE);
464 }
465
466 bool 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
474 void wxTopLevelWindowMSW::Restore()
475 {
476 DoShowWindow(SW_RESTORE);
477 }
478
479 // ----------------------------------------------------------------------------
480 // wxTopLevelWindowMSW misc
481 // ----------------------------------------------------------------------------
482
483 void 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 }