[EXPLORER] -Make CSysPagerWnd, CTaskSwitchWnd, CTrayClockWnd and CTrayNotifyWnd proper com objects so that their lifetime is managed properly.

This commit is contained in:
Giannis Adamopoulos 2018-01-28 14:21:45 +02:00
parent 478348ead1
commit 455bce68b5
9 changed files with 490 additions and 390 deletions

View file

@ -332,19 +332,18 @@ CreateStartMenuSite(IN OUT ITrayWindow *Tray, const IID & riid, PVOID * ppv);
*/ */
/* TrayClockWnd */ /* TrayClockWnd */
#define TCWM_GETMINIMUMSIZE (WM_USER + 0x100) HRESULT CTrayClockWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv);
#define TCWM_UPDATETIME (WM_USER + 0x101)
/* TrayNotifyWnd */ /* TrayNotifyWnd */
#define TNWM_GETMINIMUMSIZE (WM_USER + 0x100) #define TNWM_GETMINIMUMSIZE (WM_USER + 0x100)
#define TNWM_SHOWTRAY (WM_USER + 0x103)
#define TNWM_CHANGETRAYPOS (WM_USER + 0x104) #define TNWM_CHANGETRAYPOS (WM_USER + 0x104)
#define NTNWM_REALIGN (0x1) #define NTNWM_REALIGN (0x1)
class CTrayNotifyWnd; HRESULT CTrayNotifyWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv);
HWND CreateTrayNotifyWnd(IN HWND hwndParent, CTrayNotifyWnd** ppinstance); /* SysPagerWnd */
HRESULT CSysPagerWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv);
/* /*
* taskswnd.c * taskswnd.c
@ -353,8 +352,7 @@ HWND CreateTrayNotifyWnd(IN HWND hwndParent, CTrayNotifyWnd** ppinstance);
#define TSWM_ENABLEGROUPING (WM_USER + 1) #define TSWM_ENABLEGROUPING (WM_USER + 1)
#define TSWM_UPDATETASKBARPOS (WM_USER + 2) #define TSWM_UPDATETASKBARPOS (WM_USER + 2)
HWND HRESULT CTaskSwitchWnd_CreateInstance(IN HWND hWndParent, IN OUT ITrayWindow *Tray, REFIID riid, void **ppv);
CreateTaskSwitchWnd(IN HWND hWndParent, IN OUT ITrayWindow *Tray);
HRESULT HRESULT
Tray_OnStartMenuDismissed(ITrayWindow* Tray); Tray_OnStartMenuDismissed(ITrayWindow* Tray);
@ -362,16 +360,4 @@ Tray_OnStartMenuDismissed(ITrayWindow* Tray);
HRESULT HRESULT
IsSameObject(IN IUnknown *punk1, IN IUnknown *punk2); IsSameObject(IN IUnknown *punk1, IN IUnknown *punk2);
/*
* syspager.c
*/
#include "syspager.h"
/*
* trayclock.c
*/
#include "trayclock.h"
#endif /* _EXPLORER_PRECOMP__H_ */ #endif /* _EXPLORER_PRECOMP__H_ */

View file

