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