[EXPLORER][SHELL32][USER32] Implement 'Show the Desktop' action of Task Bar (#668)
[reactos.git] / base / shell / explorer / traywnd.cpp
index f9d1f2a..8fd6c55 100644 (file)
@@ -2,6 +2,7 @@
  * ReactOS Explorer
  *
  * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
+ * Copyright 2018 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
  *
  * this library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -20,6 +21,7 @@
 
 #include "precomp.h"
 #include <commoncontrols.h>
+#include <traycmd.h>
 
 HRESULT TrayWindowCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu);
 
@@ -55,6 +57,78 @@ HRESULT TrayWindowCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, ICont
 
 static const WCHAR szTrayWndClass[] = L"Shell_TrayWnd";
 
+struct EFFECTIVE_INFO
+{
+    HWND hwndFound;
+    HWND hwndDesktop;
+    HWND hwndProgman;
+    HWND hTrayWnd;
+    BOOL bMustBeInMonitor;
+};
+
+static BOOL CALLBACK
+FindEffectiveProc(HWND hwnd, LPARAM lParam)
+{
+    EFFECTIVE_INFO *pei = (EFFECTIVE_INFO *)lParam;
+
+    if (!IsWindowVisible(hwnd) || IsIconic(hwnd))
+        return TRUE;    // continue
+
+    if (pei->hTrayWnd == hwnd || pei->hwndDesktop == hwnd ||
+        pei->hwndProgman == hwnd)
+    {
+        return TRUE;    // continue
+    }
+
+    if (pei->bMustBeInMonitor)
+    {
+        // is the window in the nearest monitor?
+        HMONITOR hMon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
+        if (hMon)
+        {
+            MONITORINFO info;
+            ZeroMemory(&info, sizeof(info));
+            info.cbSize = sizeof(info);
+            if (GetMonitorInfoW(hMon, &info))
+            {
+                RECT rcWindow, rcMonitor, rcIntersect;
+                rcMonitor = info.rcMonitor;
+
+                GetWindowRect(hwnd, &rcWindow);
+
+                if (!IntersectRect(&rcIntersect, &rcMonitor, &rcWindow))
+                    return TRUE;    // continue
+            }
+        }
+    }
+
+    pei->hwndFound = hwnd;
+    return FALSE;   // stop if found
+}
+
+static BOOL
+IsThereAnyEffectiveWindow(BOOL bMustBeInMonitor)
+{
+    EFFECTIVE_INFO ei;
+    ei.hwndFound = NULL;
+    ei.hwndDesktop = GetDesktopWindow();
+    ei.hTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL);
+    ei.hwndProgman = FindWindowW(L"Progman", NULL);
+    ei.bMustBeInMonitor = bMustBeInMonitor;
+
+    EnumWindows(FindEffectiveProc, (LPARAM)&ei);
+    if (ei.hwndFound && FALSE)
+    {
+        WCHAR szClass[64], szText[64];
+        GetClassNameW(ei.hwndFound, szClass, _countof(szClass));
+        GetWindowTextW(ei.hwndFound, szText, _countof(szText));
+        MessageBoxW(NULL, szText, szClass, 0);
+    }
+    return ei.hwndFound != NULL;
+}
+
+CSimpleArray<HWND>  g_MinimizedAll;
+
 /*
  * ITrayWindow
  */
@@ -209,7 +283,7 @@ class CTrayWindow :
     HWND m_TaskSwitch;
     HWND m_TrayNotify;
 
-    CTrayNotifyWnd* m_TrayNotifyInstance;
+    CComPtr<IUnknown> m_TrayNotifyInstance;
 
     DWORD    m_Position;
     HMONITOR m_Monitor;
@@ -237,12 +311,6 @@ public:
         DWORD Flags;
         struct
         {
-            DWORD AutoHide : 1;
-            DWORD AlwaysOnTop : 1;
-            DWORD SmSmallIcons : 1;
-            DWORD HideClock : 1;
-            DWORD Locked : 1;
-
             /* UI Status */
             DWORD InSizeMove : 1;
             DWORD IsDragging : 1;
@@ -333,7 +401,19 @@ public:
 
     LRESULT DoExitWindows()
     {
+        /* Display the ReactOS Shutdown Dialog */
         ExitWindowsDialog(m_hWnd);
+
+        /*
+         * If the user presses CTRL+ALT+SHIFT while exiting
+         * the shutdown dialog, exit the shell cleanly.
+         */
+        if ((GetKeyState(VK_CONTROL) & 0x8000) &&
+            (GetKeyState(VK_SHIFT)   & 0x8000) &&
+            (GetKeyState(VK_MENU)    & 0x8000))
+        {
+            PostMessage(WM_QUIT, 0, 0);
+        }
         return 0;
     }
 
@@ -359,7 +439,13 @@ public:
 
         m_RunFileDlgOwner = hwnd;
 
-        RunFileDlg(hwnd, NULL, NULL, NULL, NULL, RFF_CALCDIRECTORY);
+        // build the default directory from two environment variables
+        CStringW strDefaultDir, strHomePath;
+        strDefaultDir.GetEnvironmentVariable(L"HOMEDRIVE");
+        strHomePath.GetEnvironmentVariable(L"HOMEPATH");
+        strDefaultDir += strHomePath;
+
+        RunFileDlg(hwnd, NULL, (LPCWSTR)strDefaultDir, NULL, NULL, RFF_CALCDIRECTORY);
 
         m_RunFileDlgOwner = NULL;
         ::DestroyWindow(hwnd);
@@ -411,7 +497,7 @@ public:
 
         m_TrayPropertiesOwner = hwnd;
 
-        DisplayTrayProperties(hwnd);
+        DisplayTrayProperties(hwnd, m_hWnd);
 
         m_TrayPropertiesOwner = NULL;
         ::DestroyWindow(hwnd);
@@ -473,6 +559,18 @@ public:
                      SW_SHOWNORMAL);
     }
 