@ -29,6 +29,236 @@ typedef struct _SYS_PAGER_COPY_DATA
NOTIFYICONDATA nicon_data; NOTIFYICONDATA nicon_data;
} SYS_PAGER_COPY_DATA, *PSYS_PAGER_COPY_DATA; } SYS_PAGER_COPY_DATA, *PSYS_PAGER_COPY_DATA;
struct InternalIconData : NOTIFYICONDATA
{
// Must keep a separate copy since the original is unioned with uTimeout.
UINT uVersionCopy;
};
struct IconWatcherData
{
HANDLE hProcess;
DWORD ProcessId;
NOTIFYICONDATA IconData;
IconWatcherData(CONST 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();
virtual ~CIconWatcher();
bool Initialize(_In_ HWND hWndParent);
void Uninitialize();
bool AddIconToWatcher(_In_ CONST NOTIFYICONDATA *iconData);
bool RemoveIconFromWatcher(_In_ CONST NOTIFYICONDATA *iconData);
IconWatcherData* GetListEntry(_In_opt_ CONST NOTIFYICONDATA *iconData, _In_opt_ HANDLE hProcess, _In_ bool Remove);
private:
static UINT WINAPI WatcherThread(_In_opt_ LPVOID lpParam);
};
class CBalloonQueue
{
public:
static const int TimerInterval = 2000;
static const int BalloonsTimerId = 1;
static const int MinTimeout = 10000;
static const int MaxTimeout = 30000;
static const int CooldownBetweenBalloons = 2000;
private:
struct Info
{
InternalIconData * pSource;
WCHAR szInfo[256];
WCHAR szInfoTitle[64];
WPARAM uIcon;
UINT uTimeout;
Info(InternalIconData * source)
{
pSource = source;
StrNCpy(szInfo, source->szInfo, _countof(szInfo));
StrNCpy(szInfoTitle, source->szInfoTitle, _countof(szInfoTitle));
uIcon = source->dwInfoFlags & NIIF_ICON_MASK;
if (source->dwInfoFlags == NIIF_USER)
uIcon = reinterpret_cast<WPARAM>(source->hIcon);
uTimeout = source->uTimeout;
}
};
HWND m_hwndParent;
CTooltips * m_tooltips;
CAtlList<Info> m_queue;
CToolbar<InternalIconData> * m_toolbar;
InternalIconData * m_current;
bool m_currentClosed;
int m_timer;
public:
CBalloonQueue();
void Init(HWND hwndParent, CToolbar<InternalIconData> * toolbar, CTooltips * balloons);
void Deinit();
bool OnTimer(int timerId);
void UpdateInfo(InternalIconData * notifyItem);
void RemoveInfo(InternalIconData * notifyItem);
void CloseCurrent();
private:
int IndexOf(InternalIconData * pdata);
void SetTimer(int length);
void Show(Info& info);
void Close(IN OUT InternalIconData * notifyItem);
};
class CNotifyToolbar :
public CWindowImplBaseT< CToolbar<InternalIconData>, CControlWinTraits >
{
HIMAGELIST m_ImageList;
int m_VisibleButtonCount;
CBalloonQueue * m_BalloonQueue;
public:
CNotifyToolbar();
virtual ~CNotifyToolbar();
int GetVisibleButtonCount();
int FindItem(IN HWND hWnd, IN UINT uID, InternalIconData ** pdata);
int FindExistingSharedIcon(HICON handle);
BOOL AddButton(IN CONST NOTIFYICONDATA *iconData);
BOOL SwitchVersion(IN CONST NOTIFYICONDATA *iconData);
BOOL UpdateButton(IN CONST NOTIFYICONDATA *iconData);
BOOL RemoveButton(IN CONST NOTIFYICONDATA *iconData);
VOID ResizeImagelist();
private:
VOID SendMouseEvent(IN WORD wIndex, IN UINT uMsg, IN WPARAM wParam);
LRESULT OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnTooltipShow(INT uCode, LPNMHDR hdr, BOOL& bHandled);
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, CBalloonQueue * queue);
};
extern const WCHAR szSysPagerWndClass[];
class CSysPagerWnd :
public CComCoClass<CSysPagerWnd>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public CWindowImpl < CSysPagerWnd, CWindow, CControlWinTraits >,
public IOleWindow,
public CIconWatcher
{
CNotifyToolbar Toolbar;
CTooltips m_Balloons;
CBalloonQueue m_BalloonQueue;
public:
CSysPagerWnd();
virtual ~CSysPagerWnd();
LRESULT DrawBackground(HDC hdc);
LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnGetInfoTip(INT uCode, LPNMHDR hdr, BOOL& bHandled);
LRESULT OnCustomDraw(INT uCode, LPNMHDR hdr, BOOL& bHandled);
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCtxMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnBalloonPop(UINT uCode, LPNMHDR hdr, BOOL& bHandled);
LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
public:
HRESULT WINAPI GetWindow(HWND* phwnd)
{
if (!phwnd)
return E_INVALIDARG;
*phwnd = m_hWnd;
return S_OK;
}
HRESULT WINAPI ContextSensitiveHelp(BOOL fEnterMode)
{
return E_NOTIMPL;
}
DECLARE_NOT_AGGREGATABLE(CSysPagerWnd)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CSysPagerWnd)
COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
END_COM_MAP()
BOOL NotifyIcon(DWORD notify_code, _In_ CONST NOTIFYICONDATA *iconData);
void GetSize(IN BOOL IsHorizontal, IN PSIZE size);
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)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
MESSAGE_HANDLER(WM_COPYDATA, OnCopyData)
MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChanged)
MESSAGE_HANDLER(TNWM_GETMINIMUMSIZE, OnGetMinimumSize)
NOTIFY_CODE_HANDLER(TTN_POP, OnBalloonPop)
NOTIFY_CODE_HANDLER(TBN_GETINFOTIPW, OnGetInfoTip)
NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
END_MSG_MAP()
HRESULT Initialize(IN HWND hWndParent);
};
CIconWatcher::CIconWatcher() : CIconWatcher::CIconWatcher() :
m_hWatcherThread(NULL), m_hWatcherThread(NULL),
m_WakeUpEvent(NULL), m_WakeUpEvent(NULL),
@ -1204,22 +1434,27 @@ LRESULT CSysPagerWnd::OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam,
return 0; return 0;
} }
HWND CSysPagerWnd::_Init(IN HWND hWndParent) LRESULT CSysPagerWnd::OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
DWORD dwStyle; GetSize((BOOL)wParam, (PSIZE)lParam);
return 0;
}
HRESULT CSysPagerWnd::Initialize(IN HWND hWndParent)
{
/* Create the window. The tray window is going to move it to the correct /* Create the window. The tray window is going to move it to the correct
position and resize it as needed. */ position and resize it as needed. */
dwStyle = WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE; DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE;
Create(hWndParent, 0, NULL, dwStyle); Create(hWndParent, 0, NULL, dwStyle);
if (!m_hWnd) if (!m_hWnd)
{ return E_FAIL;
return NULL;
}
SetWindowTheme(m_hWnd, L"TrayNotify", NULL); SetWindowTheme(m_hWnd, L"TrayNotify", NULL);
return m_hWnd; return S_OK;
}
HRESULT CSysPagerWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv)
{
return ShellObjectCreatorInit<CSysPagerWnd>(hwndParent, riid, ppv);
} }

