[EXPLORER] -Open the start menu on mouse down. Patch by Joachim Henze (reactosfanboy...
[reactos.git] / reactos / base / shell / explorer / traywnd.cpp
index 45f30ec..88908e2 100644 (file)
@@ -53,8 +53,6 @@ HRESULT TrayWindowCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, ICont
 #define IDHK_DESKTOP 0x1fe
 #define IDHK_PAGER 0x1ff
 
-static LONG TrayWndCount = 0;
-
 static const WCHAR szTrayWndClass[] = L"Shell_TrayWnd";
 
 /*
@@ -64,7 +62,7 @@ static const WCHAR szTrayWndClass[] = L"Shell_TrayWnd";
 const GUID IID_IShellDesktopTray = { 0x213e2df9, 0x9a14, 0x4328, { 0x99, 0xb1, 0x69, 0x61, 0xf9, 0x14, 0x3c, 0xe9 } };
 
 class CStartButton
-    : public CWindow
+    : public CWindowImpl<CStartButton>
 {
     HIMAGELIST m_ImageList;
     SIZE       m_Size;
@@ -88,17 +86,12 @@ 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 };
 
@@ -106,26 +99,34 @@ public:
             !SendMessageW(BCM_GETIDEALSIZE, 0, (LPARAM) &Size))
         {
             Size.cx = 2 * GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CYCAPTION) * 3;
-            Size.cy = 2 * GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CYCAPTION);
         }
 
+        Size.cy = max(Size.cy, GetSystemMetrics(SM_CYCAPTION));
+
         /* Save the size of the start button */
         m_Size = Size;
     }
 
-    VOID Initialize()
+    VOID UpdateFont()
     {
-        SetWindowTheme(m_hWnd, L"Start", NULL);
-
         /* Get the system fonts, we use the caption font, always bold, though. */
         NONCLIENTMETRICS ncm = {sizeof(ncm)};
-        if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE))
-        {
-            ncm.lfCaptionFont.lfWeight = FW_BOLD;
-            m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
-        }
+        if (!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE))
+            return;
+
+        if (m_Font)
+            DeleteObject(m_Font);
+
+        ncm.lfCaptionFont.lfWeight = FW_BOLD;
+        m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
 
         SetFont(m_Font, FALSE);
+    }
+
+    VOID Initialize()
+    {
+        SubclassWindow(m_hWnd);
+        SetWindowTheme(m_hWnd, L"Start", NULL);
 
         m_ImageList = ImageList_LoadImageW(hExplorerInstance,
                                            MAKEINTRESOURCEW(IDB_START),
@@ -167,6 +168,20 @@ public:
 
         return m_hWnd;
     }
+
+    LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    {
+        if (uMsg == WM_KEYUP && wParam != VK_SPACE)
+            return 0;
+
+        GetParent().PostMessage(TWM_OPENSTARTMENU);
+        return 0;
+    }
+
+    BEGIN_MSG_MAP(CStartButton)
+        MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
+    END_MSG_MAP()
+
 };
 
 class CTrayWindow :
@@ -174,16 +189,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;
@@ -236,7 +252,6 @@ public:
     CTrayWindow() :
         m_StartButton(),
         m_Theme(NULL),
-        m_CaptionFont(NULL),
         m_Font(NULL),
         m_DesktopWnd(NULL),
         m_Rebar(NULL),
@@ -267,12 +282,6 @@ public:
             m_ShellServices = NULL;
         }
 
-        if (m_CaptionFont != NULL)
-        {
-            DeleteObject(m_CaptionFont);
-            m_CaptionFont = NULL;
-        }
-
         if (m_Font != NULL)
         {
             DeleteObject(m_Font);
@@ -285,8 +294,7 @@ public:
             m_Theme = NULL;
         }
 
-        if (InterlockedDecrement(&TrayWndCount) == 0)
-            PostQuitMessage(0);
+        PostQuitMessage(0);
     }
 
 
@@ -511,6 +519,7 @@ public:
             break;
 
         case ID_SHELL_CMD_CUST_NOTIF:
+            ShowCustomizeNotifyIcons(hExplorerInstance, m_hWnd);
             break;
 
         case ID_SHELL_CMD_ADJUST_DAT:
@@ -733,28 +742,35 @@ public:
      *    ##### moving and sizing handling #####
      */
 
