X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e121a72a52e2baef60588bf361e9b2de3181464a..fb35f0c79ca42d888391f0394dec56d04cf71890:/src/msw/toplevel.cpp diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 03ef96e8d8..14caef0e56 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -39,6 +39,8 @@ #include "wx/msw/private.h" +#include "wx/popupwin.h" + #ifndef ICON_BIG #define ICON_BIG 1 #endif @@ -68,25 +70,32 @@ wxWindowList wxModelessWindows; // the name of the default wxWindows class extern const wxChar *wxCanvasClassName; +// the hidden parent for wxFRAME_NO_TASKBAR unowned frames +wxWindow *wxTopLevelWindowMSW::ms_hiddenParent = NULL; + // ============================================================================ // wxTopLevelWindowMSW implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// wxDialog helpers +// ---------------------------------------------------------------------------- + // Dialog window proc LONG APIENTRY _EXPORT -wxDlgProc(HWND WXUNUSED(hWnd), UINT message, WPARAM WXUNUSED(wParam), LPARAM WXUNUSED(lParam)) +wxDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { - if ( message == WM_INITDIALOG ) + switch ( message ) { - // for this message, returning TRUE tells system to set focus to the - // first control in the dialog box - return TRUE; - } - else - { - // for all the other ones, FALSE means that we didn't process the - // message - return FALSE; + case WM_INITDIALOG: + // for this message, returning TRUE tells system to set focus to + // the first control in the dialog box, but as we set the focus + // ourselves, we return FALSE from here as well, so fall through + + default: + // for all the other ones, FALSE means that we didn't process the + // message + return FALSE; } } @@ -169,14 +178,30 @@ WXDWORD wxTopLevelWindowMSW::MSWGetStyle(long style, WXDWORD *exflags) const #if !defined(__WIN16__) && !defined(__SC__) if ( !(GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) ) { - // make all frames appear in the win9x shell taskbar unless - // wxFRAME_TOOL_WINDOW or wxFRAME_NO_TASKBAR is given - without - // giving them WS_EX_APPWINDOW style, the child (i.e. owned) frames - // wouldn't appear in it - if ( (style & wxFRAME_TOOL_WINDOW) || (style & wxFRAME_NO_TASKBAR) ) + if ( style & wxFRAME_TOOL_WINDOW ) + { + // create the palette-like window *exflags |= WS_EX_TOOLWINDOW; - else if ( !(style & wxFRAME_NO_TASKBAR) ) + } + + // We have to solve 2 different problems here: + // + // 1. frames with wxFRAME_NO_TASKBAR flag shouldn't appear in the + // taskbar even if they don't have a parent + // + // 2. frames without this style should appear in the taskbar even + // if they're owned (Windows only puts non owned windows into + // the taskbar normally) + // + // The second one is solved here by using WS_EX_APPWINDOW flag, the + // first one is dealt with in our MSWGetParent() method + // implementation + if ( !(style & wxFRAME_NO_TASKBAR) && GetParent() ) + { + // need to force the frame to appear in the taskbar *exflags |= WS_EX_APPWINDOW; + } + //else: nothing to do [here] } #endif // !Win16 @@ -192,6 +217,46 @@ WXDWORD wxTopLevelWindowMSW::MSWGetStyle(long style, WXDWORD *exflags) const return msflags; } +WXHWND wxTopLevelWindowMSW::MSWGetParent() const +{ + // for the frames without wxFRAME_FLOAT_ON_PARENT style we should use NULL + // parent HWND or it would be always on top of its parent which is not what + // we usually want (in fact, we only want it for frames with the + // wxFRAME_FLOAT_ON_PARENT flag) + wxWindow *parent; + if ( HasFlag(wxFRAME_FLOAT_ON_PARENT) ) + { + parent = GetParent(); + + // this flag doesn't make sense then and will be ignored + wxASSERT_MSG( parent, + _T("wxFRAME_FLOAT_ON_PARENT but no parent?") ); + } + else // don't float on parent, must not be owned + { + parent = NULL; + } + + // now deal with the 2nd taskbar-related problem (see comments above in + // MSWGetStyle()) + if ( HasFlag(wxFRAME_NO_TASKBAR) && !parent ) + { + if ( !ms_hiddenParent ) + { + ms_hiddenParent = new wxTopLevelWindowMSW(NULL, -1, _T("")); + + // we shouldn't leave it in wxTopLevelWindows or we wouldn't + // terminate the app when the last user-created frame is deleted -- + // see ~wxTopLevelWindowMSW + wxTopLevelWindows.DeleteObject(ms_hiddenParent); + } + + parent = ms_hiddenParent; + } + + return parent ? parent->GetHWND() : NULL; +} + bool wxTopLevelWindowMSW::CreateDialog(const void *dlgTemplate, const wxString& title, const wxPoint& pos, @@ -396,6 +461,13 @@ bool wxTopLevelWindowMSW::Create(wxWindow *parent, wxTopLevelWindowMSW::~wxTopLevelWindowMSW() { + if ( this == ms_hiddenParent ) + { + // stop [infinite] recursion which would otherwise happen when we do + // "delete ms_hiddenParent" below + return; + } + wxTopLevelWindows.DeleteObject(this); if ( wxModelessWindows.Find(this) ) @@ -404,6 +476,12 @@ wxTopLevelWindowMSW::~wxTopLevelWindowMSW() // If this is the last top-level window, exit. if ( wxTheApp && (wxTopLevelWindows.Number() == 0) ) { + if ( ms_hiddenParent ) + { + delete ms_hiddenParent; + ms_hiddenParent = NULL; + } + wxTheApp->SetTopWindow(NULL); if ( wxTheApp->GetExitOnFrameDelete() ) @@ -649,3 +727,41 @@ bool wxTopLevelWindowMSW::EnableCloseButton(bool enable) return TRUE; } +// ---------------------------------------------------------------------------- +// wxTopLevelWindowMSW message processing +// ---------------------------------------------------------------------------- + +long wxTopLevelWindowMSW::HandleNcActivate(bool activate) +{ +#if wxUSE_POPUPWIN + /* + Normally, when another top level (whether it is overlapped or popup) + window is shown, it is activated and the parent window (i.e. we) loses + the activation. This, however, looks very ugly when the child window is + a [custom] combobox which we implement using a popup window as surely + opening a combobox shouldn't result in deactivating the parent window. + + So we don't redraw the title bar in this case, even if we still return + TRUE to let the change of activation to take place as otherwise the + controls inside the popup window wouldn't work properly. + */ + if ( !activate && wxPopupWindow::FindPopupFor(this) ) + { + return TRUE; + } +#endif // wxUSE_POPUPWIN + + return FALSE; +} + +long +wxTopLevelWindowMSW::MSWWindowProc(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam) +{ + if ( msg == WM_NCACTIVATE && HandleNcActivate(wParam != 0) ) + { + // we processed WM_NCACTIVATE ourselves + return TRUE; + } + + return wxTopLevelWindowBase::MSWWindowProc(msg, wParam, lParam); +}