[EXPLORER]: Simplify the creation of the tray band site and the tasks band.
[reactos.git] / reactos / base / shell / explorer / traywnd.cpp
index f4cca03..a8bc029 100644 (file)
@@ -53,9 +53,7 @@ HRESULT TrayWindowCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, ICont
 #define IDHK_DESKTOP 0x1fe
 #define IDHK_PAGER 0x1ff
 
-static LONG TrayWndCount = 0;
-
-static const WCHAR szTrayWndClass [] = TEXT("Shell_TrayWnd");
+static const WCHAR szTrayWndClass[] = L"Shell_TrayWnd";
 
 /*
  * ITrayWindow
@@ -64,16 +62,15 @@ static const WCHAR szTrayWndClass [] = TEXT("Shell_TrayWnd");
 const GUID IID_IShellDesktopTray = { 0x213e2df9, 0x9a14, 0x4328, { 0x99, 0xb1, 0x69, 0x61, 0xf9, 0x14, 0x3c, 0xe9 } };
 
 class CStartButton
-    : public CContainedWindow
+    : public CWindow
 {
     HIMAGELIST m_ImageList;
     SIZE       m_Size;
     HFONT      m_Font;
 
 public:
-    CStartButton(CMessageMap *pObject, DWORD dwMsgMapID)
-        : CContainedWindow(pObject, dwMsgMapID),
-          m_ImageList(NULL),
+    CStartButton()
+        : m_ImageList(NULL),
           m_Font(NULL)
     {
         m_Size.cx = 0;
@@ -89,260 +86,89 @@ public:
             DeleteObject(m_Font);
     }
 
-    HFONT GetFont()
-    {
-        return m_Font;
-    }
-
     SIZE GetSize()
     {
         return m_Size;
     }
 
-    VOID UpdateSize(IN HBITMAP hbmStart = NULL)
+    VOID UpdateSize()
     {
         SIZE Size = { 0, 0 };
 
         if (m_ImageList == NULL ||
             !SendMessageW(BCM_GETIDEALSIZE, 0, (LPARAM) &Size))
         {
-            Size.cx = 2 * GetSystemMetrics(SM_CXEDGE);
-            Size.cy = 2 * GetSystemMetrics(SM_CYEDGE);
-
-            if (hbmStart == NULL)
-            {
-                hbmStart = (HBITMAP) SendMessageW(BM_GETIMAGE, IMAGE_BITMAP, 0);
-            }
-
-            if (hbmStart != NULL)
-            {
-                BITMAP bmp;
-
-                if (GetObject(hbmStart, sizeof(bmp), &bmp) != 0)
-                {
-                    Size.cx += bmp.bmWidth;
-                    Size.cy += max(bmp.bmHeight, GetSystemMetrics(SM_CYCAPTION));
-                }
-                else
-                {
-                    /* Huh?! Shouldn't happen... */
-                    goto DefSize;
-                }
-            }
-            else
-            {
-DefSize:
-                Size.cx += GetSystemMetrics(SM_CXMINIMIZED);
-                Size.cy += GetSystemMetrics(SM_CYCAPTION);
-            }
+            Size.cx = 2 * GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CYCAPTION) * 3;
         }
 
+        if (GetWindowTheme(m_hWnd))
+            Size.cy = max(Size.cy, GetSystemMetrics(SM_CYCAPTION));
+        else
+            Size.cy = max(Size.cy, GetSystemMetrics(SM_CYSIZE) + (2 * GetSystemMetrics(SM_CYEDGE)));
+
         /* Save the size of the start button */
         m_Size = Size;
     }
 
-    BOOL CreateImageList()
+    VOID UpdateFont()
     {
-        HICON hIconStart;
-        SIZE IconSize;
-
-        if (m_ImageList != NULL)
-            return TRUE;
-
-        IconSize.cx = GetSystemMetrics(SM_CXSMICON);
-        IconSize.cy = GetSystemMetrics(SM_CYSMICON);
-
-        /* Load the start button icon and create a image list for it */
-        hIconStart = (HICON) LoadImage(hExplorerInstance,
-                                       MAKEINTRESOURCE(IDI_START),
-                                       IMAGE_ICON,
-                                       IconSize.cx,
-                                       IconSize.cy,
-                                       LR_SHARED | LR_DEFAULTCOLOR);
-
-        if (hIconStart == NULL)
-            return FALSE;
-
-        m_ImageList = ImageList_Create(IconSize.cx,
-                                        IconSize.cy,
-                                        ILC_COLOR32 | ILC_MASK,
-                                        1, 1);
-        if (m_ImageList == NULL)
-            return FALSE;
+        /* Get the system fonts, we use the caption font, always bold, though. */
+        NONCLIENTMETRICS ncm = {sizeof(ncm)};
+        if (!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE))
+            return;
 
-        int s = ImageList_ReplaceIcon(m_ImageList, -1, hIconStart);
-        if (s < 0)
-        {
-            /* Failed to add the icon! */
-            ImageList_Destroy(m_ImageList);
-            m_ImageList = NULL;
+        if (m_Font)
+            DeleteObject(m_Font);
 
-            return FALSE;
-        }
+        ncm.lfCaptionFont.lfWeight = FW_BOLD;
+        m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
 
-        return TRUE;
+        SetFont(m_Font, FALSE);
     }
 
-    HBITMAP CreateBitmap()
+    VOID Initialize()
     {
-        WCHAR szStartCaption[32];
-        HFONT hFontOld;
-        HDC hDC = NULL;
-        HDC hDCScreen = NULL;
-        SIZE Size, SmallIcon;
-        HBITMAP hbmpOld;
-        HBITMAP hBitmap = NULL;
-        HICON hIconStart;
-        BOOL Ret;
-        UINT Flags;
-        RECT rcButton;
-
-        /* NOTE: this is the backwards compatibility code that is used if the
-        Common Controls Version 6.0 are not available! */
-
-        if (!LoadString(hExplorerInstance,
-            IDS_START,
-            szStartCaption,
-            sizeof(szStartCaption) / sizeof(szStartCaption[0])))
-        {
-            return NULL;
-        }
-
-        /* Load the start button icon */
-        SmallIcon.cx = GetSystemMetrics(SM_CXSMICON);
-        SmallIcon.cy = GetSystemMetrics(SM_CYSMICON);
-        hIconStart = (HICON) LoadImage(hExplorerInstance,
-                                       MAKEINTRESOURCE(IDI_START),
-                                       IMAGE_ICON,
-                                       SmallIcon.cx,
-                                       SmallIcon.cy,
-                                       LR_SHARED | LR_DEFAULTCOLOR);
-
-        hDCScreen = ::GetDC(NULL);
-        if (hDCScreen == NULL)
-            goto Cleanup;
-
-        hDC = CreateCompatibleDC(hDCScreen);
-        if (hDC == NULL)
-            goto Cleanup;
-
-        hFontOld = (HFONT) SelectObject(hDC, m_Font);
-
-        Ret = GetTextExtentPoint32(hDC,
-                                   szStartCaption,
-                                   _tcslen(szStartCaption),
-                                   &Size);
-
-        SelectObject(hDC, hFontOld);
-        if (!Ret)
-            goto Cleanup;
-
-        /* Make sure the height is at least the size of a caption icon. */
-        if (hIconStart != NULL)
-            Size.cx += SmallIcon.cx + 4;
-        Size.cy = max(Size.cy, SmallIcon.cy);
-
-        /* Create the bitmap */
-        hBitmap = CreateCompatibleBitmap(hDCScreen,
-                                      Size.cx,
-                                      Size.cy);
-        if (hBitmap == NULL)
-            goto Cleanup;
-
-        /* Caluclate the button rect */
-        rcButton.left = 0;
-        rcButton.top = 0;
-        rcButton.right = Size.cx;
-        rcButton.bottom = Size.cy;
-
-        /* Draw the button */
-        hbmpOld = (HBITMAP) SelectObject(hDC, hBitmap);
-
-        Flags = DC_TEXT | DC_INBUTTON;
-        if (hIconStart != NULL)
-            Flags |= DC_ICON;
-
-        DrawCaptionTemp(NULL,
-                        hDC,
-                        &rcButton,
-                        m_Font,
-                        hIconStart,
-                        szStartCaption,
-                        Flags);
-
-        SelectObject(hDC, hbmpOld);
-
-        if (!Ret)
-            goto Cleanup;
-
-Cleanup:
-        if (hDCScreen != NULL)
-        {
-            ::ReleaseDC(NULL, hDCScreen);
-        }
+        SetWindowTheme(m_hWnd, L"Start", NULL);
 
-        if (hDC != NULL)
-            DeleteDC(hDC);
+        m_ImageList = ImageList_LoadImageW(hExplorerInstance,
+                                           MAKEINTRESOURCEW(IDB_START),
+                                           0, 0, 0,
+                                           IMAGE_BITMAP,
+                                           LR_LOADTRANSPARENT | LR_CREATEDIBSECTION);
 
-        return hBitmap;
+        BUTTON_IMAGELIST bil = {m_ImageList, {1,1,1,1}, BUTTON_IMAGELIST_ALIGN_LEFT};
+        SendMessageW(BCM_SETIMAGELIST, 0, (LPARAM) &bil);
+        UpdateSize();
     }
 
-    VOID Initialize()
+    HWND Create(HWND hwndParent)
     {
-        NONCLIENTMETRICS ncm;
-
-        SetWindowTheme(m_hWnd, L"Start", NULL);
-
-        if (m_Font == NULL)
+        WCHAR szStartCaption[32];
+        if (!LoadStringW(hExplorerInstance,
+                         IDS_START,
+                         szStartCaption,
+                         _countof(szStartCaption)))
         {
-            /* Get the system fonts, we use the caption font, always bold, though. */
-            ncm.cbSize = sizeof(ncm);
-            if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE))
-            {
-                ncm.lfCaptionFont.lfWeight = FW_BOLD;
-                m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
-            }
+            wcscpy(szStartCaption, L"Start");
         }
 
-        SendMessage(WM_SETFONT, (WPARAM) m_Font, FALSE);
-
-        if (CreateImageList())
-        {
-            BUTTON_IMAGELIST bil;
-
-            /* Try to set the start button image. this requires the Common
-            Controls 6.0 to be present (XP and later) */
-            bil.himl = m_ImageList;
-            bil.margin.left = bil.margin.right = 1;
-            bil.margin.top = bil.margin.bottom = 1;
-            bil.uAlign = BUTTON_IMAGELIST_ALIGN_LEFT;
-
-            if (SendMessageW(BCM_SETIMAGELIST, 0, (LPARAM) &bil))
-            {
-                /* We're using the image list, remove the BS_BITMAP style and
-                don't center it horizontally */
-                SetWindowStyle(m_hWnd, BS_BITMAP | BS_RIGHT, 0);
-
-                UpdateSize();
-                return;
-            }
-
-            /* Fall back to the deprecated method on older systems that don't
-            support Common Controls 6.0 */
-            ImageList_Destroy(m_ImageList);
-            m_ImageList = NULL;
-        }
+        DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | BS_PUSHBUTTON | BS_LEFT | BS_VCENTER;
 
-        HBITMAP hbmStart = CreateBitmap();
-        if (hbmStart != NULL)
-        {
-            UpdateSize(hbmStart);
+        m_hWnd = CreateWindowEx(
+            0,
+            WC_BUTTON,
+            szStartCaption,
+            dwStyle,
+            0, 0, 0, 0,
+            hwndParent,
+            (HMENU) IDC_STARTBTN,
+            hExplorerInstance,
+            NULL);
 
-            HBITMAP hbmOld = (HBITMAP) SendMessageW(BM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbmStart);
+        if (m_hWnd)
+            Initialize();
 
-            if (hbmOld != NULL)
-                DeleteObject(hbmOld);
-        }
+        return m_hWnd;
     }
 };
 
@@ -351,16 +177,17 @@ class CTrayWindow :
     public CComObjectRootEx<CComMultiThreadModelNoCS>,
     public CWindowImpl < CTrayWindow, CWindow, CControlWinTraits >,
     public ITrayWindow,
-    public IShellDesktopTray
+    public IShellDesktopTray,
+    public IOleWindow
 {
     CStartButton m_StartButton;
 
     CComPtr<IMenuBand>  m_StartMenuBand;
     CComPtr<IMenuPopup> m_StartMenuPopup;
 
+    CComPtr<IDeskBand> m_TaskBand;
     HTHEME m_Theme;
 
-    HFONT m_CaptionFont;
     HFONT m_Font;
 
     HWND m_DesktopWnd;
@@ -411,9 +238,8 @@ public:
 
 public:
     CTrayWindow() :
-        m_StartButton(this, 1),
+        m_StartButton(),
         m_Theme(NULL),
-        m_CaptionFont(NULL),
         m_Font(NULL),
         m_DesktopWnd(NULL),
         m_Rebar(NULL),
@@ -444,12 +270,6 @@ public:
             m_ShellServices = NULL;
         }
 
-        if (m_CaptionFont != NULL)
-        {
-            DeleteObject(m_CaptionFont);
-            m_CaptionFont = NULL;
-        }
-
         if (m_Font != NULL)
         {
             DeleteObject(m_Font);
@@ -462,378 +282,833 @@ public:
             m_Theme = NULL;
         }
 