View file

@ -1,207 +0,0 @@
#pragma once
struct InternalIconData : NOTIFYICONDATA
{
// Must keep a separate copy since the original is unioned with uTimeout.
UINT uVersionCopy;
};
struct IconWatcherData
{
HANDLE hProcess;
DWORD ProcessId;
NOTIFYICONDATA IconData;
IconWatcherData(CONST 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();
virtual ~CIconWatcher();
bool Initialize(_In_ HWND hWndParent);
void Uninitialize();
bool AddIconToWatcher(_In_ CONST NOTIFYICONDATA *iconData);
bool RemoveIconFromWatcher(_In_ CONST NOTIFYICONDATA *iconData);
IconWatcherData* GetListEntry(_In_opt_ CONST NOTIFYICONDATA *iconData, _In_opt_ HANDLE hProcess, _In_ bool Remove);
private:
static UINT WINAPI WatcherThread(_In_opt_ LPVOID lpParam);
};
class CBalloonQueue
{
public:
static const int TimerInterval = 2000;
static const int BalloonsTimerId = 1;
static const int MinTimeout = 10000;
static const int MaxTimeout = 30000;
static const int CooldownBetweenBalloons = 2000;
private:
struct Info
{
InternalIconData * pSource;
WCHAR szInfo[256];
WCHAR szInfoTitle[64];
WPARAM uIcon;
UINT uTimeout;
Info(InternalIconData * source)
{
pSource = source;
StrNCpy(szInfo, source->szInfo, _countof(szInfo));
StrNCpy(szInfoTitle, source->szInfoTitle, _countof(szInfoTitle));
uIcon = source->dwInfoFlags & NIIF_ICON_MASK;
if (source->dwInfoFlags == NIIF_USER)
uIcon = reinterpret_cast<WPARAM>(source->hIcon);
uTimeout = source->uTimeout;
}
};
HWND m_hwndParent;
CTooltips * m_tooltips;
CAtlList<Info> m_queue;
CToolbar<InternalIconData> * m_toolbar;
InternalIconData * m_current;
bool m_currentClosed;
int m_timer;
public:
CBalloonQueue();
void Init(HWND hwndParent, CToolbar<InternalIconData> * toolbar, CTooltips * balloons);
void Deinit();
bool OnTimer(int timerId);
void UpdateInfo(InternalIconData * notifyItem);
void RemoveInfo(InternalIconData * notifyItem);
void CloseCurrent();
private:
int IndexOf(InternalIconData * pdata);
void SetTimer(int length);
void Show(Info& info);
void Close(IN OUT InternalIconData * notifyItem);
};
class CNotifyToolbar :
public CWindowImplBaseT< CToolbar<InternalIconData>, CControlWinTraits >
{
HIMAGELIST m_ImageList;
int m_VisibleButtonCount;
CBalloonQueue * m_BalloonQueue;
public:
CNotifyToolbar();
virtual ~CNotifyToolbar();
int GetVisibleButtonCount();
int FindItem(IN HWND hWnd, IN UINT uID, InternalIconData ** pdata);
int FindExistingSharedIcon(HICON handle);
BOOL AddButton(IN CONST NOTIFYICONDATA *iconData);
BOOL SwitchVersion(IN CONST NOTIFYICONDATA *iconData);
BOOL UpdateButton(IN CONST NOTIFYICONDATA *iconData);
BOOL RemoveButton(IN CONST NOTIFYICONDATA *iconData);
VOID ResizeImagelist();
private:
VOID SendMouseEvent(IN WORD wIndex, IN UINT uMsg, IN WPARAM wParam);
LRESULT OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnTooltipShow(INT uCode, LPNMHDR hdr, BOOL& bHandled);
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, CBalloonQueue * queue);
};
extern const WCHAR szSysPagerWndClass[];
class CSysPagerWnd :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public CWindowImpl < CSysPagerWnd, CWindow, CControlWinTraits >,
public CIconWatcher
{
CNotifyToolbar Toolbar;
CTooltips m_Balloons;
CBalloonQueue m_BalloonQueue;
public:
CSysPagerWnd();
virtual ~CSysPagerWnd();
LRESULT DrawBackground(HDC hdc);
LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnGetInfoTip(INT uCode, LPNMHDR hdr, BOOL& bHandled);
LRESULT OnCustomDraw(INT uCode, LPNMHDR hdr, BOOL& bHandled);
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCtxMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnBalloonPop(UINT uCode, LPNMHDR hdr, BOOL& bHandled);
LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
public:
BOOL NotifyIcon(DWORD notify_code, _In_ CONST NOTIFYICONDATA *iconData);
void GetSize(IN BOOL IsHorizontal, IN PSIZE size);
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)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
MESSAGE_HANDLER(WM_COPYDATA, OnCopyData)
MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChanged)
NOTIFY_CODE_HANDLER(TTN_POP, OnBalloonPop)
NOTIFY_CODE_HANDLER(TBN_GETINFOTIPW, OnGetInfoTip)
NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
END_MSG_MAP()
HWND _Init(IN HWND hWndParent);
};

