Added #include for non PCH compilers
[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 licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
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/dialog.h"
35 #include "wx/string.h"
36 #include "wx/log.h"
37 #include "wx/intl.h"
38 #include "wx/frame.h"
39 #include "wx/containr.h" // wxSetFocusToChild()
40 #endif //WX_PRECOMP
41
42 #include "wx/module.h"
43
44 #include "wx/msw/private.h"
45 #if defined(__WXWINCE__)
46 #include <ole2.h>
47 #include <shellapi.h>
48 #if _WIN32_WCE < 400
49 #include <aygshell.h>
50 #endif
51 #include "wx/msw/wince/missing.h"
52 #endif
53
54 #include "wx/msw/missing.h"
55 #include "wx/msw/winundef.h"
56
57 #include "wx/display.h"
58
59 #ifndef ICON_BIG
60 #define ICON_BIG 1
61 #endif
62
63 #ifndef ICON_SMALL
64 #define ICON_SMALL 0
65 #endif
66
67 // ----------------------------------------------------------------------------
68 // stubs for missing functions under MicroWindows
69 // ----------------------------------------------------------------------------
70
71 #ifdef __WXMICROWIN__
72
73 // static inline bool IsIconic(HWND WXUNUSED(hwnd)) { return FALSE; }
74 static inline bool IsZoomed(HWND WXUNUSED(hwnd)) { return FALSE; }
75
76 #endif // __WXMICROWIN__
77
78 // NB: wxDlgProc must be defined here and not in dialog.cpp because the latter
79 // is not included by wxUniv build which does need wxDlgProc
80 LONG APIENTRY _EXPORT
81 wxDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
82
83 // ----------------------------------------------------------------------------
84 // globals
85 // ----------------------------------------------------------------------------
86
87 // list of all frames and modeless dialogs
88 wxWindowList wxModelessWindows;
89
90 // the name of the default wxWindows class
91 extern const wxChar *wxCanvasClassName;
92
93 // ----------------------------------------------------------------------------
94 // wxTLWHiddenParentModule: used to manage the hidden parent window (we need a
95 // module to ensure that the window is always deleted)
96 // ----------------------------------------------------------------------------
97
98 class wxTLWHiddenParentModule : public wxModule
99 {
100 public:
101 // module init/finalize
102 virtual bool OnInit();
103 virtual void OnExit();
104
105 // get the hidden window (creates on demand)
106 static HWND GetHWND();
107
108 private:
109 // the HWND of the hidden parent
110 static HWND ms_hwnd;
111
112 // the class used to create it
113 static const wxChar *ms_className;
114
115 DECLARE_DYNAMIC_CLASS(wxTLWHiddenParentModule)
116 };
117
118 IMPLEMENT_DYNAMIC_CLASS(wxTLWHiddenParentModule, wxModule)
119
120 // ============================================================================
121 // wxTopLevelWindowMSW implementation
122 // ============================================================================
123
124 BEGIN_EVENT_TABLE(wxTopLevelWindowMSW, wxTopLevelWindowBase)
125 EVT_ACTIVATE(wxTopLevelWindowMSW::OnActivate)
126 END_EVENT_TABLE()
127
128 // ----------------------------------------------------------------------------
129 // wxTopLevelWindowMSW creation
130 // ----------------------------------------------------------------------------
131
132 void wxTopLevelWindowMSW::Init()
133 {
134 m_iconized =
135 m_maximizeOnShow = FALSE;
136
137 // Data to save/restore when calling ShowFullScreen
138 m_fsStyle = 0;
139 m_fsOldWindowStyle = 0;
140 m_fsIsMaximized = FALSE;
141 m_fsIsShowing = FALSE;
142
143 m_winLastFocused = (wxWindow *)NULL;
144 }
145
146 WXDWORD wxTopLevelWindowMSW::MSWGetStyle(long style, WXDWORD *exflags) const
147 {
148 // let the base class deal with the common styles but fix the ones which
149 // don't make sense for us (we also deal with the borders ourselves)
150 WXDWORD msflags = wxWindow::MSWGetStyle
151 (
152 (style & ~wxBORDER_MASK) | wxBORDER_NONE, exflags
153 ) & ~WS_CHILD & ~WS_VISIBLE;
154
155 // first select the kind of window being created
156 //
157 // note that if we don't set WS_POPUP, Windows assumes WS_OVERLAPPED and
158 // creates a window with both caption and border, hence we also test it
159 // below in some other cases
160 if ( style & wxFRAME_TOOL_WINDOW )
161 {
162 msflags |= WS_POPUP;
163 }
164 //else: WS_OVERLAPPED is 0 anyhow, so it is on by default
165
166 // border and caption styles
167 if ( style & wxRESIZE_BORDER )
168 msflags |= WS_THICKFRAME;
169 else if ( exflags && ((style & wxBORDER_DOUBLE) || (style & wxBORDER_RAISED)) )
170 *exflags |= WS_EX_DLGMODALFRAME;
171 else if ( !(style & wxBORDER_NONE) )
172 msflags |= WS_BORDER;
173 else
174 msflags |= WS_POPUP;
175
176 // normally we consider that all windows without caption must be popups,
177 // but CE is an exception: there windows normally do not have the caption
178 // but shouldn't be made popups as popups can't have menus and don't look
179 // like normal windows anyhow
180 if ( style & wxCAPTION )
181 msflags |= WS_CAPTION;
182 #ifndef __WXWINCE__
183 else
184 msflags |= WS_POPUP;
185 #endif // !__WXWINCE__
186
187 // next translate the individual flags
188 if ( style & wxMINIMIZE_BOX )
189 msflags |= WS_MINIMIZEBOX;
190 if ( style & wxMAXIMIZE_BOX )
191 msflags |= WS_MAXIMIZEBOX;
192 if ( style & wxSYSTEM_MENU )
193 msflags |= WS_SYSMENU;
194
195 // NB: under CE these 2 styles are not supported currently, we should
196 // call Minimize()/Maximize() "manually" if we want to support them
197 if ( style & wxMINIMIZE )
198 msflags |= WS_MINIMIZE;
199 if ( style & wxMAXIMIZE )
200 msflags |= WS_MAXIMIZE;
201
202 // Keep this here because it saves recoding this function in wxTinyFrame
203 if ( style & (wxTINY_CAPTION_VERT | wxTINY_CAPTION_HORIZ) )
204 msflags |= WS_CAPTION;
205
206 if ( exflags )
207 {
208 // there is no taskbar under CE, so omit all this
209 #ifndef __WXWINCE__
210 if ( !(GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) )
211 {
212 if ( style & wxFRAME_TOOL_WINDOW )
213 {
214 // create the palette-like window
215 *exflags |= WS_EX_TOOLWINDOW;
216
217 // tool windows shouldn't appear on the taskbar (as documented)
218 style |= wxFRAME_NO_TASKBAR;
219 }
220
221 // We have to solve 2 different problems here:
222 //
223 // 1. frames with wxFRAME_NO_TASKBAR flag shouldn't appear in the
224 // taskbar even if they don't have a parent
225 //
226 // 2. frames without this style should appear in the taskbar even
227 // if they're owned (Windows only puts non owned windows into
228 // the taskbar normally)
229 //
230 // The second one is solved here by using WS_EX_APPWINDOW flag, the
231 // first one is dealt with in our MSWGetParent() method
232 // implementation
233 if ( !(style & wxFRAME_NO_TASKBAR) && GetParent() )
234 {
235 // need to force the frame to appear in the taskbar
236 *exflags |= WS_EX_APPWINDOW;
237 }
238 //else: nothing to do [here]
239 }
240 #endif // !__WXWINCE__
241
242 if ( style & wxSTAY_ON_TOP )
243 *exflags |= WS_EX_TOPMOST;
244
245 if ( GetExtraStyle() & wxFRAME_EX_CONTEXTHELP )
246 *exflags |= WS_EX_CONTEXTHELP;
247 }
248
249 return msflags;
250 }
251
252 WXHWND wxTopLevelWindowMSW::MSWGetParent() const
253 {
254 // for the frames without wxFRAME_FLOAT_ON_PARENT style we should use NULL
255 // parent HWND or it would be always on top of its parent which is not what
256 // we usually want (in fact, we only want it for frames with the
257 // wxFRAME_FLOAT_ON_PARENT flag)
258 HWND hwndParent = NULL;
259 if ( HasFlag(wxFRAME_FLOAT_ON_PARENT) )
260 {
261 const wxWindow *parent = GetParent();
262
263 if ( !parent )
264 {
265 // this flag doesn't make sense then and will be ignored
266 wxFAIL_MSG( _T("wxFRAME_FLOAT_ON_PARENT but no parent?") );
267 }
268 else
269 {
270 hwndParent = GetHwndOf(parent);
271 }
272 }
273 //else: don't float on parent, must not be owned
274
275 // now deal with the 2nd taskbar-related problem (see comments above in
276 // MSWGetStyle())
277 if ( HasFlag(wxFRAME_NO_TASKBAR) && !hwndParent )
278 {
279 // use hidden parent
280 hwndParent = wxTLWHiddenParentModule::GetHWND();
281 }
282
283 return (WXHWND)hwndParent;
284 }
285
286 bool wxTopLevelWindowMSW::CreateDialog(const void *dlgTemplate,
287 const wxString& title,
288 const wxPoint& pos,
289 const wxSize& size)
290 {
291 #ifdef __WXMICROWIN__
292 // no dialogs support under MicroWin yet
293 return CreateFrame(title, pos, size);
294 #else // !__WXMICROWIN__
295 wxWindow *parent = GetParent();
296
297 // for the dialogs without wxDIALOG_NO_PARENT style, use the top level
298 // app window as parent - this avoids creating modal dialogs without
299 // parent
300 if ( !parent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) )
301 {
302 parent = wxTheApp->GetTopWindow();
303
304 if ( parent )
305 {
306 // don't use transient windows as parents, this is dangerous as it
307 // can lead to a crash if the parent is destroyed before the child
308 //
309 // also don't use the window which is currently hidden as then the
310 // dialog would be hidden as well
311 if ( (parent->GetExtraStyle() & wxWS_EX_TRANSIENT) ||
312 !parent->IsShown() )
313 {
314 parent = NULL;
315 }
316 }
317 }
318
319 m_hWnd = (WXHWND)::CreateDialogIndirect
320 (
321 wxGetInstance(),
322 (DLGTEMPLATE*)dlgTemplate,
323 parent ? GetHwndOf(parent) : NULL,
324 (DLGPROC)wxDlgProc
325 );
326
327 if ( !m_hWnd )
328 {
329 wxFAIL_MSG(wxT("Failed to create dialog. Incorrect DLGTEMPLATE?"));
330
331 wxLogSysError(wxT("Can't create dialog using memory template"));
332
333 return FALSE;
334 }
335
336 WXDWORD exflags;
337 (void)MSWGetCreateWindowFlags(&exflags);
338
339 if ( exflags )
340 {
341 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exflags);
342 ::SetWindowPos(GetHwnd(),
343 exflags & WS_EX_TOPMOST ? HWND_TOPMOST : 0,
344 0, 0, 0, 0,
345 SWP_NOSIZE |
346 SWP_NOMOVE |
347 (exflags & WS_EX_TOPMOST ? 0 : SWP_NOZORDER) |
348 SWP_NOACTIVATE);
349 }
350
351 #if defined(__WIN95__)
352 // For some reason, the system menu is activated when we use the
353 // WS_EX_CONTEXTHELP style, so let's set a reasonable icon
354 if ( exflags & WS_EX_CONTEXTHELP )
355 {
356 wxFrame *winTop = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
357 if ( winTop )
358 {
359 wxIcon icon = winTop->GetIcon();
360 if ( icon.Ok() )
361 {
362 ::SendMessage(GetHwnd(), WM_SETICON,
363 (WPARAM)TRUE,
364 (LPARAM)GetHiconOf(icon));
365 }
366 }
367 }
368 #endif // __WIN95__
369
370 // move the dialog to its initial position without forcing repainting
371 int x, y, w, h;
372 (void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
373
374 if ( x == (int)CW_USEDEFAULT )
375 {
376 // centre it on the screen - what else can we do?
377 wxSize sizeDpy = wxGetDisplaySize();
378
379 x = (sizeDpy.x - w) / 2;
380 y = (sizeDpy.y - h) / 2;
381 }
382
383 if ( !::MoveWindow(GetHwnd(), x, y, w, h, FALSE) )
384 {
385 wxLogLastError(wxT("MoveWindow"));
386 }
387
388 if ( !title.empty() )
389 {
390 ::SetWindowText(GetHwnd(), title);
391 }
392
393 SubclassWin(m_hWnd);
394
395 return TRUE;
396 #endif // __WXMICROWIN__/!__WXMICROWIN__
397 }
398
399 bool wxTopLevelWindowMSW::CreateFrame(const wxString& title,
400 const wxPoint& pos,
401 const wxSize& size)
402 {
403 WXDWORD exflags;
404 WXDWORD flags = MSWGetCreateWindowFlags(&exflags);
405
406 return MSWCreate(wxCanvasClassName, title, pos, size, flags, exflags);
407 }
408
409 bool wxTopLevelWindowMSW::Create(wxWindow *parent,
410 wxWindowID id,
411 const wxString& title,
412 const wxPoint& pos,
413 const wxSize& size,
414 long style,
415 const wxString& name)
416 {
417 bool ret wxDUMMY_INITIALIZE(false);
418
419 // init our fields
420 Init();
421
422 wxSize sizeReal = size;
423 if ( !sizeReal.IsFullySpecified() )
424 {
425 sizeReal.SetDefaults(GetDefaultSize());
426 }
427
428 m_windowStyle = style;
429
430 SetName(name);
431
432 m_windowId = id == -1 ? NewControlId() : id;
433
434 wxTopLevelWindows.Append(this);
435
436 if ( parent )
437 parent->AddChild(this);
438
439 if ( GetExtraStyle() & wxTOPLEVEL_EX_DIALOG )
440 {
441 // we have different dialog templates to allows creation of dialogs
442 // with & without captions under MSWindows, resizeable or not (but a
443 // resizeable dialog always has caption - otherwise it would look too
444 // strange)
445
446 // we need 3 additional WORDs for dialog menu, class and title (as we
447 // don't use DS_SETFONT we don't need the fourth WORD for the font)
448 static const int dlgsize = sizeof(DLGTEMPLATE) + (sizeof(WORD) * 3);
449 DLGTEMPLATE *dlgTemplate = (DLGTEMPLATE *)malloc(dlgsize);
450 memset(dlgTemplate, 0, dlgsize);
451
452 // these values are arbitrary, they won't be used normally anyhow
453 dlgTemplate->x = 34;
454 dlgTemplate->y = 22;
455 dlgTemplate->cx = 144;
456 dlgTemplate->cy = 75;
457
458 // reuse the code in MSWGetStyle() but correct the results slightly for
459 // the dialog
460 dlgTemplate->style = MSWGetStyle(style, NULL);
461
462 // all dialogs are popups
463 dlgTemplate->style |= WS_POPUP;
464
465 // force 3D-look if necessary, it looks impossibly ugly otherwise
466 if ( style & (wxRESIZE_BORDER | wxCAPTION) )
467 dlgTemplate->style |= DS_MODALFRAME;
468
469 ret = CreateDialog(dlgTemplate, title, pos, sizeReal);
470 free(dlgTemplate);
471 }
472 else // !dialog
473 {
474 ret = CreateFrame(title, pos, sizeReal);
475 }
476
477 if ( ret && !(GetWindowStyleFlag() & wxCLOSE_BOX) )
478 {
479 EnableCloseButton(false);
480 }
481
482 // for some reason we need to manually send ourselves this message as
483 // otherwise the mnemonics are always shown -- even if they're configured
484 // to be hidden until "Alt" is pressed in the control panel
485 //
486 // this could indicate a bug somewhere else but for now this is the only
487 // fix we have
488 if ( ret )
489 {
490 SendMessage
491 (
492 GetHwnd(),
493 WM_UPDATEUISTATE,
494 MAKEWPARAM(UIS_INITIALIZE, UISF_HIDEFOCUS | UISF_HIDEACCEL),
495 0
496 );
497 }
498
499 return ret;
500 }
501
502 wxTopLevelWindowMSW::~wxTopLevelWindowMSW()
503 {
504 if ( wxModelessWindows.Find(this) )
505 wxModelessWindows.DeleteObject(this);
506
507 // after destroying an owned window, Windows activates the next top level
508 // window in Z order but it may be different from our owner (to reproduce
509 // this simply Alt-TAB to another application and back before closing the
510 // owned frame) whereas we always want to yield activation to our parent
511 if ( HasFlag(wxFRAME_FLOAT_ON_PARENT) )
512 {
513 wxWindow *parent = GetParent();
514 if ( parent )
515 {
516 ::BringWindowToTop(GetHwndOf(parent));
517 }
518 }
519 }
520
521 // ----------------------------------------------------------------------------
522 // wxTopLevelWindowMSW showing
523 // ----------------------------------------------------------------------------
524
525 void wxTopLevelWindowMSW::DoShowWindow(int nShowCmd)
526 {
527 ::ShowWindow(GetHwnd(), nShowCmd);
528
529 m_iconized = nShowCmd == SW_MINIMIZE;
530 }
531
532 bool wxTopLevelWindowMSW::Show(bool show)
533 {
534 // don't use wxWindow version as we want to call DoShowWindow() ourselves
535 if ( !wxWindowBase::Show(show) )
536 return FALSE;
537
538 int nShowCmd;
539 if ( show )
540 {
541 if ( m_maximizeOnShow )
542 {
543 // show and maximize
544 nShowCmd = SW_MAXIMIZE;
545
546 m_maximizeOnShow = FALSE;
547 }
548 else // just show
549 {
550 if ( GetWindowStyle() & wxFRAME_TOOL_WINDOW )
551 nShowCmd = SW_SHOWNA;
552 else
553 nShowCmd = SW_SHOW;
554 }
555 }
556 else // hide
557 {
558 nShowCmd = SW_HIDE;
559 }
560
561 DoShowWindow(nShowCmd);
562
563 if ( show )
564 {
565 ::BringWindowToTop(GetHwnd());
566
567 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_windowId);
568 event.SetEventObject( this );
569 GetEventHandler()->ProcessEvent(event);
570 }
571 else // hide
572 {
573 // Try to highlight the correct window (the parent)
574 if ( GetParent() )
575 {
576 HWND hWndParent = GetHwndOf(GetParent());
577 if (hWndParent)
578 ::BringWindowToTop(hWndParent);
579 }
580 }
581
582 return TRUE;
583 }
584
585 // ----------------------------------------------------------------------------
586 // wxTopLevelWindowMSW maximize/minimize
587 // ----------------------------------------------------------------------------
588
589 void wxTopLevelWindowMSW::Maximize(bool maximize)
590 {
591 if ( IsShown() )
592 {
593 // just maximize it directly
594 DoShowWindow(maximize ? SW_MAXIMIZE : SW_RESTORE);
595 }
596 else // hidden
597 {
598 // we can't maximize the hidden frame because it shows it as well, so
599 // just remember that we should do it later in this case
600 m_maximizeOnShow = maximize;
601 }
602 }
603
604 bool wxTopLevelWindowMSW::IsMaximized() const
605 {
606 #ifdef __WXWINCE__
607 return FALSE;
608 #else
609 return ::IsZoomed(GetHwnd()) != 0;
610 #endif
611 }
612
613 void wxTopLevelWindowMSW::Iconize(bool iconize)
614 {
615 DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE);
616 }
617
618 bool wxTopLevelWindowMSW::IsIconized() const
619 {
620 #ifdef __WXWINCE__
621 return FALSE;
622 #else
623 // also update the current state
624 ((wxTopLevelWindowMSW *)this)->m_iconized = ::IsIconic(GetHwnd()) != 0;
625
626 return m_iconized;
627 #endif
628 }
629
630 void wxTopLevelWindowMSW::Restore()
631 {
632 DoShowWindow(SW_RESTORE);
633 }
634
635 // ----------------------------------------------------------------------------
636 // wxTopLevelWindowMSW fullscreen
637 // ----------------------------------------------------------------------------
638
639 bool wxTopLevelWindowMSW::ShowFullScreen(bool show, long style)
640 {
641 if ( show == IsFullScreen() )
642 {
643 // nothing to do
644 return TRUE;
645 }
646
647 m_fsIsShowing = show;
648
649 if ( show )
650 {
651 m_fsStyle = style;
652
653 // zap the frame borders
654
655 // save the 'normal' window style
656 m_fsOldWindowStyle = GetWindowLong(GetHwnd(), GWL_STYLE);
657
658 // save the old position, width & height, maximize state
659 m_fsOldSize = GetRect();
660 m_fsIsMaximized = IsMaximized();
661
662 // decide which window style flags to turn off
663 LONG newStyle = m_fsOldWindowStyle;
664 LONG offFlags = 0;
665
666 if (style & wxFULLSCREEN_NOBORDER)
667 {
668 offFlags |= WS_BORDER;
669 #ifndef __WXWINCE__
670 offFlags |= WS_THICKFRAME;
671 #endif
672 }
673 if (style & wxFULLSCREEN_NOCAPTION)
674 offFlags |= WS_CAPTION | WS_SYSMENU;
675
676 newStyle &= ~offFlags;
677
678 // change our window style to be compatible with full-screen mode
679 ::SetWindowLong(GetHwnd(), GWL_STYLE, newStyle);
680
681 wxRect rect;
682 #if wxUSE_DISPLAY
683 // resize to the size of the display containing us
684 int dpy = wxDisplay::GetFromWindow(this);
685 if ( dpy != wxNOT_FOUND )
686 {
687 rect = wxDisplay(dpy).GetGeometry();
688 }
689 else // fall back to the main desktop
690 #else // wxUSE_DISPLAY
691 {
692 // resize to the size of the desktop
693 wxCopyRECTToRect(wxGetWindowRect(::GetDesktopWindow()), rect);
694 #ifdef __WXWINCE__
695 // FIXME: size of the bottom menu (toolbar)
696 // should be taken in account
697 rect.height += rect.y;
698 rect.y = 0;
699 #endif
700 }
701 #endif // wxUSE_DISPLAY
702
703 SetSize(rect);
704
705 // now flush the window style cache and actually go full-screen
706 long flags = SWP_FRAMECHANGED;
707
708 // showing the frame full screen should also show it if it's still
709 // hidden
710 if ( !IsShown() )
711 {
712 // don't call wxWindow version to avoid flicker from calling
713 // ::ShowWindow() -- we're going to show the window at the correct
714 // location directly below -- but do call the wxWindowBase version
715 // to sync the internal m_isShown flag
716 wxWindowBase::Show();
717
718 flags |= SWP_SHOWWINDOW;
719 }
720
721 SetWindowPos(GetHwnd(), HWND_TOP,
722 rect.x, rect.y, rect.width, rect.height,
723 flags);
724
725 #if defined(__WXWINCE__) && _WIN32_WCE < 400
726 ::SHFullScreen(GetHwnd(), SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON);
727 #endif
728
729 // finally send an event allowing the window to relayout itself &c
730 wxSizeEvent event(rect.GetSize(), GetId());
731 GetEventHandler()->ProcessEvent(event);
732 }
733 else // stop showing full screen
734 {
735 #if defined(__WXWINCE__) && _WIN32_WCE < 400
736 ::SHFullScreen(GetHwnd(), SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON);
737 #endif
738 Maximize(m_fsIsMaximized);
739 SetWindowLong(GetHwnd(),GWL_STYLE, m_fsOldWindowStyle);
740 SetWindowPos(GetHwnd(),HWND_TOP,m_fsOldSize.x, m_fsOldSize.y,
741 m_fsOldSize.width, m_fsOldSize.height, SWP_FRAMECHANGED);
742 }
743
744 return TRUE;
745 }
746
747 // ----------------------------------------------------------------------------
748 // wxTopLevelWindowMSW misc
749 // ----------------------------------------------------------------------------
750
751 void wxTopLevelWindowMSW::SetIcon(const wxIcon& icon)
752 {
753 SetIcons( wxIconBundle( icon ) );
754 }
755
756 void wxTopLevelWindowMSW::SetIcons(const wxIconBundle& icons)
757 {
758 wxTopLevelWindowBase::SetIcons(icons);
759
760 #if defined(__WIN95__) && !defined(__WXMICROWIN__)
761 const wxIcon& sml = icons.GetIcon( wxSize( 16, 16 ) );
762 if( sml.Ok() && sml.GetWidth() == 16 && sml.GetHeight() == 16 )
763 {
764 ::SendMessage( GetHwndOf( this ), WM_SETICON, ICON_SMALL,
765 (LPARAM)GetHiconOf(sml) );
766 }
767
768 const wxIcon& big = icons.GetIcon( wxSize( 32, 32 ) );
769 if( big.Ok() && big.GetWidth() == 32 && big.GetHeight() == 32 )
770 {
771 ::SendMessage( GetHwndOf( this ), WM_SETICON, ICON_BIG,
772 (LPARAM)GetHiconOf(big) );
773 }
774 #endif // __WIN95__
775 }
776
777 bool wxTopLevelWindowMSW::EnableCloseButton(bool enable)
778 {
779 #if !defined(__WXMICROWIN__)
780 // get system (a.k.a. window) menu
781 HMENU hmenu = GetSystemMenu(GetHwnd(), FALSE /* get it */);
782 if ( !hmenu )
783 {
784 // no system menu at all -- ok if we want to remove the close button
785 // anyhow, but bad if we want to show it
786 return !enable;
787 }
788
789 // enabling/disabling the close item from it also automatically
790 // disables/enables the close title bar button
791 if ( ::EnableMenuItem(hmenu, SC_CLOSE,
792 MF_BYCOMMAND |
793 (enable ? MF_ENABLED : MF_GRAYED)) == -1 )
794 {
795 wxLogLastError(_T("EnableMenuItem(SC_CLOSE)"));
796
797 return FALSE;
798 }
799
800 // update appearance immediately
801 if ( !::DrawMenuBar(GetHwnd()) )
802 {
803 wxLogLastError(_T("DrawMenuBar"));
804 }
805 #endif // !__WXMICROWIN__
806
807 return TRUE;
808 }
809
810 #ifndef __WXWINCE__
811
812 bool wxTopLevelWindowMSW::SetShape(const wxRegion& region)
813 {
814 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), FALSE,
815 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
816
817 // The empty region signifies that the shape should be removed from the
818 // window.
819 if ( region.IsEmpty() )
820 {
821 if (::SetWindowRgn(GetHwnd(), NULL, TRUE) == 0)
822 {
823 wxLogLastError(_T("SetWindowRgn"));
824 return FALSE;
825 }
826 return TRUE;
827 }
828
829 // Windows takes ownership of the region, so
830 // we'll have to make a copy of the region to give to it.
831 DWORD noBytes = ::GetRegionData(GetHrgnOf(region), 0, NULL);
832 RGNDATA *rgnData = (RGNDATA*) new char[noBytes];
833 ::GetRegionData(GetHrgnOf(region), noBytes, rgnData);
834 HRGN hrgn = ::ExtCreateRegion(NULL, noBytes, rgnData);
835 delete[] (char*) rgnData;
836
837 // SetWindowRgn expects the region to be in coordinants
838 // relative to the window, not the client area. Figure
839 // out the offset, if any.
840 RECT rect;
841 DWORD dwStyle = ::GetWindowLong(GetHwnd(), GWL_STYLE);
842 DWORD dwExStyle = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
843 ::GetClientRect(GetHwnd(), &rect);
844 ::AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
845 ::OffsetRgn(hrgn, -rect.left, -rect.top);
846
847 // Now call the shape API with the new region.
848 if (::SetWindowRgn(GetHwnd(), hrgn, TRUE) == 0)
849 {
850 wxLogLastError(_T("SetWindowRgn"));
851 return FALSE;
852 }
853 return TRUE;
854 }
855
856 #endif // !__WXWINCE__
857
858 // ----------------------------------------------------------------------------
859 // wxTopLevelWindow event handling
860 // ----------------------------------------------------------------------------
861
862 // Default activation behaviour - set the focus for the first child
863 // subwindow found.
864 void wxTopLevelWindowMSW::OnActivate(wxActivateEvent& event)
865 {
866 if ( event.GetActive() )
867 {
868 // restore focus to the child which was last focused unless we already
869 // have it
870 wxLogTrace(_T("focus"), _T("wxTLW %08x activated."), (int) m_hWnd);
871
872 wxWindow *winFocus = FindFocus();
873 if ( !winFocus || wxGetTopLevelParent(winFocus) != this )
874 {
875 wxWindow *parent = m_winLastFocused ? m_winLastFocused->GetParent()
876 : NULL;
877 if ( !parent )
878 {
879 parent = this;
880 }
881
882 wxSetFocusToChild(parent, &m_winLastFocused);
883 }
884 }
885 else // deactivating
886 {
887 // remember the last focused child if it is our child
888 m_winLastFocused = FindFocus();
889
890 if ( m_winLastFocused )
891 {
892 // let it know that it doesn't have focus any more
893 m_winLastFocused->HandleKillFocus((WXHWND)NULL);
894
895 // and don't remember it if it's a child from some other frame
896 if ( wxGetTopLevelParent(m_winLastFocused) != this )
897 {
898 m_winLastFocused = NULL;
899 }
900 }
901
902 wxLogTrace(_T("focus"),
903 _T("wxTLW %08x deactivated, last focused: %08x."),
904 (int) m_hWnd,
905 (int) (m_winLastFocused ? GetHwndOf(m_winLastFocused)
906 : NULL));
907
908 event.Skip();
909 }
910 }
911
912 // the DialogProc for all wxWindows dialogs
913 LONG APIENTRY _EXPORT
914 wxDlgProc(HWND WXUNUSED(hDlg),
915 UINT message,
916 WPARAM WXUNUSED(wParam),
917 LPARAM WXUNUSED(lParam))
918 {
919 switch ( message )
920 {
921 case WM_INITDIALOG:
922 // for this message, returning TRUE tells system to set focus to
923 // the first control in the dialog box, but as we set the focus
924 // ourselves, we return FALSE from here as well, so fall through
925
926 default:
927 // for all the other ones, FALSE means that we didn't process the
928 // message
929 return FALSE;
930 }
931 }
932
933 // ============================================================================
934 // wxTLWHiddenParentModule implementation
935 // ============================================================================
936
937 HWND wxTLWHiddenParentModule::ms_hwnd = NULL;
938
939 const wxChar *wxTLWHiddenParentModule::ms_className = NULL;
940
941 bool wxTLWHiddenParentModule::OnInit()
942 {
943 ms_hwnd = NULL;
944 ms_className = NULL;
945
946 return TRUE;
947 }
948
949 void wxTLWHiddenParentModule::OnExit()
950 {
951 if ( ms_hwnd )
952 {
953 if ( !::DestroyWindow(ms_hwnd) )
954 {
955 wxLogLastError(_T("DestroyWindow(hidden TLW parent)"));
956 }
957
958 ms_hwnd = NULL;
959 }
960
961 if ( ms_className )
962 {
963 if ( !::UnregisterClass(ms_className, wxGetInstance()) )
964 {
965 wxLogLastError(_T("UnregisterClass(\"wxTLWHiddenParent\")"));
966 }
967
968 ms_className = NULL;
969 }
970 }
971
972 /* static */
973 HWND wxTLWHiddenParentModule::GetHWND()
974 {
975 if ( !ms_hwnd )
976 {
977 if ( !ms_className )
978 {
979 static const wxChar *HIDDEN_PARENT_CLASS = _T("wxTLWHiddenParent");
980
981 WNDCLASS wndclass;
982 wxZeroMemory(wndclass);
983
984 wndclass.lpfnWndProc = DefWindowProc;
985 wndclass.hInstance = wxGetInstance();
986 wndclass.lpszClassName = HIDDEN_PARENT_CLASS;
987
988 if ( !::RegisterClass(&wndclass) )
989 {
990 wxLogLastError(_T("RegisterClass(\"wxTLWHiddenParent\")"));
991 }
992 else
993 {
994 ms_className = HIDDEN_PARENT_CLASS;
995 }
996 }
997
998 ms_hwnd = ::CreateWindow(ms_className, wxEmptyString, 0, 0, 0, 0, 0, NULL,
999 (HMENU)NULL, wxGetInstance(), NULL);
1000 if ( !ms_hwnd )
1001 {
1002 wxLogLastError(_T("CreateWindow(hidden TLW parent)"));
1003 }
1004 }
1005
1006 return ms_hwnd;
1007 }
1008
1009