-        if (InterlockedDecrement(&TrayWndCount) == 0)
-            PostQuitMessage(0);
+        PostQuitMessage(0);
     }
 
-    /*
-     * ITrayWindow
-     */
 
-    BOOL UpdateNonClientMetrics()
-    {
-        NONCLIENTMETRICS ncm;
-        ncm.cbSize = sizeof(ncm);
-        if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
-        {
-            if (m_Font != NULL)
-                DeleteObject(m_Font);
 
-            m_Font = CreateFontIndirect(&ncm.lfMessageFont);
-            return TRUE;
-        }
 
-        return FALSE;
-    }
 
-    VOID SetWindowsFont()
-    {
-        if (m_TrayNotify != NULL)
-        {
-            SendMessage(m_TrayNotify, WM_SETFONT, (WPARAM) m_Font, TRUE);
-        }
-    }
+    /**********************************************************
+     *    ##### command handling #####
+     */
 
-    HMONITOR GetScreenRectFromRect(
-        IN OUT RECT *pRect,
-        IN DWORD dwFlags)
+    HRESULT ExecResourceCmd(int id)
     {
-        MONITORINFO mi;
-        HMONITOR hMon;
+        WCHAR szCommand[256];
+        WCHAR *pszParameters;
 
-        mi.cbSize = sizeof(mi);
-        hMon = MonitorFromRect(pRect,
-                               dwFlags);
-        if (hMon != NULL &&
-            GetMonitorInfo(hMon,
-            &mi))
+        if (!LoadStringW(hExplorerInstance,
+                         id,
+                         szCommand,
+                         _countof(szCommand)))
         {
-            *pRect = mi.rcMonitor;
+            return E_FAIL;
         }
-        else
-        {
-            pRect->left = 0;
-            pRect->top = 0;
-            pRect->right = GetSystemMetrics(SM_CXSCREEN);
-            pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
 
-            hMon = NULL;
+        pszParameters = wcschr(szCommand, L'>');
+        if (pszParameters)
+        {
+            *pszParameters = 0;
+            pszParameters++;
         }
 
-        return hMon;
+        ShellExecuteW(m_hWnd, NULL, szCommand, pszParameters, NULL, SW_SHOWNORMAL);
+        return S_OK;
     }
 
-    HMONITOR GetMonitorFromRect(
-        IN const RECT *pRect)
+    LRESULT DoExitWindows()
     {
-        HMONITOR hMon;
+        ExitWindowsDialog(m_hWnd);
+        return 0;
+    }
 
-        /* In case the monitor sizes or saved sizes differ a bit (probably
-           not a lot, only so the tray window overlaps into another monitor
-           now), minimize the risk that we determine a wrong monitor by
-           using the center point of the tray window if we can't determine
-           it using the rectangle. */
-        hMon = MonitorFromRect(pRect,
-                               MONITOR_DEFAULTTONULL);
-        if (hMon == NULL)
-        {
-            POINT pt;
+    DWORD WINAPI RunFileDlgThread()
+    {
+        HWND hwnd;
+        RECT posRect;
 
-            pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
-            pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
+        m_StartButton.GetWindowRect(&posRect);
 
-            /* be less error-prone, find the nearest monitor */
-            hMon = MonitorFromPoint(pt,
-                                    MONITOR_DEFAULTTONEAREST);
-        }
+        hwnd = CreateWindowEx(0,
+                              WC_STATIC,
+                              NULL,
+                              WS_OVERLAPPED | WS_DISABLED | WS_CLIPSIBLINGS | WS_BORDER | SS_LEFT,
+                              posRect.left,
+                              posRect.top,
+                              posRect.right - posRect.left,
+                              posRect.bottom - posRect.top,
+                              NULL,
+                              NULL,
+                              NULL,
+                              NULL);
 
-        return hMon;
+        m_RunFileDlgOwner = hwnd;
+
+        RunFileDlg(hwnd, NULL, NULL, NULL, NULL, RFF_CALCDIRECTORY);
+
+        m_RunFileDlgOwner = NULL;
+        ::DestroyWindow(hwnd);
+
+        return 0;
     }
 
-    HMONITOR GetScreenRect(
-        IN HMONITOR hMonitor,
-        IN OUT RECT *pRect)
+    static DWORD WINAPI s_RunFileDlgThread(IN OUT PVOID pParam)
     {
-        HMONITOR hMon = NULL;
+        CTrayWindow * This = (CTrayWindow*) pParam;
+        return This->RunFileDlgThread();
+    }
 
-        if (hMonitor != NULL)
+    void DisplayRunFileDlg()
+    {
+        HWND hRunDlg;
+        if (m_RunFileDlgOwner)
         {
-            MONITORINFO mi;
-
-            mi.cbSize = sizeof(mi);
-            if (!GetMonitorInfo(hMonitor,
-                &mi))
+            hRunDlg = ::GetLastActivePopup(m_RunFileDlgOwner);
+            if (hRunDlg != NULL &&
+                hRunDlg != m_RunFileDlgOwner)
             {
-                /* Hm, the monitor is gone? Try to find a monitor where it
-                   could be located now */
-                hMon = GetMonitorFromRect(
-                    pRect);
-                if (hMon == NULL ||
-                    !GetMonitorInfo(hMon,
-                    &mi))
-                {
-                    hMon = NULL;
-                    goto GetPrimaryRect;
-                }
+                SetForegroundWindow(hRunDlg);
+                return;
             }
-
-            *pRect = mi.rcMonitor;
-        }
-        else
-        {
-GetPrimaryRect:
-            pRect->left = 0;
-            pRect->top = 0;
-            pRect->right = GetSystemMetrics(SM_CXSCREEN);
-            pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
         }
 
-        return hMon;
+        CloseHandle(CreateThread(NULL, 0, s_RunFileDlgThread, this, 0, NULL));
     }
 
-    VOID MakeTrayRectWithSize(IN DWORD Position,
-                              IN const SIZE *pTraySize,
-                              IN OUT RECT *pRect)
+    DWORD WINAPI TrayPropertiesThread()
     {
-        switch (Position)
-        {
-        case ABE_LEFT:
-            pRect->right = pRect->left + pTraySize->cx;
-            break;
+        HWND hwnd;
+        RECT posRect;
 
-        case ABE_TOP:
-            pRect->bottom = pRect->top + pTraySize->cy;
-            break;
+        m_StartButton.GetWindowRect(&posRect);
+        hwnd = CreateWindowEx(0,
+                              WC_STATIC,
+                              NULL,
+                              WS_OVERLAPPED | WS_DISABLED | WS_CLIPSIBLINGS | WS_BORDER | SS_LEFT,
+                              posRect.left,
+                              posRect.top,
+                              posRect.right - posRect.left,
+                              posRect.bottom - posRect.top,
+                              NULL,
+                              NULL,
+                              NULL,
+                              NULL);
 
-        case ABE_RIGHT:
-            pRect->left = pRect->right - pTraySize->cx;
-            break;
+        m_TrayPropertiesOwner = hwnd;
 
-        case ABE_BOTTOM:
-        default:
-            pRect->top = pRect->bottom - pTraySize->cy;
-            break;
-        }
-    }
+        DisplayTrayProperties(hwnd);
 
-    VOID GetTrayRectFromScreenRect(IN DWORD Position,
-                                   IN const RECT *pScreen,
-                                   IN const SIZE *pTraySize OPTIONAL,
-                                   OUT RECT *pRect)
-    {
-        if (pTraySize == NULL)
-            pTraySize = &m_TraySize;
-
-        *pRect = *pScreen;
-
-        /* Move the border outside of the screen */
-        InflateRect(pRect,
-                    GetSystemMetrics(SM_CXEDGE),
-                    GetSystemMetrics(SM_CYEDGE));
+        m_TrayPropertiesOwner = NULL;
+        ::DestroyWindow(hwnd);
 
-        MakeTrayRectWithSize(Position, pTraySize, pRect);
+        return 0;
     }
 
-    BOOL IsPosHorizontal()
+    static DWORD WINAPI s_TrayPropertiesThread(IN OUT PVOID pParam)
     {
-        return m_Position == ABE_TOP || m_Position == ABE_BOTTOM;
+        CTrayWindow *This = (CTrayWindow*) pParam;
+
+        return This->TrayPropertiesThread();
     }
 
-    HMONITOR CalculateValidSize(
-        IN DWORD Position,
-        IN OUT RECT *pRect)
+    HWND STDMETHODCALLTYPE DisplayProperties()
     {
-        RECT rcScreen;
-        //BOOL Horizontal;
-        HMONITOR hMon;
-        SIZE szMax, szWnd;
-
-        //Horizontal = IsPosHorizontal();
-
-        szWnd.cx = pRect->right - pRect->left;
-        szWnd.cy = pRect->bottom - pRect->top;
-
-        rcScreen = *pRect;
-        hMon = GetScreenRectFromRect(
-            &rcScreen,
-            MONITOR_DEFAULTTONEAREST);
-
-        /* Calculate the maximum size of the tray window and limit the window
-           size to half of the screen's size. */
-        szMax.cx = (rcScreen.right - rcScreen.left) / 2;
-        szMax.cy = (rcScreen.bottom - rcScreen.top) / 2;
-        if (szWnd.cx > szMax.cx)
-            szWnd.cx = szMax.cx;
-        if (szWnd.cy > szMax.cy)
-            szWnd.cy = szMax.cy;
-
-        /* FIXME - calculate */
+        HWND hTrayProp;
 
-        GetTrayRectFromScreenRect(
-            Position,
-            &rcScreen,
-            &szWnd,
-            pRect);
+        if (m_TrayPropertiesOwner)
+        {
+            hTrayProp = ::GetLastActivePopup(m_TrayPropertiesOwner);
+            if (hTrayProp != NULL &&
+                hTrayProp != m_TrayPropertiesOwner)
+            {
+                SetForegroundWindow(hTrayProp);
+                return NULL;
+            }
+        }
 
-        return hMon;
+        CloseHandle(CreateThread(NULL, 0, s_TrayPropertiesThread, this, 0, NULL));
+        return NULL;
     }
 
-#if 0
-    VOID
-        GetMinimumWindowSize(
-        OUT RECT *pRect)
+    VOID OpenCommonStartMenuDirectory(IN HWND hWndOwner, IN LPCTSTR lpOperation)
     {
-        RECT rcMin = {0};
-
-        AdjustWindowRectEx(&rcMin,
-                           GetWindowLong(m_hWnd,
-                           GWL_STYLE),
-                           FALSE,
-                           GetWindowLong(m_hWnd,
-                           GWL_EXSTYLE));
+        WCHAR szDir[MAX_PATH];
 
-        *pRect = rcMin;
+        if (SHGetSpecialFolderPath(hWndOwner,
+            szDir,
+            CSIDL_COMMON_STARTMENU,
+            FALSE))
+        {
+            ShellExecute(hWndOwner,
+                         lpOperation,
+                         szDir,
+                         NULL,
+                         NULL,
+                         SW_SHOWNORMAL);
+        }
     }
-#endif
 
-
-    DWORD GetDraggingRectFromPt(
-        IN POINT pt,
-        OUT RECT *pRect,
-        OUT HMONITOR *phMonitor)
+    VOID OpenTaskManager(IN HWND hWndOwner)
     {
-        HMONITOR hMon, hMonNew;
-        DWORD PosH, PosV, Pos;
-        SIZE DeltaPt, ScreenOffset;
-        RECT rcScreen;
+        ShellExecute(hWndOwner,
+                     TEXT("open"),
+                     TEXT("taskmgr.exe"),
+                     NULL,
+                     NULL,
+                     SW_SHOWNORMAL);
+    }
 
-        rcScreen.left = 0;
-        rcScreen.top = 0;
+    BOOL STDMETHODCALLTYPE ExecContextMenuCmd(IN UINT uiCmd)
+    {
+        switch (uiCmd)
+        {
+        case ID_SHELL_CMD_PROPERTIES:
+            DisplayProperties();
+            break;
 
-        /* Determine the screen rectangle */
-        hMon = MonitorFromPoint(pt,
-                                MONITOR_DEFAULTTONULL);
+        case ID_SHELL_CMD_OPEN_ALL_USERS:
+            OpenCommonStartMenuDirectory(m_hWnd,
+                                         TEXT("open"));
+            break;
 
-        if (hMon != NULL)
-        {
-            MONITORINFO mi;
+        case ID_SHELL_CMD_EXPLORE_ALL_USERS:
+            OpenCommonStartMenuDirectory(m_hWnd,
+                                         TEXT("explore"));
+            break;
 
-            mi.cbSize = sizeof(mi);
-            if (!GetMonitorInfo(hMon,
-                &mi))
+        case ID_LOCKTASKBAR:
+            if (SHRestricted(REST_CLASSICSHELL) == 0)
             {
-                hMon = NULL;
-                goto GetPrimaryScreenRect;
+                Lock(!Locked);
             }
+            break;
 
-            /* make left top corner of the screen zero based to
-               make calculations easier */
-            pt.x -= mi.rcMonitor.left;
-            pt.y -= mi.rcMonitor.top;
-
-            ScreenOffset.cx = mi.rcMonitor.left;
-            ScreenOffset.cy = mi.rcMonitor.top;
-            rcScreen.right = mi.rcMonitor.right - mi.rcMonitor.left;
-            rcScreen.bottom = mi.rcMonitor.bottom - mi.rcMonitor.top;
-        }
-        else
-        {
-GetPrimaryScreenRect:
-            ScreenOffset.cx = 0;
-            ScreenOffset.cy = 0;
-            rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
-            rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
-        }
+        case ID_SHELL_CMD_OPEN_TASKMGR:
+            OpenTaskManager(m_hWnd);
+            break;
 
-        /* Calculate the nearest screen border */
-        if (pt.x < rcScreen.right / 2)
-        {
-            DeltaPt.cx = pt.x;
-            PosH = ABE_LEFT;
-        }
-        else
-        {
-            DeltaPt.cx = rcScreen.right - pt.x;
-            PosH = ABE_RIGHT;
-        }
+        case ID_SHELL_CMD_UNDO_ACTION:
+            break;
 
-        if (pt.y < rcScreen.bottom / 2)
-        {
-            DeltaPt.cy = pt.y;
-            PosV = ABE_TOP;
-        }
-        else
-        {
-            DeltaPt.cy = rcScreen.bottom - pt.y;
-            PosV = ABE_BOTTOM;
-        }
+        case ID_SHELL_CMD_SHOW_DESKTOP:
+            break;
 
-        Pos = (DeltaPt.cx * rcScreen.bottom < DeltaPt.cy * rcScreen.right) ? PosH : PosV;
+        case ID_SHELL_CMD_TILE_WND_H:
+            TileWindows(NULL, MDITILE_HORIZONTAL, NULL, 0, NULL);
+            break;
 
-        /* Fix the screen origin to be relative to the primary monitor again */
-        OffsetRect(&rcScreen,
-                   ScreenOffset.cx,
-                   ScreenOffset.cy);
+        case ID_SHELL_CMD_TILE_WND_V:
+            TileWindows(NULL, MDITILE_VERTICAL, NULL, 0, NULL);
+            break;
 
-        RECT rcPos = m_TrayRects[Pos];
+        case ID_SHELL_CMD_CASCADE_WND:
+            CascadeWindows(NULL, MDITILE_SKIPDISABLED, NULL, 0, NULL);
+            break;
 
-        hMonNew = GetMonitorFromRect(&rcPos);
-        if (hMon != hMonNew)
-        {
-            SIZE szTray;
+        case ID_SHELL_CMD_CUST_NOTIF:
+            ShowCustomizeNotifyIcons(hExplorerInstance, m_hWnd);
+            break;
 
-            /* Recalculate the rectangle, we're dragging to another monitor.
-               We don't need to recalculate the rect on single monitor systems. */
-            szTray.cx = rcPos.right - rcPos.left;
-            szTray.cy = rcPos.bottom - rcPos.top;
+        case ID_SHELL_CMD_ADJUST_DAT:
+            //FIXME: Use SHRunControlPanel
+            ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
+            break;
 
-            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
-        {
-            /* 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;
-            }
+        default:
+            TRACE("ITrayWindow::ExecContextMenuCmd(%u): Unhandled Command ID!\n", uiCmd);
+            return FALSE;
         }
 
-        *phMonitor = hMon;
-
-        return Pos;
+        return TRUE;
     }
 
-    DWORD GetDraggingRectFromRect(
-        IN OUT RECT *pRect,
-        OUT HMONITOR *phMonitor)
+    LRESULT HandleHotKey(DWORD id)
     {
-        POINT pt;
-
-        /* Calculate the center of the rectangle. We call
-           GetDraggingRectFromPt to calculate a valid
-           dragging rectangle */
-        pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
-        pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
-
-        return GetDraggingRectFromPt(
-            pt,
-            pRect,
-            phMonitor);
-    }
-
+        switch (id)
+        {
+        case IDHK_RUN:
+            DisplayRunFileDlg();
+            break;
+        case IDHK_HELP:
+            ExecResourceCmd(IDS_HELP_COMMAND);
+            break;
+        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); 
+            break;
+        case IDHK_FIND:
+            SHFindFiles(NULL, NULL);
+            break;
+        case IDHK_FIND_COMPUTER:
+            SHFindComputer(NULL, NULL);
+            break;
+        case IDHK_SYS_PROPERTIES:
+            //FIXME: Use SHRunControlPanel
+            ShellExecuteW(m_hWnd, NULL, L"sysdm.cpl", NULL, NULL, SW_NORMAL);
+            break;
+        case IDHK_NEXT_TASK:
+            break;
+        case IDHK_PREV_TASK:
+            break;
+        case IDHK_MINIMIZE_ALL:
+            break;
+        case IDHK_RESTORE_ALL:
+            break;
+        case IDHK_DESKTOP:
+            break;
+        case IDHK_PAGER:
+            break;
+        }
+
+        return 0;
+    }
+
+    LRESULT HandleCommand(UINT uCommand)
+    {
+        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 IDM_SHUTDOWN:
+            DoExitWindows();
+            break;
+        }
+
+        return FALSE;
+    }
+
+
+    UINT TrackMenu(
+        IN HMENU hMenu,
+        IN POINT *ppt OPTIONAL,
+        IN HWND hwndExclude OPTIONAL,
+        IN BOOL TrackUp,
+        IN BOOL IsContextMenu)
+    {
+        TPMPARAMS tmp, *ptmp = NULL;
+        POINT pt;
+        UINT cmdId;
+        UINT fuFlags;
+
+        if (hwndExclude != NULL)
+        {
+            /* Get the client rectangle and map it to screen coordinates */
+            if (::GetClientRect(hwndExclude,
+                &tmp.rcExclude) &&
+                ::MapWindowPoints(hwndExclude,
+                NULL,
+                (LPPOINT) &tmp.rcExclude,
+                2) != 0)
+            {
+                ptmp = &tmp;
+            }
+        }
+
+        if (ppt == NULL)
+        {
+            if (ptmp == NULL &&
+                GetClientRect(&tmp.rcExclude) &&
+                MapWindowPoints(
+                NULL,
+                (LPPOINT) &tmp.rcExclude,
+                2) != 0)
+            {
+                ptmp = &tmp;
+            }
+
+            if (ptmp != NULL)
+            {
+                /* NOTE: TrackPopupMenuEx will eventually align the track position
+                         for us, no need to take care of it here as long as the
+                         coordinates are somewhere within the exclusion rectangle */
+                pt.x = ptmp->rcExclude.left;
+                pt.y = ptmp->rcExclude.top;
+            }
+            else
+                pt.x = pt.y = 0;
+        }
+        else
+            pt = *ppt;
+
+        tmp.cbSize = sizeof(tmp);
+
+        fuFlags = TPM_RETURNCMD | TPM_VERTICAL;
+        fuFlags |= (TrackUp ? TPM_BOTTOMALIGN : TPM_TOPALIGN);
+        if (IsContextMenu)
+            fuFlags |= TPM_RIGHTBUTTON;
+        else
+            fuFlags |= (TrackUp ? TPM_VERNEGANIMATION : TPM_VERPOSANIMATION);
+
+        cmdId = TrackPopupMenuEx(hMenu,
+                                 fuFlags,
+                                 pt.x,
+                                 pt.y,
+                                 m_hWnd,
+                                 ptmp);
+
+        return cmdId;
+    }
+
+    HRESULT TrackCtxMenu(
+        IN IContextMenu * contextMenu,
+        IN POINT *ppt OPTIONAL,
+        IN HWND hwndExclude OPTIONAL,
+        IN BOOL TrackUp,
+        IN PVOID Context OPTIONAL)
+    {
+        INT x = ppt->x;
+        INT y = ppt->y;
+        HRESULT hr;
+        UINT uCommand;
+        HMENU popup = CreatePopupMenu();
+
+        if (popup == NULL)
+            return E_FAIL;
+
+        TRACE("Before Query\n");
+        hr = contextMenu->QueryContextMenu(popup, 0, 0, UINT_MAX, CMF_NORMAL);
+        if (FAILED_UNEXPECTEDLY(hr))
+        {
+            TRACE("Query failed\n");
+            DestroyMenu(popup);
+            return hr;
+        }
+
+        TRACE("Before Tracking\n");
+        uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, x, y, m_hWnd, NULL);
+
+        if (uCommand != 0)
+        {
+            TRACE("Before InvokeCommand\n");
+            CMINVOKECOMMANDINFO cmi = { 0 };
+            cmi.cbSize = sizeof(cmi);
+            cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
+            cmi.hwnd = m_hWnd;
+            hr = contextMenu->InvokeCommand(&cmi);
+        }
+        else
+        {
+            TRACE("TrackPopupMenu failed. Code=%d, LastError=%d\n", uCommand, GetLastError());
+            hr = S_FALSE;
+        }
+
+        DestroyMenu(popup);
+        return hr;
+    }
+
+
+
+
+
+    /**********************************************************
+     *    ##### moving and sizing handling #####
+     */
+
+    void UpdateFonts()
+    {
+        m_StartButton.UpdateFont();
+
+        NONCLIENTMETRICS ncm = {sizeof(ncm)};
+        if (!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE))
+        {
+            ERR("SPI_GETNONCLIENTMETRICS failed\n");
+            return;
+        }
+
+        if (m_Font != NULL)
+            DeleteObject(m_Font);
+
+        ncm.lfCaptionFont.lfWeight = FW_NORMAL;
+        m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
+        if (!m_Font)
+        {
+            ERR("CreateFontIndirect failed\n");
+            return;
+        }
+
+        SendMessage(m_Rebar, WM_SETFONT, (WPARAM) m_Font, TRUE);
+        SendMessage(m_TaskSwitch, WM_SETFONT, (WPARAM) m_Font, TRUE);
+        SendMessage(m_TrayNotify, WM_SETFONT, (WPARAM) m_Font, TRUE);
+    }
+
+    HMONITOR GetScreenRectFromRect(
+        IN OUT RECT *pRect,
+        IN DWORD dwFlags)
+    {
+        MONITORINFO mi;
+        HMONITOR hMon;
+
+        mi.cbSize = sizeof(mi);
+        hMon = MonitorFromRect(pRect, dwFlags);
+        if (hMon != NULL &&
+            GetMonitorInfo(hMon, &mi))
+        {
+            *pRect = mi.rcMonitor;
+        }
+        else
+        {
+            pRect->left = 0;
+            pRect->top = 0;
+            pRect->right = GetSystemMetrics(SM_CXSCREEN);
+            pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
+
+            hMon = NULL;
+        }
+
+        return hMon;
+    }
+
+    HMONITOR GetMonitorFromRect(
+        IN const RECT *pRect)
+    {
+        HMONITOR hMon;
+
+        /* In case the monitor sizes or saved sizes differ a bit (probably
+           not a lot, only so the tray window overlaps into another monitor
+           now), minimize the risk that we determine a wrong monitor by
+           using the center point of the tray window if we can't determine
+           it using the rectangle. */
+        hMon = MonitorFromRect(pRect, MONITOR_DEFAULTTONULL);
+        if (hMon == NULL)
+        {
+            POINT pt;
+
+            pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
+            pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
+
+            /* be less error-prone, find the nearest monitor */
+            hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
+        }
+
+        return hMon;
+    }
+
+    HMONITOR GetScreenRect(
+        IN HMONITOR hMonitor,
+        IN OUT RECT *pRect)
+    {
+        HMONITOR hMon = NULL;
+
+        if (hMonitor != NULL)
+        {
+            MONITORINFO mi;
+
+            mi.cbSize = sizeof(mi);
+            if (!GetMonitorInfo(hMonitor, &mi))
+            {
+                /* Hm, the monitor is gone? Try to find a monitor where it
+                   could be located now */
+                hMon = GetMonitorFromRect(pRect);
+                if (hMon == NULL ||
+                    !GetMonitorInfo(hMon, &mi))
+                {
+                    hMon = NULL;
+                    goto GetPrimaryRect;
+                }
+            }
+
+            *pRect = mi.rcMonitor;
+        }
+        else
+        {
+GetPrimaryRect:
+            pRect->left = 0;
+            pRect->top = 0;
+            pRect->right = GetSystemMetrics(SM_CXSCREEN);
+            pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
+        }
+
+        return hMon;
+    }
+
+    VOID AdjustSizerRect(RECT *rc, DWORD pos)
+    {
+        switch (pos)
+        {
+            case ABE_TOP:
+                rc->bottom -= GetSystemMetrics(SM_CXSIZEFRAME);
+                break;
+            case ABE_BOTTOM:
+                rc->top += GetSystemMetrics(SM_CXSIZEFRAME);
+                break;
+            case ABE_LEFT:
+                rc->right -= GetSystemMetrics(SM_CYSIZEFRAME);
+                break;
+            case ABE_RIGHT:
+                rc->left += GetSystemMetrics(SM_CYSIZEFRAME);
+                break;
+        }
+
+    }
+
+    VOID MakeTrayRectWithSize(IN DWORD Position,
+                              IN const SIZE *pTraySize,
+                              IN OUT RECT *pRect)
+    {
+        switch (Position)
+        {
+        case ABE_LEFT:
+            pRect->right = pRect->left + pTraySize->cx;
+            break;
+
+        case ABE_TOP:
+            pRect->bottom = pRect->top + pTraySize->cy;
+            break;
+
+        case ABE_RIGHT:
+            pRect->left = pRect->right - pTraySize->cx;
+            break;
+
+        case ABE_BOTTOM:
+        default:
+            pRect->top = pRect->bottom - pTraySize->cy;
+            break;
+        }
+    }
+
+    VOID GetTrayRectFromScreenRect(IN DWORD Position,
+                                   IN const RECT *pScreen,
+                                   IN const SIZE *pTraySize OPTIONAL,
+                                   OUT RECT *pRect)
+    {
+        if (pTraySize == NULL)
+            pTraySize = &m_TraySize;
+
+        *pRect = *pScreen;
+
+        if(!IsThemeActive())
+        {
+            /* Move the border outside of the screen */
+            InflateRect(pRect,
+                        GetSystemMetrics(SM_CXEDGE),
+                        GetSystemMetrics(SM_CYEDGE));
+        }
+
+        MakeTrayRectWithSize(Position, pTraySize, pRect);
+    }
+
+    BOOL IsPosHorizontal()
+    {
+        return m_Position == ABE_TOP || m_Position == ABE_BOTTOM;
+    }
+
+    HMONITOR CalculateValidSize(
+        IN DWORD Position,
+        IN OUT RECT *pRect)
+    {
+        RECT rcScreen;
+        //BOOL Horizontal;
+        HMONITOR hMon;
+        SIZE szMax, szWnd;
+
+        //Horizontal = IsPosHorizontal();
+
+        szWnd.cx = pRect->right - pRect->left;
+        szWnd.cy = pRect->bottom - pRect->top;
+
+        rcScreen = *pRect;
+        hMon = GetScreenRectFromRect(
+            &rcScreen,
+            MONITOR_DEFAULTTONEAREST);
+
+        /* Calculate the maximum size of the tray window and limit the window
+           size to half of the screen's size. */
+        szMax.cx = (rcScreen.right - rcScreen.left) / 2;
+        szMax.cy = (rcScreen.bottom - rcScreen.top) / 2;
+        if (szWnd.cx > szMax.cx)
+            szWnd.cx = szMax.cx;
+        if (szWnd.cy > szMax.cy)
+            szWnd.cy = szMax.cy;
+
+        /* FIXME - calculate */
+
+        GetTrayRectFromScreenRect(Position,
+                                  &rcScreen,
+                                  &szWnd,
+                                  pRect);
+
+        return hMon;
+    }
+
+#if 0
+    VOID
+        GetMinimumWindowSize(
+        OUT RECT *pRect)
+    {
+        RECT rcMin = {0};
+
+        AdjustWindowRectEx(&rcMin,
+                           GetWindowLong(m_hWnd,
+                           GWL_STYLE),
+                           FALSE,
+                           GetWindowLong(m_hWnd,
+                           GWL_EXSTYLE));
+
+        *pRect = rcMin;
+    }
+#endif
+
+
+    DWORD GetDraggingRectFromPt(
+        IN POINT pt,
+        OUT RECT *pRect,
+        OUT HMONITOR *phMonitor)
+    {
+        HMONITOR hMon, hMonNew;
+        DWORD PosH, PosV, Pos;
+        SIZE DeltaPt, ScreenOffset;
+        RECT rcScreen;
+
+        rcScreen.left = 0;
+        rcScreen.top = 0;
+
+        /* Determine the screen rectangle */
+        hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
+        if (hMon != NULL)
+        {
+            MONITORINFO mi;
+
+            mi.cbSize = sizeof(mi);
+            if (!GetMonitorInfo(hMon, &mi))
+            {
+                hMon = NULL;
+                goto GetPrimaryScreenRect;
+            }
+
+            /* make left top corner of the screen zero based to
+               make calculations easier */
+            pt.x -= mi.rcMonitor.left;
+            pt.y -= mi.rcMonitor.top;
+
+            ScreenOffset.cx = mi.rcMonitor.left;
+            ScreenOffset.cy = mi.rcMonitor.top;
+            rcScreen.right = mi.rcMonitor.right - mi.rcMonitor.left;
+            rcScreen.bottom = mi.rcMonitor.bottom - mi.rcMonitor.top;
+        }
+        else
+        {
+GetPrimaryScreenRect:
+            ScreenOffset.cx = 0;
+            ScreenOffset.cy = 0;
+            rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
+            rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
+        }
+
+        /* Calculate the nearest screen border */
+        if (pt.x < rcScreen.right / 2)
+        {
+            DeltaPt.cx = pt.x;
+            PosH = ABE_LEFT;
+        }
+        else
+        {
+            DeltaPt.cx = rcScreen.right - pt.x;
+            PosH = ABE_RIGHT;
+        }
+
+        if (pt.y < rcScreen.bottom / 2)
+        {
+            DeltaPt.cy = pt.y;
+            PosV = ABE_TOP;
+        }
+        else
+        {
+            DeltaPt.cy = rcScreen.bottom - pt.y;
+            PosV = ABE_BOTTOM;
+        }
+
+        Pos = (DeltaPt.cx * rcScreen.bottom < DeltaPt.cy * rcScreen.right) ? PosH : PosV;
+
+        /* Fix the screen origin to be relative to the primary monitor again */
+        OffsetRect(&rcScreen,
+                   ScreenOffset.cx,
+                   ScreenOffset.cy);
+
+        RECT rcPos = m_TrayRects[Pos];
+
+        hMonNew = GetMonitorFromRect(&rcPos);
+        if (hMon != hMonNew)
+        {
+            SIZE szTray;
+
+            /* Recalculate the rectangle, we're dragging to another monitor.
+               We don't need to recalculate the rect on single monitor systems. */
+            szTray.cx = rcPos.right - rcPos.left;
+            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
+        {
+            /* 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;
+
+        return Pos;
+    }
+
+    DWORD GetDraggingRectFromRect(
+        IN OUT RECT *pRect,
+        OUT HMONITOR *phMonitor)
+    {
+        POINT pt;
+
+        /* Calculate the center of the rectangle. We call
+           GetDraggingRectFromPt to calculate a valid
+           dragging rectangle */
+        pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
+        pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
+
+        return GetDraggingRectFromPt(
+            pt,
+            pRect,
+            phMonitor);
+    }
+
     VOID ChangingWinPos(IN OUT LPWINDOWPOS pwp)
     {
         RECT rcTray;
@@ -864,9 +1139,8 @@ GetPrimaryScreenRect:
                 //m_TrayRects[DraggingPosition] = rcTray;
             }
 
-            //Monitor = CalculateValidSize(
-            //                                                   DraggingPosition,
-            //                                                   &rcTray);
+            //Monitor = CalculateValidSize(DraggingPosition,
+            //                             &rcTray);
 
             m_Monitor = m_DraggingMonitor;
             m_Position = m_DraggingPosition;
@@ -986,10 +1260,10 @@ ChangePos:
         if (m_PreviousMonitor != m_Monitor)
         {
             GetScreenRect(m_PreviousMonitor, &rcWorkArea);
-            SystemParametersInfo(SPI_SETWORKAREA,
-                                 1,
-                                 &rcWorkArea,
-                                 SPIF_SENDCHANGE);
+            SystemParametersInfoW(SPI_SETWORKAREA,
+                                  1,
+                                  &rcWorkArea,
+                                  SPIF_SENDCHANGE);
         }
 
         rcTray = m_TrayRects[m_Position];
@@ -997,8 +1271,8 @@ ChangePos:
         GetScreenRect(m_Monitor, &rcWorkArea);
         m_PreviousMonitor = m_Monitor;
 
-        /* If AutoHide is false then change the workarea to exclude the area that
-           the taskbar covers. */
+        /* If AutoHide is false then change the workarea to exclude
+           the area that the taskbar covers. */
         if (!AutoHide)
         {
             switch (m_Position)
@@ -1018,10 +1292,14 @@ ChangePos:
             }
         }
 
-        SystemParametersInfo(SPI_SETWORKAREA,
-                             1,
-                             &rcWorkArea,
-                             SPIF_SENDCHANGE);
+        /*
+         * Resize the current monitor work area. Win32k will also send
+         * a WM_SIZE message to automatically resize the desktop.
+         */
+        SystemParametersInfoW(SPI_SETWORKAREA,
+                              1,
+                              &rcWorkArea,
+                              SPIF_SENDCHANGE);
 #endif
     }
 
