[EXPLORER-NEW]
[reactos.git] / base / shell / explorer-new / trayntfy.cpp
index 87b6902..c74994a 100644 (file)
@@ -28,14 +28,6 @@ typedef unsigned short USHORT;
  */
 static const WCHAR szSysPagerWndClass [] = TEXT("SysPager");
 
-typedef struct _NOTIFY_ITEM
-{
-    struct _NOTIFY_ITEM *next;
-    INT Index;
-    INT IconIndex;
-    NOTIFYICONDATA iconData;
-} NOTIFY_ITEM, *PNOTIFY_ITEM, **PPNOTIFY_ITEM;
-
 // Data comes from shell32/systray.cpp -> TrayNotifyCDS_Dummy
 typedef struct _SYS_PAGER_COPY_DATA
 {
@@ -44,235 +36,280 @@ typedef struct _SYS_PAGER_COPY_DATA
     NOTIFYICONDATA  nicon_data;
 } SYS_PAGER_COPY_DATA, *PSYS_PAGER_COPY_DATA;
 
-class CSysPagerWnd :
-    public CComObjectRootEx<CComMultiThreadModelNoCS>,
-    public CWindowImpl < CSysPagerWnd, CWindow, CControlWinTraits >
+template<typename TItemData>
+class CToolbar :
+    public CWindowImpl < CToolbar<TItemData>, CWindow, CControlWinTraits>
 {
-    CContainedWindow NotificationBar;
-
-    HWND hWndToolbar;
-    HIMAGELIST SysIcons;
-    PNOTIFY_ITEM NotifyItems;
-    INT ButtonCount;
-    INT VisibleButtonCount;
 
 public:
-    CSysPagerWnd() :
-        NotificationBar(this, 1),
-        hWndToolbar(NULL),
-        SysIcons(NULL),
-        NotifyItems(NULL),
-        ButtonCount(0),
-        VisibleButtonCount(0)
+    int GetItemCount()
     {
+        return this->SendMessageW(TB_BUTTONCOUNT);
     }
-    virtual ~CSysPagerWnd() { }
 
-    PNOTIFY_ITEM CreateNotifyItemData()
+    DWORD GetButton(int index, TBBUTTON * btn)
     {
-        PNOTIFY_ITEM *findNotifyPointer = &NotifyItems;
-        PNOTIFY_ITEM notifyItem;
+        return this->SendMessageW(TB_GETBUTTON, index, (LPARAM) btn);
+    }
 
-        notifyItem = (PNOTIFY_ITEM) HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, sizeof(*notifyItem));
-        if (notifyItem == NULL)
-            return NULL;
+    DWORD AddButton(TBBUTTON * btn)
+    {
+        return this->SendMessageW(TB_ADDBUTTONS, 1, (LPARAM) btn);
+    }
 
-        notifyItem->next = NULL;
+    DWORD AddButtons(int count, TBBUTTON * buttons)
+    {
+        return this->SendMessageW(TB_ADDBUTTONS, count, (LPARAM) buttons);
+    }
 
-        while (*findNotifyPointer != NULL)
-        {
-            findNotifyPointer = &(*findNotifyPointer)->next;
-        }
+    DWORD InsertButton(int insertAt, TBBUTTON * btn)
+    {
+        return this->SendMessageW(TB_INSERTBUTTON, insertAt, (LPARAM) btn);
+    }
 
-        *findNotifyPointer = notifyItem;
+    DWORD MoveButton(int oldIndex, int newIndex)
+    {
+        return this->SendMessageW(TB_MOVEBUTTON, oldIndex, newIndex);
+    }
 
-        return notifyItem;
+    DWORD DeleteButton(int index)
+    {
+        return this->SendMessageW(TB_DELETEBUTTON, index, 0);
     }
 