-    BOOL UpdateNonClientMetrics()
+    void UpdateFonts()
     {
-        NONCLIENTMETRICS ncm;
-        ncm.cbSize = sizeof(ncm);
-        if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
-        {
-            if (m_Font != NULL)
-                DeleteObject(m_Font);
+        /* There is nothing to do if themes are not enabled */
+        if (m_Theme)
+            return;
 
-            m_Font = CreateFontIndirect(&ncm.lfMessageFont);
-            return TRUE;
+        m_StartButton.UpdateFont();
+
+        NONCLIENTMETRICS ncm = {sizeof(ncm)};
+        if (!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE))
+        {
+            ERR("SPI_GETNONCLIENTMETRICS failed\n");
+            return;
         }
 
-        return FALSE;
-    }
+        if (m_Font != NULL)
+            DeleteObject(m_Font);
 
-    VOID SetWindowsFont()
-    {
-        if (m_TrayNotify != NULL)
+        ncm.lfCaptionFont.lfWeight = FW_NORMAL;
+        m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
+        if (!m_Font)
         {
-            SendMessage(m_TrayNotify, WM_SETFONT, (WPARAM) m_Font, TRUE);
+            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(
@@ -847,6 +863,35 @@ GetPrimaryRect:
         return hMon;
     }
 
+    VOID AdjustSizerRect(RECT *rc, DWORD pos)
+    {
+        int iSizerPart[4] = {TBP_SIZINGBARLEFT, TBP_SIZINGBARTOP, TBP_SIZINGBARRIGHT, TBP_SIZINGBARBOTTOM};
+        SIZE size;
+
+        if (pos > ABE_BOTTOM)
+            pos = ABE_BOTTOM;
+
+        HRESULT hr = GetThemePartSize(m_Theme, NULL, iSizerPart[pos], 0, NULL, TS_TRUE, &size);
+        if (FAILED_UNEXPECTEDLY(hr))
+            return;
+
+        switch (pos)
+        {
+            case ABE_TOP:
+                rc->bottom -= size.cy;
+                break;
+            case ABE_BOTTOM:
+                rc->top += size.cy;
+                break;
+            case ABE_LEFT:
+                rc->right -= size.cx;
+                break;
+            case ABE_RIGHT:
+                rc->left += size.cx;
+                break;
+        }
+    }
+
     VOID MakeTrayRectWithSize(IN DWORD Position,
                               IN const SIZE *pTraySize,
                               IN OUT RECT *pRect)
@@ -882,10 +927,13 @@ GetPrimaryRect:
 
         *pRect = *pScreen;
 
-        /* Move the border outside of the screen */
-        InflateRect(pRect,
-                    GetSystemMetrics(SM_CXEDGE),
-                    GetSystemMetrics(SM_CYEDGE));
+        if(!m_Theme)
+        {
+            /* Move the border outside of the screen */
+            InflateRect(pRect,
+                        GetSystemMetrics(SM_CXEDGE),
+                        GetSystemMetrics(SM_CYEDGE));
+        }
 
         MakeTrayRectWithSize(Position, pTraySize, pRect);
     }
@@ -1294,6 +1342,16 @@ 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,
@@ -1374,8 +1432,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(!m_Theme)
+            {
+                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;
@@ -1402,8 +1470,16 @@ ChangePos:
            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(!m_Theme)
+        {
+            WndSize.cx = 2 * (EdgeSize.cx + DlgFrameSize.cx);
+            WndSize.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
+        }
+        else
+        {
+            WndSize.cx = StartBtnSize.cx;
+            WndSize.cy = StartBtnSize.cy - EdgeSize.cx;
+        }
 
         if (WndSize.cx < sr.Size.cx)
             WndSize.cx = sr.Size.cx;
@@ -1565,6 +1641,41 @@ ChangePos:
         }
     }
 
