[EXPLORER] Minor cleanup/comment fixes.
[reactos.git] / base / shell / explorer / trayntfy.cpp
index 1864e33..63dc236 100644 (file)
 
 #include "precomp.h"
 
-/*
- * SysPagerWnd
- */
-static const WCHAR szSysPagerWndClass [] = L"SysPager";
-
-// Data comes from shell32/systray.cpp -> TrayNotifyCDS_Dummy
-typedef struct _SYS_PAGER_COPY_DATA
-{
-    DWORD           cookie;
-    DWORD           notify_code;
-    NOTIFYICONDATA  nicon_data;
-} SYS_PAGER_COPY_DATA, *PSYS_PAGER_COPY_DATA;
-
-
-struct IconWatcherData
-{
-    HANDLE hProcess;
-    DWORD ProcessId;
-    NOTIFYICONDATA IconData;
-
-    IconWatcherData(NOTIFYICONDATA *iconData) :
-        hProcess(NULL), ProcessId(0)
-    {
-        IconData.cbSize = sizeof(NOTIFYICONDATA);
-        IconData.hWnd = iconData->hWnd;
-        IconData.uID = iconData->uID;
-        IconData.guidItem = iconData->guidItem;
-    }
-
-    ~IconWatcherData()
-    {
-        if (hProcess)
-        {
-            CloseHandle(hProcess);
-        }
-    }
-};
-
-class CIconWatcher
-{
-    CAtlList<IconWatcherData *> m_WatcherList;
-    CRITICAL_SECTION m_ListLock;
-    HANDLE m_hWatcherThread;
-    HANDLE m_WakeUpEvent;
-    HWND m_hwndSysTray;
-    bool m_Loop;
-
-public:
-    CIconWatcher() :
-        m_hWatcherThread(NULL),
-        m_WakeUpEvent(NULL),
-        m_hwndSysTray(NULL),
-        m_Loop(false)
-    {
-    }
-
-    virtual ~CIconWatcher()
-    {
-        Uninitialize();
-        DeleteCriticalSection(&m_ListLock);
-
-        if (m_WakeUpEvent)
-            CloseHandle(m_WakeUpEvent);
-        if (m_hWatcherThread)
-            CloseHandle(m_hWatcherThread);
-    }
-
-    bool Initialize(_In_ HWND hWndParent)
-    {
-        m_hwndSysTray = hWndParent;
-
-        InitializeCriticalSection(&m_ListLock);
-        m_WakeUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
-        if (m_WakeUpEvent == NULL)
-            return false;
-
-        m_hWatcherThread = (HANDLE)_beginthreadex(NULL,
-                                                  0,
-                                                  WatcherThread,
-                                                  (LPVOID)this,
-                                                  0,
-                                                  NULL);
-        if (m_hWatcherThread == NULL)
-            return false;
-
-        return true;
-    }
-
-    void Uninitialize()
-    {
-        m_Loop = false;
-        if (m_WakeUpEvent)
-            SetEvent(m_WakeUpEvent);
-
-        EnterCriticalSection(&m_ListLock);
-
-        POSITION Pos;
-        for (size_t i = 0; i < m_WatcherList.GetCount(); i++)
-        {
-            Pos = m_WatcherList.FindIndex(i);
-            if (Pos)
-            {
-                IconWatcherData *Icon;
-                Icon = m_WatcherList.GetAt(Pos);
-                delete Icon;
-            }
-        }
-        m_WatcherList.RemoveAll();
-
-        LeaveCriticalSection(&m_ListLock);
-    }
-
-    bool AddIconToWatcher(_In_ NOTIFYICONDATA *iconData)
-    {
-        DWORD ProcessId;
-        (void)GetWindowThreadProcessId(iconData->hWnd, &ProcessId);
-
-        HANDLE hProcess;
-        hProcess = OpenProcess(SYNCHRONIZE, FALSE, ProcessId);
-        if (hProcess == NULL)
-        {
-            return false;
-        }
-
-        IconWatcherData *Icon = new IconWatcherData(iconData);
-        Icon->hProcess = hProcess;
-        Icon->ProcessId;
-
-        bool Added = false;
-        EnterCriticalSection(&m_ListLock);
-
-        // The likelyhood of someone having more than 64 icons in their tray is
-        // pretty slim. We could spin up a new thread for each multiple of 64, but
-        // it's not worth the effort, so we just won't bother watching those icons
-        if (m_WatcherList.GetCount() < MAXIMUM_WAIT_OBJECTS)
-        {
-            m_WatcherList.AddTail(Icon);
-            SetEvent(m_WakeUpEvent);
-            Added = true;
-        }
-
-        LeaveCriticalSection(&m_ListLock);
-
-        if (!Added)
-        {
-            delete Icon;
-        }
-
-        return Added;
-    }
-
-    bool RemoveIconFromWatcher(_In_ NOTIFYICONDATA *iconData)
-    {
-        EnterCriticalSection(&m_ListLock);
-        
-        IconWatcherData *Icon;
-        Icon = GetListEntry(iconData, NULL, true);
-
-        SetEvent(m_WakeUpEvent);
-        LeaveCriticalSection(&m_ListLock);
-
-        delete Icon;
-        return true;
-    }
-
-    IconWatcherData* GetListEntry(_In_opt_ NOTIFYICONDATA *iconData, _In_opt_ HANDLE hProcess, _In_ bool Remove)
-    {
-        IconWatcherData *Entry = NULL;
-        POSITION NextPosition = m_WatcherList.GetHeadPosition();
-        POSITION Position;
-        do
-        {
-            Position = NextPosition;
-
-            Entry = m_WatcherList.GetNext(NextPosition);
-            if (Entry)
-            {
-                if ((iconData && ((Entry->IconData.hWnd == iconData->hWnd) && (Entry->IconData.uID == iconData->uID))) ||
-                     (hProcess && (Entry->hProcess == hProcess)))
-                {
-                    if (Remove)
-                        m_WatcherList.RemoveAt(Position);
-                    break;
-                }
-            }
-            Entry = NULL;
-
-        } while (NextPosition != NULL);
-
-        return Entry;
-    }
-
-private:
-
-    static UINT WINAPI WatcherThread(_In_opt_ LPVOID lpParam)
-    {
-        CIconWatcher* This = reinterpret_cast<CIconWatcher *>(lpParam);
-        HANDLE *WatchList = NULL;
-
-        This->m_Loop = true;
-        while (This->m_Loop)
-        {
-            EnterCriticalSection(&This->m_ListLock);
-
-            DWORD Size;
-            Size = This->m_WatcherList.GetCount() + 1;
-            ASSERT(Size <= MAXIMUM_WAIT_OBJECTS);
-
-            if (WatchList)
-                delete WatchList;
-            WatchList = new HANDLE[Size];
-            WatchList[0] = This->m_WakeUpEvent;
-
-            POSITION Pos;
-            for (size_t i = 0; i < This->m_WatcherList.GetCount(); i++)
-            {
-                Pos = This->m_WatcherList.FindIndex(i);
-                if (Pos)
-                {
-                    IconWatcherData *Icon;
-                    Icon = This->m_WatcherList.GetAt(Pos);
-                    WatchList[i + 1] = Icon->hProcess;
-                }
-            }
-
-            LeaveCriticalSection(&This->m_ListLock);
-
-            DWORD Status;
-            Status = WaitForMultipleObjects(Size,
-                                            WatchList,
-                                            FALSE,
-                                            INFINITE);
-            if (Status == WAIT_OBJECT_0)
-            {
-                // We've been kicked, we have updates to our list (or we're exiting the thread)
-                if (This->m_Loop)
-                    TRACE("Updating watched icon list");
-            }
-            else if ((Status >= WAIT_OBJECT_0 + 1) && (Status < Size))
-            {
-                IconWatcherData *Icon;
-                Icon = This->GetListEntry(NULL, WatchList[Status], false);
-
-                TRACE("Pid %lu owns a notification icon and has stopped without deleting it. We'll cleanup on its behalf", Icon->ProcessId);
-
-                int len = FIELD_OFFSET(SYS_PAGER_COPY_DATA, nicon_data) + Icon->IconData.cbSize;
-                PSYS_PAGER_COPY_DATA pnotify_data = (PSYS_PAGER_COPY_DATA)new BYTE[len];
-                pnotify_data->cookie = 1;
-                pnotify_data->notify_code = NIM_DELETE;
-                memcpy(&pnotify_data->nicon_data, &Icon->IconData, Icon->IconData.cbSize);
-
-                COPYDATASTRUCT data;
-                data.dwData = 1;
-                data.cbData = len;
-                data.lpData = pnotify_data;
-
-                BOOL Success = FALSE;
-                HWND parentHWND = ::GetParent(GetParent(This->m_hwndSysTray));
-                if (parentHWND)
-                    Success = ::SendMessage(parentHWND, WM_COPYDATA, (WPARAM)&Icon->IconData, (LPARAM)&data);
-
-                delete pnotify_data;
-
-                if (!Success)
-                {
-                    // If we failed to handle the delete message, forcibly remove it
-                    This->RemoveIconFromWatcher(&Icon->IconData);
-                }
-            }
-            else
-            {
-                if (Status == WAIT_FAILED)
-                {
-                    Status = GetLastError();
-                }
-                ERR("Failed to wait on process handles : %lu\n", Status);
-                This->Uninitialize();
-            }
-        }
-
-        if (WatchList)
-            delete WatchList;
-
-        return 0;
-    }
-};
-
-
-class CNotifyToolbar :
-    public CWindowImplBaseT< CToolbar<NOTIFYICONDATA>, CControlWinTraits >
-{
-    HIMAGELIST m_ImageList;
-    int m_VisibleButtonCount;
-
-public:
-    CNotifyToolbar() :
-        m_ImageList(NULL),
-        m_VisibleButtonCount(0)
-    {
-    }
-
-    ~CNotifyToolbar()
-    {
-    }
-
-    int GetVisibleButtonCount()
-    {
-        return m_VisibleButtonCount;
-    }
-
-    int FindItem(IN HWND hWnd, IN UINT uID, NOTIFYICONDATA ** pdata)
-    {
-        int count = GetButtonCount();
-
-        for (int i = 0; i < count; i++)
-        {
-            NOTIFYICONDATA * data;
-
-            data = GetItemData(i);
-
-            if (data->hWnd == hWnd &&
-                data->uID == uID)
-            {
-                if (pdata)
-                    *pdata = data;
-                return i;
-            }
-        }
-
-        return -1;
-    }
-
-    int FindExistingSharedIcon(HICON handle)
-    {
-        int count = GetButtonCount();
-        for (int i = 0; i < count; i++)
-        {
-            NOTIFYICONDATA * data = GetItemData(i);
-            if (data->hIcon == handle)
-            {
-                TBBUTTON btn;
-                GetButton(i, &btn);
-                return btn.iBitmap;
-            }
-        }
-
-        return -1;
-    }
-
-    BOOL AddButton(IN CONST NOTIFYICONDATA *iconData)
-    {
-        TBBUTTON tbBtn;
-        NOTIFYICONDATA * notifyItem;
-        WCHAR text[] = L"";
-
-        TRACE("Adding icon %d from hWnd %08x flags%s%s state%s%s", 
-            iconData->uID, iconData->hWnd,
-            (iconData->uFlags & NIF_ICON) ? " ICON" : "",
-            (iconData->uFlags & NIF_STATE) ? " STATE" : "",
-            (iconData->dwState & NIS_HIDDEN) ? " HIDDEN" : "",
-            (iconData->dwState & NIS_SHAREDICON) ? " SHARED" : "");
-
-        int index = FindItem(iconData->hWnd, iconData->uID, &notifyItem);
-        if (index >= 0)
-        {
-            TRACE("Icon %d from hWnd %08x ALREADY EXISTS!", iconData->uID, iconData->hWnd);
-            return FALSE;
-        }
-
-        notifyItem = new NOTIFYICONDATA();
-        ZeroMemory(notifyItem, sizeof(*notifyItem));
-
-        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 = GetButtonCount();
-
-        if (iconData->uFlags & NIF_STATE)
-        {
-            notifyItem->dwState = iconData->dwState & iconData->dwStateMask;
-        }
-
-        if (iconData->uFlags & NIF_MESSAGE)
-        {
-            notifyItem->uCallbackMessage = iconData->uCallbackMessage;
-        }
-
-        if (iconData->uFlags & NIF_ICON)
-        {
-            notifyItem->hIcon = iconData->hIcon;
-            BOOL hasSharedIcon = notifyItem->dwState & NIS_SHAREDICON;
-            if (hasSharedIcon)
-            {
-                INT iIcon = FindExistingSharedIcon(notifyItem->hIcon);
-                if (iIcon < 0)
-                {
-                    notifyItem->hIcon = NULL;
-                    TRACE("Shared icon requested, but HICON not found!!!");
-                }
-                tbBtn.iBitmap = iIcon;
-            }
-            else
-            {
-                tbBtn.iBitmap = ImageList_AddIcon(m_ImageList, notifyItem->hIcon);
-            }
-        }
-
-        if (iconData->uFlags & NIF_TIP)
-        {
-            StringCchCopy(notifyItem->szTip, _countof(notifyItem->szTip), iconData->szTip);
-        }
-
-        m_VisibleButtonCount++;
-        if (notifyItem->dwState & NIS_HIDDEN)
-        {
-            tbBtn.fsState |= TBSTATE_HIDDEN;
-            m_VisibleButtonCount--;
-        }
-
-        /* TODO: support NIF_INFO, NIF_GUID, NIF_REALTIME, NIF_SHOWTIP */
-
-        CToolbar::AddButton(&tbBtn);
-        SetButtonSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
-
-        return TRUE;
-    }
-
-    BOOL UpdateButton(IN CONST NOTIFYICONDATA *iconData)
-    {
-        NOTIFYICONDATA * notifyItem;
-        TBBUTTONINFO tbbi = { 0 };
-
-        TRACE("Updating icon %d from hWnd %08x flags%s%s state%s%s",
-            iconData->uID, iconData->hWnd,
-            (iconData->uFlags & NIF_ICON) ? " ICON" : "",
-            (iconData->uFlags & NIF_STATE) ? " STATE" : "",
-            (iconData->dwState & NIS_HIDDEN) ? " HIDDEN" : "",
-            (iconData->dwState & NIS_SHAREDICON) ? " SHARED" : "");
-
-        int index = FindItem(iconData->hWnd, iconData->uID, &notifyItem);
-        if (index < 0)
-        {
-            WARN("Icon %d from hWnd %08x DOES NOT EXIST!", iconData->uID, iconData->hWnd);
-            return AddButton(iconData);
-        }
-
-        TBBUTTON btn;
-        GetButton(index, &btn);
-        int oldIconIndex = btn.iBitmap;
-
-        tbbi.cbSize = sizeof(tbbi);
-        tbbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND;
-        tbbi.idCommand = index;
-
-        if (iconData->uFlags & NIF_STATE)
-        {
-            if (iconData->dwStateMask & NIS_HIDDEN &&
-                (notifyItem->dwState & NIS_HIDDEN) != (iconData->dwState & NIS_HIDDEN))
-            {
-                tbbi.dwMask |= TBIF_STATE;
-                if (iconData->dwState & NIS_HIDDEN)
-                {
-                    tbbi.fsState |= TBSTATE_HIDDEN;
-                    m_VisibleButtonCount--;
-                }
-                else
-                {
-                    tbbi.fsState &= ~TBSTATE_HIDDEN;
-                    m_VisibleButtonCount++;
-                }
-            }
-
-            notifyItem->dwState &= ~iconData->dwStateMask;
-            notifyItem->dwState |= (iconData->dwState & iconData->dwStateMask);
-        }
-
-        if (iconData->uFlags & NIF_MESSAGE)
-        {
-            notifyItem->uCallbackMessage = iconData->uCallbackMessage;
-        }
-
-        if (iconData->uFlags & NIF_ICON)
-        {
-            BOOL hasSharedIcon = notifyItem->dwState & NIS_SHAREDICON;
-            if (hasSharedIcon)
-            {
-                INT iIcon = FindExistingSharedIcon(iconData->hIcon);
-                if (iIcon >= 0)
-                {
-                    notifyItem->hIcon = iconData->hIcon;
-                    tbbi.dwMask |= TBIF_IMAGE;
-                    tbbi.iImage = iIcon;
-                }
-                else
-                {
-                    TRACE("Shared icon requested, but HICON not found!!! IGNORING!");
-                }
-            }
-            else
-            {
-                notifyItem->hIcon = iconData->hIcon;
-                tbbi.dwMask |= TBIF_IMAGE;
-                tbbi.iImage = ImageList_ReplaceIcon(m_ImageList, oldIconIndex, notifyItem->hIcon);
-            }
-        }
-
-        if (iconData->uFlags & NIF_TIP)
-        {
-            StringCchCopy(notifyItem->szTip, _countof(notifyItem->szTip), iconData->szTip);
-        }
-
-        /* TODO: support NIF_INFO, NIF_GUID, NIF_REALTIME, NIF_SHOWTIP */
-
-        SetButtonInfo(index, &tbbi);
-
-        return TRUE;
-    }
-
-    BOOL RemoveButton(IN CONST NOTIFYICONDATA *iconData)
-    {
-        NOTIFYICONDATA * notifyItem;
-
-        TRACE("Removing icon %d from hWnd %08x", iconData->uID, iconData->hWnd);
-
-        int index = FindItem(iconData->hWnd, iconData->uID, &notifyItem);
-        if (index < 0)
-        {
-            TRACE("Icon %d from hWnd %08x ALREADY MISSING!", iconData->uID, iconData->hWnd);
-
-            return FALSE;
-        }
-
-        if (!(notifyItem->dwState & NIS_HIDDEN))
-        {
-            m_VisibleButtonCount--;
-        }
-
-        if (!(notifyItem->dwState & NIS_SHAREDICON))
-        {
-            TBBUTTON btn;
-            GetButton(index, &btn);
-            int oldIconIndex = btn.iBitmap;
-            ImageList_Remove(m_ImageList, oldIconIndex);
-
-            // Update other icons!
-            int count = GetButtonCount();
-            for (int i = 0; i < count; i++)
-            {
-                TBBUTTON btn;
-                GetButton(i, &btn);
-
-                if (btn.iBitmap > oldIconIndex)
-                {
-                    TBBUTTONINFO tbbi2 = { 0 };
-                    tbbi2.cbSize = sizeof(tbbi2);
-                    tbbi2.dwMask = TBIF_BYINDEX | TBIF_IMAGE;
-                    tbbi2.iImage = btn.iBitmap-1;
-                    SetButtonInfo(i, &tbbi2);
-                }
-            }
-        }
-
-        delete notifyItem;
-        DeleteButton(index);
-
-        return TRUE;
-    }
-
-    VOID GetTooltipText(int index, LPTSTR szTip, DWORD cchTip)
-    {
-        NOTIFYICONDATA * notifyItem;
-        notifyItem = GetItemData(index);
-
-        if (notifyItem)
-        {
-            StringCchCopy(szTip, cchTip, notifyItem->szTip);
-        }
-    }
-
-    VOID ResizeImagelist()
-    {
-        int cx, cy;
-        HIMAGELIST iml;
-
-        if (!ImageList_GetIconSize(m_ImageList, &cx, &cy))
-            return;
-
-        if (cx == GetSystemMetrics(SM_CXSMICON) && cy == GetSystemMetrics(SM_CYSMICON))
-            return;
-
-        iml = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 0, 1000);
-        if (!iml)
-            return;
-
-        ImageList_Destroy(m_ImageList);
-        m_ImageList = iml;
-        SetImageList(m_ImageList);
-
-        int count = GetButtonCount();
-        for (int i = 0; i < count; i++)
-        {
-            NOTIFYICONDATA * data = GetItemData(i);
-            BOOL hasSharedIcon = data->dwState & NIS_SHAREDICON;
-            INT iIcon = hasSharedIcon ? FindExistingSharedIcon(data->hIcon) : -1;
-            if (iIcon < 0)
-                iIcon = ImageList_AddIcon(iml, data->hIcon);
-            TBBUTTONINFO tbbi = { sizeof(tbbi), TBIF_BYINDEX | TBIF_IMAGE, 0, iIcon};
-            SetButtonInfo(i, &tbbi);
-        }
-
-        SetButtonSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
-    }
-
-private:
-
-    VOID SendMouseEvent(IN WORD wIndex, IN UINT uMsg, IN WPARAM wParam)
-    {
-        static LPCWSTR eventNames [] = {
-            L"WM_MOUSEMOVE",
-            L"WM_LBUTTONDOWN",
-            L"WM_LBUTTONUP",
-            L"WM_LBUTTONDBLCLK",
-            L"WM_RBUTTONDOWN",
-            L"WM_RBUTTONUP",
-            L"WM_RBUTTONDBLCLK",
-            L"WM_MBUTTONDOWN",
-            L"WM_MBUTTONUP",
-            L"WM_MBUTTONDBLCLK",
-            L"WM_MOUSEWHEEL",
-            L"WM_XBUTTONDOWN",
-            L"WM_XBUTTONUP",
-            L"WM_XBUTTONDBLCLK"
-        };
-
-        NOTIFYICONDATA * notifyItem = GetItemData(wIndex);
-
-        if (!::IsWindow(notifyItem->hWnd))
-        {
-            // We detect and destroy icons with invalid handles only on mouse move over systray, same as MS does.
-            // Alternatively we could search for them periodically (would waste more resources).
-            TRACE("Destroying icon %d with invalid handle hWnd=%08x\n", notifyItem->uID, notifyItem->hWnd);
-
-            RemoveButton(notifyItem);
-
-            HWND parentHWND = ::GetParent(::GetParent(GetParent()));
-            ::SendMessage(parentHWND, WM_SIZE, 0, 0);
-
-            return;
-        }
-
-        if (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST)
-        {
-            TRACE("Sending message %S from button %d to %p (msg=%x, w=%x, l=%x)...\n",
-                     eventNames[uMsg - WM_MOUSEFIRST], wIndex,
-                     notifyItem->hWnd, notifyItem->uCallbackMessage, notifyItem->uID, uMsg);
-        }
-
-        DWORD pid;
-        GetWindowThreadProcessId(notifyItem->hWnd, &pid);
-
-        if (pid == GetCurrentProcessId() ||
-            (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST))
-        {
-            ::PostMessage(notifyItem->hWnd,
-                          notifyItem->uCallbackMessage,
-                          notifyItem->uID,
-                          uMsg);
-        }
-        else
-        {
-            SendMessage(notifyItem->hWnd,
-                        notifyItem->uCallbackMessage,
-                        notifyItem->uID,
-                        uMsg);
-        }
-    }
-
-    LRESULT OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
-
-        INT iBtn = HitTest(&pt);
-
-        if (iBtn >= 0)
-        {
-            SendMouseEvent(iBtn, uMsg, wParam);
-        }
-
-        bHandled = FALSE;
-        return FALSE;
-    }
-
-    LRESULT OnTooltipShow(INT uCode, LPNMHDR hdr, BOOL& bHandled)
-    {
-        RECT rcTip, rcItem;
-        ::GetWindowRect(hdr->hwndFrom, &rcTip);
-
-        SIZE szTip = { rcTip.right - rcTip.left, rcTip.bottom - rcTip.top };
-
-        INT iBtn = GetHotItem();
-
-        if (iBtn >= 0)
-        {
-            MONITORINFO monInfo = { 0 };
-            HMONITOR hMon = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
-
-            monInfo.cbSize = sizeof(monInfo);
-
-            if (hMon)
-                GetMonitorInfo(hMon, &monInfo);
-            else
-                ::GetWindowRect(GetDesktopWindow(), &monInfo.rcMonitor);
-
-            GetItemRect(iBtn, &rcItem);
-
-            POINT ptItem = { rcItem.left, rcItem.top };
-            SIZE szItem = { rcItem.right - rcItem.left, rcItem.bottom - rcItem.top };
-            ClientToScreen(&ptItem);
-
-            ptItem.x += szItem.cx / 2;
-            ptItem.y -= szTip.cy;
-
-            if (ptItem.x + szTip.cx > monInfo.rcMonitor.right)
-                ptItem.x = monInfo.rcMonitor.right - szTip.cx;
-
-            if (ptItem.y + szTip.cy > monInfo.rcMonitor.bottom)
-                ptItem.y = monInfo.rcMonitor.bottom - szTip.cy;
-
-            if (ptItem.x < monInfo.rcMonitor.left)
-                ptItem.x = monInfo.rcMonitor.left;
-
-            if (ptItem.y < monInfo.rcMonitor.top)
-                ptItem.y = monInfo.rcMonitor.top;
-
-            TRACE("ptItem { %d, %d }\n", ptItem.x, ptItem.y);
-
-            ::SetWindowPos(hdr->hwndFrom, NULL, ptItem.x, ptItem.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
-
-            return TRUE;
-        }
-
-        bHandled = FALSE;
-        return 0;
-    }
-
-
-public:
-    BEGIN_MSG_MAP(CNotifyToolbar)
-        MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseEvent)
-        NOTIFY_CODE_HANDLER(TTN_SHOW, OnTooltipShow)
-    END_MSG_MAP()
-
-    void Initialize(HWND hWndParent)
-    {
-        DWORD styles =
-            WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN |
-            TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_WRAPABLE | TBSTYLE_TRANSPARENT |
-            CCS_TOP | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NODIVIDER;
-
-        SubclassWindow(CToolbar::Create(hWndParent, styles));
-
-        SetWindowTheme(m_hWnd, L"TrayNotify", NULL);
-
-        m_ImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 0, 1000);        
-        SetImageList(m_ImageList);
-
-        TBMETRICS tbm = {sizeof(tbm)};
-        tbm.dwMask = TBMF_BARPAD | TBMF_BUTTONSPACING | TBMF_PAD;
-        tbm.cxPad = 1;
-        tbm.cyPad = 1;
-        tbm.cxButtonSpacing = 1;
-        tbm.cyButtonSpacing = 1;
-        SetMetrics(&tbm);
-
-        SetButtonSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
-    }
-};
-
-class CSysPagerWnd :
-    public CComObjectRootEx<CComMultiThreadModelNoCS>,
-    public CWindowImpl < CSysPagerWnd, CWindow, CControlWinTraits >,
-    public CIconWatcher
-{
-    CNotifyToolbar Toolbar;
-
-public:
-    CSysPagerWnd() {}
-    virtual ~CSysPagerWnd() {}
-
-    LRESULT DrawBackground(HDC hdc)
-    {
-        RECT rect;
-
-        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.Initialize(m_hWnd);
-        CIconWatcher::Initialize(m_hWnd);
-
-        // Explicitly request running applications to re-register their systray icons
-        ::SendNotifyMessageW(HWND_BROADCAST,
-                             RegisterWindowMessageW(L"TaskbarCreated"),
-                             0, 0);
-
-        return TRUE;
-    }
-
-    LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        CIconWatcher::Uninitialize();
-        return TRUE;
-    }
-
-    BOOL NotifyIconCmd(WPARAM wParam, LPARAM lParam)
-    {
-        PCOPYDATASTRUCT cpData = (PCOPYDATASTRUCT) lParam;
-        if (cpData->dwData == 1)
-        {
-            SYS_PAGER_COPY_DATA * data;
-            NOTIFYICONDATA *iconData;
-            BOOL ret = FALSE;
-
-            int VisibleButtonCount = Toolbar.GetVisibleButtonCount();
-
-            data = (PSYS_PAGER_COPY_DATA) cpData->lpData;
-            iconData = &data->nicon_data;
-
-            TRACE("NotifyIconCmd received. Code=%d\n", data->notify_code);
-            switch (data->notify_code)
-            {
-            case NIM_ADD:
-                ret = Toolbar.AddButton(iconData);
-                if (ret == TRUE)
-                {
-                    (void)AddIconToWatcher(iconData);
-                }
-                break;
-            case NIM_MODIFY:
-                ret = Toolbar.UpdateButton(iconData);
-                break;
-            case NIM_DELETE:
-                ret = Toolbar.RemoveButton(iconData);
-                if (ret == TRUE)
-                {
-                    (void)RemoveIconFromWatcher(iconData);
-                }
-                break;
-            default:
-                TRACE("NotifyIconCmd received with unknown code %d.\n", data->notify_code);
-                return FALSE;
-            }
-
-            if (VisibleButtonCount != Toolbar.GetVisibleButtonCount())
-            {
-                HWND parentHWND = ::GetParent(GetParent());
-                ::SendMessage(parentHWND, WM_SIZE, 0, 0);
-            }
-
-            return ret;
-        }
-
-        return TRUE;
-    }
-
-    void GetSize(IN BOOL IsHorizontal, IN PSIZE size)
-    {
-        /* Get the ideal height or width */
-#if 0 
-        /* Unfortunately this doens't work correctly in ros */
-        Toolbar.GetIdealSize(!IsHorizontal, size);
-
-        /* Make the reference dimension an exact multiple of the icon size */
-        if (IsHorizontal)
-            size->cy -= size->cy % GetSystemMetrics(SM_CYSMICON);
-        else
-            size->cx -= size->cx % GetSystemMetrics(SM_CXSMICON);
-
-#else
-        INT rows = 0;
-        INT columns = 0;
-        INT cyButton = GetSystemMetrics(SM_CYSMICON) + 2;
-        INT cxButton = GetSystemMetrics(SM_CXSMICON) + 2;
-        int VisibleButtonCount = Toolbar.GetVisibleButtonCount();
-
-        if (IsHorizontal)
-        {
-            rows = max(size->cy / cyButton, 1);
-            columns = (VisibleButtonCount + rows - 1) / rows;
-        }
-        else
-        {
-            columns = max(size->cx / cxButton, 1);
-            rows = (VisibleButtonCount + columns - 1) / columns;
-        }
-        size->cx = columns * cxButton;
-        size->cy = rows * cyButton;
-#endif
-    }
-
-    LRESULT OnGetInfoTip(INT uCode, LPNMHDR hdr, BOOL& bHandled)
-    {
-        NMTBGETINFOTIPW * nmtip = (NMTBGETINFOTIPW *) hdr;
-        Toolbar.GetTooltipText(nmtip->iItem, nmtip->pszText, nmtip->cchTextMax);
-        return TRUE;
-    }
-
-    LRESULT OnCustomDraw(INT uCode, LPNMHDR hdr, BOOL& bHandled)
-    {
-        NMCUSTOMDRAW * cdraw = (NMCUSTOMDRAW *) hdr;
-        switch (cdraw->dwDrawStage)
-        {
-        case CDDS_PREPAINT:
-            return CDRF_NOTIFYITEMDRAW;
-
-        case CDDS_ITEMPREPAINT:
-            return TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES | TBCDRF_NOOFFSET | TBCDRF_NOMARK | TBCDRF_NOETCHEDEFFECT;
-        }
-        return TRUE;
-    }
-
-    LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        LRESULT Ret = TRUE;
-        SIZE szClient;
-        szClient.cx = LOWORD(lParam);
-        szClient.cy = HIWORD(lParam);
-
-        Ret = DefWindowProc(uMsg, wParam, lParam);
-
-        if (Toolbar)
-        {
-            Toolbar.SetWindowPos(NULL, 0, 0, szClient.cx, szClient.cy, SWP_NOZORDER);
-            Toolbar.AutoSize();
-
-            RECT 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;
-
-            Toolbar.SetWindowPos(NULL, xOff, yOff, szBar.cx, szBar.cy, SWP_NOZORDER);
-        }
-        return Ret;
-    }
-
-    LRESULT OnCtxMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        bHandled = TRUE;
-        return 0;
-    }
-
-    void ResizeImagelist()
-    {
-        Toolbar.ResizeImagelist();
-    }
-
-    DECLARE_WND_CLASS_EX(szSysPagerWndClass, CS_DBLCLKS, COLOR_3DFACE)
-
-    BEGIN_MSG_MAP(CSysPagerWnd)
-        MESSAGE_HANDLER(WM_CREATE, OnCreate)
-        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
-        MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
-        MESSAGE_HANDLER(WM_SIZE, OnSize)
-        MESSAGE_HANDLER(WM_CONTEXTMENU, OnCtxMenu)
-        NOTIFY_CODE_HANDLER(TBN_GETINFOTIPW, OnGetInfoTip)
-        NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
-    END_MSG_MAP()
-
-    HWND _Init(IN HWND hWndParent, IN BOOL bVisible)
-    {
-        DWORD dwStyle;
-
-        /* 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;
-        if (bVisible)
-            dwStyle |= WS_VISIBLE;
-
-        Create(hWndParent, 0, NULL, dwStyle);
-
-        if (!m_hWnd)
-        {
-            return NULL;
-        }
-
-        SetWindowTheme(m_hWnd, L"TrayNotify", NULL);
-
-        return m_hWnd;
-    }
-};
-
-/*
- * TrayClockWnd
- */
-
-static const WCHAR szTrayClockWndClass[] = L"TrayClockWClass";
-
-#define ID_TRAYCLOCK_TIMER  0
-#define ID_TRAYCLOCK_TIMER_INIT 1
-
-static const struct
-{
-    BOOL IsTime;
-    DWORD dwFormatFlags;
-    LPCWSTR lpFormat;
-} ClockWndFormats [] = {
-    { TRUE, 0, NULL },
-    { FALSE, 0, L"dddd" },
-    { FALSE, DATE_SHORTDATE, NULL }
-};
-
-#define CLOCKWND_FORMAT_COUNT (_ARRAYSIZE(ClockWndFormats))
-
-#define TRAY_CLOCK_WND_SPACING_X    0
-#define TRAY_CLOCK_WND_SPACING_Y    0
-
-class CTrayClockWnd :
-    public CComObjectRootEx<CComMultiThreadModelNoCS>,
-    public CWindowImpl < CTrayClockWnd, CWindow, CControlWinTraits >
-{
-    HWND hWndNotify;
-    HFONT hFont;
-    COLORREF textColor;
-    RECT rcText;
-    SYSTEMTIME LocalTime;
-
-    union
-    {
-        DWORD dwFlags;
-        struct
-        {
-            DWORD IsTimerEnabled : 1;
-            DWORD IsInitTimerEnabled : 1;
-            DWORD LinesMeasured : 1;
-            DWORD IsHorizontal : 1;
-        };
-    };
-    DWORD LineSpacing;
-    SIZE CurrentSize;
-    WORD VisibleLines;
-    SIZE LineSizes[CLOCKWND_FORMAT_COUNT];
-    WCHAR szLines[CLOCKWND_FORMAT_COUNT][48];
-
-public:
-    CTrayClockWnd() :
-        hWndNotify(NULL),
-        hFont(NULL),
-        dwFlags(0),
-        LineSpacing(0),
-        VisibleLines(0)
-    {
-        ZeroMemory(&textColor, sizeof(textColor));
-        ZeroMemory(&rcText, sizeof(rcText));
-        ZeroMemory(&LocalTime, sizeof(LocalTime));
-        ZeroMemory(&CurrentSize, sizeof(CurrentSize));
-        ZeroMemory(LineSizes, sizeof(LineSizes));
-        ZeroMemory(szLines, sizeof(szLines));
-    }
-    virtual ~CTrayClockWnd() { }
-
-    LRESULT OnThemeChanged()
-    {
-        LOGFONTW clockFont;
-        HTHEME clockTheme;
-        HFONT hFont;
-
-        clockTheme = OpenThemeData(m_hWnd, L"Clock");
-
-        if (clockTheme)
-        {
-            GetThemeFont(clockTheme,
-                NULL,
-                CLP_TIME,
-                0,
-                TMT_FONT,
-                &clockFont);
-
-            hFont = CreateFontIndirectW(&clockFont);
-
-            GetThemeColor(clockTheme,
-                CLP_TIME,
-                0,
-                TMT_TEXTCOLOR,
-                &textColor);
-
-            if (this->hFont != NULL)
-                DeleteObject(this->hFont);
-
-            SetFont(hFont, FALSE);
-        }
-        else
-        {
-            /* We don't need to set a font here, our parent will use 
-              * WM_SETFONT to set the right one when themes are not enabled. */
-            textColor = RGB(0, 0, 0);
-        }
-
-        CloseThemeData(clockTheme);
-
-        return TRUE;
-    }
-
-    LRESULT OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        return OnThemeChanged();
-    }
-
-    BOOL MeasureLines()
-    {
-        HDC hDC;
-        HFONT hPrevFont;
-        UINT c, i;
-        BOOL bRet = TRUE;
-
-        hDC = GetDC();
-        if (hDC != NULL)
-        {
-            if (hFont)
-                hPrevFont = (HFONT) SelectObject(hDC, hFont);
-
-            for (i = 0; i < CLOCKWND_FORMAT_COUNT && bRet; i++)
-            {
-                if (szLines[i][0] != L'\0' &&
-                    !GetTextExtentPointW(hDC, szLines[i], wcslen(szLines[i]),
-                                         &LineSizes[i]))
-                {
-                    bRet = FALSE;
-                    break;
-                }
-            }
-
-            if (hFont)
-                SelectObject(hDC, hPrevFont);
-
-            ReleaseDC(hDC);
-
-            if (bRet)
-            {
-                LineSpacing = 0;
-
-                /* calculate the line spacing */
-                for (i = 0, c = 0; i < CLOCKWND_FORMAT_COUNT; i++)
-                {
-                    if (LineSizes[i].cx > 0)
-                    {
-                        LineSpacing += LineSizes[i].cy;
-                        c++;
-                    }
-                }
-
-                if (c > 0)
-                {
-                    /* We want a spacing of 1/2 line */
-                    LineSpacing = (LineSpacing / c) / 2;
-                }
-
-                return TRUE;
-            }
-        }
-
-        return FALSE;
-    }
-
-    WORD GetMinimumSize(IN BOOL Horizontal, IN OUT PSIZE pSize)
-    {
-        WORD iLinesVisible = 0;
-        UINT i;
-        SIZE szMax = { 0, 0 };
-
-        if (!LinesMeasured)
-            LinesMeasured = MeasureLines();
-
-        if (!LinesMeasured)
-            return 0;
-
-        for (i = 0; i < CLOCKWND_FORMAT_COUNT; i++)
-        {
-            if (LineSizes[i].cx != 0)
-            {
-                if (iLinesVisible > 0)
-                {
-                    if (Horizontal)
-                    {
-                        if (szMax.cy + LineSizes[i].cy + (LONG) LineSpacing >
-                            pSize->cy - (2 * TRAY_CLOCK_WND_SPACING_Y))
-                        {
-                            break;
-                        }
-                    }
-                    else
-                    {
-                        if (LineSizes[i].cx > pSize->cx - (2 * TRAY_CLOCK_WND_SPACING_X))
-                            break;
-                    }
-
-                    /* Add line spacing */
-                    szMax.cy += LineSpacing;
-                }
-
-                iLinesVisible++;
-
-                /* Increase maximum rectangle */
-                szMax.cy += LineSizes[i].cy;
-                if (LineSizes[i].cx > szMax.cx - (2 * TRAY_CLOCK_WND_SPACING_X))
-                    szMax.cx = LineSizes[i].cx + (2 * TRAY_CLOCK_WND_SPACING_X);
-            }
-        }
-
-        szMax.cx += 2 * TRAY_CLOCK_WND_SPACING_X;
-        szMax.cy += 2 * TRAY_CLOCK_WND_SPACING_Y;
-
-        *pSize = szMax;
-
-        return iLinesVisible;
-    }
-
-
-    VOID UpdateWnd()
-    {
-        SIZE szPrevCurrent;
-        UINT BufSize, i;
-        INT iRet;
-        RECT rcClient;
-
-        ZeroMemory(LineSizes, sizeof(LineSizes));
-
-        szPrevCurrent = CurrentSize;
-
-        for (i = 0; i < CLOCKWND_FORMAT_COUNT; i++)
-        {
-            szLines[i][0] = L'\0';
-            BufSize = _countof(szLines[0]);
-
-            if (ClockWndFormats[i].IsTime)
-            {
-                iRet = GetTimeFormat(LOCALE_USER_DEFAULT,
-                    g_TaskbarSettings.bShowSeconds ? ClockWndFormats[i].dwFormatFlags : TIME_NOSECONDS,
-                    &LocalTime,
-                    ClockWndFormats[i].lpFormat,
-                    szLines[i],
-                    BufSize);
-            }
-            else
-            {
-                iRet = GetDateFormat(LOCALE_USER_DEFAULT,
-                    ClockWndFormats[i].dwFormatFlags,
-                    &LocalTime,
-                    ClockWndFormats[i].lpFormat,
-                    szLines[i],
-                    BufSize);
-            }
-
-            if (iRet != 0 && i == 0)
-            {
-                /* Set the window text to the time only */
-                SetWindowText(szLines[i]);
-            }
-        }
-
-        LinesMeasured = MeasureLines();
-
-        if (LinesMeasured &&
-            GetClientRect(&rcClient))
-        {
-            SIZE szWnd;
-
-            szWnd.cx = rcClient.right;
-            szWnd.cy = rcClient.bottom;
-
-            VisibleLines = GetMinimumSize(IsHorizontal, &szWnd);
-            CurrentSize = szWnd;
-        }
-
-        if (IsWindowVisible())
-        {
-            InvalidateRect(NULL, TRUE);
-
-            if (hWndNotify != NULL &&
-                (szPrevCurrent.cx != CurrentSize.cx ||
-                szPrevCurrent.cy != CurrentSize.cy))
-            {
-                NMHDR nmh;
-
-                nmh.hwndFrom = m_hWnd;
-                nmh.idFrom = GetWindowLongPtr(GWLP_ID);
-                nmh.code = NTNWM_REALIGN;
-
-                SendMessage(hWndNotify,
-                    WM_NOTIFY,
-                    (WPARAM) nmh.idFrom,
-                    (LPARAM) &nmh);
-            }
-        }
-    }
-
-    VOID Update()
-    {
-        GetLocalTime(&LocalTime);
-        UpdateWnd();
-    }
-
-    UINT CalculateDueTime()
-    {
-        UINT uiDueTime;
-
-        /* Calculate the due time */
-        GetLocalTime(&LocalTime);
-        uiDueTime = 1000 - (UINT) LocalTime.wMilliseconds;
-        if (g_TaskbarSettings.bShowSeconds)
-            uiDueTime += (UINT) LocalTime.wSecond * 100;
-        else
-            uiDueTime += (59 - (UINT) LocalTime.wSecond) * 1000;
-
-        if (uiDueTime < USER_TIMER_MINIMUM || uiDueTime > USER_TIMER_MAXIMUM)
-            uiDueTime = 1000;
-        else
-        {
-            /* Add an artificial delay of 0.05 seconds to make sure the timer
-               doesn't fire too early*/
-            uiDueTime += 50;
-        }
-
-        return uiDueTime;
-    }
-
-    BOOL ResetTime()
-    {
-        UINT uiDueTime;
-        BOOL Ret;
-
-        /* Disable all timers */
-        if (IsTimerEnabled)
-        {
-            KillTimer(ID_TRAYCLOCK_TIMER);
-            IsTimerEnabled = FALSE;
-        }
-
-        if (IsInitTimerEnabled)
-        {
-            KillTimer(ID_TRAYCLOCK_TIMER_INIT);
-        }
-
-        uiDueTime = CalculateDueTime();
-
-        /* Set the new timer */
-        Ret = SetTimer(ID_TRAYCLOCK_TIMER_INIT, uiDueTime, NULL) != 0;
-        IsInitTimerEnabled = Ret;
-
-        /* Update the time */
-        Update();
-
-        return Ret;
-    }
-
-    VOID CalibrateTimer()
-    {
-        UINT uiDueTime;
-        BOOL Ret;
-        UINT uiWait1, uiWait2;
-
-        /* Kill the initialization timer */
-        KillTimer(ID_TRAYCLOCK_TIMER_INIT);
-        IsInitTimerEnabled = FALSE;
-
-        uiDueTime = CalculateDueTime();
-
-        if (g_TaskbarSettings.bShowSeconds)
-        {
-            uiWait1 = 1000 - 200;
-            uiWait2 = 1000;
-        }
-        else
-        {
-            uiWait1 = 60 * 1000 - 200;
-            uiWait2 = 60 * 1000;
-        }
-
-        if (uiDueTime > uiWait1)
-        {
-            /* The update of the clock will be up to 200 ms late, but that's
-               acceptable. We're going to setup a timer that fires depending
-               uiWait2. */
-            Ret = SetTimer(ID_TRAYCLOCK_TIMER, uiWait2, NULL) != 0;
-            IsTimerEnabled = Ret;
-
-            /* Update the time */
-            Update();
-        }
-        else
-        {
-            /* Recalibrate the timer and recalculate again when the current
-               minute/second ends. */
-            ResetTime();
-        }
-    }
-
-    LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        /* Disable all timers */
-        if (IsTimerEnabled)
-        {
-            KillTimer(ID_TRAYCLOCK_TIMER);
-        }
-
-        if (IsInitTimerEnabled)
-        {
-            KillTimer(ID_TRAYCLOCK_TIMER_INIT);
-        }
-
-        return TRUE;
-    }
-
-    LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        RECT rcClient;
-        HFONT hPrevFont;
-        INT iPrevBkMode;
-        UINT i, line;
-
-        PAINTSTRUCT ps;
-        HDC hDC = (HDC) wParam;
-
-        if (wParam == 0)
-        {
-            hDC = BeginPaint(&ps);
-        }
-
-        if (hDC == NULL)
-            return FALSE;
-
-        if (LinesMeasured &&
-            GetClientRect(&rcClient))
-        {
-            iPrevBkMode = SetBkMode(hDC, TRANSPARENT);
-
-            SetTextColor(hDC, textColor);
-
-            hPrevFont = (HFONT) SelectObject(hDC, hFont);
-
-            rcClient.left = (rcClient.right / 2) - (CurrentSize.cx / 2);
-            rcClient.top = (rcClient.bottom / 2) - (CurrentSize.cy / 2);
-            rcClient.right = rcClient.left + CurrentSize.cx;
-            rcClient.bottom = rcClient.top + CurrentSize.cy;
-
-            for (i = 0, line = 0;
-                 i < CLOCKWND_FORMAT_COUNT && line < VisibleLines;
-                 i++)
-            {
-                if (LineSizes[i].cx != 0)
-                {
-                    TextOut(hDC,
-                        rcClient.left + (CurrentSize.cx / 2) - (LineSizes[i].cx / 2) +
-                        TRAY_CLOCK_WND_SPACING_X,
-                        rcClient.top + TRAY_CLOCK_WND_SPACING_Y,
-                        szLines[i],
-                        wcslen(szLines[i]));
-
-                    rcClient.top += LineSizes[i].cy + LineSpacing;
-                    line++;
-                }
-            }
-
-            SelectObject(hDC, hPrevFont);
-
-            SetBkMode(hDC, iPrevBkMode);
-        }
-
-        if (wParam == 0)
-        {
-            EndPaint(&ps);
-        }
-
-        return TRUE;
-    }
-
-    VOID SetFont(IN HFONT hNewFont, IN BOOL bRedraw)
-    {
-        hFont = hNewFont;
-        LinesMeasured = MeasureLines();
-        if (bRedraw)
-        {
-            InvalidateRect(NULL, TRUE);
-        }
-    }
-
-    LRESULT DrawBackground(HDC hdc)
-    {
-        RECT rect;
-
-        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 OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        switch (wParam)
-        {
-        case ID_TRAYCLOCK_TIMER:
-            Update();
-            break;
-
-        case ID_TRAYCLOCK_TIMER_INIT:
-            CalibrateTimer();
-            break;
-        }
-        return TRUE;
-    }
-
-    LRESULT OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        IsHorizontal = (BOOL) wParam;
-
-        return (LRESULT) GetMinimumSize((BOOL) wParam, (PSIZE) lParam) != 0;
-    }
-
-    LRESULT OnUpdateTime(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        return (LRESULT) ResetTime();
-    }
-
-    LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        return HTTRANSPARENT;
-    }
-
-    LRESULT OnSetFont(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        SetFont((HFONT) wParam, (BOOL) LOWORD(lParam));
-        return TRUE;
-    }
-
-    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        ResetTime();
-        return TRUE;
-    }
-
-    LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        SIZE szClient;
-
-        szClient.cx = LOWORD(lParam);
-        szClient.cy = HIWORD(lParam);
-
-        VisibleLines = GetMinimumSize(IsHorizontal, &szClient);
-        CurrentSize = szClient;
-
-        InvalidateRect(NULL, TRUE);
-        return TRUE;
-    }
-
-    DECLARE_WND_CLASS_EX(szTrayClockWndClass, CS_DBLCLKS, COLOR_3DFACE)
-
-    BEGIN_MSG_MAP(CTrayClockWnd)
-        MESSAGE_HANDLER(WM_CREATE, OnCreate)
-        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
-        MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
-        MESSAGE_HANDLER(WM_SIZE, OnSize)
-        MESSAGE_HANDLER(WM_PAINT, OnPaint)
-        MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
-        MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
-        MESSAGE_HANDLER(WM_TIMER, OnTimer)
-        MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest)
-        MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
-        MESSAGE_HANDLER(TCWM_GETMINIMUMSIZE, OnGetMinimumSize)
-        MESSAGE_HANDLER(TCWM_UPDATETIME, OnUpdateTime)
-
-    END_MSG_MAP()
-
-    HWND _Init(IN HWND hWndParent, IN BOOL bVisible)
-    {
-        IsHorizontal = TRUE;
-
-        hWndNotify = hWndParent;
-
-        /* Create the window. The tray window is going to move it to the correct
-            position and resize it as needed. */
-        DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
-        if (bVisible)
-            dwStyle |= WS_VISIBLE;
-
-        Create(hWndParent, 0, NULL, dwStyle);
-
-        if (m_hWnd != NULL)
-            SetWindowTheme(m_hWnd, L"TrayNotify", NULL);
-
-        return m_hWnd;
-
-    }
-};
-
 /*
  * TrayNotifyWnd
  */
 