-    PPNOTIFY_ITEM FindPPNotifyItemByIconData(IN CONST NOTIFYICONDATA *iconData)
+    DWORD GetButtonInfo(int cmdId, TBBUTTONINFO * info)
+    {
+        return this->SendMessageW(TB_GETBUTTONINFO, cmdId, (LPARAM) info);
+    }
+    
+    DWORD SetButtonInfo(int cmdId, TBBUTTONINFO * info)
     {
-        PPNOTIFY_ITEM findNotifyPointer = &NotifyItems;
+        return this->SendMessageW(TB_SETBUTTONINFO, cmdId, (LPARAM) info);
+    }
 
-        while (*findNotifyPointer != NULL)
-        {
-            if ((*findNotifyPointer)->iconData.hWnd == iconData->hWnd &&
-                (*findNotifyPointer)->iconData.uID == iconData->uID)
-            {
-                return findNotifyPointer;
-            }
-            findNotifyPointer = &(*findNotifyPointer)->next;
-        }
+public:
+    DWORD SetButtonSize(int w, int h)
+    {
+        return this->SendMessageW(TB_SETBUTTONSIZE, 0, MAKELONG(w, h));
+    }
+
+public:
+    DWORD AutoSize()
+    {
+        return this->SendMessageW(TB_AUTOSIZE);
+    }
+
+public:
+    TItemData * GetItemData(int index)
+    {
+        TBBUTTON btn;
+        GetButton(index, &btn);
+        return (TItemData*) btn.dwData;
+    }
+
+    DWORD SetItemData(int index, TItemData * data)
+    {
+        TBBUTTONINFOW info = { 0 };
+        info.cbSize = sizeof(info);
+        info.dwMask = TBIF_BYINDEX | TBIF_LPARAM;
+        info.lParam = (DWORD_PTR) data;
+        return SetButtonInfo(index, &info);
+    }
+};
+
+class CNotifyToolbar :
+    public CToolbar<NOTIFYICONDATA>
+{
+    static const int ICON_SIZE = 16;
+
+    HIMAGELIST SysIcons;
+    int VisibleButtonCount;
 
-        return NULL;
+public:
+    CNotifyToolbar() :
+        SysIcons(NULL),
+        VisibleButtonCount(0)
+    {
+    }
+
+    ~CNotifyToolbar()
+    {
+    }
+
+    int GetVisibleItemCount()
+    {
+        return VisibleButtonCount;
     }
 
-    PPNOTIFY_ITEM FindPPNotifyItemByIndex(IN WORD wIndex)
+    int FindItemByIconData(IN CONST NOTIFYICONDATA *iconData, NOTIFYICONDATA ** pdata)
     {
-        PPNOTIFY_ITEM findNotifyPointer = &NotifyItems;
+        int count = GetItemCount();
 
-        while (*findNotifyPointer != NULL)
+        for (int i = 0; i < count; i++)
         {
-            if ((*findNotifyPointer)->Index == wIndex)
+            NOTIFYICONDATA * data;
+
+            data = GetItemData(i);
+
+            if (data->hWnd == iconData->hWnd &&
+                data->uID == iconData->uID)
             {
-                return findNotifyPointer;
+                if (pdata)
+                    *pdata = data;
+                return i;
             }
-            findNotifyPointer = &(*findNotifyPointer)->next;
         }
 
-        return NULL;
+        return -1;
     }
 
-    VOID UpdateButton(IN CONST NOTIFYICONDATA *iconData)
+    VOID AddButton(IN CONST NOTIFYICONDATA *iconData)
     {
-        TBBUTTONINFO tbbi = { 0 };
-        PNOTIFY_ITEM notifyItem;
-        PPNOTIFY_ITEM NotifyPointer;
+        TBBUTTON tbBtn;
+        NOTIFYICONDATA * notifyItem;
+        WCHAR text [] = TEXT("");
 
-        NotifyPointer = FindPPNotifyItemByIconData(iconData);
-        notifyItem = *NotifyPointer;
+        notifyItem = new NOTIFYICONDATA();
+        ZeroMemory(notifyItem, sizeof(*notifyItem));
 
-        tbbi.cbSize = sizeof(tbbi);
-        tbbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND;
-        tbbi.idCommand = notifyItem->Index;
+        notifyItem->hWnd = iconData->hWnd;
+        notifyItem->uID = iconData->uID;
+
+        tbBtn.fsState = TBSTATE_ENABLED;
+        tbBtn.fsStyle = BTNS_NOPREFIX;
+        tbBtn.dwData = (DWORD_PTR)notifyItem;
+        tbBtn.iString = (INT_PTR) text;
+        tbBtn.idCommand = GetItemCount();
 
         if (iconData->uFlags & NIF_MESSAGE)
         {
-            notifyItem->iconData.uCallbackMessage = iconData->uCallbackMessage;
+            notifyItem->uCallbackMessage = iconData->uCallbackMessage;
         }
 
         if (iconData->uFlags & NIF_ICON)
         {
-            tbbi.dwMask |= TBIF_IMAGE;
-            notifyItem->IconIndex = tbbi.iImage = ImageList_AddIcon(SysIcons, iconData->hIcon);
+            tbBtn.iBitmap = ImageList_AddIcon(SysIcons, iconData->hIcon);
         }
 
         if (iconData->uFlags & NIF_TIP)
         {
-            StringCchCopy(notifyItem->iconData.szTip, _countof(notifyItem->iconData.szTip), iconData->szTip);
+            StringCchCopy(notifyItem->szTip, _countof(notifyItem->szTip), iconData->szTip);
         }
 
+        VisibleButtonCount++;
         if (iconData->uFlags & NIF_STATE)
         {
-            if (iconData->dwStateMask & NIS_HIDDEN &&
-                (notifyItem->iconData.dwState & NIS_HIDDEN) != (iconData->dwState & NIS_HIDDEN))
+            notifyItem->dwState &= ~iconData->dwStateMask;
+            notifyItem->dwState |= (iconData->dwState & iconData->dwStateMask);
+            if (notifyItem->dwState & NIS_HIDDEN)
             {
-                tbbi.dwMask |= TBIF_STATE;
-                if (iconData->dwState & NIS_HIDDEN)
-                {
-                    tbbi.fsState |= TBSTATE_HIDDEN;
-                    VisibleButtonCount--;
-                }
-                else
-                {
-                    tbbi.fsState &= ~TBSTATE_HIDDEN;
-                    VisibleButtonCount++;
-                }
+                tbBtn.fsState |= TBSTATE_HIDDEN;
+                VisibleButtonCount--;
             }
 
-            notifyItem->iconData.dwState &= ~iconData->dwStateMask;
-            notifyItem->iconData.dwState |= (iconData->dwState & iconData->dwStateMask);
         }
 
         /* TODO: support NIF_INFO, NIF_GUID, NIF_REALTIME, NIF_SHOWTIP */
 
-        NotificationBar.SendMessageW(TB_SETBUTTONINFO, (WPARAM) notifyItem->Index, (LPARAM) &tbbi);
+        CToolbar::AddButton(&tbBtn);
+        SetButtonSize(ICON_SIZE, ICON_SIZE);
     }
 
-    VOID AddButton(IN CONST NOTIFYICONDATA *iconData)
+    VOID UpdateButton(IN CONST NOTIFYICONDATA *iconData)
     {
-        TBBUTTON tbBtn;
-        PNOTIFY_ITEM notifyItem;
-        WCHAR text [] = TEXT("");
-
-        notifyItem = CreateNotifyItemData();
-
-        notifyItem->next = NULL;
-        notifyItem->Index = ButtonCount;
-        ButtonCount++;
-        VisibleButtonCount++;
+        NOTIFYICONDATA * notifyItem;
+        TBBUTTONINFO tbbi = { 0 };
 
-        notifyItem->iconData.hWnd = iconData->hWnd;
-        notifyItem->iconData.uID = iconData->uID;
+        int index = FindItemByIconData(iconData, &notifyItem);
+        if (index < 0)
+        {
+            AddButton(iconData);
+            return;
+        }
 
-        tbBtn.fsState = TBSTATE_ENABLED;
-        tbBtn.fsStyle = BTNS_NOPREFIX;
-        tbBtn.dwData = notifyItem->Index;
+        tbbi.cbSize = sizeof(tbbi);
+        tbbi.dwMask = TBIF_BYINDEX | TBIF_STATE;
+        GetButtonInfo(index, &tbbi);
 
-        tbBtn.iString = (INT_PTR) text;
-        tbBtn.idCommand = notifyItem->Index;
+        tbbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND;
+        tbbi.idCommand = index;
 
         if (iconData->uFlags & NIF_MESSAGE)
         {
-            notifyItem->iconData.uCallbackMessage = iconData->uCallbackMessage;
+            notifyItem->uCallbackMessage = iconData->uCallbackMessage;
         }
 
         if (iconData->uFlags & NIF_ICON)
         {
-            notifyItem->IconIndex = tbBtn.iBitmap = ImageList_AddIcon(SysIcons, iconData->hIcon);
+            tbbi.dwMask |= TBIF_IMAGE;
+            tbbi.iImage = ImageList_AddIcon(SysIcons, iconData->hIcon);
         }
 
-        /* TODO: support NIF_TIP */
+        if (iconData->uFlags & NIF_TIP)
+        {
+            StringCchCopy(notifyItem->szTip, _countof(notifyItem->szTip), iconData->szTip);
+        }
 
         if (iconData->uFlags & NIF_STATE)
         {
-            notifyItem->iconData.dwState &= ~iconData->dwStateMask;
-            notifyItem->iconData.dwState |= (iconData->dwState & iconData->dwStateMask);
-            if (notifyItem->iconData.dwState & NIS_HIDDEN)
+            if (iconData->dwStateMask & NIS_HIDDEN &&
+                (notifyItem->dwState & NIS_HIDDEN) != (iconData->dwState & NIS_HIDDEN))
             {
-                tbBtn.fsState |= TBSTATE_HIDDEN;
-                VisibleButtonCount--;
+                tbbi.dwMask |= TBIF_STATE;
+                if (iconData->dwState & NIS_HIDDEN)
+                {
+                    if ((tbbi.fsState & TBSTATE_HIDDEN) == 0)
+                    {
+                        tbbi.fsState |= TBSTATE_HIDDEN;
+                        VisibleButtonCount--;
+                    }
+                }
+                else
+                {
+                    if ((tbbi.fsState & TBSTATE_HIDDEN) != 0)
+                    {
+                        tbbi.fsState &= ~TBSTATE_HIDDEN;
+                        VisibleButtonCount++;
+                    }
+                }
             }
 
+            notifyItem->dwState &= ~iconData->dwStateMask;
+            notifyItem->dwState |= (iconData->dwState & iconData->dwStateMask);
         }
 
         /* TODO: support NIF_INFO, NIF_GUID, NIF_REALTIME, NIF_SHOWTIP */
 
-        NotificationBar.SendMessageW(TB_INSERTBUTTON, notifyItem->Index, (LPARAM) &tbBtn);
-
-        NotificationBar.SendMessageW(TB_SETBUTTONSIZE, 0, MAKELONG(16, 16));
+        SetButtonInfo(index, &tbbi);
     }
 
     VOID RemoveButton(IN CONST NOTIFYICONDATA *iconData)
     {
-        PPNOTIFY_ITEM NotifyPointer;
-
-        NotifyPointer = FindPPNotifyItemByIconData(iconData);
-        if (NotifyPointer)
-        {
-            PNOTIFY_ITEM deleteItem;
-            PNOTIFY_ITEM updateItem;
-            deleteItem = *NotifyPointer;
-
-            NotificationBar.SendMessageW(TB_DELETEBUTTON, deleteItem->Index, 0);
+        NOTIFYICONDATA * notifyItem;
 
-            *NotifyPointer = updateItem = deleteItem->next;
-
-            if (!(deleteItem->iconData.dwState & NIS_HIDDEN))
-                VisibleButtonCount--;
-            HeapFree(hProcessHeap,
-                0,
-                deleteItem);
-            ButtonCount--;
+        int index = FindItemByIconData(iconData, &notifyItem);
+        if (index < 0)
+            return;
 
-            while (updateItem != NULL)
-            {
-                TBBUTTONINFO tbbi;
-                updateItem->Index--;
-                tbbi.cbSize = sizeof(tbbi);
-                tbbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND;
-                tbbi.idCommand = updateItem->Index;
+        DeleteButton(index);
+        delete notifyItem;
+    }
 
-                NotificationBar.SendMessageW(TB_SETBUTTONINFO, updateItem->Index, (LPARAM) &tbbi);
+    VOID GetTooltip(int index, LPTSTR szTip, DWORD cchTip)
+    {
+        NOTIFYICONDATA * notifyItem;
+        notifyItem = GetItemData(index);
 
-                updateItem = updateItem->next;
-            }
+        if (notifyItem)
+        {
+            StringCchCopy(szTip, cchTip, notifyItem->szTip);
         }
     }
 
+private:
+
     VOID SendMouseEvent(IN WORD wIndex, IN UINT uMsg, IN WPARAM wParam)
     {
-        PPNOTIFY_ITEM NotifyPointer;
-
         static LPCWSTR eventNames [] = {
             L"WM_MOUSEMOVE",
             L"WM_LBUTTONDOWN",
@@ -290,66 +327,63 @@ public:
             L"WM_XBUTTONDBLCLK"
         };
 
-        NotifyPointer = FindPPNotifyItemByIndex(wIndex);
-        if (!NotifyPointer)
-            return;
-
-        PNOTIFY_ITEM notifyItem = *NotifyPointer;
+        NOTIFYICONDATA * notifyItem = GetItemData(wIndex);
 
-        if (!::IsWindow(notifyItem->iconData.hWnd))
+        if (!::IsWindow(notifyItem->hWnd))
             return;
 
         if (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST)
         {
             DbgPrint("Sending message %S from button %d to %p (msg=%x, w=%x, l=%x)...\n",
                      eventNames[uMsg - WM_MOUSEFIRST], wIndex,
-                     notifyItem->iconData.hWnd, notifyItem->iconData.uCallbackMessage, notifyItem->iconData.uID, uMsg);
+                     notifyItem->hWnd, notifyItem->uCallbackMessage, notifyItem->uID, uMsg);
         }
 
         DWORD pid;
-        GetWindowThreadProcessId(notifyItem->iconData.hWnd, &pid);
+        GetWindowThreadProcessId(notifyItem->hWnd, &pid);
 
         if (pid == GetCurrentProcessId() ||
             (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST))
         {
-            PostMessage(notifyItem->iconData.hWnd,
-                notifyItem->iconData.uCallbackMessage,
-                notifyItem->iconData.uID,
-                uMsg);
+            PostMessage(notifyItem->hWnd,
+                        notifyItem->uCallbackMessage,
+                        notifyItem->uID,
+                        uMsg);
         }
         else
         {
-            SendMessage(notifyItem->iconData.hWnd,
-                notifyItem->iconData.uCallbackMessage,
-                notifyItem->iconData.uID,
-                uMsg);
+            SendMessage(notifyItem->hWnd,
+                        notifyItem->uCallbackMessage,
+                        notifyItem->uID,
+                        uMsg);
         }
     }
 
-    LRESULT DrawBackground(HDC hdc)
+    LRESULT OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        RECT rect;
+        POINT pt;
+        INT iBtn;
 
-        GetClientRect(&rect);
-        DrawThemeParentBackground(m_hWnd, hdc, &rect);
+        pt.x = LOWORD(lParam);
+        pt.y = HIWORD(lParam);
 
-        return TRUE;
-    }
+        iBtn = (INT) SendMessageW(TB_HITTEST, 0, (LPARAM) &pt);
 