@@ -1039,13 +1317,23 @@ ChangePos:
             rcTray.bottom += m_AutoHideOffset.cy;
         }
 
+        IUnknown_Exec(m_TrayBandSite,
+                      IID_IDeskBand,
+                      DBID_BANDINFOCHANGED,
+                      0,
+                      NULL,
+                      NULL);
+
+        FitToRebar(&rcTray);
+        m_TrayRects[m_Position] = rcTray;
+
         /* Move the tray window */
         SetWindowPos(NULL,
                      rcTray.left,
                      rcTray.top,
                      rcTray.right - rcTray.left,
                      rcTray.bottom - rcTray.top,
-                     SWP_NOZORDER);
+                     SWP_NOZORDER | SWP_NOACTIVATE);
 
         ResizeWorkArea();
 
@@ -1119,8 +1407,18 @@ ChangePos:
                entire window size, not just the client size. However, we
                use a thinner border than a standard thick border, so that
                the start button and bands are not stuck to the screen border. */
-            sr.Size.cx = StartBtnSize.cx + (2 * (EdgeSize.cx + DlgFrameSize.cx));
-            sr.Size.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
+            if(!IsThemeActive())
+            {
+                sr.Size.cx = StartBtnSize.cx + (2 * (EdgeSize.cx + DlgFrameSize.cx));
+                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);
+            }
 
             /* Use the primary screen by default */
             rcScreen.left = 0;