View file

@ -38,6 +38,7 @@ class CTaskBand :
{ {
CComPtr<ITrayWindow> m_Tray; CComPtr<ITrayWindow> m_Tray;
CComPtr<IUnknown> m_Site; CComPtr<IUnknown> m_Site;
CComPtr<IUnknown> m_TasksWnd;
HWND m_hWnd; HWND m_hWnd;
@ -250,23 +251,20 @@ public:
TRACE("CTaskBand::SetSite(0x%p)\n", pUnkSite); TRACE("CTaskBand::SetSite(0x%p)\n", pUnkSite);
hRet = IUnknown_GetWindow(pUnkSite, &hwndSite); hRet = IUnknown_GetWindow(pUnkSite, &hwndSite);
if (FAILED(hRet)) if (FAILED_UNEXPECTEDLY(hRet))
{
TRACE("Querying site window failed: 0x%x\n", hRet);
return hRet; return hRet;
}
TRACE("CreateTaskSwitchWnd(Parent: 0x%p)\n", hwndSite); TRACE("CreateTaskSwitchWnd(Parent: 0x%p)\n", hwndSite);
HWND hwndTaskSwitch = CreateTaskSwitchWnd(hwndSite, m_Tray); hRet = CTaskSwitchWnd_CreateInstance(hwndSite, m_Tray, IID_PPV_ARG(IUnknown, &m_TasksWnd));
if (!hwndTaskSwitch) if (FAILED_UNEXPECTEDLY(hRet))
{ return hRet;
ERR("CreateTaskSwitchWnd failed");
return E_FAIL; hRet = IUnknown_GetWindow(m_TasksWnd, &m_hWnd);
} if (FAILED_UNEXPECTEDLY(hRet))
return hRet;
m_Site = pUnkSite; m_Site = pUnkSite;
m_hWnd = hwndTaskSwitch;
return S_OK; return S_OK;
} }