+    void FitToRebar(PRECT pRect)
+    {
+        /* Get the rect of the rebar */
+        RECT rebarRect, taskbarRect;
+        ::GetWindowRect(m_Rebar, &rebarRect);
+        ::GetWindowRect(m_hWnd, &taskbarRect);
+        OffsetRect(&rebarRect, -taskbarRect.left, -taskbarRect.top);
+
+        /* 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;
+
+        /* Calculate the new size of the rebar and make it resize, then change the new taskbar size */
+        switch (m_Position)
+        {
+        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 ABE_BOTTOM:
+            rebarRect.top = rebarRect.bottom - (pRect->bottom - pRect->top - margins.cy);
+            ::SendMessageW(m_Rebar, RB_SIZETORECT, RBSTR_CHANGERECT,  (LPARAM)&rebarRect);
+            pRect->top = pRect->bottom - (rebarRect.bottom - rebarRect.top + margins.cy);
+            break;
+        case ABE_LEFT:
+        case ABE_RIGHT:
+            /* FIXME: what to do here? */
+            break;
+        }
+
+        CalculateValidSize(m_Position, pRect);
+    }
+
     void PopupStartMenu()
     {
         if (m_StartMenuPopup != NULL)
@@ -1789,72 +1900,55 @@ ChangePos:
     LRESULT EraseBackgroundWithTheme(HDC hdc)
     {
         RECT rect;
-        int partId;
-        HRESULT res;
+        int iSBkgndPart[4] = {TBP_BACKGROUNDLEFT, TBP_BACKGROUNDTOP, TBP_BACKGROUNDRIGHT, TBP_BACKGROUNDBOTTOM};
 
-        GetClientRect(&rect);
+        ASSERT(m_Position <= ABE_BOTTOM);
 
         if (m_Theme)
         {
             GetClientRect(&rect);
-            switch (m_Position)
-            {
-            case ABE_LEFT:
-                partId = TBP_BACKGROUNDLEFT;
-                break;
-            case ABE_TOP:
-                partId = TBP_BACKGROUNDTOP;
-                break;
-            case ABE_RIGHT:
-                partId = TBP_BACKGROUNDRIGHT;
-                break;
-            case ABE_BOTTOM:
-            default:
-                partId = TBP_BACKGROUNDBOTTOM;
-                break;
-            }
-            res = DrawThemeBackground(m_Theme, hdc, partId, 0, &rect, 0);
+            DrawThemeBackground(m_Theme, hdc, iSBkgndPart[m_Position], 0, &rect, 0);
         }
 
-        return res;
+        return 0;
     }
 
     int DrawSizerWithTheme(IN HRGN hRgn)
     {
         HDC hdc;
         RECT rect;
-        int backgroundPart;
+        int iSizerPart[4] = {TBP_SIZINGBARLEFT, TBP_SIZINGBARTOP, TBP_SIZINGBARRIGHT, TBP_SIZINGBARBOTTOM};
+        SIZE size;
+
+        ASSERT(m_Position <= ABE_BOTTOM);
+
+        HRESULT hr = GetThemePartSize(m_Theme, NULL, iSizerPart[m_Position], 0, NULL, TS_TRUE, &size);
+        if (FAILED_UNEXPECTEDLY(hr))
+            return 0;
 
         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:
-            backgroundPart = TBP_SIZINGBARLEFT;
-            rect.left = rect.right - GetSystemMetrics(SM_CXSIZEFRAME);
+            rect.left = rect.right - size.cx;
             break;
         case ABE_TOP:
-            backgroundPart = TBP_SIZINGBARTOP;
-            rect.top = rect.bottom - GetSystemMetrics(SM_CYSIZEFRAME);
+            rect.top = rect.bottom - size.cy;
             break;
         case ABE_RIGHT:
-            backgroundPart = TBP_SIZINGBARRIGHT;
-            rect.right = rect.left + GetSystemMetrics(SM_CXSIZEFRAME);
+            rect.right = rect.left + size.cx;
             break;
         case ABE_BOTTOM:
         default:
-            backgroundPart = TBP_SIZINGBARBOTTOM;
-            rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZEFRAME);
+            rect.bottom = rect.top + size.cy;
             break;
         }
-        if (IsThemeBackgroundPartiallyTransparent(m_Theme, backgroundPart, 0))
-        {
-            DrawThemeParentBackground(m_hWnd, hdc, &rect);
-        }
-        DrawThemeBackground(m_Theme, hdc, backgroundPart, 0, &rect, 0);
+
+        DrawThemeBackground(m_Theme, hdc, iSizerPart[m_Position], 0, &rect, 0);
 
         ReleaseDC(hdc);
         return 0;
@@ -1875,13 +1969,6 @@ ChangePos:
            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;
         }
 
@@ -1889,8 +1976,11 @@ ChangePos:
         if (AlwaysOnTop)
             dwExStyle |= WS_EX_TOPMOST;
 