-static const WCHAR szTrayNotifyWndClass [] = TEXT("TrayNotifyWnd");
+static const WCHAR szTrayNotifyWndClass[] = L"TrayNotifyWnd";
 
 #define TRAY_NOTIFY_WND_SPACING_X   1
 #define TRAY_NOTIFY_WND_SPACING_Y   1
 
 class CTrayNotifyWnd :
+    public CComCoClass<CTrayNotifyWnd>,
     public CComObjectRootEx<CComMultiThreadModelNoCS>,
-    public CWindowImpl < CTrayNotifyWnd, CWindow, CControlWinTraits >
+    public CWindowImpl < CTrayNotifyWnd, CWindow, CControlWinTraits >,
+    public IOleWindow
 {
-    HWND hWndNotify;
-
-    CSysPagerWnd * m_pager;
-    CTrayClockWnd * m_clock;
+    CComPtr<IUnknown> m_clock;
+    CComPtr<IUnknown> m_pager;
 
-    CComPtr<ITrayWindow> TrayWindow;
+    HWND m_hwndClock;
+    HWND m_hwndPager;
 
     HTHEME TrayTheme;
     SIZE szTrayClockMin;
@@ -1679,9 +50,8 @@ class CTrayNotifyWnd :
 
 public:
     CTrayNotifyWnd() :
-        hWndNotify(NULL),
-        m_pager(NULL),
-        m_clock(NULL),
+        m_hwndClock(NULL),
+        m_hwndPager(NULL),
         TrayTheme(NULL),
         IsHorizontal(FALSE)
     {
@@ -1733,11 +103,23 @@ public:
 
     LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        m_clock = new CTrayClockWnd();
-        m_clock->_Init(m_hWnd, !g_TaskbarSettings.sr.HideClock);
+        HRESULT hr;
 
-        m_pager = new CSysPagerWnd();
-        m_pager->_Init(m_hWnd, !g_TaskbarSettings.sr.HideClock);
+        hr = CTrayClockWnd_CreateInstance(m_hWnd, IID_PPV_ARG(IUnknown, &m_clock));
+        if (FAILED_UNEXPECTEDLY(hr))
+            return FALSE;
+
+        hr = IUnknown_GetWindow(m_clock, &m_hwndClock);
+        if (FAILED_UNEXPECTEDLY(hr))
+            return FALSE;
+
+        hr = CSysPagerWnd_CreateInstance(m_hWnd, IID_PPV_ARG(IUnknown, &m_pager));
+        if (FAILED_UNEXPECTEDLY(hr))
+            return FALSE;
+
+        hr = IUnknown_GetWindow(m_pager, &m_hwndPager);
+        if (FAILED_UNEXPECTEDLY(hr))
+            return FALSE;
 
         return TRUE;
     }
@@ -1762,7 +144,7 @@ public:
                     goto NoClock;
             }
 