+    VOID ToggleDesktop()
+    {
+        if (::IsThereAnyEffectiveWindow(TRUE))
+        {
+            ShowDesktop();
+        }
+        else
+        {
+            RestoreAll();
+        }
+    }
+
     BOOL STDMETHODCALLTYPE ExecContextMenuCmd(IN UINT uiCmd)
     {
         switch (uiCmd)
@@ -494,7 +592,7 @@ public:
         case ID_LOCKTASKBAR:
             if (SHRestricted(REST_CLASSICSHELL) == 0)
             {
-                Lock(!Locked);
+                Lock(!g_TaskbarSettings.bLock);
             }
             break;
 
@@ -506,6 +604,7 @@ public:
             break;
 
         case ID_SHELL_CMD_SHOW_DESKTOP:
+            ShowDesktop();
             break;
 
         case ID_SHELL_CMD_TILE_WND_H:
@@ -529,6 +628,10 @@ public:
             ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
             break;
 
+        case ID_SHELL_CMD_RESTORE_ALL:
+            RestoreAll();
+            break;
+
         default:
             TRACE("ITrayWindow::ExecContextMenuCmd(%u): Unhandled Command ID!\n", uiCmd);
             return FALSE;
@@ -550,7 +653,7 @@ public:
         case IDHK_EXPLORE:
             //FIXME: We don't support this yet:
             //ShellExecuteW(0, L"explore", NULL, NULL, NULL, 1);
-            ShellExecuteW(0, NULL, L"explorer.exe", NULL, NULL, 1); 
+            ShellExecuteW(0, NULL, L"explorer.exe", L"/e ,", NULL, 1);
             break;
         case IDHK_FIND:
             SHFindFiles(NULL, NULL);
@@ -567,10 +670,13 @@ public:
         case IDHK_PREV_TASK:
             break;
         case IDHK_MINIMIZE_ALL:
+            MinimizeAll();
             break;
         case IDHK_RESTORE_ALL:
+            RestoreAll();
             break;
         case IDHK_DESKTOP:
+            ToggleDesktop();
             break;
         case IDHK_PAGER:
             break;
@@ -583,35 +689,80 @@ public:
     {
         switch (uCommand)
         {
-        case IDM_TASKBARANDSTARTMENU:
-            DisplayProperties();
-            break;
-
-        case IDM_SEARCH:
-            SHFindFiles(NULL, NULL);
-            break;
-
-        case IDM_HELPANDSUPPORT:
-            ExecResourceCmd(IDS_HELP_COMMAND);
-            break;
-
-        case IDM_RUN:
-            DisplayRunFileDlg();
-            break;
-
-        /* FIXME: Handle these commands as well */
-        case IDM_SYNCHRONIZE:
-        case IDM_DISCONNECT:
-        case IDM_UNDOCKCOMPUTER:
-            break;
-
-        case IDM_LOGOFF:
-            LogoffWindowsDialog(m_hWnd); // FIXME: Maybe handle it in a similar way as DoExitWindows?
-            break;
+            case TRAYCMD_STARTMENU:
+                // TODO:
+                break;
+            case TRAYCMD_RUN_DIALOG:
+                DisplayRunFileDlg();
+                break;
+            case TRAYCMD_LOGOFF_DIALOG:
+                LogoffWindowsDialog(m_hWnd); // FIXME: Maybe handle it in a similar way as DoExitWindows?
+                break;
+            case TRAYCMD_CASCADE:
+                CascadeWindows(NULL, MDITILE_SKIPDISABLED, NULL, 0, NULL);
+                break;
+            case TRAYCMD_TILE_H:
+                TileWindows(NULL, MDITILE_HORIZONTAL, NULL, 0, NULL);
+                break;
+            case TRAYCMD_TILE_V:
+                TileWindows(NULL, MDITILE_VERTICAL, NULL, 0, NULL);
+                break;
+            case TRAYCMD_TOGGLE_DESKTOP:
+                ToggleDesktop();
+                break;
+            case TRAYCMD_DATE_AND_TIME:
+                ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
+                break;
+            case TRAYCMD_TASKBAR_PROPERTIES:
+                DisplayProperties();
+                break;
+            case TRAYCMD_MINIMIZE_ALL:
+                MinimizeAll();
+                break;
+            case TRAYCMD_RESTORE_ALL:
+                RestoreAll();
+                break;
+            case TRAYCMD_SHOW_DESKTOP:
+                ShowDesktop();
+                break;
+            case TRAYCMD_SHOW_TASK_MGR:
+                OpenTaskManager(m_hWnd);
+                break;
+            case TRAYCMD_CUSTOMIZE_TASKBAR:
+                break;
+            case TRAYCMD_LOCK_TASKBAR:
+                if (SHRestricted(REST_CLASSICSHELL) == 0)
+                {
+                    Lock(!g_TaskbarSettings.bLock);
+                }
+                break;
+            case TRAYCMD_HELP_AND_SUPPORT:
+                ExecResourceCmd(IDS_HELP_COMMAND);
+                break;
+            case TRAYCMD_CONTROL_PANEL:
+                // TODO:
+                break;
+            case TRAYCMD_SHUTDOWN_DIALOG:
+                DoExitWindows();
+                break;
+            case TRAYCMD_PRINTERS_AND_FAXES:
+                // TODO:
+                break;
+            case TRAYCMD_LOCK_DESKTOP:
+                // TODO:
+                break;
+            case TRAYCMD_SWITCH_USER_DIALOG:
+                // TODO:
+                break;
+            case TRAYCMD_SEARCH_FILES:
+                SHFindFiles(NULL, NULL);
+                break;
+            case TRAYCMD_SEARCH_COMPUTERS:
+                SHFindComputer(NULL, NULL);
+                break;
 
-        case IDM_SHUTDOWN:
-            DoExitWindows();
-            break;
+            default:
+                break;
         }
 
         return FALSE;
@@ -696,8 +847,9 @@ public:
         IN BOOL TrackUp,
         IN PVOID Context OPTIONAL)
     {
-        INT x = ppt->x;
-        INT y = ppt->y;
+        POINT pt;
+        TPMPARAMS params;
+        RECT rc;
         HRESULT hr;
         UINT uCommand;
         HMENU popup = CreatePopupMenu();
@@ -705,6 +857,17 @@ public:
         if (popup == NULL)
             return E_FAIL;
 
+        if (ppt)
+        {
+            pt = *ppt;
+        }
+        else
+        {
+            ::GetWindowRect(m_hWnd, &rc);
+            pt.x = rc.left;
+            pt.y = rc.top;
+        }
+
         TRACE("Before Query\n");
         hr = contextMenu->QueryContextMenu(popup, 0, 0, UINT_MAX, CMF_NORMAL);
         if (FAILED_UNEXPECTEDLY(hr))
@@ -715,7 +878,20 @@ public:
         }
 
         TRACE("Before Tracking\n");
-        uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, x, y, m_hWnd, NULL);
+        ::SetForegroundWindow(m_hWnd);
+        if (hwndExclude)
+        {
+            ::GetWindowRect(hwndExclude, &rc);
+            ZeroMemory(&params, sizeof(params));
+            params.cbSize = sizeof(params);
+            params.rcExclude = rc;
+            uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, pt.x, pt.y, m_hWnd, &params);
+        }
+        else
+        {
+            uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, pt.x, pt.y, m_hWnd, NULL);
+        }
+        ::PostMessage(m_hWnd, WM_NULL, 0, 0);
 
         if (uCommand != 0)
         {
@@ -1090,13 +1266,6 @@ GetPrimaryScreenRect:
             szTray.cy = rcPos.bottom - rcPos.top;
 
             GetTrayRectFromScreenRect(Pos, &rcScreen, &szTray, pRect);
-            if (AutoHide)
-            {
-                pRect->left += m_AutoHideOffset.cx;
-                pRect->right += m_AutoHideOffset.cx;
-                pRect->top += m_AutoHideOffset.cy;
-                pRect->bottom += m_AutoHideOffset.cy;
-            }
             hMon = hMonNew;
         }
         else