View file

@ -193,7 +193,10 @@ public:
}; };
class CTaskSwitchWnd : class CTaskSwitchWnd :
public CWindowImpl < CTaskSwitchWnd, CWindow, CControlWinTraits > public CComCoClass<CTaskSwitchWnd>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public CWindowImpl < CTaskSwitchWnd, CWindow, CControlWinTraits >,
public IOleWindow
{ {
CTaskToolbar m_TaskBar; CTaskToolbar m_TaskBar;
@ -1827,6 +1830,29 @@ public:
return 0; return 0;
} }
HRESULT Initialize(IN HWND hWndParent, IN OUT ITrayWindow *tray)
{
m_Tray = tray;
m_IsGroupingEnabled = TRUE; /* FIXME */
Create(hWndParent, 0, szRunningApps, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP);
if (!m_hWnd)
return E_FAIL;
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;
}
DECLARE_WND_CLASS_EX(szTaskSwitchWndClass, CS_DBLCLKS, COLOR_3DFACE) DECLARE_WND_CLASS_EX(szTaskSwitchWndClass, CS_DBLCLKS, COLOR_3DFACE)
BEGIN_MSG_MAP(CTaskSwitchWnd) BEGIN_MSG_MAP(CTaskSwitchWnd)
@ -1850,21 +1876,15 @@ public:
MESSAGE_HANDLER(WM_KLUDGEMINRECT, OnKludgeItemRect) MESSAGE_HANDLER(WM_KLUDGEMINRECT, OnKludgeItemRect)
END_MSG_MAP() END_MSG_MAP()
HWND _Init(IN HWND hWndParent, IN OUT ITrayWindow *tray) DECLARE_NOT_AGGREGATABLE(CTaskSwitchWnd)
{
m_Tray = tray; DECLARE_PROTECT_FINAL_CONSTRUCT()
m_IsGroupingEnabled = TRUE; /* FIXME */ BEGIN_COM_MAP(CTaskSwitchWnd)
return Create(hWndParent, 0, szRunningApps, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP); COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
} END_COM_MAP()
}; };
HWND HRESULT CTaskSwitchWnd_CreateInstance(IN HWND hWndParent, IN OUT ITrayWindow *Tray, REFIID riid, void **ppv)
CreateTaskSwitchWnd(IN HWND hWndParent, IN OUT ITrayWindow *Tray)
{ {
CTaskSwitchWnd * instance; return ShellObjectCreatorInit<CTaskSwitchWnd>(hWndParent, Tray, riid, ppv);
// TODO: Destroy after the window is destroyed
instance = new CTaskSwitchWnd();
return instance->_Init(hWndParent, Tray);
} }

View file