@@ -1139,161 +1437,48 @@ ChangePos:
             0,
             0,
             0,
-            SWP_NOMOVE | SWP_NOSIZE);
+            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
            loaded from the registry are at least. The windows explorer behaves
            the same way, it allows the user to save a zero width vertical tray
-           window, but not a zero height horizontal tray window. */
-        WndSize.cx = 2 * (EdgeSize.cx + DlgFrameSize.cx);
-        WndSize.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
-
-        if (WndSize.cx < sr.Size.cx)
-            WndSize.cx = sr.Size.cx;
-        if (WndSize.cy < sr.Size.cy)
-            WndSize.cy = sr.Size.cy;
-
-        /* Save the calculated size */
-        m_TraySize = WndSize;
-
-        /* Calculate all docking rectangles. We need to do this here so they're
-           initialized and dragging the tray window to another position gives
-           usable results */
-        for (Pos = ABE_LEFT;
-             Pos <= ABE_BOTTOM;
-             Pos++)
-        {
-            GetTrayRectFromScreenRect(
-                Pos,
-                &rcScreen,
-                &m_TraySize,
-                &m_TrayRects[Pos]);
-            //        TRACE("m_TrayRects[%d(%d)]: %d,%d,%d,%d\n", Pos, Position, m_TrayRects[Pos].left, m_TrayRects[Pos].top, m_TrayRects[Pos].right, m_TrayRects[Pos].bottom);
-        }
-
-        /* Determine which monitor we are on. It shouldn't matter which docked
-           position rectangle we use */
-        m_Monitor = GetMonitorFromRect(&m_TrayRects[ABE_LEFT]);
-    }
-
-    UINT TrackMenu(
-        IN HMENU hMenu,
-        IN POINT *ppt OPTIONAL,
-        IN HWND hwndExclude OPTIONAL,
-        IN BOOL TrackUp,
-        IN BOOL IsContextMenu)
-    {
-        TPMPARAMS tmp, *ptmp = NULL;
-        POINT pt;
-        UINT cmdId;
-        UINT fuFlags;
-
-        if (hwndExclude != NULL)
-        {
-            /* Get the client rectangle and map it to screen coordinates */
-            if (::GetClientRect(hwndExclude,
-                &tmp.rcExclude) &&
-                ::MapWindowPoints(hwndExclude,
-                NULL,
-                (LPPOINT) &tmp.rcExclude,
-                2) != 0)
-            {
-                ptmp = &tmp;
-            }
-        }
-
-        if (ppt == NULL)
-        {
-            if (ptmp == NULL &&
-                GetClientRect(&tmp.rcExclude) &&
-                MapWindowPoints(
-                NULL,
-                (LPPOINT) &tmp.rcExclude,
-                2) != 0)
-            {
-                ptmp = &tmp;
-            }
-
-            if (ptmp != NULL)
-            {
-                /* NOTE: TrackPopupMenuEx will eventually align the track position
-                         for us, no need to take care of it here as long as the
-                         coordinates are somewhere within the exclusion rectangle */
-                pt.x = ptmp->rcExclude.left;
-                pt.y = ptmp->rcExclude.top;
-            }
-            else
-                pt.x = pt.y = 0;
-        }
-        else
-            pt = *ppt;
-
-        tmp.cbSize = sizeof(tmp);
-
-        fuFlags = TPM_RETURNCMD | TPM_VERTICAL;
-        fuFlags |= (TrackUp ? TPM_BOTTOMALIGN : TPM_TOPALIGN);
-        if (IsContextMenu)
-            fuFlags |= TPM_RIGHTBUTTON;
-        else
-            fuFlags |= (TrackUp ? TPM_VERNEGANIMATION : TPM_VERPOSANIMATION);
-
-        cmdId = TrackPopupMenuEx(hMenu,
-                                 fuFlags,
-                                 pt.x,
-                                 pt.y,
-                                 m_hWnd,
-                                 ptmp);
-
-        return cmdId;
-    }
-
-    HRESULT TrackCtxMenu(
-        IN IContextMenu * contextMenu,
-        IN POINT *ppt OPTIONAL,
-        IN HWND hwndExclude OPTIONAL,
-        IN BOOL TrackUp,
-        IN PVOID Context OPTIONAL)
-    {
-        INT x = ppt->x;
-        INT y = ppt->y;
-        HRESULT hr;
-        UINT uCommand;
-        HMENU popup = CreatePopupMenu();
-
-        if (popup == NULL)
-            return E_FAIL;
-
-        TRACE("Before Query\n");
-        hr = contextMenu->QueryContextMenu(popup, 0, 0, UINT_MAX, CMF_NORMAL);
-        if (FAILED_UNEXPECTEDLY(hr))
-        {
-            TRACE("Query failed\n");
-            DestroyMenu(popup);
-            return hr;
-        }
-        
-        TRACE("Before Tracking\n");
-        uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, x, y, m_hWnd, NULL);
-
-        if (uCommand != 0)
-        {
-            TRACE("Before InvokeCommand\n");
-            CMINVOKECOMMANDINFO cmi = { 0 };
-            cmi.cbSize = sizeof(cmi);
-            cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
-            cmi.hwnd = m_hWnd;
-            hr = contextMenu->InvokeCommand(&cmi);
+           window, but not a zero height horizontal tray window. */
+        if(!IsThemeActive())
+        {
+            WndSize.cx = 2 * (EdgeSize.cx + DlgFrameSize.cx);
+            WndSize.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
         }
         else
         {
-            TRACE("TrackPopupMenu failed. Code=%d, LastError=%d\n", uCommand, GetLastError());
-            hr = S_FALSE;
+            WndSize.cx = StartBtnSize.cx;
+            WndSize.cy = StartBtnSize.cy - EdgeSize.cx;
         }
 
-        DestroyMenu(popup);
-        return hr;
+        if (WndSize.cx < sr.Size.cx)
+            WndSize.cx = sr.Size.cx;
+        if (WndSize.cy < sr.Size.cy)
+            WndSize.cy = sr.Size.cy;
+
+        /* Save the calculated size */
+        m_TraySize = WndSize;
+
+        /* Calculate all docking rectangles. We need to do this here so they're
+           initialized and dragging the tray window to another position gives
+           usable results */
+        for (Pos = ABE_LEFT; Pos <= ABE_BOTTOM; Pos++)
+        {
+            GetTrayRectFromScreenRect(Pos,
+                                      &rcScreen,
+                                      &m_TraySize,
+                                      &m_TrayRects[Pos]);
+            // TRACE("m_TrayRects[%d(%d)]: %d,%d,%d,%d\n", Pos, Position, m_TrayRects[Pos].left, m_TrayRects[Pos].top, m_TrayRects[Pos].right, m_TrayRects[Pos].bottom);
+        }
+
+        /* Determine which monitor we are on. It shouldn't matter which docked
+           position rectangle we use */
+        m_Monitor = GetMonitorFromRect(&m_TrayRects[ABE_LEFT]);
     }
 
     VOID AlignControls(IN PRECT prcClient OPTIONAL)