@@ -1104,13 +1273,6 @@ GetPrimaryScreenRect:
             /* The user is dragging the tray window on the same monitor. We don't need
                to recalculate the rectangle */
             *pRect = rcPos;
-            if (AutoHide)
-            {
-                pRect->left += m_AutoHideOffset.cx;
-                pRect->right += m_AutoHideOffset.cx;
-                pRect->top += m_AutoHideOffset.cy;
-                pRect->bottom += m_AutoHideOffset.cy;
-            }
         }
 
         *phMonitor = hMon;
@@ -1146,13 +1308,6 @@ GetPrimaryScreenRect:
             rcTray.top = pwp->y;
             rcTray.right = rcTray.left + pwp->cx;
             rcTray.bottom = rcTray.top + pwp->cy;
-            if (AutoHide)
-            {
-                rcTray.left -= m_AutoHideOffset.cx;
-                rcTray.right -= m_AutoHideOffset.cx;
-                rcTray.top -= m_AutoHideOffset.cy;
-                rcTray.bottom -= m_AutoHideOffset.cy;
-            }
 
             if (!EqualRect(&rcTray,
                 &m_TrayRects[m_DraggingPosition]))
@@ -1204,13 +1359,6 @@ GetPrimaryScreenRect:
                     MakeTrayRectWithSize(m_Position, &szWnd, &rcTray);
                 }
 
-                if (AutoHide)
-                {
-                    rcTray.left -= m_AutoHideOffset.cx;
-                    rcTray.right -= m_AutoHideOffset.cx;
-                    rcTray.top -= m_AutoHideOffset.cy;
-                    rcTray.bottom -= m_AutoHideOffset.cy;
-                }
                 m_TrayRects[m_Position] = rcTray;
             }
             else
@@ -1219,20 +1367,21 @@ GetPrimaryScreenRect:
                    new size or position is valid. this is to prevent changes to the window
                    without user interaction. */
                 rcTray = m_TrayRects[m_Position];
+
+                if (g_TaskbarSettings.sr.AutoHide)
+                {
+                    rcTray.left += m_AutoHideOffset.cx;
+                    rcTray.right += m_AutoHideOffset.cx;
+                    rcTray.top += m_AutoHideOffset.cy;
+                    rcTray.bottom += m_AutoHideOffset.cy;
+                }
+
             }
 
 ChangePos:
             m_TraySize.cx = rcTray.right - rcTray.left;
             m_TraySize.cy = rcTray.bottom - rcTray.top;
 
-            if (AutoHide)
-            {
-                rcTray.left += m_AutoHideOffset.cx;
-                rcTray.right += m_AutoHideOffset.cx;
-                rcTray.top += m_AutoHideOffset.cy;
-                rcTray.bottom += m_AutoHideOffset.cy;
-            }
-
             pwp->flags &= ~(SWP_NOMOVE | SWP_NOSIZE);
             pwp->x = rcTray.left;
             pwp->y = rcTray.top;
@@ -1300,7 +1449,7 @@ ChangePos:
 
         /* If AutoHide is false then change the workarea to exclude
            the area that the taskbar covers. */
