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