-            m_clock->SendMessage(TCWM_GETMINIMUMSIZE, (WPARAM) IsHorizontal, (LPARAM) &szClock);
+            ::SendMessage(m_hwndClock, TNWM_GETMINIMUMSIZE, (WPARAM) IsHorizontal, (LPARAM) &szClock);
 
             szTrayClockMin = szClock;
         }
@@ -1779,7 +161,7 @@ public:
             szTray.cx = pSize->cx - 2 * TRAY_NOTIFY_WND_SPACING_X;
         }
 
-        m_pager->GetSize(IsHorizontal, &szTray);
+        ::SendMessage(m_hwndPager, TNWM_GETMINIMUMSIZE, (WPARAM) IsHorizontal, (LPARAM) &szTray);
 
         szTrayNotify = szTray;
 
@@ -1791,6 +173,7 @@ public:
                 pSize->cx += TRAY_NOTIFY_WND_SPACING_X + szTrayClockMin.cx;
 
             pSize->cx += szTray.cx;
+            pSize->cx += ContentMargin.cxLeftWidth + ContentMargin.cxRightWidth;
         }
         else
         {
@@ -1800,11 +183,9 @@ public:
                 pSize->cy += TRAY_NOTIFY_WND_SPACING_Y + szTrayClockMin.cy;
 
             pSize->cy += szTray.cy;
+            pSize->cy += ContentMargin.cyTopHeight + ContentMargin.cyBottomHeight;
         }
 