-        if (!AutoHide)
+        if (!g_TaskbarSettings.sr.AutoHide)
         {
             switch (m_Position)
             {
@@ -1332,18 +1481,7 @@ ChangePos:
 
     VOID CheckTrayWndPosition()
     {
-        RECT rcTray;
-
-        rcTray = m_TrayRects[m_Position];
-
-        if (AutoHide)
-        {
-            rcTray.left += m_AutoHideOffset.cx;
-            rcTray.right += m_AutoHideOffset.cx;
-            rcTray.top += m_AutoHideOffset.cy;
-            rcTray.bottom += m_AutoHideOffset.cy;
-        }
-
+        /* Force the rebar bands to resize */
         IUnknown_Exec(m_TrayBandSite,
                       IID_IDeskBand,
                       DBID_BANDINFOCHANGED,
@@ -1351,39 +1489,22 @@ ChangePos:
                       NULL,
                       NULL);
 
-        FitToRebar(&rcTray);
-        m_TrayRects[m_Position] = rcTray;
+        /* Calculate the size of the taskbar based on the rebar */
+        FitToRebar(&m_TrayRects[m_Position]);
 
         /* Move the tray window */
-        SetWindowPos(NULL,
-                     rcTray.left,
-                     rcTray.top,
-                     rcTray.right - rcTray.left,
-                     rcTray.bottom - rcTray.top,
-                     SWP_NOZORDER | SWP_NOACTIVATE);
-
+        /* The handler of WM_WINDOWPOSCHANGING will override whatever size
+         * and position we use here with m_TrayRects */
+        SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE);
         ResizeWorkArea();
-
         ApplyClipping(TRUE);
     }
 
-    typedef struct _TW_STUCKRECTS2
-    {
-        DWORD cbSize;
-        LONG Unknown;
-        DWORD dwFlags;
-        DWORD Position;
-        SIZE Size;
-        RECT Rect;
-    } TW_STRUCKRECTS2, *PTW_STUCKRECTS2;
-
     VOID RegLoadSettings()
     {
         DWORD Pos;
-        TW_STRUCKRECTS2 sr;
         RECT rcScreen;
         SIZE WndSize, EdgeSize, DlgFrameSize;
-        DWORD cbSize = sizeof(sr);
         SIZE StartBtnSize = m_StartButton.GetSize();
 
         EdgeSize.cx = GetSystemMetrics(SM_CXEDGE);
@@ -1391,44 +1512,12 @@ ChangePos:
         DlgFrameSize.cx = GetSystemMetrics(SM_CXDLGFRAME);
         DlgFrameSize.cy = GetSystemMetrics(SM_CYDLGFRAME);
 
-        if (SHGetValue(hkExplorer,
-            TEXT("StuckRects2"),
-            TEXT("Settings"),
-            NULL,
-            &sr,
-            &cbSize) == ERROR_SUCCESS &&
-            sr.cbSize == sizeof(sr))
-        {
-            AutoHide = (sr.dwFlags & ABS_AUTOHIDE) != 0;
-            AlwaysOnTop = (sr.dwFlags & ABS_ALWAYSONTOP) != 0;
-            SmSmallIcons = (sr.dwFlags & 0x4) != 0;
-            HideClock = (sr.dwFlags & 0x8) != 0;
-
-            /* FIXME: Are there more flags? */
-
-#if WIN7_DEBUG_MODE
-            m_Position = ABE_LEFT;
-#else
-            if (sr.Position > ABE_BOTTOM)
-                m_Position = ABE_BOTTOM;
-            else
-                m_Position = sr.Position;
-#endif
+        m_Position = g_TaskbarSettings.sr.Position;
+        rcScreen = g_TaskbarSettings.sr.Rect;
+        GetScreenRectFromRect(&rcScreen, MONITOR_DEFAULTTONEAREST);
 
-            /* Try to find out which monitor the tray window was located on last.
-               Here we're only interested in the monitor screen that we think
-               is the last one used. We're going to determine on which monitor
-               we really are after calculating the docked position. */
-            rcScreen = sr.Rect;
-            GetScreenRectFromRect(
-                &rcScreen,
-                MONITOR_DEFAULTTONEAREST);
-        }
-        else
+        if (!g_TaskbarSettings.sr.Size.cx || !g_TaskbarSettings.sr.Size.cy)
         {
-            m_Position = ABE_BOTTOM;
-            AlwaysOnTop = TRUE;
-
             /* Use the minimum size of the taskbar, we'll use the start
                button as a minimum for now. Make sure we calculate the
                entire window size, not just the client size. However, we
@@ -1436,36 +1525,17 @@ ChangePos:
                the start button and bands are not stuck to the screen border. */
             if(!m_Theme)
             {
-                sr.Size.cx = StartBtnSize.cx + (2 * (EdgeSize.cx + DlgFrameSize.cx));
-                sr.Size.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
+                g_TaskbarSettings.sr.Size.cx = StartBtnSize.cx + (2 * (EdgeSize.cx + DlgFrameSize.cx));
+                g_TaskbarSettings.sr.Size.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
             }
             else
             {
-                sr.Size.cx = StartBtnSize.cx - EdgeSize.cx;
-                sr.Size.cy = StartBtnSize.cy - EdgeSize.cy;
-                if(!Locked)
-                    sr.Size.cy += GetSystemMetrics(SM_CYSIZEFRAME);
+                g_TaskbarSettings.sr.Size.cx = StartBtnSize.cx - EdgeSize.cx;
+                g_TaskbarSettings.sr.Size.cy = StartBtnSize.cy - EdgeSize.cy;
+                if(!g_TaskbarSettings.bLock)
+                    g_TaskbarSettings.sr.Size.cy += GetSystemMetrics(SM_CYSIZEFRAME);
             }
-
-            /* Use the primary screen by default */
-            rcScreen.left = 0;
-            rcScreen.top = 0;
-            rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
-            rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
-            GetScreenRectFromRect(
-                &rcScreen,
-                MONITOR_DEFAULTTOPRIMARY);
         }
-
-        if (m_hWnd != NULL)
-            SetWindowPos(
-            AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
-            0,
-            0,
-            0,
-            0,
-            SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
-
         /* Determine a minimum tray window rectangle. The "client" height is
            zero here since we cannot determine an optimal minimum width when
            loaded as a vertical tray window. We just need to make sure the values
@@ -1483,10 +1553,10 @@ ChangePos:
             WndSize.cy = StartBtnSize.cy - EdgeSize.cx;
         }
 
-        if (WndSize.cx < sr.Size.cx)
-            WndSize.cx = sr.Size.cx;
-        if (WndSize.cy < sr.Size.cy)
-            WndSize.cy = sr.Size.cy;
+        if (WndSize.cx < g_TaskbarSettings.sr.Size.cx)
+            WndSize.cx = g_TaskbarSettings.sr.Size.cx;
+        if (WndSize.cy < g_TaskbarSettings.sr.Size.cy)
+            WndSize.cy = g_TaskbarSettings.sr.Size.cy;
 
         /* Save the calculated size */
         m_TraySize = WndSize;
@@ -1788,12 +1858,9 @@ ChangePos:
 
     void ProcessAutoHide()
     {
-        RECT rc = m_TrayRects[m_Position];
         INT w = m_TraySize.cx - GetSystemMetrics(SM_CXBORDER) * 2 - 1;
         INT h = m_TraySize.cy - GetSystemMetrics(SM_CYBORDER) * 2 - 1;
 
-        TRACE("AutoHide Timer received for %u, rc=(%d, %d, %d, %d), w=%d, h=%d.\n", m_AutoHideState, rc.left, rc.top, rc.right, rc.bottom, w, h);
-
         switch (m_AutoHideState)
         {
         case AUTOHIDE_HIDING:
@@ -1899,13 +1966,7 @@ ChangePos:
             break;
         }
 
-        rc.left += m_AutoHideOffset.cx;
-        rc.right += m_AutoHideOffset.cx;
-        rc.top += m_AutoHideOffset.cy;
-        rc.bottom += m_AutoHideOffset.cy;
-
-        TRACE("AutoHide Changing position to (%d, %d, %d, %d) and state=%u.\n", rc.left, rc.top, rc.right, rc.bottom, m_AutoHideState);
-        SetWindowPos(NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
+        SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER);
     }
 
 
@@ -1992,7 +2053,7 @@ ChangePos:
         }
 
         DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
-        if (AlwaysOnTop)
+        if (g_TaskbarSettings.sr.AlwaysOnTop)
             dwExStyle |= WS_EX_TOPMOST;
 
         DWORD dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
@@ -2048,18 +2109,18 @@ ChangePos:
 
     BOOL STDMETHODCALLTYPE Lock(IN BOOL bLock)
     {
-        BOOL bPrevLock = Locked;
+        BOOL bPrevLock = g_TaskbarSettings.bLock;
 
-        if (Locked != bLock)
+        if (g_TaskbarSettings.bLock != bLock)
         {
-            Locked = bLock;
+            g_TaskbarSettings.bLock = bLock;
 
             if (m_TrayBandSite != NULL)
             {
                 if (!SUCCEEDED(m_TrayBandSite->Lock(bLock)))
                 {
                     /* Reset?? */
-                    Locked = bPrevLock;
+                    g_TaskbarSettings.bLock = bPrevLock;
                     return bPrevLock;
                 }
             }
@@ -2072,7 +2133,7 @@ ChangePos:
                     RECT rcGripper = {0};
                     AdjustSizerRect(&rcGripper, Pos);
 
-                    if(Locked)
+                    if(g_TaskbarSettings.bLock)
                     {
                         m_TrayRects[Pos].top += rcGripper.top;
                         m_TrayRects[Pos].left += rcGripper.left;
@@ -2133,7 +2194,7 @@ ChangePos:
         if (!m_ContextMenu)
             return E_INVALIDARG;
 
-        return m_ContextMenu->GetCommandString(idCmd, uType, pwReserved, pszName, cchMax);        
+        return m_ContextMenu->GetCommandString(idCmd, uType, pwReserved, pszName, cchMax);
     }
 
 
@@ -2169,6 +2230,11 @@ ChangePos:
         if (FAILED_UNEXPECTEDLY(hRet))
             return FALSE;
 
+        /* Create the tray notification window */
+        hRet = CTrayNotifyWnd_CreateInstance(m_hWnd, IID_PPV_ARG(IUnknown, &m_TrayNotifyInstance));
+        if (FAILED_UNEXPECTEDLY(hRet))
+            return FALSE;
+
         /* Get the hwnd of the rebar */
         hRet = IUnknown_GetWindow(m_TrayBandSite, &m_Rebar);
         if (FAILED_UNEXPECTEDLY(hRet))
@@ -2179,21 +2245,26 @@ ChangePos:
         if (FAILED_UNEXPECTEDLY(hRet))
             return FALSE;
 
-        SetWindowTheme(m_Rebar, L"TaskBar", NULL);
+        /* Get the hwnd of the tray notification window */
+        hRet = IUnknown_GetWindow(m_TrayNotifyInstance, &m_TrayNotify);
+        if (FAILED_UNEXPECTEDLY(hRet))
+            return FALSE;
 
-        /* Create the tray notification window */
-        m_TrayNotify = CreateTrayNotifyWnd(this, HideClock, &m_TrayNotifyInstance);
+        SetWindowTheme(m_Rebar, L"TaskBar", NULL);
 
         UpdateFonts();
 
         InitShellServices(&m_ShellServices);
 
-        if (AutoHide)
+        if (g_TaskbarSettings.sr.AutoHide)
         {
             m_AutoHideState = AUTOHIDE_HIDING;
             SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_HIDE, NULL);
         }
 
+        /* Set the initial lock state in the band site */
+        m_TrayBandSite->Lock(g_TaskbarSettings.bLock);
+
         RegisterHotKey(m_hWnd, IDHK_RUN, MOD_WIN, 'R');
         RegisterHotKey(m_hWnd, IDHK_MINIMIZE_ALL, MOD_WIN, 'M');
         RegisterHotKey(m_hWnd, IDHK_RESTORE_ALL, MOD_WIN|MOD_SHIFT, 'M');
@@ -2271,10 +2342,7 @@ ChangePos:
     LRESULT OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
         if (m_TrayNotify)
-        {
-            TRACE("WM_COPYDATA notify message received. Handling...\n");
-            return TrayNotify_NotifyIconCmd(m_TrayNotifyInstance, wParam, lParam);
-        }
+            ::SendMessageW(m_TrayNotify, uMsg, wParam, lParam);
         return TRUE;
     }
 
@@ -2285,6 +2353,10 @@ ChangePos:
             bHandled = FALSE;
             return 0;
         }
+        else if (g_TaskbarSettings.bLock)
+        {
+            return 0;
+        }
 
         return DrawSizerWithTheme((HRGN) wParam);
     }