@@ -1329,7 +1514,7 @@ ChangePos:
             return;
         }
 
-        /* Limit the Start button width to the client width, if neccessary */
+        /* Limit the Start button width to the client width, if necessary */
         StartSize = m_StartButton.GetSize();
         if (StartSize.cx > rcClient.right)
             StartSize.cx = rcClient.right;
@@ -1365,9 +1550,9 @@ ChangePos:
 
         if (m_TrayNotify != NULL &&
             SendMessage(m_TrayNotify,
-            TNWM_GETMINIMUMSIZE,
-            (WPARAM) Horizontal,
-            (LPARAM) &TraySize))
+                        TNWM_GETMINIMUMSIZE,
+                        (WPARAM)Horizontal,
+                        (LPARAM)&TraySize))
         {
             /* Move the tray notification window to the desired location */
             if (Horizontal)
@@ -1421,412 +1606,274 @@ ChangePos:
                                    SWP_NOZORDER | SWP_NOACTIVATE);
         }
 
-        if (dwp != NULL)
-            EndDeferWindowPos(dwp);
-
-        if (m_TaskSwitch != NULL)
-        {
-            /* Update the task switch window configuration */
-            SendMessage(m_TaskSwitch, TSWM_UPDATETASKBARPOS, 0, 0);
-        }
-    }
-
-    LRESULT OnThemeChanged()
-    {
-        if (m_Theme)
-            CloseThemeData(m_Theme);
-
-        if (IsThemeActive())
-            m_Theme = OpenThemeData(m_hWnd, L"TaskBar");
-        else
-            m_Theme = NULL;
-
-        if (Locked && m_Theme)
-        {
-            SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, 0);
-        }
-        else
-        {
-            SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, WS_THICKFRAME | WS_BORDER);
-        }
-        SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
-
-        return TRUE;
-    }
-
-    LRESULT OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        return OnThemeChanged();
-    }
-
-    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        WCHAR szStartCaption[32];
-
-        ((ITrayWindow*)this)->AddRef();
-
-        SetWindowTheme(m_hWnd, L"TaskBar", NULL);
-        OnThemeChanged();
-
-        InterlockedIncrement(&TrayWndCount);
-
-        if (!LoadString(hExplorerInstance,
-            IDS_START,
-            szStartCaption,
-            sizeof(szStartCaption) / sizeof(szStartCaption[0])))
-        {
-            szStartCaption[0] = TEXT('\0');
-        }
-
-        if (m_CaptionFont == NULL)
-        {
-            NONCLIENTMETRICS ncm;
-
-            /* Get the system fonts, we use the caption font,
-               always bold, though. */
-            ncm.cbSize = sizeof(ncm);
-            if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE))
-            {
-                if (m_CaptionFont == NULL)
-                {
-                    ncm.lfCaptionFont.lfWeight = FW_NORMAL;
-                    m_CaptionFont = CreateFontIndirect(&ncm.lfCaptionFont);
-                }
-            }
-        }
-        
-        /* Create the Start button */
-        m_StartButton.SubclassWindow(CreateWindowEx(
-            0,
-            WC_BUTTON,
-            szStartCaption,
-            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
-            BS_PUSHBUTTON | BS_CENTER | BS_VCENTER | BS_BITMAP,
-            0,
-            0,
-            0,
-            0,
-            m_hWnd,
-            (HMENU) IDC_STARTBTN,
-            hExplorerInstance,
-            NULL));
-
-        if (m_StartButton.m_hWnd)
-        {
-            m_StartButton.Initialize();
-        }
-
-        /* Load the saved tray window settings */
-        RegLoadSettings();
-
-        /* Create and initialize the start menu */
-        HBITMAP hbmBanner = LoadBitmap(hExplorerInstance, MAKEINTRESOURCE(IDB_STARTMENU));
-        m_StartMenuPopup = CreateStartMenu(this, &m_StartMenuBand, hbmBanner, 0);
-
-        /* Load the tray band site */
-        if (m_TrayBandSite != NULL)
-        {
-            m_TrayBandSite.Release();
-        }
-
-        m_TrayBandSite = CreateTrayBandSite(this, &m_Rebar, &m_TaskSwitch);
-        SetWindowTheme(m_Rebar, L"TaskBar", NULL);
-
-        /* Create the tray notification window */
-        m_TrayNotify = CreateTrayNotifyWnd(this, HideClock, &m_TrayNotifyInstance);
-
-        if (UpdateNonClientMetrics())
-        {
-            SetWindowsFont();
-        }
-
-        /* Move the tray window to the right position and resize it if neccessary */
-        CheckTrayWndPosition();
-
-        /* Align all controls on the tray window */
-        AlignControls(NULL);
-
-        InitShellServices(&(m_ShellServices));
-
-        if (AutoHide)
-        {
-            m_AutoHideState = AUTOHIDE_HIDING;
-            SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_HIDE, NULL);
-        }
-
-        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');
-        RegisterHotKey(m_hWnd, IDHK_HELP, MOD_WIN, VK_F1);
-        RegisterHotKey(m_hWnd, IDHK_EXPLORE, MOD_WIN, 'E');
-        RegisterHotKey(m_hWnd, IDHK_FIND, MOD_WIN, 'F');
-        RegisterHotKey(m_hWnd, IDHK_FIND_COMPUTER, MOD_WIN|MOD_CONTROL, 'F');
-        RegisterHotKey(m_hWnd, IDHK_NEXT_TASK, MOD_WIN, VK_TAB);
-        RegisterHotKey(m_hWnd, IDHK_PREV_TASK, MOD_WIN|MOD_SHIFT, VK_TAB);
-        RegisterHotKey(m_hWnd, IDHK_SYS_PROPERTIES, MOD_WIN, VK_PAUSE);
-        RegisterHotKey(m_hWnd, IDHK_DESKTOP, MOD_WIN, 'D');
-        RegisterHotKey(m_hWnd, IDHK_PAGER, MOD_WIN, 'B');
-
-        return TRUE;
-    }
-
-    HRESULT STDMETHODCALLTYPE Open()
-    {
-        RECT rcWnd;
-
-        /* Check if there's already a window created and try to show it.
-           If it was somehow destroyed just create a new tray window. */
-        if (m_hWnd != NULL && IsWindow())
-        {
-            if (!IsWindowVisible())
-            {
-                CheckTrayWndPosition();
-
-                ShowWindow(SW_SHOW);
-            }
-
-            return S_OK;
-        }
-
-        DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
-        if (AlwaysOnTop)
-            dwExStyle |= WS_EX_TOPMOST;
-
-        DWORD dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
-            WS_BORDER | WS_THICKFRAME;
-
-        ZeroMemory(&rcWnd, sizeof(rcWnd));
-        if (m_Position != (DWORD) -1)
-            rcWnd = m_TrayRects[m_Position];
-
-        if (!Create(NULL, rcWnd, NULL, dwStyle, dwExStyle))
-            return E_FAIL;
-
-        return S_OK;
-    }
-
-    HRESULT STDMETHODCALLTYPE Close()
-    {
-        if (m_hWnd != NULL)
-        {
-            SendMessage(m_hWnd,
-                        WM_APP_TRAYDESTROY,
-                        0,
-                        0);
-        }
-
-        return S_OK;
-    }
-
-    HWND STDMETHODCALLTYPE GetHWND()
-    {
-        return m_hWnd;
-    }
-
-    BOOL STDMETHODCALLTYPE IsSpecialHWND(IN HWND hWnd)
-    {
-        return (m_hWnd == hWnd ||
-                (m_DesktopWnd != NULL && m_hWnd == m_DesktopWnd));
-    }
-
-    BOOL STDMETHODCALLTYPE
-        IsHorizontal()
-    {
-        return IsPosHorizontal();
-    }
-
-    HFONT STDMETHODCALLTYPE GetCaptionFonts(OUT HFONT *phBoldCaption OPTIONAL)
-    {
-        if (phBoldCaption != NULL)
-            *phBoldCaption = m_StartButton.GetFont();
-
-        return m_CaptionFont;
-    }
-
-    DWORD WINAPI TrayPropertiesThread()
-    {
-        HWND hwnd;
-        RECT posRect;
-
-        m_StartButton.GetWindowRect(&posRect);
-        hwnd = CreateWindowEx(0,
-                              WC_STATIC,
-                              NULL,
-                              WS_OVERLAPPED | WS_DISABLED | WS_CLIPSIBLINGS | WS_BORDER | SS_LEFT,
-                              posRect.left,
-                              posRect.top,
-                              posRect.right - posRect.left,
-                              posRect.bottom - posRect.top,
-                              NULL,
-                              NULL,
-                              NULL,
-                              NULL);
-
-        m_TrayPropertiesOwner = hwnd;
-
-        DisplayTrayProperties(hwnd);
-
-        m_TrayPropertiesOwner = NULL;
-        ::DestroyWindow(hwnd);
-
-        return 0;
-    }
-
-    static DWORD WINAPI s_TrayPropertiesThread(IN OUT PVOID pParam)
-    {
-        CTrayWindow *This = (CTrayWindow*) pParam;
-
-        return This->TrayPropertiesThread();
-    }
-
-    HWND STDMETHODCALLTYPE DisplayProperties()
-    {
-        HWND hTrayProp;
-
-        if (m_TrayPropertiesOwner)
-        {
-            hTrayProp = ::GetLastActivePopup(m_TrayPropertiesOwner);
-            if (hTrayProp != NULL &&
-                hTrayProp != m_TrayPropertiesOwner)
-            {
-                SetForegroundWindow(hTrayProp);
-                return NULL;
-            }
-        }
-
-        CloseHandle(CreateThread(NULL, 0, s_TrayPropertiesThread, this, 0, NULL));
-        return NULL;
-    }
-
-    VOID OpenCommonStartMenuDirectory(IN HWND hWndOwner, IN LPCTSTR lpOperation)
-    {
-        WCHAR szDir[MAX_PATH];
+        if (dwp != NULL)
+            EndDeferWindowPos(dwp);
 
-        if (SHGetSpecialFolderPath(hWndOwner,
-            szDir,
-            CSIDL_COMMON_STARTMENU,
-            FALSE))
+        if (m_TaskSwitch != NULL)
         {
-            ShellExecute(hWndOwner,
-                         lpOperation,
-                         NULL,
-                         NULL,
-                         szDir,
-                         SW_SHOWNORMAL);
+            /* Update the task switch window configuration */
+            SendMessage(m_TaskSwitch, TSWM_UPDATETASKBARPOS, 0, 0);
         }
     }
 