-        pSize->cy += ContentMargin.cyTopHeight + ContentMargin.cyBottomHeight;
-        pSize->cx += ContentMargin.cxLeftWidth + ContentMargin.cxRightWidth;
-
         return TRUE;
     }
 
@@ -1830,55 +211,35 @@ public:
                 szClock.cy = szTrayClockMin.cy;
             }
 
-            m_clock->SetWindowPos(
+            ::SetWindowPos(m_hwndClock,
                 NULL,
                 ptClock.x,
                 ptClock.y,
                 szClock.cx,
                 szClock.cy,
                 SWP_NOZORDER);
-
-            POINT ptPager;
-
-            if (IsHorizontal)
-            {
-                ptPager.x = ContentMargin.cxLeftWidth;
-                ptPager.y = (pszClient->cy - szTrayNotify.cy)/2;
-            }
-            else
-            {
-                ptPager.x = (pszClient->cx - szTrayNotify.cx)/2;
-                ptPager.y = ContentMargin.cyTopHeight;
-            }
-
-            m_pager->SetWindowPos(
-                NULL,
-                ptPager.x,
-                ptPager.y,
-                szTrayNotify.cx,
-                szTrayNotify.cy,
-                SWP_NOZORDER);
         }
-    }
 
-    LRESULT DrawBackground(HDC hdc)
-    {
-        HRESULT res;
-        RECT rect;
-
-        GetClientRect(&rect);
+        POINT ptPager;
 
-        if (TrayTheme)
+        if (IsHorizontal)
         {
-            if (IsThemeBackgroundPartiallyTransparent(TrayTheme, TNP_BACKGROUND, 0))
-            {
-                DrawThemeParentBackground(m_hWnd, hdc, &rect);
-            }
-
-            res = DrawThemeBackground(TrayTheme, hdc, TNP_BACKGROUND, 0, &rect, 0);
+            ptPager.x = ContentMargin.cxLeftWidth;
+            ptPager.y = (pszClient->cy - szTrayNotify.cy)/2;
+        }
+        else
+        {
+            ptPager.x = (pszClient->cx - szTrayNotify.cx)/2;
+            ptPager.y = ContentMargin.cyTopHeight;
         }
 
-        return res;
+        ::SetWindowPos(m_hwndPager,
+            NULL,
+            ptPager.x,
+            ptPager.y,
+            szTrayNotify.cx,
+            szTrayNotify.cy,
+            SWP_NOZORDER);
     }
 
     LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