@ -25,6 +25,123 @@
* TrayClockWnd * TrayClockWnd
*/ */
const struct
{
BOOL IsTime;
DWORD dwFormatFlags;
LPCWSTR lpFormat;
} ClockWndFormats[] = {
{ TRUE, 0, NULL },
{ FALSE, 0, L"dddd" },
{ FALSE, DATE_SHORTDATE, NULL }
};
const UINT ClockWndFormatsCount = _ARRAYSIZE(ClockWndFormats);
#define CLOCKWND_FORMAT_COUNT ClockWndFormatsCount
extern const WCHAR szTrayClockWndClass[];
class CTrayClockWnd :
public CComCoClass<CTrayClockWnd>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public CWindowImpl < CTrayClockWnd, CWindow, CControlWinTraits >,
public IOleWindow
{
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();
virtual ~CTrayClockWnd();
private:
LRESULT OnThemeChanged();
LRESULT OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
BOOL MeasureLines();
WORD GetMinimumSize(IN BOOL Horizontal, IN OUT PSIZE pSize);
VOID UpdateWnd();
VOID Update();
UINT CalculateDueTime();
BOOL ResetTime();
VOID CalibrateTimer();
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
VOID SetFont(IN HFONT hNewFont, IN BOOL bRedraw);
LRESULT DrawBackground(HDC hdc);
LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSetFont(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnTaskbarSettingsChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnNcLButtonDblClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
public:
HRESULT WINAPI GetWindow(HWND* phwnd)
{
if (!phwnd)
return E_INVALIDARG;
*phwnd = m_hWnd;
return S_OK;
}
HRESULT WINAPI ContextSensitiveHelp(BOOL fEnterMode)
{
return E_NOTIMPL;
}
DECLARE_NOT_AGGREGATABLE(CTrayClockWnd)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CTrayClockWnd)
COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
END_COM_MAP()
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(TNWM_GETMINIMUMSIZE, OnGetMinimumSize)
MESSAGE_HANDLER(TWM_SETTINGSCHANGED, OnTaskbarSettingsChanged)
MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClick)
END_MSG_MAP()
HRESULT Initialize(IN HWND hWndParent);
};
const WCHAR szTrayClockWndClass[] = L"TrayClockWClass"; const WCHAR szTrayClockWndClass[] = L"TrayClockWClass";
#define ID_TRAYCLOCK_TIMER 0 #define ID_TRAYCLOCK_TIMER 0
@ -578,7 +695,7 @@ LRESULT CTrayClockWnd::OnNcLButtonDblClick(UINT uMsg, WPARAM wParam, LPARAM lPar
return TRUE; return TRUE;
} }
HWND CTrayClockWnd::_Init(IN HWND hWndParent) HRESULT CTrayClockWnd::Initialize(IN HWND hWndParent)
{ {
IsHorizontal = TRUE; IsHorizontal = TRUE;
@ -589,10 +706,16 @@ HWND CTrayClockWnd::_Init(IN HWND hWndParent)
dwStyle |= WS_VISIBLE; dwStyle |= WS_VISIBLE;
Create(hWndParent, 0, NULL, dwStyle); Create(hWndParent, 0, NULL, dwStyle);
if (!m_hWnd)
return E_FAIL;
if (m_hWnd != NULL) SetWindowTheme(m_hWnd, L"TrayNotify", NULL);
SetWindowTheme(m_hWnd, L"TrayNotify", NULL);
return m_hWnd; return S_OK;
}; };
HRESULT CTrayClockWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv)
{
return ShellObjectCreatorInit<CTrayClockWnd>(hwndParent, riid, ppv);
}

View file

@ -1,94 +0,0 @@
#pragma once
const struct
{
BOOL IsTime;
DWORD dwFormatFlags;
LPCWSTR lpFormat;
} ClockWndFormats[] = {
{ TRUE, 0, NULL },
{ FALSE, 0, L"dddd" },
{ FALSE, DATE_SHORTDATE, NULL }
};
const UINT ClockWndFormatsCount = _ARRAYSIZE(ClockWndFormats);
#define CLOCKWND_FORMAT_COUNT ClockWndFormatsCount
extern const WCHAR szTrayClockWndClass[];
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();
virtual ~CTrayClockWnd();
private:
LRESULT OnThemeChanged();
LRESULT OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
BOOL MeasureLines();
WORD GetMinimumSize(IN BOOL Horizontal, IN OUT PSIZE pSize);
VOID UpdateWnd();
VOID Update();
UINT CalculateDueTime();
BOOL ResetTime();
VOID CalibrateTimer();
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
VOID SetFont(IN HFONT hNewFont, IN BOOL bRedraw);
LRESULT DrawBackground(HDC hdc);
LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSetFont(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnTaskbarSettingsChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnNcLButtonDblClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
public:
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(TWM_SETTINGSCHANGED, OnTaskbarSettingsChanged)
MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClick)
END_MSG_MAP()
HWND _Init(IN HWND hWndParent);
};

