From 9dfef5ac200277eb1943cde5c1beafa2f392ab88 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
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.50.0