@@ -1891,27 +252,16 @@ public:
             return 0;
         }
 
-        return DrawBackground(hdc);
-    }
+        RECT rect;
+        GetClientRect(&rect);
+        if (IsThemeBackgroundPartiallyTransparent(TrayTheme, TNP_BACKGROUND, 0))
+            DrawThemeParentBackground(m_hWnd, hdc, &rect);
 
-    BOOL NotifyIconCmd(WPARAM wParam, LPARAM lParam)
-    {
-        if (m_pager)
-        {
-            return m_pager->NotifyIconCmd(wParam, lParam);
-        }
+        DrawThemeBackground(TrayTheme, hdc, TNP_BACKGROUND, 0, &rect, 0);
 
         return TRUE;
     }
 
-    BOOL GetClockRect(OUT PRECT rcClock)
-    {
-        if (!m_clock->IsWindowVisible())
-            return FALSE;
-
-        return m_clock->GetWindowRect(rcClock);
-    }
-
     LRESULT OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
         BOOL Horizontal = (BOOL) wParam;
@@ -1928,16 +278,6 @@ public:
         return (LRESULT) GetMinimumSize((PSIZE) lParam);
     }
 
-    LRESULT OnUpdateTime(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-    {
-        if (m_clock != NULL)
-        {
-            /* Forward the message to the tray clock window procedure */
-            return m_clock->OnUpdateTime(uMsg, wParam, lParam, bHandled);
-        }
-        return FALSE;
-    }
-
     LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
         SIZE szClient;
@@ -1955,127 +295,77 @@ public:
         return HTTRANSPARENT;
     }
 