-        DWORD dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
-            WS_BORDER | WS_THICKFRAME;
+        DWORD dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+        if(!m_Theme)
+        {
+            dwStyle |= WS_THICKFRAME | WS_BORDER;
+        }
 
         ZeroMemory(&rcWnd, sizeof(rcWnd));
         if (m_Position != (DWORD) -1)
@@ -1899,6 +1989,12 @@ ChangePos:
         if (!Create(NULL, rcWnd, NULL, dwStyle, dwExStyle))
             return E_FAIL;
 
+        /* Align all controls on the tray window */
+        AlignControls(NULL);
+
+        /* Move the tray window to the right position and resize it if necessary */
+        CheckTrayWndPosition();
+
         return S_OK;
     }
 
@@ -1931,14 +2027,6 @@ ChangePos:
         return IsPosHorizontal();
     }
 
-    HFONT STDMETHODCALLTYPE GetCaptionFonts(OUT HFONT *phBoldCaption OPTIONAL)
-    {
-        if (phBoldCaption != NULL)
-            *phBoldCaption = m_StartButton.GetFont();
-
-        return m_CaptionFont;
-    }
-
     BOOL STDMETHODCALLTYPE Lock(IN BOOL bLock)
     {
         BOOL bPrevLock = Locked;
@@ -1957,16 +2045,33 @@ ChangePos:
                 }
             }
 
-            if (Locked && m_Theme)
-            {
-                SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, 0);
-            }
-            else
+            if (m_Theme)
             {
-                SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, WS_THICKFRAME | WS_BORDER);
+                /* 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_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
-
+            SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);
+            ResizeWorkArea();
+            ApplyClipping(TRUE);
         }
 
         return bPrevLock;
@@ -1983,29 +2088,12 @@ ChangePos:
 
     LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
+        HRESULT hRet;
+
         ((ITrayWindow*)this)->AddRef();
 
         SetWindowTheme(m_hWnd, L"TaskBar", NULL);
 
-        InterlockedIncrement(&TrayWndCount);
-
-        if (m_CaptionFont == NULL)
-        {
-            NONCLIENTMETRICS ncm;
-
-            /* Get the system fonts, we use the caption font,
-               always bold, though. */
-            ncm.cbSize = sizeof(ncm);
-            if (SystemParametersInfoW(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.Create(m_hWnd);
 
@@ -2016,23 +2104,32 @@ ChangePos:
         HBITMAP hbmBanner = LoadBitmapW(hExplorerInstance, MAKEINTRESOURCEW(IDB_STARTMENU));
         m_StartMenuPopup = CreateStartMenu(this, &m_StartMenuBand, hbmBanner, 0);
 
-        /* Load the tray band site */
-        m_TrayBandSite = CreateTrayBandSite(this, &m_Rebar, &m_TaskSwitch);
+        /* Create the task band */
+        hRet = CTaskBand_CreateInstance(this, m_StartButton.m_hWnd, 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);
 
-        if (UpdateNonClientMetrics())
-        {
-            SetWindowsFont();
-        }
-
-        /* Move the tray window to the right position and resize it if necessary */
-        CheckTrayWndPosition();
-
-        /* Align all controls on the tray window */
-        AlignControls(NULL);
+        UpdateFonts();
 
         InitShellServices(&m_ShellServices);
 
@@ -2063,12 +2160,9 @@ ChangePos:
         if (m_Theme)
             CloseThemeData(m_Theme);
 
-        if (IsThemeActive())
-            m_Theme = OpenThemeData(m_hWnd, L"TaskBar");
-        else
-            m_Theme = NULL;
+        m_Theme = OpenThemeData(m_hWnd, L"TaskBar");
 
-        if (Locked && m_Theme)
+        if (m_Theme)
         {
             SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, 0);
         }
@@ -2081,6 +2175,19 @@ ChangePos:
         return TRUE;
     }
 
+    LRESULT OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    {
+        if (wParam == SPI_SETNONCLIENTMETRICS)
+        {
+            SendMessage(m_TaskSwitch, uMsg, wParam, lParam);
+            UpdateFonts();
+            AlignControls(NULL);
+            CheckTrayWndPosition();
+        }
+
+        return 0;
+    }
+
     LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
         HDC hdc = (HDC) wParam;
@@ -2096,15 +2203,9 @@ ChangePos:
 
     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 necessary */
         CheckTrayWndPosition();
 
-        /* Align all controls on the tray window */
-        AlignControls(NULL);
-
         return TRUE;
     }
 