-    VOID OpenTaskManager(IN HWND hWndOwner)
+    void FitToRebar(PRECT pRect)
     {
-        ShellExecute(hWndOwner,
-                     TEXT("open"),
-                     TEXT("taskmgr.exe"),
-                     NULL,
-                     NULL,
-                     SW_SHOWNORMAL);
-    }
+        /* Get the rect of the rebar */
+        RECT rebarRect, taskbarRect;
+        ::GetWindowRect(m_Rebar, &rebarRect);
+        ::GetWindowRect(m_hWnd, &taskbarRect);
+        OffsetRect(&rebarRect, -taskbarRect.left, -taskbarRect.top);
 
-    BOOL STDMETHODCALLTYPE ExecContextMenuCmd(IN UINT uiCmd)
-    {
-        BOOL bHandled = TRUE;
+        /* Calculate the difference of size of the taskbar and the rebar */
+        SIZE margins;
+        margins.cx = taskbarRect.right - taskbarRect.left - rebarRect.right + rebarRect.left;
+        margins.cy = taskbarRect.bottom - taskbarRect.top - rebarRect.bottom + rebarRect.top;
 
-        switch (uiCmd)
+        /* Calculate the new size of the rebar and make it resize, then change the new taskbar size */
+        switch (m_Position)
         {
-        case ID_SHELL_CMD_PROPERTIES:
-            DisplayProperties();
-            break;
-
-        case ID_SHELL_CMD_OPEN_ALL_USERS:
-            OpenCommonStartMenuDirectory(m_hWnd,
-                                         TEXT("open"));
+        case ABE_TOP:
+            rebarRect.bottom = rebarRect.top + pRect->bottom - pRect->top - margins.cy;
+            ::SendMessageW(m_Rebar, RB_SIZETORECT, RBSTR_CHANGERECT,  (LPARAM)&rebarRect);
+            pRect->bottom = pRect->top + rebarRect.bottom - rebarRect.top + margins.cy;
             break;
-
-        case ID_SHELL_CMD_EXPLORE_ALL_USERS:
-            OpenCommonStartMenuDirectory(m_hWnd,
-                                         TEXT("explore"));
+        case ABE_BOTTOM:
+            rebarRect.top = rebarRect.bottom - (pRect->bottom - pRect->top - margins.cy);
+            ::SendMessageW(m_Rebar, RB_SIZETORECT, RBSTR_CHANGERECT,  (LPARAM)&rebarRect);
+            ERR("rebarRect: %d, %d, %d,%d\n", rebarRect.top, rebarRect.left, rebarRect.right, rebarRect.bottom);
+            pRect->top = pRect->bottom - (rebarRect.bottom - rebarRect.top + margins.cy);
             break;
-
-        case ID_LOCKTASKBAR:
-            if (SHRestricted(REST_CLASSICSHELL) == 0)
-            {
-                Lock(!Locked);
-            }
+        case ABE_LEFT:
+        case ABE_RIGHT:
+            /* FIXME: what to do here? */
             break;
+        }
 
-        case ID_SHELL_CMD_OPEN_TASKMGR:
-            OpenTaskManager(m_hWnd);
-            break;
+        CalculateValidSize(m_Position, pRect);
+    }
 
-        case ID_SHELL_CMD_UNDO_ACTION:
-            break;
+    void PopupStartMenu()
+    {
+        if (m_StartMenuPopup != NULL)
+        {
+            POINTL pt;
+            RECTL rcExclude;
+            DWORD dwFlags = 0;
 
-        case ID_SHELL_CMD_SHOW_DESKTOP:
-            break;
+            if (m_StartButton.GetWindowRect((RECT*) &rcExclude))
+            {
+                switch (m_Position)
+                {
+                case ABE_BOTTOM:
+                    pt.x = rcExclude.left;
+                    pt.y = rcExclude.top;
+                    dwFlags |= MPPF_TOP;
+                    break;
+                case ABE_TOP:
+                    pt.x = rcExclude.left;
+                    pt.y = rcExclude.bottom;
+                    dwFlags |= MPPF_BOTTOM;
+                    break;
+                case ABE_LEFT:
+                    pt.x = rcExclude.right;
+                    pt.y = rcExclude.top;
+                    dwFlags |= MPPF_RIGHT;
+                    break;
+                case ABE_RIGHT:
+                    pt.x = rcExclude.left;
+                    pt.y = rcExclude.top;
+                    dwFlags |= MPPF_LEFT;
+                    break;
+                }
 
-        case ID_SHELL_CMD_TILE_WND_H:
-            TileWindows(NULL, MDITILE_HORIZONTAL, NULL, 0, NULL);
-            break;
+                m_StartMenuPopup->Popup(&pt, &rcExclude, dwFlags);
 
-        case ID_SHELL_CMD_TILE_WND_V:
-            TileWindows(NULL, MDITILE_VERTICAL, NULL, 0, NULL);
-            break;
+                m_StartButton.SendMessageW(BM_SETSTATE, TRUE, 0);
+            }
+        }
+    }
 
-        case ID_SHELL_CMD_CASCADE_WND:
-            CascadeWindows(NULL, MDITILE_SKIPDISABLED, NULL, 0, NULL);
-            break;
+    void ProcessMouseTracking()
+    {
+        RECT rcCurrent;
+        POINT pt;
+        BOOL over;
+        UINT state = m_AutoHideState;
 
-        case ID_SHELL_CMD_CUST_NOTIF:
-            break;
+        GetCursorPos(&pt);
+        GetWindowRect(&rcCurrent);
+        over = PtInRect(&rcCurrent, pt);
 
-        case ID_SHELL_CMD_ADJUST_DAT:
-            //FIXME: Use SHRunControlPanel
-            ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
-            break;
+        if (m_StartButton.SendMessage( BM_GETSTATE, 0, 0) != BST_UNCHECKED)
+        {
+            over = TRUE;
+        }
 
-        default:
-            TRACE("ITrayWindow::ExecContextMenuCmd(%u): Unhandled Command ID!\n", uiCmd);
-            bHandled = FALSE;
-            break;
+        if (over)
+        {
+            if (state == AUTOHIDE_HIDING)
+            {
+                TRACE("AutoHide cancelling hide.\n");
+                m_AutoHideState = AUTOHIDE_SHOWING;
+                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
+            }
+            else if (state == AUTOHIDE_HIDDEN)
+            {
+                TRACE("AutoHide starting show.\n");
+                m_AutoHideState = AUTOHIDE_SHOWING;
+                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_SHOW, NULL);
+            }
         }
+        else
+        {
+            if (state == AUTOHIDE_SHOWING)
+            {
+                TRACE("AutoHide cancelling show.\n");
+                m_AutoHideState = AUTOHIDE_HIDING;
+                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
+            }
+            else if (state == AUTOHIDE_SHOWN)
+            {
+                TRACE("AutoHide starting hide.\n");
+                m_AutoHideState = AUTOHIDE_HIDING;
+                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_HIDE, NULL);
+            }
 
-        return bHandled;
+            KillTimer(TIMER_ID_MOUSETRACK);
+        }
     }
 
-    BOOL STDMETHODCALLTYPE Lock(IN BOOL bLock)
+    void ProcessAutoHide()
     {
-        BOOL bPrevLock = Locked;
+        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;
 
-        if (Locked != bLock)
+        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)
         {
-            Locked = bLock;
+        case AUTOHIDE_HIDING:
+            switch (m_Position)
+            {
+            case ABE_LEFT:
+                m_AutoHideOffset.cy = 0;
+                m_AutoHideOffset.cx -= AUTOHIDE_SPEED_HIDE;
+                if (m_AutoHideOffset.cx < -w)
+                    m_AutoHideOffset.cx = -w;
+                break;
+            case ABE_TOP:
+                m_AutoHideOffset.cx = 0;
+                m_AutoHideOffset.cy -= AUTOHIDE_SPEED_HIDE;
+                if (m_AutoHideOffset.cy < -h)
+                    m_AutoHideOffset.cy = -h;
+                break;
+            case ABE_RIGHT:
+                m_AutoHideOffset.cy = 0;
+                m_AutoHideOffset.cx += AUTOHIDE_SPEED_HIDE;
+                if (m_AutoHideOffset.cx > w)
+                    m_AutoHideOffset.cx = w;
+                break;
+            case ABE_BOTTOM:
+                m_AutoHideOffset.cx = 0;
+                m_AutoHideOffset.cy += AUTOHIDE_SPEED_HIDE;
+                if (m_AutoHideOffset.cy > h)
+                    m_AutoHideOffset.cy = h;
+                break;
+            }
 
-            if (m_TrayBandSite != NULL)
+            if (m_AutoHideOffset.cx != w && m_AutoHideOffset.cy != h)
             {
-                if (!SUCCEEDED(m_TrayBandSite->Lock(bLock)))
-                {
-                    /* Reset?? */
-                    Locked = bPrevLock;
-                    return bPrevLock;
-                }
+                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
+                break;
+            }
+
+            /* fallthrough */
+        case AUTOHIDE_HIDDEN:
+
+            switch (m_Position)
+            {
+            case ABE_LEFT:
+                m_AutoHideOffset.cx = -w;
+                m_AutoHideOffset.cy = 0;
+                break;
+            case ABE_TOP:
+                m_AutoHideOffset.cx = 0;
+                m_AutoHideOffset.cy = -h;
+                break;
+            case ABE_RIGHT:
+                m_AutoHideOffset.cx = w;
+                m_AutoHideOffset.cy = 0;
+                break;
+            case ABE_BOTTOM:
+                m_AutoHideOffset.cx = 0;
+                m_AutoHideOffset.cy = h;
+                break;
+            }
+
+            KillTimer(TIMER_ID_AUTOHIDE);
+            m_AutoHideState = AUTOHIDE_HIDDEN;
+            break;
+
+        case AUTOHIDE_SHOWING:
+            if (m_AutoHideOffset.cx >= AUTOHIDE_SPEED_SHOW)
+            {
+                m_AutoHideOffset.cx -= AUTOHIDE_SPEED_SHOW;
+            }
+            else if (m_AutoHideOffset.cx <= -AUTOHIDE_SPEED_SHOW)
+            {
+                m_AutoHideOffset.cx += AUTOHIDE_SPEED_SHOW;
+            }
+            else
+            {
+                m_AutoHideOffset.cx = 0;
             }
 
-            if (Locked && m_Theme)
+            if (m_AutoHideOffset.cy >= AUTOHIDE_SPEED_SHOW)
+            {
+                m_AutoHideOffset.cy -= AUTOHIDE_SPEED_SHOW;
+            }
+            else if (m_AutoHideOffset.cy <= -AUTOHIDE_SPEED_SHOW)
+            {
+                m_AutoHideOffset.cy += AUTOHIDE_SPEED_SHOW;
+            }
+            else
             {
-                SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, 0);
+                m_AutoHideOffset.cy = 0;
             }
-            else
+
+            if (m_AutoHideOffset.cx != 0 || m_AutoHideOffset.cy != 0)
             {
-                SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, WS_THICKFRAME | WS_BORDER);
+                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
+                break;
             }
-            SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
 
+            /* fallthrough */
+        case AUTOHIDE_SHOWN:
+
+            KillTimer(TIMER_ID_AUTOHIDE);
+            m_AutoHideState = AUTOHIDE_SHOWN;
+            break;
         }
 
-        return bPrevLock;
+        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);
     }
 
 
-    LRESULT DrawBackground(HDC hdc)
+
+
+
+    /**********************************************************
+     *    ##### taskbar drawing #####
+     */
+
+    LRESULT EraseBackgroundWithTheme(HDC hdc)
     {
         RECT rect;
         int partId;
@@ -1859,337 +1906,302 @@ ChangePos:
         return res;
     }
 