-    LRESULT OnShowClock(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    LRESULT OnCtxMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        BOOL PrevHidden = g_TaskbarSettings.sr.HideClock;
-        g_TaskbarSettings.sr.HideClock = (wParam == 0);
-
-        if (m_clock != NULL && PrevHidden != g_TaskbarSettings.sr.HideClock)
-        {
-            m_clock->ShowWindow(g_TaskbarSettings.sr.HideClock ? SW_HIDE : SW_SHOW);
-        }
-
-        return (LRESULT) (!PrevHidden);
+        bHandled = TRUE;
+        return 0;
     }
 
-    LRESULT OnTaskbarSettingsChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    LRESULT OnClockMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        TaskbarSettings* newSettings = (TaskbarSettings*)lParam;
-        if (newSettings->bShowSeconds != g_TaskbarSettings.bShowSeconds)
-        {
-            g_TaskbarSettings.bShowSeconds = newSettings->bShowSeconds;
-            /* TODO: Toggle showing seconds */
-        }
-
-        if (newSettings->sr.HideClock != g_TaskbarSettings.sr.HideClock)
-        {
-            g_TaskbarSettings.sr.HideClock = newSettings->sr.HideClock;
-            /* TODO: Toggle hiding the clock */
-        }
-
-        return 0;
+        return SendMessageW(m_hwndClock, uMsg, wParam, lParam);
     }
 