@@ -2300,7 +2372,7 @@ ChangePos:
         RECT rcClient;
         POINT pt;
 
-        if (Locked)
+        if (g_TaskbarSettings.bLock)
         {
             /* The user may not be able to resize the tray window.
             Pretend like the window is not sizeable when the user
@@ -2315,8 +2387,7 @@ ChangePos:
             pt.x = (SHORT) LOWORD(lParam);
             pt.y = (SHORT) HIWORD(lParam);
 
-            if (PtInRect(&rcClient,
-                pt))
+            if (PtInRect(&rcClient, pt))
             {
                 /* The user is trying to drag the tray window */
                 return HTCAPTION;
@@ -2346,7 +2417,6 @@ ChangePos:
             }
         }
         return HTBORDER;
-        return TRUE;
     }
 
     LRESULT OnMoving(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
@@ -2359,7 +2429,7 @@ ChangePos:
         need to be able to move the window in case the user wants to
         drag the tray window to another position or in case the user
         wants to resize the tray window. */
-        if (!Locked && GetCursorPos(&ptCursor))
+        if (!g_TaskbarSettings.bLock && GetCursorPos(&ptCursor))
         {
             IsDragging = TRUE;
             m_DraggingPosition = GetDraggingRectFromPt(ptCursor, pRect, &m_DraggingMonitor);
@@ -2367,14 +2437,6 @@ ChangePos:
         else
         {
             *pRect = m_TrayRects[m_Position];
-
-            if (AutoHide)
-            {
-                pRect->left += m_AutoHideOffset.cx;
-                pRect->right += m_AutoHideOffset.cx;
-                pRect->top += m_AutoHideOffset.cy;
-                pRect->bottom += m_AutoHideOffset.cy;
-            }
         }
         return TRUE;
     }
@@ -2383,26 +2445,18 @@ ChangePos:
     {
         PRECT pRect = (PRECT) lParam;
 
-        if (!Locked)
+        if (!g_TaskbarSettings.bLock)
         {
             FitToRebar(pRect);
         }
         else
         {
             *pRect = m_TrayRects[m_Position];
-
-            if (AutoHide)
-            {
-                pRect->left += m_AutoHideOffset.cx;
-                pRect->right += m_AutoHideOffset.cx;
-                pRect->top += m_AutoHideOffset.cy;
-                pRect->bottom += m_AutoHideOffset.cy;
-            }
         }
         return TRUE;
     }
 
-    LRESULT OnWindowPosChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
         ChangingWinPos((LPWINDOWPOS) lParam);
         return TRUE;
@@ -2438,7 +2492,7 @@ ChangePos:
     {
         InSizeMove = TRUE;
         IsDragging = FALSE;
-        if (!Locked)
+        if (!g_TaskbarSettings.bLock)
         {
             /* Remove the clipping on multi monitor systems while dragging around */
             ApplyClipping(FALSE);
@@ -2449,7 +2503,7 @@ ChangePos:
     LRESULT OnExitSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
         InSizeMove = FALSE;
-        if (!Locked)
+        if (!g_TaskbarSettings.bLock)
         {
             FitToRebar(&m_TrayRects[m_Position]);
 
@@ -2524,7 +2578,7 @@ ChangePos:
 
     LRESULT OnNcLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        /* This handler implements the trick that makes  the start button to 
+        /* This handler implements the trick that makes  the start button to
            get pressed when the user clicked left or below the button */
 
         POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
@@ -2693,23 +2747,11 @@ HandleTrayContextMenu:
 
     LRESULT OnNcLButtonDblClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
+        /* Let the clock handle the double click */
+        ::SendMessageW(m_TrayNotify, uMsg, wParam, lParam);
+
         /* We "handle" this message so users can't cause a weird maximize/restore
         window animation when double-clicking the tray window! */
-
-        /* We should forward mouse messages to child windows here.
-        Right now, this is only clock double-click */
-        RECT rcClock;
-        if (TrayNotify_GetClockRect(m_TrayNotifyInstance, &rcClock))
-        {
-            POINT ptClick;
-            ptClick.x = MAKEPOINTS(lParam).x;
-            ptClick.y = MAKEPOINTS(lParam).y;
-            if (PtInRect(&rcClock, ptClick))
-            {
-                //FIXME: use SHRunControlPanel
-                ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
-            }
-        }
         return TRUE;
     }
 
@@ -2764,6 +2806,88 @@ HandleTrayContextMenu:
         return HandleHotKey(wParam);
     }
 
+    struct MINIMIZE_INFO
+    {
+        HWND hwndDesktop;
+        HWND hTrayWnd;
+        HWND hwndProgman;
+        BOOL bRet;
+        CSimpleArray<HWND> *pMinimizedAll;
+        BOOL bShowDesktop;
+    };
+
+    static BOOL IsDialog(HWND hwnd)
+    {
+        WCHAR szClass[32];
+        GetClassNameW(hwnd, szClass, _countof(szClass));
+        return wcscmp(szClass, L"#32770") == 0;
+    }
+
+    static BOOL CALLBACK MinimizeWindowsProc(HWND hwnd, LPARAM lParam)
+    {
+        MINIMIZE_INFO *info = (MINIMIZE_INFO *)lParam;
+        if (hwnd == info->hwndDesktop || hwnd == info->hTrayWnd ||
+            hwnd == info->hwndProgman)
+        {
+            return TRUE;
+        }
+        if (!info->bShowDesktop)
+        {
+            if (!::IsWindowEnabled(hwnd) || IsDialog(hwnd))
+                return TRUE;
+            HWND hwndOwner = ::GetWindow(hwnd, GW_OWNER);
+            if (hwndOwner && !::IsWindowEnabled(hwndOwner))
+                return TRUE;
+        }
+        if (::IsWindowVisible(hwnd) && !::IsIconic(hwnd))
+        {
+            ::ShowWindowAsync(hwnd, SW_MINIMIZE);
+            info->bRet = TRUE;
+            info->pMinimizedAll->Add(hwnd);
+        }
+        return TRUE;
+    }
+
+    VOID MinimizeAll(BOOL bShowDesktop = FALSE)
+    {
+        MINIMIZE_INFO info;
+        info.hwndDesktop = GetDesktopWindow();;
+        info.hTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL);
+        info.hwndProgman = FindWindowW(L"Progman", NULL);
+        info.bRet = FALSE;
+        info.pMinimizedAll = &g_MinimizedAll;
+        info.bShowDesktop = bShowDesktop;
+        EnumWindows(MinimizeWindowsProc, (LPARAM)&info);
+
+        // invalid handles should be cleared to avoid mismatch of handles
+        for (INT i = 0; i < g_MinimizedAll.GetSize(); ++i)
+        {
+            if (!::IsWindow(g_MinimizedAll[i]))
+                g_MinimizedAll[i] = NULL;
+        }
+
+        ::SetForegroundWindow(m_DesktopWnd);
+        ::SetFocus(m_DesktopWnd);
+    }
+
+    VOID ShowDesktop()
+    {
+        MinimizeAll(TRUE);
+    }
+
+    VOID RestoreAll()
+    {
+        for (INT i = g_MinimizedAll.GetSize() - 1; i >= 0; --i)
+        {
+            HWND hwnd = g_MinimizedAll[i];
+            if (::IsWindowVisible(hwnd) && ::IsIconic(hwnd))
+            {
+                ::ShowWindow(hwnd, SW_RESTORE);
+            }
+        }
+        g_MinimizedAll.RemoveAll();
+    }
+
     LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
         LRESULT Ret = FALSE;
@@ -2782,7 +2906,7 @@ HandleTrayContextMenu:
 
     LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        if (AutoHide)
+        if (g_TaskbarSettings.sr.AutoHide)
         {
             SetTimer(TIMER_ID_MOUSETRACK, MOUSETRACK_INTERVAL, NULL);
         }
@@ -2809,7 +2933,7 @@ HandleTrayContextMenu:
     {
         RECT *rc = NULL;
         /* Ignore WM_NCCALCSIZE if we are not themed or locked */
-        if(!m_Theme || Locked)
+        if(!m_Theme || g_TaskbarSettings.bLock)
         {
             bHandled = FALSE;
             return 0;
@@ -2834,6 +2958,24 @@ HandleTrayContextMenu:
         return 0;
     }
 
+    LRESULT OnInitMenuPopup(INT code, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    {
+        HMENU hMenu = (HMENU)wParam;
+        if (::IsThereAnyEffectiveWindow(FALSE))
+        {
+            ::EnableMenuItem(hMenu, ID_SHELL_CMD_CASCADE_WND, MF_BYCOMMAND | MF_ENABLED);
+            ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_H, MF_BYCOMMAND | MF_ENABLED);
+            ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_V, MF_BYCOMMAND | MF_ENABLED);
+        }
+        else
+        {
+            ::EnableMenuItem(hMenu, ID_SHELL_CMD_CASCADE_WND, MF_BYCOMMAND | MF_GRAYED);
+            ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_H, MF_BYCOMMAND | MF_GRAYED);
+            ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_V, MF_BYCOMMAND | MF_GRAYED);
+        }
+        return 0;
+    }
+
     LRESULT OnRebarAutoSize(INT code, LPNMHDR nmhdr, BOOL& bHandled)
     {
 #if 0
@@ -2845,14 +2987,14 @@ HandleTrayContextMenu:
         RECT rc;
         ::GetWindowRect(m_hWnd, &rc);
 
-        SIZE szWindow = { 
-            rc.right - rc.left, 
+        SIZE szWindow = {
+            rc.right - rc.left,
             rc.bottom - rc.top };
-        SIZE szTarget = { 
-            as->rcTarget.right - as->rcTarget.left, 
+        SIZE szTarget = {
+            as->rcTarget.right - as->rcTarget.left,
             as->rcTarget.bottom - as->rcTarget.top };
-        SIZE szActual = { 
-            as->rcActual.right - as->rcActual.left, 
+        SIZE szActual = {
+            as->rcActual.right - as->rcActual.left,
             as->rcActual.bottom - as->rcActual.top };
 
         SIZE borders = {
@@ -2885,6 +3027,41 @@ HandleTrayContextMenu:
         return 0;
     }
 
+    LRESULT OnTaskbarSettingsChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    {
+        TaskbarSettings* newSettings = (TaskbarSettings*)lParam;
+
+        /* Propagate the new settings to the children */
+        ::SendMessageW(m_TaskSwitch, uMsg, wParam, lParam);
+        ::SendMessageW(m_TrayNotify, uMsg, wParam, lParam);
+
+        /* Toggle autohide */
+        if (newSettings->sr.AutoHide != g_TaskbarSettings.sr.AutoHide)
+        {
+            g_TaskbarSettings.sr.AutoHide = newSettings->sr.AutoHide;
+            memset(&m_AutoHideOffset, 0, sizeof(m_AutoHideOffset));
+            m_AutoHideState = AUTOHIDE_SHOWN;
+            if (!newSettings->sr.AutoHide)
+                SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER);
+            else
+                SetTimer(TIMER_ID_MOUSETRACK, MOUSETRACK_INTERVAL, NULL);
+        }
+
+        /* Toggle lock state */
+        Lock(newSettings->bLock);
+
+        /* Toggle OnTop state */
+        if (newSettings->sr.AlwaysOnTop != g_TaskbarSettings.sr.AlwaysOnTop)
+        {
+            g_TaskbarSettings.sr.AlwaysOnTop = newSettings->sr.AlwaysOnTop;
+            HWND hWndInsertAfter = newSettings->sr.AlwaysOnTop ? HWND_TOPMOST : HWND_BOTTOM;
+            SetWindowPos(hWndInsertAfter, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
+        }
+
+        g_TaskbarSettings.Save();
+        return 0;
+    }
+
     DECLARE_WND_CLASS_EX(szTrayWndClass, CS_DBLCLKS, COLOR_3DFACE)
 
     BEGIN_MSG_MAP(CTrayWindow)
@@ -2925,7 +3102,7 @@ HandleTrayContextMenu:
         MESSAGE_HANDLER(WM_CTLCOLORBTN, OnCtlColorBtn)
         MESSAGE_HANDLER(WM_MOVING, OnMoving)
         MESSAGE_HANDLER(WM_SIZING, OnSizing)
-        MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChange)
+        MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChanging)
         MESSAGE_HANDLER(WM_ENTERSIZEMOVE, OnEnterSizeMove)
         MESSAGE_HANDLER(WM_EXITSIZEMOVE, OnExitSizeMove)
         MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNcLButtonDown)
@@ -2935,11 +3112,13 @@ HandleTrayContextMenu:
         MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
         MESSAGE_HANDLER(WM_NCMOUSEMOVE, OnMouseMove)
         MESSAGE_HANDLER(WM_APP_TRAYDESTROY, OnAppTrayDestroy)
-        MESSAGE_HANDLER(TWM_OPENSTARTMENU, OnOpenStartMenu)
-        MESSAGE_HANDLER(TWM_DOEXITWINDOWS, OnDoExitWindows)
         MESSAGE_HANDLER(WM_CLOSE, OnDoExitWindows)
         MESSAGE_HANDLER(WM_HOTKEY, OnHotkey)
         MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize)