View file

@ -31,11 +31,16 @@ static const WCHAR szTrayNotifyWndClass [] = TEXT("TrayNotifyWnd");
#define TRAY_NOTIFY_WND_SPACING_Y 1 #define TRAY_NOTIFY_WND_SPACING_Y 1
class CTrayNotifyWnd : class CTrayNotifyWnd :
public CComCoClass<CTrayNotifyWnd>,
public CComObjectRootEx<CComMultiThreadModelNoCS>, public CComObjectRootEx<CComMultiThreadModelNoCS>,
public CWindowImpl < CTrayNotifyWnd, CWindow, CControlWinTraits > public CWindowImpl < CTrayNotifyWnd, CWindow, CControlWinTraits >,
public IOleWindow
{ {
CSysPagerWnd * m_pager; CComPtr<IUnknown> m_clock;
CTrayClockWnd * m_clock; CComPtr<IUnknown> m_pager;
HWND m_hwndClock;
HWND m_hwndPager;
HTHEME TrayTheme; HTHEME TrayTheme;
SIZE szTrayClockMin; SIZE szTrayClockMin;
@ -45,8 +50,8 @@ class CTrayNotifyWnd :
public: public:
CTrayNotifyWnd() : CTrayNotifyWnd() :
m_pager(NULL), m_hwndClock(NULL),
m_clock(NULL), m_hwndPager(NULL),
TrayTheme(NULL), TrayTheme(NULL),
IsHorizontal(FALSE) IsHorizontal(FALSE)
{ {
@ -98,11 +103,23 @@ public:
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
m_clock = new CTrayClockWnd(); HRESULT hr;
m_clock->_Init(m_hWnd);
m_pager = new CSysPagerWnd(); hr = CTrayClockWnd_CreateInstance(m_hWnd, IID_PPV_ARG(IUnknown, &m_clock));
m_pager->_Init(m_hWnd); 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; return TRUE;
} }
@ -127,7 +144,7 @@ public:
goto NoClock; goto NoClock;
} }
m_clock->SendMessage(TCWM_GETMINIMUMSIZE, (WPARAM) IsHorizontal, (LPARAM) &szClock); ::SendMessage(m_hwndClock, TNWM_GETMINIMUMSIZE, (WPARAM) IsHorizontal, (LPARAM) &szClock);
szTrayClockMin = szClock; szTrayClockMin = szClock;
} }
@ -144,7 +161,7 @@ public:
szTray.cx = pSize->cx - 2 * TRAY_NOTIFY_WND_SPACING_X; 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; szTrayNotify = szTray;
@ -195,7 +212,7 @@ public:
szClock.cy = szTrayClockMin.cy; szClock.cy = szTrayClockMin.cy;
} }
m_clock->SetWindowPos( ::SetWindowPos(m_hwndClock,
NULL, NULL,
ptClock.x, ptClock.x,
ptClock.y, ptClock.y,
@ -216,7 +233,7 @@ public:
ptPager.y = ContentMargin.cyTopHeight; ptPager.y = ContentMargin.cyTopHeight;
} }
m_pager->SetWindowPos( ::SetWindowPos(m_hwndPager,
NULL, NULL,
ptPager.x, ptPager.x,
ptPager.y, ptPager.y,
@ -287,16 +304,12 @@ public:
LRESULT OnClockMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT OnClockMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
if (m_clock != NULL) return SendMessageW(m_hwndClock, uMsg, wParam, lParam);
return m_clock->SendMessageW(uMsg, wParam, lParam);
return TRUE;
} }
LRESULT OnPagerMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT OnPagerMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
if (m_pager) return SendMessageW(m_hwndPager, uMsg, wParam, lParam);
return m_pager->SendMessage(uMsg, wParam, lParam);
return TRUE;
} }
LRESULT OnRealign(INT uCode, LPNMHDR hdr, BOOL& bHandled) LRESULT OnRealign(INT uCode, LPNMHDR hdr, BOOL& bHandled)
@ -305,6 +318,26 @@ public:
return GetParent().SendMessage(WM_NOTIFY, 0, (LPARAM)hdr); return GetParent().SendMessage(WM_NOTIFY, 0, (LPARAM)hdr);
} }
HRESULT WINAPI GetWindow(HWND* phwnd)
{
if (!phwnd)
return E_INVALIDARG;
*phwnd = m_hWnd;
return S_OK;
}
HRESULT WINAPI ContextSensitiveHelp(BOOL fEnterMode)
{
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) DECLARE_WND_CLASS_EX(szTrayNotifyWndClass, CS_DBLCLKS, COLOR_3DFACE)
BEGIN_MSG_MAP(CTrayNotifyWnd) BEGIN_MSG_MAP(CTrayNotifyWnd)
@ -323,18 +356,17 @@ public:
MESSAGE_HANDLER(TNWM_GETMINIMUMSIZE, OnGetMinimumSize) MESSAGE_HANDLER(TNWM_GETMINIMUMSIZE, OnGetMinimumSize)
END_MSG_MAP() END_MSG_MAP()
HWND _Init(IN HWND hwndParent) HRESULT Initialize(IN HWND hwndParent)
{ {
DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
return Create(hwndParent, 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 HWND hwndParent, CTrayNotifyWnd** ppinstance) HRESULT CTrayNotifyWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv)
{ {
CTrayNotifyWnd * pTrayNotify = new CTrayNotifyWnd(); return ShellObjectCreatorInit<CTrayNotifyWnd>(hwndParent, riid, ppv);
// TODO: Destroy after the window is destroyed
*ppinstance = pTrayNotify;
return pTrayNotify->_Init(hwndParent);
} }

View file

@ -209,7 +209,7 @@ class CTrayWindow :
HWND m_TaskSwitch; HWND m_TaskSwitch;
HWND m_TrayNotify; HWND m_TrayNotify;
CTrayNotifyWnd* m_TrayNotifyInstance; CComPtr<IUnknown> m_TrayNotifyInstance;
DWORD m_Position; DWORD m_Position;
HMONITOR m_Monitor; HMONITOR m_Monitor;
@ -2048,6 +2048,11 @@ ChangePos:
if (FAILED_UNEXPECTEDLY(hRet)) if (FAILED_UNEXPECTEDLY(hRet))
return FALSE; return FALSE;
/* Create the tray notification window */
hRet = CTrayNotifyWnd_CreateInstance(m_hWnd, IID_PPV_ARG(IUnknown, &m_TrayNotifyInstance));
if (FAILED_UNEXPECTEDLY(hRet))
return FALSE;
/* Get the hwnd of the rebar */ /* Get the hwnd of the rebar */
hRet = IUnknown_GetWindow(m_TrayBandSite, &m_Rebar); hRet = IUnknown_GetWindow(m_TrayBandSite, &m_Rebar);
if (FAILED_UNEXPECTEDLY(hRet)) if (FAILED_UNEXPECTEDLY(hRet))
@ -2058,10 +2063,12 @@ ChangePos:
if (FAILED_UNEXPECTEDLY(hRet)) if (FAILED_UNEXPECTEDLY(hRet))
return FALSE; return FALSE;
SetWindowTheme(m_Rebar, L"TaskBar", NULL); /* Get the hwnd of the tray notification window */
hRet = IUnknown_GetWindow(m_TrayNotifyInstance, &m_TrayNotify);
if (FAILED_UNEXPECTEDLY(hRet))
return FALSE;
/* Create the tray notification window */ SetWindowTheme(m_Rebar, L"TaskBar", NULL);
m_TrayNotify = CreateTrayNotifyWnd(m_hWnd, &m_TrayNotifyInstance);
UpdateFonts(); UpdateFonts();