compilation fix for !USE_PCH (patch 569132)
[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 #include "wx/frame.h"
38 #include "wx/containr.h" // wxSetFocusToChild()
39 #endif //WX_PRECOMP
40
41 #include "wx/msw/private.h"
42
43 #include "wx/popupwin.h"
44
45 #ifndef ICON_BIG
46 #define ICON_BIG 1
47 #endif
48
49 #ifndef ICON_SMALL
50 #define ICON_SMALL 0
51 #endif
52
53 // ----------------------------------------------------------------------------
54 // stubs for missing functions under MicroWindows
55 // ----------------------------------------------------------------------------
56
57 #ifdef __WXMICROWIN__
58
59 // static inline bool IsIconic(HWND WXUNUSED(hwnd)) { return FALSE; }
60 static inline bool IsZoomed(HWND WXUNUSED(hwnd)) { return FALSE; }
61
62 #endif // __WXMICROWIN__
63
64 // this is defined in dialog.cpp
65 LONG APIENTRY _EXPORT
66 wxDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
67
68 // ----------------------------------------------------------------------------
69 // globals
70 // ----------------------------------------------------------------------------
71
72 // list of all frames and modeless dialogs
73 wxWindowList wxModelessWindows;
74
75 // the name of the default wxWindows class
76 extern const wxChar *wxCanvasClassName;
77
78 // the hidden parent for wxFRAME_NO_TASKBAR unowned frames
79 wxWindow *wxTopLevelWindowMSW::ms_hiddenParent = NULL;
80
81 // ============================================================================
82 // wxTopLevelWindowMSW implementation
83 // ============================================================================
84
85 BEGIN_EVENT_TABLE(wxTopLevelWindowMSW, wxTopLevelWindowBase)
86 EVT_ACTIVATE(wxTopLevelWindowMSW::OnActivate)
87 END_EVENT_TABLE()
88
89 // ----------------------------------------------------------------------------
90 // wxTopLevelWindowMSW creation
91 // ----------------------------------------------------------------------------
92
93 void wxTopLevelWindowMSW::Init()
94 {
95 m_iconized =
96 m_maximizeOnShow = FALSE;
97
98 // unlike (almost?) all other windows, frames are created hidden
99 m_isShown = FALSE;
100
101 // Data to save/restore when calling ShowFullScreen
102 m_fsStyle = 0;
103 m_fsOldWindowStyle = 0;
104 m_fsIsMaximized = FALSE;
105 m_fsIsShowing = FALSE;
106
107 m_winLastFocused = (wxWindow *)NULL;
108 }
109
110 WXDWORD wxTopLevelWindowMSW::MSWGetStyle(long style, WXDWORD *exflags) const
111 {
112 // let the base class deal with the common styles but fix the ones which
113 // don't make sense for us (we also deal with the borders ourselves)
114 WXDWORD msflags = wxWindow::MSWGetStyle
115 (
116 (style & ~wxBORDER_MASK) | wxBORDER_NONE, exflags
117 ) & ~WS_CHILD;
118
119 // first select the kind of window being created
120 //
121 // note that if we don't set WS_POPUP, Windows assumes WS_OVERLAPPED and
122 // creates a window with both caption and border, hence we also test it
123 // below in some other cases
124 if ( style & wxFRAME_TOOL_WINDOW )
125 msflags |= WS_POPUP;
126 else
127 msflags |= WS_OVERLAPPED;
128
129 // border and caption styles
130 if ( style & wxRESIZE_BORDER )
131 msflags |= WS_THICKFRAME;
132 else if ( !(style & wxBORDER_NONE) )
133 msflags |= WS_BORDER;
134 else
135 msflags |= WS_POPUP;
136
137 if ( style & wxCAPTION )
138 msflags |= WS_CAPTION;
139 else
140 msflags |= WS_POPUP;
141
142 // next translate the individual flags
143 if ( style & wxMINIMIZE_BOX )
144 msflags |= WS_MINIMIZEBOX;
145 if ( style & wxMAXIMIZE_BOX )
146 msflags |= WS_MAXIMIZEBOX;
147 if ( style & wxSYSTEM_MENU )
148 msflags |= WS_SYSMENU;
149 if ( style & wxMINIMIZE )
150 msflags |= WS_MINIMIZE;
151 if ( style & wxMAXIMIZE )
152 msflags |= WS_MAXIMIZE;
153
154 // Keep this here because it saves recoding this function in wxTinyFrame
155 #if wxUSE_ITSY_BITSY && !defined(__WIN32__)
156 if ( style & wxTINY_CAPTION_VERT )
157 msflags |= IBS_VERTCAPTION;
158 if ( style & wxTINY_CAPTION_HORIZ )
159 msflags |= IBS_HORZCAPTION;
160 #else
161 if ( style & (wxTINY_CAPTION_VERT | wxTINY_CAPTION_HORIZ) )
162 msflags |= WS_CAPTION;
163 #endif
164
165 if ( exflags )
166 {
167 #if !defined(__WIN16__) && !defined(__SC__)
168 if ( !(GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) )
169 {
170 if ( style & wxFRAME_TOOL_WINDOW )
171 {
172 // create the palette-like window
173 *exflags |= WS_EX_TOOLWINDOW;
174 }
175
176 // We have to solve 2 different problems here:
177 //
178 // 1. frames with wxFRAME_NO_TASKBAR flag shouldn't appear in the
179 // taskbar even if they don't have a parent
180 //
181 // 2. frames without this style should appear in the taskbar even
182 // if they're owned (Windows only puts non owned windows into
183 // the taskbar normally)
184 //
185 // The second one is solved here by using WS_EX_APPWINDOW flag, the
186 // first one is dealt with in our MSWGetParent() method
187 // implementation
188 if ( !(style & wxFRAME_NO_TASKBAR) && GetParent() )
189 {
190 // need to force the frame to appear in the taskbar
191 *exflags |= WS_EX_APPWINDOW;
192 }
193 //else: nothing to do [here]
194 }
195 #endif // !Win16
196
197 if ( style & wxSTAY_ON_TOP )
198 *exflags |= WS_EX_TOPMOST;
199
200 #ifdef __WIN32__
201 if ( GetExtraStyle() & wxFRAME_EX_CONTEXTHELP )
202 *exflags |= WS_EX_CONTEXTHELP;
203 #endif // __WIN32__
204 }
205
206 return msflags;
207 }
208
209 WXHWND wxTopLevelWindowMSW::MSWGetParent() const
210 {
211 // for the frames without wxFRAME_FLOAT_ON_PARENT style we should use NULL
212 // parent HWND or it would be always on top of its parent which is not what
213 // we usually want (in fact, we only want it for frames with the
214 // wxFRAME_FLOAT_ON_PARENT flag)
215 wxWindow *parent;
216 if ( HasFlag(wxFRAME_FLOAT_ON_PARENT) )
217 {
218 parent = GetParent();
219
220 // this flag doesn't make sense then and will be ignored
221 wxASSERT_MSG( parent,
222 _T("wxFRAME_FLOAT_ON_PARENT but no parent?") );
223 }
224 else // don't float on parent, must not be owned
225 {
226 parent = NULL;
227 }
228
229 // now deal with the 2nd taskbar-related problem (see comments above in
230 // MSWGetStyle())
231 if ( HasFlag(wxFRAME_NO_TASKBAR) && !parent )
232 {
233 if ( !ms_hiddenParent )
234 {
235 ms_hiddenParent = new wxTopLevelWindowMSW(NULL, -1, _T(""));
236
237 // we shouldn't leave it in wxTopLevelWindows or we wouldn't
238 // terminate the app when the last user-created frame is deleted --
239 // see ~wxTopLevelWindowMSW
240 wxTopLevelWindows.DeleteObject(ms_hiddenParent);
241 }
242
243 parent = ms_hiddenParent;
244 }
245
246 return parent ? parent->GetHWND() : NULL;
247 }
248
249 bool wxTopLevelWindowMSW::CreateDialog(const void *dlgTemplate,
250 const wxString& title,
251 const wxPoint& pos,
252 const wxSize& size)
253 {
254 #ifdef __WXMICROWIN__
255 // no dialogs support under MicroWin yet
256 return CreateFrame(title, pos, size);
257 #else // !__WXMICROWIN__
258 wxWindow *parent = GetParent();
259
260 // for the dialogs without wxDIALOG_NO_PARENT style, use the top level
261 // app window as parent - this avoids creating modal dialogs without
262 // parent
263 if ( !parent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) )
264 {
265 parent = wxTheApp->GetTopWindow();
266
267 if ( parent )
268 {
269 // don't use transient windows as parents, this is dangerous as it
270 // can lead to a crash if the parent is destroyed before the child
271 //
272 // also don't use the window which is currently hidden as then the
273 // dialog would be hidden as well
274 if ( (parent->GetExtraStyle() & wxWS_EX_TRANSIENT) ||
275 !parent->IsShown() )
276 {
277 parent = NULL;
278 }
279 }
280 }
281
282 m_hWnd = (WXHWND)::CreateDialogIndirect
283 (
284 wxGetInstance(),
285 (DLGTEMPLATE*)dlgTemplate,
286 parent ? GetHwndOf(parent) : NULL,
287 (DLGPROC)wxDlgProc
288 );
289
290 if ( !m_hWnd )
291 {
292 wxFAIL_MSG(_("Failed to create dialog. Incorrect DLGTEMPLATE?"));
293
294 wxLogSysError(_("Can't create dialog using memory template"));
295
296 return FALSE;
297 }
298
299 WXDWORD exflags;
300 (void)MSWGetCreateWindowFlags(&exflags);
301
302 if ( exflags )
303 {
304 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exflags);
305 ::SetWindowPos(GetHwnd(), NULL, 0, 0, 0, 0,
306 SWP_NOSIZE |
307 SWP_NOMOVE |
308 SWP_NOZORDER |
309 SWP_NOACTIVATE);
310 }
311
312 #if defined(__WIN95__)
313 // For some reason, the system menu is activated when we use the
314 // WS_EX_CONTEXTHELP style, so let's set a reasonable icon
315 if ( exflags & WS_EX_CONTEXTHELP )
316 {
317 wxFrame *winTop = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
318 if ( winTop )
319 {
320 wxIcon icon = winTop->GetIcon();
321 if ( icon.Ok() )
322 {
323 ::SendMessage(GetHwnd(), WM_SETICON,
324 (WPARAM)TRUE,
325 (LPARAM)GetHiconOf(icon));
326 }
327 }
328 }
329 #endif // __WIN95__
330
331 // move the dialog to its initial position without forcing repainting
332 int x, y, w, h;
333 if ( !MSWGetCreateWindowCoords(pos, size, x, y, w, h) )
334 {
335 x =
336 w = (int)CW_USEDEFAULT;
337 }
338
339 // we can't use CW_USEDEFAULT here as we're not calling CreateWindow()
340 // and passing CW_USEDEFAULT to MoveWindow() results in resizing the
341 // window to (0, 0) size which breaks quite a lot of things, e.g. the
342 // sizer calculation in wxSizer::Fit()
343 if ( w == (int)CW_USEDEFAULT )
344 {
345 // the exact number doesn't matter, the dialog will be resized
346 // again soon anyhow but it should be big enough to allow
347 // calculation relying on "totalSize - clientSize > 0" work, i.e.
348 // at least greater than the title bar height
349 w =
350 h = 100;
351 }
352
353 if ( x == (int)CW_USEDEFAULT )
354 {
355 // centre it on the screen - what else can we do?
356 wxSize sizeDpy = wxGetDisplaySize();
357
358 x = (sizeDpy.x - w) / 2;
359 y = (sizeDpy.y - h) / 2;
360 }
361
362 if ( !::MoveWindow(GetHwnd(), x, y, w, h, FALSE) )
363 {
364 wxLogLastError(wxT("MoveWindow"));
365 }
366
367 if ( !title.empty() )
368 {
369 ::SetWindowText(GetHwnd(), title);
370 }
371
372 SubclassWin(m_hWnd);
373
374 return TRUE;
375 #endif // __WXMICROWIN__/!__WXMICROWIN__
376 }
377
378 bool wxTopLevelWindowMSW::CreateFrame(const wxString& title,
379 const wxPoint& pos,
380 const wxSize& size)
381 {
382 WXDWORD exflags;
383 WXDWORD flags = MSWGetCreateWindowFlags(&exflags);
384
385 return MSWCreate(wxCanvasClassName, title, pos, size, flags, exflags);
386 }
387
388 bool wxTopLevelWindowMSW::Create(wxWindow *parent,
389 wxWindowID id,
390 const wxString& title,
391 const wxPoint& pos,
392 const wxSize& size,
393 long style,
394 const wxString& name)
395 {
396 // init our fields
397 Init();
398
399 m_windowStyle = style;
400
401 SetName(name);
402
403 m_windowId = id == -1 ? NewControlId() : id;
404
405 wxTopLevelWindows.Append(this);
406
407 if ( parent )
408 parent->AddChild(this);
409
410 if ( GetExtraStyle() & wxTOPLEVEL_EX_DIALOG )
411 {
412 // we have different dialog templates to allows creation of dialogs
413 // with & without captions under MSWindows, resizeable or not (but a
414 // resizeable dialog always has caption - otherwise it would look too
415 // strange)
416
417 // we need 3 additional WORDs for dialog menu, class and title (as we
418 // don't use DS_SETFONT we don't need the fourth WORD for the font)
419 static const int dlgsize = sizeof(DLGTEMPLATE) + (sizeof(WORD) * 3);
420 DLGTEMPLATE *dlgTemplate = (DLGTEMPLATE *)malloc(dlgsize);
421 memset(dlgTemplate, 0, dlgsize);
422
423 // these values are arbitrary, they won't be used normally anyhow
424 dlgTemplate->x = 34;
425 dlgTemplate->y = 22;
426 dlgTemplate->cx = 144;
427 dlgTemplate->cy = 75;
428
429 // reuse the code in MSWGetStyle() but correct the results slightly for
430 // the dialog
431 dlgTemplate->style = MSWGetStyle(style, NULL);
432
433 // all dialogs are popups
434 dlgTemplate->style |= WS_POPUP;
435
436 // force 3D-look if necessary, it looks impossibly ugly otherwise
437 if ( style & (wxRESIZE_BORDER | wxCAPTION) )
438 dlgTemplate->style |= DS_MODALFRAME;
439
440 bool ret = CreateDialog(dlgTemplate, title, pos, size);
441 free(dlgTemplate);
442
443 return ret;
444 }
445 else // !dialog
446 {
447 return CreateFrame(title, pos, size);
448 }
449 }
450
451 wxTopLevelWindowMSW::~wxTopLevelWindowMSW()
452 {
453 if ( this == ms_hiddenParent )
454 {
455 // stop [infinite] recursion which would otherwise happen when we do
456 // "delete ms_hiddenParent" below
457 return;
458 }
459
460 wxTopLevelWindows.DeleteObject(this);
461
462 if ( wxModelessWindows.Find(this) )
463 wxModelessWindows.DeleteObject(this);
464
465 // after destroying an owned window, Windows activates the next top level
466 // window in Z order but it may be different from our owner (to reproduce
467 // this simply Alt-TAB to another application and back before closing the
468 // owned frame) whereas we always want to yield activation to our parent
469 if ( HasFlag(wxFRAME_FLOAT_ON_PARENT) )
470 {
471 wxWindow *parent = GetParent();
472 if ( parent )
473 {
474 ::BringWindowToTop(GetHwndOf(parent));
475 }
476 }
477
478 // If this is the last top-level window, exit.
479 if ( wxTheApp && (wxTopLevelWindows.Number() == 0) )
480 {
481 if ( ms_hiddenParent )
482 {
483 delete ms_hiddenParent;
484 ms_hiddenParent = NULL;
485 }
486
487 wxTheApp->SetTopWindow(NULL);
488
489 if ( wxTheApp->GetExitOnFrameDelete() )
490 {
491 ::PostQuitMessage(0);
492 }
493 }
494 }
495
496 // ----------------------------------------------------------------------------
497 // wxTopLevelWindowMSW showing
498 // ----------------------------------------------------------------------------
499
500 void wxTopLevelWindowMSW::DoShowWindow(int nShowCmd)
501 {
502 ::ShowWindow(GetHwnd(), nShowCmd);
503
504 m_iconized = nShowCmd == SW_MINIMIZE;
505 }
506
507 bool wxTopLevelWindowMSW::Show(bool show)
508 {
509 // don't use wxWindow version as we want to call DoShowWindow() ourselves
510 if ( !wxWindowBase::Show(show) )
511 return FALSE;
512
513 int nShowCmd;
514 if ( show )
515 {
516 if ( m_maximizeOnShow )
517 {
518 // show and maximize
519 nShowCmd = SW_MAXIMIZE;
520
521 m_maximizeOnShow = FALSE;
522 }
523 else // just show
524 {
525 nShowCmd = SW_SHOW;
526 }
527 }
528 else // hide
529 {
530 nShowCmd = SW_HIDE;
531 }
532
533 DoShowWindow(nShowCmd);
534
535 if ( show )
536 {
537 ::BringWindowToTop(GetHwnd());
538
539 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_windowId);
540 event.SetEventObject( this );
541 GetEventHandler()->ProcessEvent(event);
542 }
543 else // hide
544 {
545 // Try to highlight the correct window (the parent)
546 if ( GetParent() )
547 {
548 HWND hWndParent = GetHwndOf(GetParent());
549 if (hWndParent)
550 ::BringWindowToTop(hWndParent);
551 }
552 }
553
554 return TRUE;
555 }
556
557 // ----------------------------------------------------------------------------
558 // wxTopLevelWindowMSW maximize/minimize
559 // ----------------------------------------------------------------------------
560
561 void wxTopLevelWindowMSW::Maximize(bool maximize)
562 {
563 if ( IsShown() )
564 {
565 // just maximize it directly
566 DoShowWindow(maximize ? SW_MAXIMIZE : SW_RESTORE);
567 }
568 else // hidden
569 {
570 // we can't maximize the hidden frame because it shows it as well, so
571 // just remember that we should do it later in this case
572 m_maximizeOnShow = TRUE;
573 }
574 }
575
576 bool wxTopLevelWindowMSW::IsMaximized() const
577 {
578 return ::IsZoomed(GetHwnd()) != 0;
579 }
580
581 void wxTopLevelWindowMSW::Iconize(bool iconize)
582 {
583 DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE);
584 }
585
586 bool wxTopLevelWindowMSW::IsIconized() const
587 {
588 // also update the current state
589 ((wxTopLevelWindowMSW *)this)->m_iconized = ::IsIconic(GetHwnd()) != 0;
590
591 return m_iconized;
592 }
593
594 void wxTopLevelWindowMSW::Restore()
595 {
596 DoShowWindow(SW_RESTORE);
597 }
598
599 // ----------------------------------------------------------------------------
600 // wxTopLevelWindowMSW fullscreen
601 // ----------------------------------------------------------------------------
602
603 bool wxTopLevelWindowMSW::ShowFullScreen(bool show, long style)
604 {
605 if (show)
606 {
607 if (IsFullScreen())
608 return FALSE;
609
610 m_fsIsShowing = TRUE;
611 m_fsStyle = style;
612
613 // zap the frame borders
614
615 // save the 'normal' window style
616 m_fsOldWindowStyle = GetWindowLong((HWND)GetHWND(), GWL_STYLE);
617
618 // save the old position, width & height, maximize state
619 m_fsOldSize = GetRect();
620 m_fsIsMaximized = IsMaximized();
621
622 // decide which window style flags to turn off
623 LONG newStyle = m_fsOldWindowStyle;
624 LONG offFlags = 0;
625
626 if (style & wxFULLSCREEN_NOBORDER)
627 offFlags |= WS_BORDER | WS_THICKFRAME;
628 if (style & wxFULLSCREEN_NOCAPTION)
629 offFlags |= (WS_CAPTION | WS_SYSMENU);
630
631 newStyle &= (~offFlags);
632
633 // change our window style to be compatible with full-screen mode
634 ::SetWindowLong((HWND)GetHWND(), GWL_STYLE, newStyle);
635
636 // resize to the size of the desktop
637 int width, height;
638
639 RECT rect = wxGetWindowRect(::GetDesktopWindow());
640 width = rect.right - rect.left;
641 height = rect.bottom - rect.top;
642
643 SetSize(width, height);
644
645 // now flush the window style cache and actually go full-screen
646 SetWindowPos((HWND)GetHWND(), HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED);
647
648 wxSizeEvent event(wxSize(width, height), GetId());
649 GetEventHandler()->ProcessEvent(event);
650
651 return TRUE;
652 }
653 else
654 {
655 if (!IsFullScreen())
656 return FALSE;
657
658 m_fsIsShowing = FALSE;
659
660 Maximize(m_fsIsMaximized);
661 SetWindowLong((HWND)GetHWND(),GWL_STYLE, m_fsOldWindowStyle);
662 SetWindowPos((HWND)GetHWND(),HWND_TOP,m_fsOldSize.x, m_fsOldSize.y,
663 m_fsOldSize.width, m_fsOldSize.height, SWP_FRAMECHANGED);
664
665 return TRUE;
666 }
667 }
668
669 // ----------------------------------------------------------------------------
670 // wxTopLevelWindowMSW misc
671 // ----------------------------------------------------------------------------
672
673 void wxTopLevelWindowMSW::SetIcon(const wxIcon& icon)
674 {
675 SetIcons( wxIconBundle( icon ) );
676 }
677
678 void wxTopLevelWindowMSW::SetIcons(const wxIconBundle& icons)
679 {
680 wxTopLevelWindowBase::SetIcons(icons);
681
682 #if defined(__WIN95__) && !defined(__WXMICROWIN__)
683 const wxIcon& sml = icons.GetIcon( wxSize( 16, 16 ) );
684 if( sml.Ok() && sml.GetWidth() == 16 && sml.GetHeight() == 16 )
685 {
686 ::SendMessage( GetHwndOf( this ), WM_SETICON, ICON_SMALL,
687 (LPARAM)GetHiconOf(sml) );
688 }
689
690 const wxIcon& big = icons.GetIcon( wxSize( 32, 32 ) );
691 if( big.Ok() && big.GetWidth() == 32 && big.GetHeight() == 32 )
692 {
693 ::SendMessage( GetHwndOf( this ), WM_SETICON, ICON_BIG,
694 (LPARAM)GetHiconOf(big) );
695 }
696 #endif // __WIN95__
697 }
698
699 bool wxTopLevelWindowMSW::EnableCloseButton(bool enable)
700 {
701 #ifndef __WXMICROWIN__
702 // get system (a.k.a. window) menu
703 HMENU hmenu = ::GetSystemMenu(GetHwnd(), FALSE /* get it */);
704 if ( !hmenu )
705 {
706 wxLogLastError(_T("GetSystemMenu"));
707
708 return FALSE;
709 }
710
711 // enabling/disabling the close item from it also automatically
712 // disables/enables the close title bar button
713 if ( ::EnableMenuItem(hmenu, SC_CLOSE,
714 MF_BYCOMMAND |
715 (enable ? MF_ENABLED : MF_GRAYED)) == -1 )
716 {
717 wxLogLastError(_T("EnableMenuItem(SC_CLOSE)"));
718
719 return FALSE;
720 }
721
722 // update appearance immediately
723 if ( !::DrawMenuBar(GetHwnd()) )
724 {
725 wxLogLastError(_T("DrawMenuBar"));
726 }
727 #endif // !__WXMICROWIN__
728
729 return TRUE;
730 }
731
732 // ----------------------------------------------------------------------------
733 // wxTopLevelWindow event handling
734 // ----------------------------------------------------------------------------
735
736 // Default activation behaviour - set the focus for the first child
737 // subwindow found.
738 void wxTopLevelWindowMSW::OnActivate(wxActivateEvent& event)
739 {
740 if ( event.GetActive() )
741 {
742 // restore focus to the child which was last focused
743 wxLogTrace(_T("focus"), _T("wxTLW %08x activated."), m_hWnd);
744
745 wxWindow *parent = m_winLastFocused ? m_winLastFocused->GetParent()
746 : NULL;
747 if ( !parent )
748 {
749 parent = this;
750 }
751
752 wxSetFocusToChild(parent, &m_winLastFocused);
753 }
754 else // deactivating
755 {
756 // remember the last focused child if it is our child
757 m_winLastFocused = FindFocus();
758
759 // so we NULL it out if it's a child from some other frame
760 wxWindow *win = m_winLastFocused;
761 while ( win )
762 {
763 if ( win->IsTopLevel() )
764 {
765 if ( win != this )
766 {
767 m_winLastFocused = NULL;
768 }
769
770 break;
771 }
772
773 win = win->GetParent();
774 }
775
776 wxLogTrace(_T("focus"),
777 _T("wxTLW %08x deactivated, last focused: %08x."),
778 m_hWnd,
779 m_winLastFocused ? GetHwndOf(m_winLastFocused)
780 : NULL);
781
782 event.Skip();
783 }
784 }
785