[EXPLORER]: Simplify the creation of the tray band site and the tasks band.

- CTrayBandSite: Rename its constructor to CTrayBandSite_CreateInstance. Let the CTrayWindow create the CTasksBand and pass it to the constructor. Use a standard com interface to see if the tasks band was added while loading and don't use an explorer specific interface for it. Make CTrayBandSite::_Init a bit clearer.
- CTrayWindow: Implement the IOleWindow interface and create the CTaskBand before creating the CTrayBandSite. Then use standard com interfaces to get their respective HRND.
- CTaskBand: Rename its constructor to CTaskBand_CreateInstance. Remove a hack that was using its IOleWindow to act like the IOleWindow of the CTrayWindow during the creation of the CTrayBandSite. This is possible since the IOleWindow of the CTrayWindow is passed to the SetDeskBarSite method of CTrayBandSite.

svn path=/trunk/; revision=74224
This commit is contained in:
Giannis Adamopoulos 2017-03-23 15:39:34 +00:00
parent 0cd03197e2
commit b8b7eedce2
4 changed files with 142 additions and 219 deletions

View file

@ -232,32 +232,8 @@ ShowCustomizeNotifyIcons(HINSTANCE, HWND);
* taskband.cpp
*/
/* Internal Task Band CLSID */
extern const GUID CLSID_ITaskBand;
#define INTERFACE ITaskBand
DECLARE_INTERFACE_(ITaskBand, IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD_(HRESULT, QueryInterface) (THIS_ REFIID riid, void** ppvObject) PURE;
STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE;
/*** ITaskBand methods ***/
STDMETHOD_(HRESULT, GetRebarBandID)(THIS_ DWORD *pdwBandID) PURE;
};
#undef INTERFACE
#if defined(COBJMACROS)
/*** IUnknown methods ***/
#define ITaskBand_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
#define ITaskBand_AddRef(p) (p)->lpVtbl->AddRef(p)
#define ITaskBand_Release(p) (p)->lpVtbl->Release(p)
/*** ITaskBand methods ***/
#define ITaskBand_GetRebarBandID(p,a) (p)->lpVtbl->GetRebarBandID(p,a)
#endif
ITaskBand *
CreateTaskBand(IN OUT ITrayWindow *Tray);
extern const GUID CLSID_ITaskBand; /* Internal Task Band CLSID */
HRESULT CTaskBand_CreateInstance(IN ITrayWindow *Tray, REFIID riid, void **ppv);
/*
* tbsite.cpp
@ -296,10 +272,7 @@ DECLARE_INTERFACE_(ITrayBandSite, IUnknown)
#define ITrayBandSite_Lock(p,a) (p)->lpVtbl->Lock(p,a)
#endif
ITrayBandSite *
CreateTrayBandSite(IN OUT ITrayWindow *Tray,
OUT HWND *phWndRebar,
OUT HWND *phWndTaskSwitch);
HRESULT CTrayBandSite_CreateInstance(IN ITrayWindow *tray, IN IDeskBand* pTaskBand, OUT ITrayBandSite** pBandSite);
/*
* startmnu.cpp

View file

@ -21,7 +21,7 @@
#include "precomp.h"
/*****************************************************************************
** ITaskBand ****************************************************************
** CTaskBand ****************************************************************
*****************************************************************************/
const GUID CLSID_ITaskBand = { 0x68284FAA, 0x6A48, 0x11D0, { 0x8C, 0x78, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xB4 } };
@ -30,7 +30,6 @@ class CTaskBand :
public CComCoClass<CTaskBand>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IObjectWithSite,
public ITaskBand,
public IDeskBand,
public IDeskBar,
public IPersistStream,
@ -53,41 +52,16 @@ public:
virtual ~CTaskBand() { }
virtual HRESULT STDMETHODCALLTYPE GetRebarBandID(
OUT DWORD *pdwBandID)
{
if (m_BandID != (DWORD) -1)
{
if (pdwBandID != NULL)
*pdwBandID = m_BandID;
return S_OK;
}
return E_FAIL;
}
/*****************************************************************************/
virtual HRESULT STDMETHODCALLTYPE GetWindow(
OUT HWND *phwnd)
virtual HRESULT STDMETHODCALLTYPE GetWindow(OUT HWND *phwnd)
{
/* NOTE: We have to return the tray window here so that ITaskBarClient
knows the parent window of the Rebar control it creates when
calling ITaskBarClient::SetDeskBarSite()! However, once we
created a window we return the task switch window! */
if (m_hWnd != NULL)
*phwnd = m_hWnd;
else
*phwnd = m_Tray->GetHWND();
TRACE("ITaskBand::GetWindow(0x%p->0x%p)\n", phwnd, *phwnd);
if (*phwnd != NULL)
return S_OK;
return E_FAIL;
if (!m_hWnd)
return E_FAIL;
if (!phwnd)
return E_INVALIDARG;
*phwnd = m_hWnd;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(
@ -125,7 +99,7 @@ public:
IN DWORD dwViewMode,
IN OUT DESKBANDINFO *pdbi)
{
TRACE("ITaskBand::GetBandInfo(0x%x,0x%x,0x%p) hWnd=0x%p\n", dwBandID, dwViewMode, pdbi, m_hWnd);
TRACE("CTaskBand::GetBandInfo(0x%x,0x%x,0x%p) hWnd=0x%p\n", dwBandID, dwViewMode, pdbi, m_hWnd);
if (m_hWnd != NULL)
{
@ -231,7 +205,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetClassID(
OUT CLSID *pClassID)
{
TRACE("ITaskBand::GetClassID(0x%p)\n", pClassID);
TRACE("CTaskBand::GetClassID(0x%p)\n", pClassID);
/* We're going to return the (internal!) CLSID of the task band interface */
*pClassID = CLSID_ITaskBand;
return S_OK;
@ -246,7 +220,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE Load(
IN IStream *pStm)
{
TRACE("ITaskBand::Load called\n");
TRACE("CTaskBand::Load called\n");
/* Nothing to do */
return S_OK;
}
@ -262,7 +236,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetSizeMax(
OUT ULARGE_INTEGER *pcbSize)
{
TRACE("ITaskBand::GetSizeMax called\n");
TRACE("CTaskBand::GetSizeMax called\n");
/* We don't need any space for the task band */
pcbSize->QuadPart = 0;
return S_OK;
@ -275,7 +249,7 @@ public:
HRESULT hRet;
HWND hwndSite;
TRACE("ITaskBand::SetSite(0x%p)\n", pUnkSite);
TRACE("CTaskBand::SetSite(0x%p)\n", pUnkSite);
hRet = IUnknown_GetWindow(pUnkSite, &hwndSite);
if (FAILED(hRet))
@ -303,7 +277,7 @@ public:
IN REFIID riid,
OUT VOID **ppvSite)
{
TRACE("ITaskBand::GetSite(0x%p,0x%p)\n", riid, ppvSite);
TRACE("CTaskBand::GetSite(0x%p,0x%p)\n", riid, ppvSite);
if (m_Site != NULL)
{
@ -323,7 +297,7 @@ public:
IN LPARAM lParam,
OUT LRESULT *plrResult)
{
TRACE("ITaskBand: IWinEventHandler::ProcessMessage(0x%p, 0x%x, 0x%p, 0x%p, 0x%p)\n", hWnd, uMsg, wParam, lParam, plrResult);
TRACE("CTaskBand: IWinEventHandler::ProcessMessage(0x%p, 0x%x, 0x%p, 0x%p, 0x%p)\n", hWnd, uMsg, wParam, lParam, plrResult);
return E_NOTIMPL;
}
@ -333,7 +307,7 @@ public:
if (hWnd == m_hWnd ||
IsChild(m_hWnd, hWnd))
{
TRACE("ITaskBand::ContainsWindow(0x%p) returns S_OK\n", hWnd);
TRACE("CTaskBand::ContainsWindow(0x%p) returns S_OK\n", hWnd);
return S_OK;
}
@ -353,7 +327,7 @@ public:
/*****************************************************************************/
HRESULT STDMETHODCALLTYPE _Init(IN OUT ITrayWindow *tray)
HRESULT STDMETHODCALLTYPE Initialize(IN OUT ITrayWindow *tray)
{
m_Tray = tray;
m_BandID = (DWORD) -1;
@ -374,21 +348,7 @@ public:
END_COM_MAP()
};
ITaskBand * CreateTaskBand(IN OUT ITrayWindow *Tray)
HRESULT CTaskBand_CreateInstance(IN ITrayWindow *Tray, REFIID riid, void **ppv)
{
HRESULT hr;
CTaskBand * tb = new CComObject<CTaskBand>();
if (!tb)
return NULL;
hr = tb->AddRef();
hr = tb->_Init(Tray);
if (FAILED_UNEXPECTEDLY(hr))
tb->Release();
return tb;
return ShellObjectCreatorInit<CTaskBand>(Tray, riid, ppv);
}

View file

@ -40,7 +40,7 @@ class CTrayBandSite :
CComPtr<IUnknown> m_Inner;
CComPtr<IBandSite> m_BandSite;
CComPtr<ITaskBand> m_TaskBand;
CComPtr<IDeskBand> m_TaskBand;
CComPtr<IWinEventHandler> m_WindowEventHandler;
CComPtr<IContextMenu> m_ContextMenu;
@ -447,38 +447,28 @@ public:
virtual BOOL HasTaskBand()
{
ASSERT(m_TaskBand != NULL);
CComPtr<IPersist> pBand;
CLSID BandCLSID;
DWORD dwBandID;
UINT uBand = 0;
return SUCCEEDED(m_TaskBand->GetRebarBandID(NULL));
}
virtual HRESULT AddTaskBand()
{
#if 0
/* FIXME: This is the code for the simple taskbar */
IObjectWithSite *pOws;
HRESULT hRet;
hRet = TaskBand->QueryInterface(
&IID_IObjectWithSite,
(PVOID*) &pOws);
if (SUCCEEDED(hRet))
/* Enumerate all bands */
while (SUCCEEDED(m_BandSite->EnumBands(uBand, &dwBandID)))
{
hRet = pOws->SetSite(
(IUnknown *)TaskBand);
pOws->Release();
if (SUCCEEDED(m_BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist, &pBand))))
{
if (SUCCEEDED(pBand->GetClassID(&BandCLSID)))
{
if (IsEqualGUID(BandCLSID, CLSID_ITaskBand))
{
return TRUE;
}
}
}
uBand++;
}
return hRet;
#else
if (!HasTaskBand())
{
return m_BandSite->AddBand(m_TaskBand);
}
return S_OK;
#endif
return FALSE;
}
virtual HRESULT Update()
@ -642,139 +632,103 @@ public:
return hRet;
}
HRESULT _Init(IN OUT ITrayWindow *tray, OUT HWND *phWndRebar, OUT HWND *phwndTaskSwitch)
HRESULT _Init(IN ITrayWindow *tray, IN IDeskBand* pTaskBand)
{
CComPtr<IDeskBarClient> pDbc;
CComPtr<IDeskBand> pDb;
CComPtr<IOleWindow> pOw;
HRESULT hRet;
*phWndRebar = NULL;
*phwndTaskSwitch = NULL;
m_Tray = tray;
m_TaskBand = pTaskBand;
/* Create a RebarBandSite provided by the shell */
/* Create the RebarBandSite */
hRet = CoCreateInstance(CLSID_RebarBandSite,
static_cast<IBandSite*>(this),
CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IUnknown, &m_Inner));
if (!SUCCEEDED(hRet))
{
static_cast<IBandSite*>(this),
CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IUnknown, &m_Inner));
if (FAILED_UNEXPECTEDLY(hRet))
return hRet;
}
hRet = m_Inner->QueryInterface(IID_PPV_ARG(IBandSite, &m_BandSite));
if (!SUCCEEDED(hRet))
{
if (FAILED_UNEXPECTEDLY(hRet))
return hRet;
}
hRet = m_Inner->QueryInterface(IID_PPV_ARG(IWinEventHandler, &m_WindowEventHandler));
if (!SUCCEEDED(hRet))
{
if (FAILED_UNEXPECTEDLY(hRet))
return hRet;
}
m_TaskBand = CreateTaskBand(m_Tray);
if (m_TaskBand != NULL)
hRet = m_Inner->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDbc));
if (FAILED_UNEXPECTEDLY(hRet))
return hRet;
/* Crete the rebar in the tray */
hRet = pDbc->SetDeskBarSite(tray);
if (FAILED_UNEXPECTEDLY(hRet))
return hRet;
hRet = pDbc->GetWindow(&m_Rebar);
if (FAILED_UNEXPECTEDLY(hRet))
return hRet;
SetWindowStyle(m_Rebar, RBS_BANDBORDERS, 0);
/* Set the Desk Bar mode to the current one */
DWORD dwMode = 0;
/* FIXME: We need to set the mode (and update) whenever the user docks
the tray window to another monitor edge! */
if (!m_Tray->IsHorizontal())
dwMode = DBIF_VIEWMODE_VERTICAL;
hRet = pDbc->SetModeDBC(dwMode);
/* Load the saved state of the task band site */
/* FIXME: We should delay loading shell extensions, also see DBID_DELAYINIT */
Load();
/* Add the task bar band if it hasn't been added while loading */
if (!HasTaskBand())
{
/* Add the task band to the site */
hRet = m_BandSite->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDbc));
if (SUCCEEDED(hRet))
{
hRet = m_TaskBand->QueryInterface(IID_PPV_ARG(IOleWindow, &pOw));
if (SUCCEEDED(hRet))
{
/* We cause IDeskBarClient to create the rebar control by passing the new
task band to it. The band reports the tray window handle as window handle
so that IDeskBarClient knows the parent window of the Rebar control that
it wants to create. */
hRet = pDbc->SetDeskBarSite(pOw);
if (SUCCEEDED(hRet))
{
/* The Rebar control is now created, we can query the window handle */
hRet = pDbc->GetWindow(&m_Rebar);
if (SUCCEEDED(hRet))
{
/* We need to manually remove the RBS_BANDBORDERS style! */
SetWindowStyle(m_Rebar, RBS_BANDBORDERS, 0);
}
}
}
if (SUCCEEDED(hRet))
{
DWORD dwMode = 0;
/* Set the Desk Bar mode to the current one */
/* FIXME: We need to set the mode (and update) whenever the user docks
the tray window to another monitor edge! */
if (!m_Tray->IsHorizontal())
dwMode = DBIF_VIEWMODE_VERTICAL;
hRet = pDbc->SetModeDBC(dwMode);
}
pDbc->Release();
}
/* Load the saved state of the task band site */
/* FIXME: We should delay loading shell extensions, also see DBID_DELAYINIT */
Load();
/* Add the task bar band if it hasn't been added already */
hRet = AddTaskBand();
if (SUCCEEDED(hRet))
{
hRet = m_TaskBand->QueryInterface(IID_PPV_ARG(IDeskBand, &pDb));
if (SUCCEEDED(hRet))
{
hRet = pDb->GetWindow(phwndTaskSwitch);
if (!SUCCEEDED(hRet))
*phwndTaskSwitch = NULL;
}
}
/* Should we send this after showing it? */
Update();
/* FIXME: When should we send this? Does anyone care anyway? */
FinishInit();
/* Activate the band site */
Show(
TRUE);
hRet = m_BandSite->AddBand(m_TaskBand);
if (FAILED_UNEXPECTEDLY(hRet))
return hRet;
}
*phWndRebar = m_Rebar;
/* Should we send this after showing it? */
Update();
/* FIXME: When should we send this? Does anyone care anyway? */
FinishInit();
/* Activate the band site */
Show(TRUE);
return S_OK;
}
};
/*******************************************************************/
ITrayBandSite*
CreateTrayBandSite(IN OUT ITrayWindow *Tray,
OUT HWND *phWndRebar,
OUT HWND *phWndTaskSwitch)
HRESULT CTrayBandSite_CreateInstance(IN ITrayWindow *tray, IN IDeskBand* pTaskBand, OUT ITrayBandSite** pBandSite)
{
HRESULT hr;
CTrayBandSite * tb = new CTrayBandSite();
if (!tb)
return NULL;
return E_FAIL;
tb->AddRef();
hr = tb->_Init(Tray, phWndRebar, phWndTaskSwitch);
hr = tb->_Init(tray, pTaskBand);
if (FAILED_UNEXPECTEDLY(hr))
{
tb->Release();
return hr;
}
return tb;
*pBandSite = tb;
return S_OK;
}