-    LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        HDC hdc = (HDC) wParam;
-
-        if (!m_Theme)
-        {
-            bHandled = FALSE;
-            return 0;
-        }
-
-        return DrawBackground(hdc);
-    }
-
-    int DrawSizer(IN HRGN hRgn)
+    int DrawSizerWithTheme(IN HRGN hRgn)
     {
         HDC hdc;
         RECT rect;
-        int backoundPart;
+        int backgroundPart;
 
         GetWindowRect(&rect);
         OffsetRect(&rect, -rect.left, -rect.top);
 
-        hdc = GetDCEx(hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_PARENTCLIP);
+        hdc = GetWindowDC();
 
         switch (m_Position)
         {
         case ABE_LEFT:
-            backoundPart = TBP_SIZINGBARLEFT;
+            backgroundPart = TBP_SIZINGBARLEFT;
             rect.left = rect.right - GetSystemMetrics(SM_CXSIZEFRAME);
             break;
         case ABE_TOP:
-            backoundPart = TBP_SIZINGBARTOP;
+            backgroundPart = TBP_SIZINGBARTOP;
             rect.top = rect.bottom - GetSystemMetrics(SM_CYSIZEFRAME);
             break;
         case ABE_RIGHT:
-            backoundPart = TBP_SIZINGBARRIGHT;
+            backgroundPart = TBP_SIZINGBARRIGHT;
             rect.right = rect.left + GetSystemMetrics(SM_CXSIZEFRAME);
             break;
         case ABE_BOTTOM:
         default:
-            backoundPart = TBP_SIZINGBARBOTTOM;
+            backgroundPart = TBP_SIZINGBARBOTTOM;
             rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZEFRAME);
             break;
         }
-        if (IsThemeBackgroundPartiallyTransparent(m_Theme, backoundPart, 0))
+        if (IsThemeBackgroundPartiallyTransparent(m_Theme, backgroundPart, 0))
         {
             DrawThemeParentBackground(m_hWnd, hdc, &rect);
         }
-        DrawThemeBackground(m_Theme, hdc, backoundPart, 0, &rect, 0);
+        DrawThemeBackground(m_Theme, hdc, backgroundPart, 0, &rect, 0);
 
         ReleaseDC(hdc);
         return 0;
     }
 
-    DWORD WINAPI RunFileDlgThread()
+
+
+
+
+    /*
+     * ITrayWindow
+     */
+    HRESULT STDMETHODCALLTYPE Open()
     {
-        HWND hwnd;
-        RECT posRect;
+        RECT rcWnd;
 
-        m_StartButton.GetWindowRect(&posRect);
+        /* Check if there's already a window created and try to show it.
+           If it was somehow destroyed just create a new tray window. */
+        if (m_hWnd != NULL && IsWindow())
+        {
+            return S_OK;
+        }
 
-        hwnd = CreateWindowEx(0,
-                              WC_STATIC,
-                              NULL,
-                              WS_OVERLAPPED | WS_DISABLED | WS_CLIPSIBLINGS | WS_BORDER | SS_LEFT,
-                              posRect.left,
-                              posRect.top,
-                              posRect.right - posRect.left,
-                              posRect.bottom - posRect.top,
-                              NULL,
-                              NULL,
-                              NULL,
-                              NULL);
+        DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
+        if (AlwaysOnTop)
+            dwExStyle |= WS_EX_TOPMOST;
 
-        m_RunFileDlgOwner = hwnd;
+        DWORD dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+        if(!IsThemeActive())
+        {
+            dwStyle |= WS_THICKFRAME | WS_BORDER;
+        }
 
-        RunFileDlg(hwnd, NULL, NULL, NULL, NULL, RFF_CALCDIRECTORY);
+        ZeroMemory(&rcWnd, sizeof(rcWnd));
+        if (m_Position != (DWORD) -1)
+            rcWnd = m_TrayRects[m_Position];
 
-        m_RunFileDlgOwner = NULL;
-        ::DestroyWindow(hwnd);
+        if (!Create(NULL, rcWnd, NULL, dwStyle, dwExStyle))
+            return E_FAIL;
 
-        return 0;
-    }
+        /* Align all controls on the tray window */
+        AlignControls(NULL);
 
-    static DWORD WINAPI s_RunFileDlgThread(IN OUT PVOID pParam)
-    {
-        CTrayWindow * This = (CTrayWindow*) pParam;
-        return This->RunFileDlgThread();
+        /* Move the tray window to the right position and resize it if necessary */
+        CheckTrayWndPosition();
+
+        return S_OK;
     }
 
-    void DisplayRunFileDlg()
+    HRESULT STDMETHODCALLTYPE Close()
     {
-        HWND hRunDlg;
-        if (m_RunFileDlgOwner)
+        if (m_hWnd != NULL)
         {
-            hRunDlg = ::GetLastActivePopup(m_RunFileDlgOwner);
-            if (hRunDlg != NULL &&
-                hRunDlg != m_RunFileDlgOwner)
-            {
-                SetForegroundWindow(hRunDlg);
-                return;
-            }
+            SendMessage(m_hWnd,
+                        WM_APP_TRAYDESTROY,
+                        0,
+                        0);
         }
 
-        CloseHandle(CreateThread(NULL, 0, s_RunFileDlgThread, this, 0, NULL));
+        return S_OK;
     }
 
-    void PopupStartMenu()
+    HWND STDMETHODCALLTYPE GetHWND()
     {
-        if (m_StartMenuPopup != NULL)
+        return m_hWnd;
+    }
+
+    BOOL STDMETHODCALLTYPE IsSpecialHWND(IN HWND hWnd)
+    {
+        return (m_hWnd == hWnd ||
+                (m_DesktopWnd != NULL && m_hWnd == m_DesktopWnd));
+    }
+
+    BOOL STDMETHODCALLTYPE IsHorizontal()
+    {
+        return IsPosHorizontal();
+    }
+
+    BOOL STDMETHODCALLTYPE Lock(IN BOOL bLock)
+    {
+        BOOL bPrevLock = Locked;
+
+        if (Locked != bLock)
         {
-            POINTL pt;
-            RECTL rcExclude;
-            DWORD dwFlags = 0;
+            Locked = bLock;
 
-            if (m_StartButton.GetWindowRect((RECT*) &rcExclude))
+            if (m_TrayBandSite != NULL)
             {
-                switch (m_Position)
+                if (!SUCCEEDED(m_TrayBandSite->Lock(bLock)))
                 {
-                case ABE_BOTTOM:
-                    pt.x = rcExclude.left;
-                    pt.y = rcExclude.top;
-                    dwFlags |= MPPF_TOP;
-                    break;
-                case ABE_TOP:
-                    pt.x = rcExclude.left;
-                    pt.y = rcExclude.bottom;
-                    dwFlags |= MPPF_BOTTOM;
-                    break;
-                case ABE_LEFT:
-                    pt.x = rcExclude.right;
-                    pt.y = rcExclude.top;
-                    dwFlags |= MPPF_RIGHT;
-                    break;
-                case ABE_RIGHT:
-                    pt.x = rcExclude.left;
-                    pt.y = rcExclude.top;
-                    dwFlags |= MPPF_LEFT;
-                    break;
+                    /* Reset?? */
+                    Locked = bPrevLock;
+                    return bPrevLock;
                 }
+            }
 
-                m_StartMenuPopup->Popup(&pt, &rcExclude, dwFlags);
-
-                m_StartButton.SendMessageW(BM_SETSTATE, TRUE, 0);
+            if (m_Theme)
+            {
+                /* Update cached tray sizes */
+                for(DWORD Pos = ABE_LEFT; Pos <= ABE_BOTTOM; Pos++)
+                {
+                    RECT rcGripper = {0};
+                    AdjustSizerRect(&rcGripper, Pos);
+
+                    if(Locked)
+                    {
+                        m_TrayRects[Pos].top += rcGripper.top;
+                        m_TrayRects[Pos].left += rcGripper.left;
+                        m_TrayRects[Pos].bottom += rcGripper.bottom;
+                        m_TrayRects[Pos].right += rcGripper.right;
+                    }
+                    else
+                    {
+                        m_TrayRects[Pos].top -= rcGripper.top;
+                        m_TrayRects[Pos].left -= rcGripper.left;
+                        m_TrayRects[Pos].bottom -= rcGripper.bottom;
+                        m_TrayRects[Pos].right -= rcGripper.right;
+                    }
+                }
             }
+            SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);
+            ResizeWorkArea();
+            ApplyClipping(TRUE);
         }
+
+        return bPrevLock;
     }
 
-    void ProcessMouseTracking()
+
+
+
+
+
+    /**********************************************************
+     *    ##### message handling #####
+     */
+
+    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        RECT rcCurrent;
-        POINT pt;
-        BOOL over;
-        UINT state = m_AutoHideState;
+        HRESULT hRet;
 
-        GetCursorPos(&pt);
-        GetWindowRect(&rcCurrent);
-        over = PtInRect(&rcCurrent, pt);
+        ((ITrayWindow*)this)->AddRef();
 
-        if (m_StartButton.SendMessage( BM_GETSTATE, 0, 0) != BST_UNCHECKED)
-        {
-            over = TRUE;
-        }
+        SetWindowTheme(m_hWnd, L"TaskBar", NULL);
 
-        if (over)
+        /* Create the Start button */
+        m_StartButton.Create(m_hWnd);
+
+        /* Load the saved tray window settings */
+        RegLoadSettings();
+
+        /* Create and initialize the start menu */
+        HBITMAP hbmBanner = LoadBitmapW(hExplorerInstance, MAKEINTRESOURCEW(IDB_STARTMENU));
+        m_StartMenuPopup = CreateStartMenu(this, &m_StartMenuBand, hbmBanner, 0);
+
+        /* Create the task band */
+        hRet = CTaskBand_CreateInstance(this, IID_PPV_ARG(IDeskBand, &m_TaskBand));
+        if (FAILED_UNEXPECTEDLY(hRet))
+            return FALSE;
+
+        /* Create the rebar band site. This actually creates the rebar and the tasks toolbar. */
+        hRet = CTrayBandSite_CreateInstance(this, m_TaskBand, &m_TrayBandSite);
+        if (FAILED_UNEXPECTEDLY(hRet))
+            return FALSE;
+
+        /* Get the hwnd of the rebar */
+        hRet = IUnknown_GetWindow(m_TrayBandSite, &m_Rebar);
+        if (FAILED_UNEXPECTEDLY(hRet))
+            return FALSE;
+
+        /* Get the hwnd of the tasks toolbar */
+        hRet = IUnknown_GetWindow(m_TaskBand, &m_TaskSwitch);
+        if (FAILED_UNEXPECTEDLY(hRet))
+            return FALSE;
+
+        SetWindowTheme(m_Rebar, L"TaskBar", NULL);
+
+        /* Create the tray notification window */
+        m_TrayNotify = CreateTrayNotifyWnd(this, HideClock, &m_TrayNotifyInstance);
+
+        UpdateFonts();
+
+        InitShellServices(&m_ShellServices);
+
+        if (AutoHide)
         {
-            if (state == AUTOHIDE_HIDING)
-            {
-                TRACE("AutoHide cancelling hide.\n");
-                m_AutoHideState = AUTOHIDE_SHOWING;
-                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
-            }
-            else if (state == AUTOHIDE_HIDDEN)
-            {
-                TRACE("AutoHide starting show.\n");
-                m_AutoHideState = AUTOHIDE_SHOWING;
-                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_SHOW, NULL);
-            }
+            m_AutoHideState = AUTOHIDE_HIDING;
+            SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_HIDE, NULL);
         }
-        else
-        {
-            if (state == AUTOHIDE_SHOWING)
-            {
-                TRACE("AutoHide cancelling show.\n");
-                m_AutoHideState = AUTOHIDE_HIDING;
-                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
-            }
-            else if (state == AUTOHIDE_SHOWN)
-            {
-                TRACE("AutoHide starting hide.\n");
-                m_AutoHideState = AUTOHIDE_HIDING;
-                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_HIDE, NULL);
-            }
 
-            KillTimer(TIMER_ID_MOUSETRACK);
-        }
+        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');
+        RegisterHotKey(m_hWnd, IDHK_HELP, MOD_WIN, VK_F1);
+        RegisterHotKey(m_hWnd, IDHK_EXPLORE, MOD_WIN, 'E');
+        RegisterHotKey(m_hWnd, IDHK_FIND, MOD_WIN, 'F');
+        RegisterHotKey(m_hWnd, IDHK_FIND_COMPUTER, MOD_WIN|MOD_CONTROL, 'F');
+        RegisterHotKey(m_hWnd, IDHK_NEXT_TASK, MOD_WIN, VK_TAB);
+        RegisterHotKey(m_hWnd, IDHK_PREV_TASK, MOD_WIN|MOD_SHIFT, VK_TAB);
+        RegisterHotKey(m_hWnd, IDHK_SYS_PROPERTIES, MOD_WIN, VK_PAUSE);
+        RegisterHotKey(m_hWnd, IDHK_DESKTOP, MOD_WIN, 'D');
+        RegisterHotKey(m_hWnd, IDHK_PAGER, MOD_WIN, 'B');
+
+        return TRUE;
     }
 
-    void ProcessAutoHide()
+    LRESULT OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        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;
+        if (m_Theme)
+            CloseThemeData(m_Theme);
 
-        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);
+        if (IsThemeActive())
+            m_Theme = OpenThemeData(m_hWnd, L"TaskBar");
+        else
+            m_Theme = NULL;
 