@@ -2225,37 +2326,7 @@ ChangePos:
 
         if (!Locked)
         {
-            /* Get the rect of the rebar */
-            RECT rebarRect, taskbarRect;
-            ::GetWindowRect(m_Rebar, &rebarRect);
-            ::GetWindowRect(m_hWnd, &taskbarRect);
-            OffsetRect(&rebarRect, -taskbarRect.left, -taskbarRect.top);
-
-            /* 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;
-
-            /* Calculate the new size of the rebar and make it resize, then change the new taskbar size */
-            switch (m_Position)
-            {
-            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 ABE_BOTTOM:
-                rebarRect.top = rebarRect.bottom - (pRect->bottom - pRect->top - margins.cy);
-                ::SendMessageW(m_Rebar, RB_SIZETORECT, RBSTR_CHANGERECT,  (LPARAM)&rebarRect);
-                pRect->top = pRect->bottom - (rebarRect.bottom - rebarRect.top + margins.cy);
-                break;
-            case ABE_LEFT:
-            case ABE_RIGHT:
-                /* FIXME: what to do here? */
-                break;
-            }
-
-            CalculateValidSize(m_Position, pRect);
+            FitToRebar(pRect);
         }
         else
         {
@@ -2281,7 +2352,6 @@ ChangePos:
     LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
         RECT rcClient;
-        InvalidateRect(NULL, TRUE);
         if (wParam == SIZE_RESTORED && lParam == 0)
         {
             ResizeWorkArea();
@@ -2391,6 +2461,63 @@ ChangePos:
         return TRUE;
     }
 
+    LRESULT OnNcLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    {
+        /* This handler implements the trick that makes  the start button to 
+           get pressed when the user clicked left or below the button */
+
+        POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
+        WINDOWINFO wi = {sizeof(WINDOWINFO)};
+        RECT rcStartBtn;
+
+        bHandled = FALSE;
+
+        m_StartButton.GetWindowRect(&rcStartBtn);
+        GetWindowInfo(m_hWnd, &wi);
+
+        switch (m_Position)
+        {
+            case ABE_TOP:
+            case ABE_LEFT:
+            {
+                if (pt.x > rcStartBtn.right || pt.y > rcStartBtn.bottom)
+                    return 0;
+                break;
+            }
+            case ABE_RIGHT:
+            {
+                if (pt.x < rcStartBtn.left || pt.y > rcStartBtn.bottom)
+                    return 0;
+
+                if (rcStartBtn.right + (int)wi.cxWindowBorders * 2 + 1 < wi.rcWindow.right &&
+                    pt.x > rcStartBtn.right)
+                {
+                    return 0;
+                }
+                break;
+            }
+            case ABE_BOTTOM:
+            {
+                if (pt.x > rcStartBtn.right || pt.y < rcStartBtn.top)
+                {
+                    return 0;
+                }
+
+                if (rcStartBtn.bottom + (int)wi.cyWindowBorders * 2 + 1 < wi.rcWindow.bottom &&
+                    pt.y > rcStartBtn.bottom)
+                {
+                    return 0;
+                }
+
+                break;
+            }
+        }
+
+        bHandled = TRUE;
+        PopupStartMenu();
+        return 0;
+    }
+
     LRESULT OnNcRButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
         /* We want the user to be able to get a context menu even on the nonclient
@@ -2584,7 +2711,6 @@ HandleTrayContextMenu:
 
         if ((HWND) lParam == m_StartButton.m_hWnd)
         {
-            PopupStartMenu();
             return FALSE;
         }
 
@@ -2620,6 +2746,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(!m_Theme || 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
@@ -2693,6 +2848,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)
@@ -2713,6 +2869,7 @@ HandleTrayContextMenu:
         MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChange)
         MESSAGE_HANDLER(WM_ENTERSIZEMOVE, OnEnterSizeMove)
         MESSAGE_HANDLER(WM_EXITSIZEMOVE, OnExitSizeMove)
+        MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNcLButtonDown)
         MESSAGE_HANDLER(WM_SYSCHAR, OnSysChar)
         MESSAGE_HANDLER(WM_NCRBUTTONUP, OnNcRButtonUp)
         MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClick)
@@ -2723,6 +2880,7 @@ HandleTrayContextMenu:
         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()
 
@@ -2815,6 +2973,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;
@@ -2826,6 +2997,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()
 };