View file

@ -177,13 +177,15 @@ class CTrayWindow :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public CWindowImpl < CTrayWindow, CWindow, CControlWinTraits >,
public ITrayWindow,
public IShellDesktopTray
public IShellDesktopTray,
public IOleWindow
{
CStartButton m_StartButton;
CComPtr<IMenuBand> m_StartMenuBand;
CComPtr<IMenuPopup> m_StartMenuPopup;
CComPtr<IDeskBand> m_TaskBand;
HTHEME m_Theme;
HFONT m_Font;
@ -2079,6 +2081,8 @@ ChangePos:
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
HRESULT hRet;
((ITrayWindow*)this)->AddRef();
SetWindowTheme(m_hWnd, L"TaskBar", NULL);
@ -2093,8 +2097,26 @@ ChangePos:
HBITMAP hbmBanner = LoadBitmapW(hExplorerInstance, MAKEINTRESOURCEW(IDB_STARTMENU));
m_StartMenuPopup = CreateStartMenu(this, &m_StartMenuBand, hbmBanner, 0);
/* Create the tray band site and its rebar */
m_TrayBandSite = CreateTrayBandSite(this, &m_Rebar, &m_TaskSwitch);
/* Create the task band */
hRet = CTaskBand_CreateInstance(this, IID_PPV_ARG(IDeskBand, &m_TaskBand));
if (FAILED_UNEXPECTEDLY(hRet))
return FALSE;
/* Create the rebar band site. This actually creates the rebar and the tasks toolbar. */
hRet = CTrayBandSite_CreateInstance(this, m_TaskBand, &m_TrayBandSite);
if (FAILED_UNEXPECTEDLY(hRet))
return FALSE;
/* Get the hwnd of the rebar */
hRet = IUnknown_GetWindow(m_TrayBandSite, &m_Rebar);
if (FAILED_UNEXPECTEDLY(hRet))
return FALSE;
/* Get the hwnd of the tasks toolbar */
hRet = IUnknown_GetWindow(m_TaskBand, &m_TaskSwitch);
if (FAILED_UNEXPECTEDLY(hRet))
return FALSE;
SetWindowTheme(m_Rebar, L"TaskBar", NULL);
/* Create the tray notification window */
@ -2890,6 +2912,19 @@ HandleTrayContextMenu:
return S_OK;
}
HRESULT WINAPI GetWindow(HWND* phwnd)
{
if (!phwnd)
return E_INVALIDARG;
*phwnd = m_hWnd;
return S_OK;
}
HRESULT WINAPI ContextSensitiveHelp(BOOL fEnterMode)
{
return E_NOTIMPL;
}
void _Init()
{
m_Position = (DWORD) -1;
@ -2901,6 +2936,7 @@ HandleTrayContextMenu:
BEGIN_COM_MAP(CTrayWindow)
/*COM_INTERFACE_ENTRY_IID(IID_ITrayWindow, ITrayWindow)*/
COM_INTERFACE_ENTRY_IID(IID_IShellDesktopTray, IShellDesktopTray)
COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
END_COM_MAP()
};