-        switch (m_AutoHideState)
+        if (m_Theme)
         {
-        case AUTOHIDE_HIDING:
-            switch (m_Position)
-            {
-            case ABE_LEFT:
-                m_AutoHideOffset.cy = 0;
-                m_AutoHideOffset.cx -= AUTOHIDE_SPEED_HIDE;
-                if (m_AutoHideOffset.cx < -w)
-                    m_AutoHideOffset.cx = -w;
-                break;
-            case ABE_TOP:
-                m_AutoHideOffset.cx = 0;
-                m_AutoHideOffset.cy -= AUTOHIDE_SPEED_HIDE;
-                if (m_AutoHideOffset.cy < -h)
-                    m_AutoHideOffset.cy = -h;
-                break;
-            case ABE_RIGHT:
-                m_AutoHideOffset.cy = 0;
-                m_AutoHideOffset.cx += AUTOHIDE_SPEED_HIDE;
-                if (m_AutoHideOffset.cx > w)
-                    m_AutoHideOffset.cx = w;
-                break;
-            case ABE_BOTTOM:
-                m_AutoHideOffset.cx = 0;
-                m_AutoHideOffset.cy += AUTOHIDE_SPEED_HIDE;
-                if (m_AutoHideOffset.cy > h)
-                    m_AutoHideOffset.cy = h;
-                break;
-            }
-
-            if (m_AutoHideOffset.cx != w && m_AutoHideOffset.cy != h)
-            {
-                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
-                break;
-            }
-
-            /* fallthrough */
-        case AUTOHIDE_HIDDEN:
-
-            switch (m_Position)
-            {
-            case ABE_LEFT:
-                m_AutoHideOffset.cx = -w;
-                m_AutoHideOffset.cy = 0;
-                break;
-            case ABE_TOP:
-                m_AutoHideOffset.cx = 0;
-                m_AutoHideOffset.cy = -h;
-                break;
-            case ABE_RIGHT:
-                m_AutoHideOffset.cx = w;
-                m_AutoHideOffset.cy = 0;
-                break;
-            case ABE_BOTTOM:
-                m_AutoHideOffset.cx = 0;
-                m_AutoHideOffset.cy = h;
-                break;
-            }
-
-            KillTimer(TIMER_ID_AUTOHIDE);
-            m_AutoHideState = AUTOHIDE_HIDDEN;
-            break;
+            SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, 0);
+        }
+        else
+        {
+            SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, WS_THICKFRAME | WS_BORDER);
+        }
+        SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
 
-        case AUTOHIDE_SHOWING:
-            if (m_AutoHideOffset.cx >= AUTOHIDE_SPEED_SHOW)
-            {
-                m_AutoHideOffset.cx -= AUTOHIDE_SPEED_SHOW;
-            }
-            else if (m_AutoHideOffset.cx <= -AUTOHIDE_SPEED_SHOW)
-            {
-                m_AutoHideOffset.cx += AUTOHIDE_SPEED_SHOW;
-            }
-            else
-            {
-                m_AutoHideOffset.cx = 0;
-            }
+        return TRUE;
+    }
 
-            if (m_AutoHideOffset.cy >= AUTOHIDE_SPEED_SHOW)
-            {
-                m_AutoHideOffset.cy -= AUTOHIDE_SPEED_SHOW;
-            }
-            else if (m_AutoHideOffset.cy <= -AUTOHIDE_SPEED_SHOW)
-            {
-                m_AutoHideOffset.cy += AUTOHIDE_SPEED_SHOW;
-            }
-            else
-            {
-                m_AutoHideOffset.cy = 0;
-            }
+    LRESULT OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    {
+        if (wParam == SPI_SETNONCLIENTMETRICS)
+        {
+            SendMessage(m_TaskSwitch, uMsg, wParam, lParam);
+            UpdateFonts();
+            AlignControls(NULL);
+            CheckTrayWndPosition();
+        }
 
-            if (m_AutoHideOffset.cx != 0 || m_AutoHideOffset.cy != 0)
-            {
-                SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
-                break;
-            }
+        return 0;
+    }
 
-            /* fallthrough */
-        case AUTOHIDE_SHOWN:
+    LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    {
+        HDC hdc = (HDC) wParam;
 
-            KillTimer(TIMER_ID_AUTOHIDE);
-            m_AutoHideState = AUTOHIDE_SHOWN;
-            break;
+        if (!m_Theme)
+        {
+            bHandled = FALSE;
+            return 0;
         }
 
-        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);
+        return EraseBackgroundWithTheme(hdc);
     }
 
     LRESULT OnDisplayChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        /* Load the saved tray window settings */
-        RegLoadSettings();
-
-        /* Move the tray window to the right position and resize it if neccessary */
+        /* Move the tray window to the right position and resize it if necessary */
         CheckTrayWndPosition();
 
-        /* Align all controls on the tray window */
-        AlignControls(NULL);
-
         return TRUE;
     }
 
@@ -2211,7 +2223,7 @@ ChangePos:
             return 0;
         }
 
-        return DrawSizer((HRGN) wParam);
+        return DrawSizerWithTheme((HRGN) wParam);
     }
 
     LRESULT OnCtlColorBtn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
@@ -2310,7 +2322,7 @@ ChangePos:
 
         if (!Locked)
         {
-            CalculateValidSize(m_Position, pRect);
+            FitToRebar(pRect);
         }
         else
         {
@@ -2336,7 +2348,6 @@ ChangePos:
     LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
         RECT rcClient;
-        InvalidateRect(NULL, TRUE);
         if (wParam == SIZE_RESTORED && lParam == 0)
         {
             ResizeWorkArea();
@@ -2401,8 +2412,7 @@ ChangePos:
                 SC_MINIMIZE,
             };
             HMENU hSysMenu;
-            INT i;
-            UINT uId;
+            UINT i, uId;
 
             /* temporarily enable the system menu */
             SetWindowStyle(m_hWnd, WS_SYSMENU, WS_SYSMENU);
@@ -2411,7 +2421,7 @@ ChangePos:
             if (hSysMenu != NULL)
             {
                 /* Disable all items that are not relevant */
-                for (i = 0; i != sizeof(uidDisableItem) / sizeof(uidDisableItem[0]); i++)
+                for (i = 0; i < _countof(uidDisableItem); i++)
                 {
                     EnableMenuItem(hSysMenu,
                                    uidDisableItem[i],
@@ -2608,17 +2618,12 @@ HandleTrayContextMenu:
         return TRUE;
     }
 
-    LRESULT DoExitWindows()
-    {
-        ExitWindowsDialog(m_hWnd);
-        return 0;
-    }
-
     LRESULT OnDoExitWindows(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        /* 
+        /*
          * TWM_DOEXITWINDOWS is send by the CDesktopBrowser to us
-         * to show the shutdown dialog.
+         * to show the shutdown dialog. Also a WM_CLOSE message sent
+         * by apps should show the dialog.
          */
         return DoExitWindows();
     }
@@ -2634,70 +2639,9 @@ HandleTrayContextMenu:
         return TRUE;
     }
 
-    HRESULT ExecResourceCmd(int id)
-    {
-        WCHAR szCommand[256];
-        WCHAR *pszParameters;
-
-        if (!LoadString(hExplorerInstance,
-                        id,
-                        szCommand,
-                        sizeof(szCommand) / sizeof(szCommand[0])))
-        {
-            return E_FAIL;
-        }
-
-        pszParameters = wcschr(szCommand, L'>');
-        if (pszParameters)
-        {
-            *pszParameters = 0;
-            pszParameters++;
-        }
-
-        ShellExecuteW(m_hWnd, NULL, szCommand, pszParameters, NULL, SW_SHOWNORMAL);
-        return S_OK;
-    }
-
     LRESULT OnHotkey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        switch (wParam)
-        {
-        case IDHK_RUN:
-            DisplayRunFileDlg();
-            break;
-        case IDHK_HELP:
-            ExecResourceCmd(IDS_HELP_COMMAND);
-            break;
-        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); 
-            break;
-        case IDHK_FIND:
-            SHFindFiles(NULL, NULL);
-            break;
-        case IDHK_FIND_COMPUTER:
-            SHFindComputer(NULL, NULL);
-            break;
-        case IDHK_SYS_PROPERTIES:
-            //FIXME: Use SHRunControlPanel
-            ShellExecuteW(m_hWnd, NULL, L"sysdm.cpl", NULL, NULL, SW_NORMAL);
-            break;
-        case IDHK_NEXT_TASK:
-            break;
-        case IDHK_PREV_TASK:
-            break;
-        case IDHK_MINIMIZE_ALL:
-            break;
-        case IDHK_RESTORE_ALL:
-            break;
-        case IDHK_DESKTOP:
-            break;
-        case IDHK_PAGER:
-            break;
-        }
-
-        return 0;
+        return HandleHotKey(wParam);
     }
 
     LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
@@ -2712,38 +2656,7 @@ HandleTrayContextMenu:
 
         if (m_TrayBandSite == NULL || FAILED_UNEXPECTEDLY(m_TrayBandSite->ProcessMessage(m_hWnd, uMsg, wParam, lParam, &Ret)))
         {
-            switch (LOWORD(wParam))
-            {
-            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 IDM_SHUTDOWN:
-                DoExitWindows();
-                break;
-            }
+            return HandleCommand(LOWORD(wParam));
         }
         return Ret;
     }
@@ -2773,6 +2686,35 @@ HandleTrayContextMenu:
         return TRUE;
     }
 
+    LRESULT OnNcCalcSize(INT code, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    {
+        RECT *rc = NULL;
+        /* Ignore WM_NCCALCSIZE if we are not themed or locked */
+        if(!IsThemeActive() || Locked)
+        {
+            bHandled = FALSE;
+            return 0;
+        }
+        if(!wParam)
+        {
+            rc = (RECT*)wParam;
+        }
+        else
+        {
+            NCCALCSIZE_PARAMS *prms = (NCCALCSIZE_PARAMS*)lParam;
+            if(prms->lppos->flags & SWP_NOSENDCHANGING)
+            {
+                bHandled = FALSE;
+                return 0;
+            }
+            rc = &prms->rgrc[0];
+        }
+
+        AdjustSizerRect(rc, m_Position);
+
+        return 0;
+    }
+
     LRESULT OnRebarAutoSize(INT code, LPNMHDR nmhdr, BOOL& bHandled)
     {
 #if 0
@@ -2846,6 +2788,7 @@ HandleTrayContextMenu:
             lParam = Msg.lParam;
         }
         MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
+        MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChanged)
         NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnRebarAutoSize) // Doesn't quite work ;P
         MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
         MESSAGE_HANDLER(WM_SIZE, OnSize)
@@ -2874,7 +2817,9 @@ HandleTrayContextMenu:
         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)
     ALT_MSG_MAP(1)
     END_MSG_MAP()
 
@@ -2967,6 +2912,19 @@ HandleTrayContextMenu:
         return S_OK;
     }
 
+    HRESULT WINAPI GetWindow(HWND* phwnd)
+    {
+        if (!phwnd)
+            return E_INVALIDARG;
+        *phwnd = m_hWnd;
+        return S_OK;
+    }
+
+    HRESULT WINAPI ContextSensitiveHelp(BOOL fEnterMode)
+    {
+        return E_NOTIMPL;
+    }
+
     void _Init()
     {
         m_Position = (DWORD) -1;
@@ -2978,6 +2936,7 @@ HandleTrayContextMenu:
     BEGIN_COM_MAP(CTrayWindow)
         /*COM_INTERFACE_ENTRY_IID(IID_ITrayWindow, ITrayWindow)*/
         COM_INTERFACE_ENTRY_IID(IID_IShellDesktopTray, IShellDesktopTray)
+        COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
     END_COM_MAP()
 };
 
@@ -3005,7 +2964,7 @@ public:
                          UINT idCmdLast,
                          UINT uFlags)
     {
-        HMENU menubase = LoadPopupMenu(hExplorerInstance, MAKEINTRESOURCE(IDM_TRAYWND));
+        HMENU menubase = LoadPopupMenu(hExplorerInstance, MAKEINTRESOURCEW(IDM_TRAYWND));
 
         if (!menubase)
             return HRESULT_FROM_WIN32(GetLastError());
@@ -3026,8 +2985,6 @@ public:
 
             TRACE("Adding item %d label %S type %d\n", mii.wID, mii.dwTypeData, mii.fType);
 
-            mii.fType |= MFT_RADIOCHECK;
-
             ::InsertMenuItemW(hPopup, i + 1, TRUE, &mii);
         }
 
@@ -3077,7 +3034,7 @@ public:
                     /* Setup and invoke the shell command */
                     cmici.cbSize = sizeof(cmici);
                     cmici.hwnd = hWndOwner;
-                    cmici.lpVerb = (LPCSTR) MAKEINTRESOURCE(uiCmdId - ID_SHELL_CMD_FIRST);
+                    cmici.lpVerb = (LPCSTR) MAKEINTRESOURCEW(uiCmdId - ID_SHELL_CMD_FIRST);
                     cmici.nShow = SW_NORMAL;
 
                     pcm->InvokeCommand(&cmici);