-    LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    LRESULT OnPagerMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        const NMHDR *nmh = (const NMHDR *) lParam;
-
-        if (nmh->hwndFrom == m_clock->m_hWnd)
-        {
-            /* Pass down notifications */
-            return m_clock->SendMessage(WM_NOTIFY, wParam, lParam);
-        }
-
-        return FALSE;
+        return SendMessageW(m_hwndPager, uMsg, wParam, lParam);
     }
 
-    LRESULT OnSetFont(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    LRESULT OnRealign(INT uCode, LPNMHDR hdr, BOOL& bHandled)
     {
-        if (m_clock != NULL)
-        {
-            m_clock->SendMessageW(WM_SETFONT, wParam, lParam);
-        }
-
-        bHandled = FALSE;
-        return FALSE;
+        hdr->hwndFrom = m_hWnd;
+        return GetParent().SendMessage(WM_NOTIFY, 0, (LPARAM)hdr);
     }
 
-    LRESULT OnCtxMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    HRESULT WINAPI GetWindow(HWND* phwnd)
     {
-        bHandled = TRUE;
-        return 0;
+        if (!phwnd)
+            return E_INVALIDARG;
+        *phwnd = m_hWnd;
+        return S_OK;
     }
 
-    LRESULT OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+    HRESULT WINAPI ContextSensitiveHelp(BOOL fEnterMode)
     {
-        if (wParam == SPI_SETNONCLIENTMETRICS)
-        {
-            m_pager->ResizeImagelist();
-        }
-        return 0;
+        return E_NOTIMPL;
     }
 
+    DECLARE_NOT_AGGREGATABLE(CTrayNotifyWnd)
+
+    DECLARE_PROTECT_FINAL_CONSTRUCT()
+    BEGIN_COM_MAP(CTrayNotifyWnd)
+        COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
+    END_COM_MAP()
+
     DECLARE_WND_CLASS_EX(szTrayNotifyWndClass, CS_DBLCLKS, COLOR_3DFACE)
 
     BEGIN_MSG_MAP(CTrayNotifyWnd)
         MESSAGE_HANDLER(WM_CREATE, OnCreate)
         MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
         MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
-        MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChanged)
         MESSAGE_HANDLER(WM_SIZE, OnSize)
         MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest)
