From 9dfef5ac200277eb1943cde5c1beafa2f392ab88 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 25 May 2002 17:11:19 +0000 Subject: [PATCH] changes to wxFRAME_NO_TASKBAR/FLOAT_ON_PARENT styles handling which should now work more as expected git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15665 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 3 +- docs/latex/wx/frame.tex | 17 ++++---- include/wx/defs.h | 2 +- include/wx/msw/toplevel.h | 7 ++++ include/wx/msw/window.h | 3 ++ src/msw/toplevel.cpp | 84 ++++++++++++++++++++++++++++++++++++--- src/msw/window.cpp | 48 ++++++++-------------- 7 files changed, 117 insertions(+), 47 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index fc25ee8c8d..f5a7413ac2 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -88,8 +88,7 @@ wxMSW: make/project files. - child frames appear in the taskbar by default now, use wxFRAME_NO_TASKBAR - style to avoid it, wxFRAME_FLOAT_ON_PARENT style is now obsolete and has no - effect + style to avoid it - all overloads of wxDC::SetClippingRegion() combine the given region with the previously selected one instead of replacing it diff --git a/docs/latex/wx/frame.tex b/docs/latex/wx/frame.tex index 0dc9cffa0f..e7cb84094b 100644 --- a/docs/latex/wx/frame.tex +++ b/docs/latex/wx/frame.tex @@ -31,18 +31,21 @@ application windows. \twocolitem{\windowstyle{wxMINIMIZE\_BOX}}{Displays a minimize box on the frame.} \twocolitem{\windowstyle{wxMAXIMIZE}}{Displays the frame maximized. Windows only.} \twocolitem{\windowstyle{wxMAXIMIZE\_BOX}}{Displays a maximize box on the frame.} -\twocolitem{\windowstyle{wxSTAY\_ON\_TOP}}{Stay on top of other windows. Windows only.} +\twocolitem{\windowstyle{wxSTAY\_ON\_TOP}}{Stay on top of all other windows, +see also wxFRAME\_FLOAT\_ON\_PARENT. Windows only.} \twocolitem{\windowstyle{wxSYSTEM\_MENU}}{Displays a system menu.} \twocolitem{\windowstyle{wxSIMPLE\_BORDER}}{Displays no border or decorations. GTK and Windows only.} \twocolitem{\windowstyle{wxRESIZE\_BORDER}}{Displays a resizeable border around the window.} \twocolitem{\windowstyle{wxFRAME\_TOOL\_WINDOW}}{Causes a frame with a small titlebar to be created; the frame does not appear in the taskbar under Windows.} -\twocolitem{\windowstyle{wxFRAME\_NO\_TASKBAR}}{Creates a normal frame but if -this frame has a parent it does not appear in the taskbar under Windows. Note -that a frame without parent will still appear in the taskbar even with this -style. Has no effect under other platforms.} -\twocolitem{\windowstyle{wxFRAME\_FLOAT\_ON\_PARENT}}{Unused any longer, use -wxFRAME\_TOOL\_WINDOW or wxFRAME\_NO\_TASKBAR instead} +\twocolitem{\windowstyle{wxFRAME\_NO\_TASKBAR}}{Creates an otherwise normal +frame but it does not appear in the taskbar under Windows (note that it will +minimize to the desktop window which may seem strange to the users and thus it +might be better to use this style only without wxMINIMIZE\_BOX style). +Has no effect under other platforms.} +\twocolitem{\windowstyle{wxFRAME\_FLOAT\_ON\_PARENT}}{The frame will always be +on top of its parent (unlike wxSTAY\_ON\_TOP). A frame created with this style +must have a non-NULL parent.} \twocolitem{\windowstyle{wxFRAME\_EX\_CONTEXTHELP}}{Under Windows, puts a query button on the caption. When pressed, Windows will go into a context-sensitive help mode and wxWindows will send a wxEVT\_HELP event if the user clicked on an application window. {\it Note} that this is an extended diff --git a/include/wx/defs.h b/include/wx/defs.h index f87619fa48..666ab31808 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -946,11 +946,11 @@ enum wxBorder #define wxDIALOG_NO_PARENT 0x0001 // Don't make owned by apps top window #define wxFRAME_NO_TASKBAR 0x0002 // No taskbar button (MSW only) #define wxFRAME_TOOL_WINDOW 0x0004 // No taskbar button, no system menu +#define wxFRAME_FLOAT_ON_PARENT 0x0008 // Always above its parent // deprecated versions defined for compatibility reasons #define wxRESIZE_BOX wxMAXIMIZE_BOX #define wxTHICK_FRAME wxRESIZE_BORDER -#define wxFRAME_FLOAT_ON_PARENT wxFRAME_TOOL_WINDOW // obsolete styles, unused any more #define wxDIALOG_MODAL 0x0020 // free flag value 0x0020 diff --git a/include/wx/msw/toplevel.h b/include/wx/msw/toplevel.h index 5db5199e47..fc21871ac3 100644 --- a/include/wx/msw/toplevel.h +++ b/include/wx/msw/toplevel.h @@ -96,6 +96,9 @@ protected: // translate wxWindows flags to Windows ones virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle) const; + // choose the right parent to use with CreateWindow() + virtual WXHWND MSWGetParent() const; + // we handle WM_NCACTIVATE specially here virtual long MSWWindowProc(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam); @@ -112,6 +115,10 @@ protected: long m_fsOldWindowStyle; bool m_fsIsMaximized; bool m_fsIsShowing; + + // the hidden parent window for the frames which shouldn't appear in the + // taskbar + static wxWindow *ms_hiddenParent; }; // list of all frames and modeless dialogs diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h index 2218c201e9..f2e843fb31 100644 --- a/include/wx/msw/window.h +++ b/include/wx/msw/window.h @@ -240,6 +240,9 @@ public: int& x, int& y, int& w, int& h) const; + // get the HWND to be used as parent of this window with CreateWindow() + virtual WXHWND MSWGetParent() const; + // creates the window of specified Windows class with given style, extended // style, title and geometry (default values // diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 83c019347d..91804dda88 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -70,6 +70,9 @@ 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 // ============================================================================ @@ -175,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 @@ -198,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, @@ -402,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) ) @@ -410,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() ) diff --git a/src/msw/window.cpp b/src/msw/window.cpp index ebd05bfd52..d219c90534 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -2903,6 +2903,11 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, return nonDefault; } +WXHWND wxWindowMSW::MSWGetParent() const +{ + return m_parent ? m_parent->GetHWND() : NULL; +} + bool wxWindowMSW::MSWCreate(const wxChar *wclass, const wxChar *title, const wxPoint& pos, @@ -2914,29 +2919,10 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, int x, y, w, h; (void)MSWGetCreateWindowCoords(pos, size, x, y, w, h); - // find the correct parent HWND - wxWindow *parent = GetParent(); - bool isChild = (style & WS_CHILD) != 0; - HWND hParent; - if ( (isChild || HasFlag(wxPOPUP_WINDOW) || HasFlag(wxFRAME_TOOL_WINDOW)) ) - { - // this is either a normal child window, a popup window or a top level - // window with wxFRAME_TOOL_WINDOW style (see below) - hParent = parent ? GetHwndOf(parent) : NULL; - } - else - { - // this is a frame without wxFRAME_TOOL_WINDOW style: we should use - // NULL parent HWND for it 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 special wxFRAME_TOOL_WINDOW as above) - hParent = NULL; - } - // controlId is menu handle for the top level windows, so set it to 0 // unless we're creating a child window int controlId; - if ( isChild ) + if ( style & WS_CHILD ) { controlId = GetId(); @@ -2963,17 +2949,17 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, wxWindowCreationHook hook(this); m_hWnd = (WXHWND)::CreateWindowEx - ( - extendedStyle, - className, - title ? title : wxT(""), - style, - x, y, w, h, - hParent, - (HMENU)controlId, - wxGetInstance(), - NULL // no extra data - ); + ( + extendedStyle, + className, + title ? title : wxT(""), + style, + x, y, w, h, + (HWND)MSWGetParent(), + (HMENU)controlId, + wxGetInstance(), + NULL // no extra data + ); if ( !m_hWnd ) { -- 2.45.2