+        MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
+        MESSAGE_HANDLER(TWM_SETTINGSCHANGED, OnTaskbarSettingsChanged)
+        MESSAGE_HANDLER(TWM_OPENSTARTMENU, OnOpenStartMenu)
+        MESSAGE_HANDLER(TWM_DOEXITWINDOWS, OnDoExitWindows)
     ALT_MSG_MAP(1)
     END_MSG_MAP()
 
@@ -3080,15 +3259,29 @@ public:
         return S_OK;
     }
 
-    virtual HRESULT STDMETHODCALLTYPE 
+    virtual HRESULT STDMETHODCALLTYPE
         QueryContextMenu(HMENU hPopup,
                          UINT indexMenu,
                          UINT idCmdFirst,
                          UINT idCmdLast,
                          UINT uFlags)
     {
-        HMENU menubase = LoadPopupMenu(hExplorerInstance, MAKEINTRESOURCEW(IDM_TRAYWND));
-        if (!menubase)
+        HMENU hMenuBase;
+
+        hMenuBase = LoadPopupMenu(hExplorerInstance, MAKEINTRESOURCEW(IDM_TRAYWND));
+
+        if (g_MinimizedAll.GetSize() != 0 && !::IsThereAnyEffectiveWindow(TRUE))
+        {
+            CStringW strRestoreAll(MAKEINTRESOURCEW(IDS_RESTORE_ALL));
+            MENUITEMINFOW mii = { sizeof(mii) };
+            mii.fMask = MIIM_ID | MIIM_TYPE;
+            mii.wID = ID_SHELL_CMD_RESTORE_ALL;
+            mii.fType = MFT_STRING;
+            mii.dwTypeData = const_cast<LPWSTR>(&strRestoreAll[0]);
+            SetMenuItemInfoW(hMenuBase, ID_SHELL_CMD_SHOW_DESKTOP, FALSE, &mii);
+        }
+
+        if (!hMenuBase)
             return HRESULT_FROM_WIN32(GetLastError());
 
         if (SHRestricted(REST_CLASSICSHELL) != 0)
@@ -3098,15 +3291,15 @@ public:
                        MF_BYCOMMAND);
         }
 
-        CheckMenuItem(hPopup,
+        CheckMenuItem(hMenuBase,
                       ID_LOCKTASKBAR,
-                      MF_BYCOMMAND | (TrayWnd->Locked ? MF_CHECKED : MF_UNCHECKED));
+                      MF_BYCOMMAND | (g_TaskbarSettings.bLock ? MF_CHECKED : MF_UNCHECKED));
 
         UINT idCmdNext;
-        idCmdNext = Shell_MergeMenus(hPopup, menubase, indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS | MM_ADDSEPARATOR);
+        idCmdNext = Shell_MergeMenus(hPopup, hMenuBase, indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS | MM_ADDSEPARATOR);
         m_idCmdCmFirst = idCmdNext - idCmdFirst;
 
-        ::DestroyMenu(menubase);
+        ::DestroyMenu(hMenuBase);
 
         if (TrayWnd->m_TrayBandSite != NULL)
         {