-        MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
-        MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
         MESSAGE_HANDLER(WM_CONTEXTMENU, OnCtxMenu) // FIXME: This handler is not necessary in Windows
+        MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnClockMessage)
+        MESSAGE_HANDLER(TWM_SETTINGSCHANGED, OnClockMessage)
+        MESSAGE_HANDLER(WM_SETFONT, OnClockMessage)
+        MESSAGE_HANDLER(WM_SETTINGCHANGE, OnPagerMessage)
+        MESSAGE_HANDLER(WM_COPYDATA, OnPagerMessage)
+        NOTIFY_CODE_HANDLER(NTNWM_REALIGN, OnRealign)
         MESSAGE_HANDLER(TNWM_GETMINIMUMSIZE, OnGetMinimumSize)
-        MESSAGE_HANDLER(TNWM_UPDATETIME, OnUpdateTime)
-        MESSAGE_HANDLER(TNWM_SHOWCLOCK, OnShowClock)
-        MESSAGE_HANDLER(TWM_SETTINGSCHANGED, OnTaskbarSettingsChanged)
     END_MSG_MAP()
 
-    HWND _Init(IN OUT ITrayWindow *TrayWindow)
+    HRESULT Initialize(IN HWND hwndParent)
     {
-        HWND hWndTrayWindow;
-
-        hWndTrayWindow = TrayWindow->GetHWND();
-        if (hWndTrayWindow == NULL)
-            return NULL;
-
-        this->TrayWindow = TrayWindow;
-        this->hWndNotify = hWndTrayWindow;
-
         DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
-        return Create(hWndTrayWindow, 0, NULL, dwStyle, WS_EX_STATICEDGE);
+        Create(hwndParent, 0, NULL, dwStyle, WS_EX_STATICEDGE);
+        if (!m_hWnd)
+            return E_FAIL;
+        return S_OK;
     }
 };
 
-HWND CreateTrayNotifyWnd(IN OUT ITrayWindow *Tray, CTrayNotifyWnd** ppinstance)
-{
-    CTrayNotifyWnd * pTrayNotify = new CTrayNotifyWnd();
-    // TODO: Destroy after the window is destroyed
-    *ppinstance = pTrayNotify;
-
-    return pTrayNotify->_Init(Tray);
-}
-
-BOOL
-TrayNotify_NotifyIconCmd(CTrayNotifyWnd* pTrayNotify, WPARAM wParam, LPARAM lParam)
-{
-    return pTrayNotify->NotifyIconCmd(wParam, lParam);
-}
-
-BOOL
-TrayNotify_GetClockRect(CTrayNotifyWnd* pTrayNotify, OUT PRECT rcClock)
+HRESULT CTrayNotifyWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv)
 {
-    return pTrayNotify->GetClockRect(rcClock);
+    return ShellObjectCreatorInit<CTrayNotifyWnd>(hwndParent, riid, ppv);
 }