-    LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        HDC hdc = (HDC) wParam;
-
-        if (!IsAppThemed())
+        if (iBtn >= 0)
         {
-            bHandled = FALSE;
-            return 0;
+            SendMouseEvent(iBtn, uMsg, wParam);
         }
 
-        return DrawBackground(hdc);
+        bHandled = FALSE;
+        return FALSE;
     }
 
-    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+public:
+    BEGIN_MSG_MAP(CNotifyToolbar)
+        MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseEvent)
+    END_MSG_MAP()
+
+    void Initialize(HWND hWndParent)
     {
         DWORD styles =
             WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN |
@@ -357,37 +391,75 @@ public:
             CCS_TOP | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NODIVIDER;
         DWORD exStyles = WS_EX_TOOLWINDOW;
 
-        hWndToolbar = CreateWindowEx(exStyles,
-            TOOLBARCLASSNAME,
-            NULL,
-            styles,
-            0,
-            0,
-            0,
-            0,
-            m_hWnd,
-            NULL,
-            hExplorerInstance,
-            NULL);
+        HWND hWndToolbar = CreateWindowEx(exStyles,
+                                          TOOLBARCLASSNAME,
+                                          NULL,
+                                          styles,
+                                          0,
+                                          0,
+                                          0,
+                                          0,
+                                          hWndParent,
+                                          NULL,
+                                          hExplorerInstance,
+                                          NULL);
         if (hWndToolbar != NULL)
         {
-            SIZE BtnSize;
-
-            NotificationBar.SubclassWindow(hWndToolbar);
+            SubclassWindow(hWndToolbar);
 
             SetWindowTheme(hWndToolbar, L"TrayNotify", NULL);
 
             /* Identify the version we're using */
-            NotificationBar.SendMessageW(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
+            SendMessageW(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
 
             SysIcons = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 1000);
-            NotificationBar.SendMessageW(TB_SETIMAGELIST, 0, (LPARAM) SysIcons);
+            SendMessageW(TB_SETIMAGELIST, 0, (LPARAM) SysIcons);
+
+            SetButtonSize(ICON_SIZE, ICON_SIZE);
+        }
+    }
+};
+
+class CSysPagerWnd :
+    public CComObjectRootEx<CComMultiThreadModelNoCS>,
+    public CWindowImpl < CSysPagerWnd, CWindow, CControlWinTraits >
+{
+    CNotifyToolbar * Toolbar;
+
+public:
+    CSysPagerWnd() :
+        Toolbar(NULL)
+    {
+    }
+    virtual ~CSysPagerWnd() { }
+
+    LRESULT DrawBackground(HDC hdc)
+    {
+        RECT rect;
 
-            BtnSize.cx = BtnSize.cy = 18;
-            NotificationBar.SendMessageW(TB_SETBUTTONSIZE, 0, MAKELONG(BtnSize.cx, BtnSize.cy));
+        GetClientRect(&rect);
+        DrawThemeParentBackground(m_hWnd, hdc, &rect);
+
+        return TRUE;
+    }
+
+    LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    {
+        HDC hdc = (HDC) wParam;
 
+        if (!IsAppThemed())
+        {
+            bHandled = FALSE;
+            return 0;
         }
 
+        return DrawBackground(hdc);
+    }
+
+    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    {
+        Toolbar = new CNotifyToolbar();
+        Toolbar->Initialize(m_hWnd);
         return TRUE;
     }
 
@@ -411,33 +483,17 @@ public:
             {
             case NIM_ADD:
             {
-                PPNOTIFY_ITEM NotifyPointer;
-
-                NotifyPointer = FindPPNotifyItemByIconData(iconData);
-                if (!NotifyPointer)
-                {
-                    AddButton(iconData);
-                }
+                Toolbar->AddButton(iconData);
                 break;
             }
             case NIM_MODIFY:
             {
-                PPNOTIFY_ITEM NotifyPointer;
-
-                NotifyPointer = FindPPNotifyItemByIconData(iconData);
-                if (!NotifyPointer)
-                {
-                    AddButton(iconData);
-                }
-                else
-                {
-                    UpdateButton(iconData);
-                }
+                Toolbar->UpdateButton(iconData);
                 break;
             }
             case NIM_DELETE:
             {
-                RemoveButton(iconData);
+                Toolbar->RemoveButton(iconData);
                 break;
             }
             default:
@@ -458,6 +514,7 @@ public:
     {
         INT rows = 0;
         TBMETRICS tbm;
+        int VisibleButtonCount = Toolbar->GetVisibleItemCount();
 
         if (wParam) /* horizontal */
         {
@@ -480,23 +537,13 @@ public:
         tbm.cxButtonSpacing = 0;
         tbm.cyButtonSpacing = 0;
 
-        NotificationBar.SendMessageW(TB_SETMETRICS, 0, (LPARAM) &tbm);
-    }
-
-    LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        return TRUE;
+        Toolbar->SendMessageW(TB_SETMETRICS, 0, (LPARAM) &tbm);
     }
 
     LRESULT OnGetInfoTip(INT uCode, LPNMHDR hdr, BOOL& bHandled)
     {
         NMTBGETINFOTIPW * nmtip = (NMTBGETINFOTIPW *) hdr;
-        PPNOTIFY_ITEM ptr = FindPPNotifyItemByIndex(nmtip->iItem);
-        if (ptr)
-        {
-            PNOTIFY_ITEM item = *ptr;
-            StringCchCopy(nmtip->pszText, nmtip->cchTextMax, item->iconData.szTip);
-        }
+        Toolbar->GetTooltip(nmtip->iItem, nmtip->pszText, nmtip->cchTextMax);
         return TRUE;
     }
 
@@ -523,43 +570,25 @@ public:
 
         Ret = DefWindowProc(uMsg, wParam, lParam);
 
-        if (hWndToolbar != NULL && hWndToolbar != m_hWnd)
+        if (Toolbar)
         {
-            NotificationBar.SetWindowPos(NULL, 0, 0, szClient.cx, szClient.cy, SWP_NOZORDER);
+            Toolbar->SetWindowPos(NULL, 0, 0, szClient.cx, szClient.cy, SWP_NOZORDER);
 
-            NotificationBar.SendMessageW(TB_AUTOSIZE);
+            Toolbar->AutoSize();
 
             RECT rc;
-            NotificationBar.GetClientRect(&rc);
+            Toolbar->GetClientRect(&rc);
 
             SIZE szBar = { rc.right - rc.left, rc.bottom - rc.top };
 
             INT xOff = (szClient.cx - szBar.cx) / 2;
             INT yOff = (szClient.cy - szBar.cy) / 2;
 
-            NotificationBar.SetWindowPos(NULL, xOff, yOff, szBar.cx, szBar.cy, SWP_NOZORDER);
+            Toolbar->SetWindowPos(NULL, xOff, yOff, szBar.cx, szBar.cy, SWP_NOZORDER);
         }
         return Ret;
     }
 
-    LRESULT OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        POINT pt;
-        INT iBtn;
-
-        pt.x = LOWORD(lParam);
-        pt.y = HIWORD(lParam);
-
-        iBtn = (INT) NotificationBar.SendMessageW(TB_HITTEST, 0, (LPARAM) &pt);
-
-        if (iBtn >= 0)
-        {
-            SendMouseEvent(iBtn, uMsg, wParam);
-        }
-
-        return FALSE;
-    }
-
     DECLARE_WND_CLASS_EX(szSysPagerWndClass, CS_DBLCLKS, COLOR_3DFACE)
 
     BEGIN_MSG_MAP(CTaskSwitchWnd)
@@ -568,18 +597,12 @@ public:
         MESSAGE_HANDLER(WM_SIZE, OnSize)
         NOTIFY_CODE_HANDLER(TBN_GETINFOTIPW, OnGetInfoTip)
         NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
-    ALT_MSG_MAP(1)
-        MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseEvent)
     END_MSG_MAP()
 
     HWND _Init(IN HWND hWndParent, IN BOOL bVisible)
     {
         DWORD dwStyle;
 
-        NotifyItems = NULL;
-        ButtonCount = 0;
-        VisibleButtonCount = 0;
-
         /* Create the window. The tray window is going to move it to the correct
             position and resize it as needed. */
         dwStyle = WS_CHILD | WS_CLIPSIBLINGS;