384 lines
11 KiB
C++
384 lines
11 KiB
C++
|
//
|
||
|
// This Channel OC code was copied from browseui. Once it is reenabled in
|
||
|
// browseui it can be removed from shdocvw.
|
||
|
//
|
||
|
|
||
|
#include "priv.h"
|
||
|
#include "cobjsafe.h"
|
||
|
|
||
|
|
||
|
STDAPI ChannelOC_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi);
|
||
|
HRESULT IUnknown_SetBandInfoSFB(IUnknown *punkBand, BANDINFOSFB *pbi);
|
||
|
IDeskBand * ChannelBand_Create(LPCITEMIDLIST pidlDefault);
|
||
|
//LPITEMIDLIST Channel_GetFolderPidl();
|
||
|
void Channels_SetBandInfoSFB(IUnknown* punkBand);
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
//
|
||
|
// ChannelOC
|
||
|
//
|
||
|
// This is an OC that wraps the above band for
|
||
|
// inclusion in the Active Desktop.
|
||
|
//
|
||
|
// TODO:
|
||
|
// - listen to ISFBand for resizes and request them
|
||
|
// from our container
|
||
|
//
|
||
|
// Do we need to register as a drop target?
|
||
|
|
||
|
#undef SUPERCLASS
|
||
|
#define SUPERCLASS CShellEmbedding
|
||
|
#undef THISCLASS
|
||
|
#define THISCLASS ChannelOC
|
||
|
|
||
|
class ChannelOC : public SUPERCLASS
|
||
|
, public IServiceProvider
|
||
|
, public IPersistPropertyBag
|
||
|
, public CObjectSafety
|
||
|
{
|
||
|
public:
|
||
|
// *** IUnknown ***
|
||
|
virtual STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj) { return SUPERCLASS::QueryInterface(riid, ppvObj); };
|
||
|
virtual STDMETHODIMP_(ULONG) AddRef(void) { return SUPERCLASS::AddRef(); }
|
||
|
virtual STDMETHODIMP_(ULONG) Release(void) { return SUPERCLASS::Release(); }
|
||
|
|
||
|
// *** CAggregatedUnknown ***
|
||
|
virtual HRESULT v_InternalQueryInterface(REFIID riid, LPVOID * ppvObj);
|
||
|
|
||
|
// *** IServiceProvider ***
|
||
|
virtual STDMETHODIMP QueryService(REFGUID guidService,
|
||
|
REFIID riid, void **ppvObj);
|
||
|
|
||
|
// *** IPersistPropertyBag ***
|
||
|
virtual STDMETHODIMP Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog);
|
||
|
virtual STDMETHODIMP Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties);
|
||
|
virtual STDMETHODIMP InitNew();
|
||
|
virtual STDMETHODIMP GetClassID(CLSID *pClassID) { return SUPERCLASS::GetClassID(pClassID); };
|
||
|
|
||
|
// *** IOleInPlaceObject ***
|
||
|
virtual STDMETHODIMP SetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect);
|
||
|
|
||
|
protected:
|
||
|
ChannelOC(IUnknown* punkOuter, LPCOBJECTINFO poi);
|
||
|
~ChannelOC();
|
||
|
friend HRESULT ChannelOC_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi);
|
||
|
|
||
|
virtual LRESULT v_WndProc(HWND, UINT, WPARAM, LPARAM);
|
||
|
|
||
|
LPITEMIDLIST _GetInitialPidl(void);
|
||
|
virtual void _OnInPlaceActivate(void); // called when we actually go in-place-active
|
||
|
virtual void _OnInPlaceDeactivate(void); // called when we actually deactivate
|
||
|
|
||
|
IDeskBand* _pBand;
|
||
|
IWinEventHandler* _pweh;
|
||
|
COLORREF _crBkgndOC;
|
||
|
COLORREF _crBorder;
|
||
|
|
||
|
// for GetBandInfo, not currently used
|
||
|
DESKBANDINFO _dbi;
|
||
|
};
|
||
|
|
||
|
ChannelOC::ChannelOC(IUnknown* punkOuter, LPCOBJECTINFO poi) :
|
||
|
CShellEmbedding(punkOuter, poi, NULL)
|
||
|
{
|
||
|
TraceMsg(TF_SHDLIFE, "ctor ChannelOC %x", this);
|
||
|
_crBkgndOC = CLR_DEFAULT;
|
||
|
_crBorder = CLR_DEFAULT;
|
||
|
}
|
||
|
|
||
|
|
||
|
ChannelOC::~ChannelOC()
|
||
|
{
|
||
|
TraceMsg(TF_SHDLIFE, "dtor ChannelOC %x", this);
|
||
|
}
|
||
|
|
||
|
HRESULT ChannelOC::v_InternalQueryInterface(REFIID riid, void **ppvObj)
|
||
|
{
|
||
|
static const QITAB qit[] = {
|
||
|
QITABENT(THISCLASS, IServiceProvider),
|
||
|
QITABENT(THISCLASS, IPersistPropertyBag),
|
||
|
QITABENT(THISCLASS, IObjectSafety),
|
||
|
{ 0 },
|
||
|
};
|
||
|
|
||
|
HRESULT hres = QISearch(this, qit, riid, ppvObj);
|
||
|
|
||
|
if (FAILED(hres))
|
||
|
hres = SUPERCLASS::v_InternalQueryInterface(riid, ppvObj);
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT ChannelOC::QueryService(REFGUID guidService, REFIID riid, void **ppvObj)
|
||
|
{
|
||
|
return IUnknown_QueryService(_pcli, guidService, riid, ppvObj);
|
||
|
}
|
||
|
|
||
|
//*** ChannelOC::IPersistPropertyBag::* {
|
||
|
//
|
||
|
HRESULT THISCLASS::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
|
||
|
{
|
||
|
ASSERT(_crBkgndOC == CLR_DEFAULT); // paranoia
|
||
|
_crBkgndOC = PropBag_ReadInt4(pPropBag, L"BGColor", CLR_DEFAULT);
|
||
|
TraceMsg(TF_WARNING, "coc.l: BGColor=%x", _crBkgndOC);
|
||
|
|
||
|
_crBorder = PropBag_ReadInt4(pPropBag, L"BorderColor", CLR_DEFAULT);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT THISCLASS::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
|
||
|
{
|
||
|
ASSERT(0);
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
HRESULT THISCLASS::InitNew()
|
||
|
{
|
||
|
ASSERT(_crBkgndOC == CLR_DEFAULT);
|
||
|
ASSERT(_crBorder == CLR_DEFAULT);
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
// }
|
||
|
|
||
|
LRESULT ChannelOC::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
LRESULT lres = 0;
|
||
|
|
||
|
switch(uMsg)
|
||
|
{
|
||
|
case WM_CONTEXTMENU:
|
||
|
return 1;
|
||
|
|
||
|
case WM_WINDOWPOSCHANGED:
|
||
|
if (_hwndChild)
|
||
|
{
|
||
|
LPWINDOWPOS lpwp = (LPWINDOWPOS)lParam;
|
||
|
|
||
|
if (!(lpwp->flags & SWP_NOSIZE))
|
||
|
{
|
||
|
SetWindowPos(_hwndChild, NULL,
|
||
|
0,0,
|
||
|
lpwp->cx, lpwp->cy,
|
||
|
SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE|
|
||
|
(lpwp->flags&(SWP_NOREDRAW|SWP_NOCOPYBITS)));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
return 0;
|
||
|
|
||
|
case WM_ERASEBKGND:
|
||
|
if ( _crBorder == CLR_DEFAULT )
|
||
|
{
|
||
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
HDC hdc = (HDC) wParam;
|
||
|
RECT rcClient;
|
||
|
GetClientRect( hwnd, &rcClient );
|
||
|
COLORREF crSave = SetBkColor(hdc, _crBorder);
|
||
|
|
||
|
ExtTextOut(hdc,0,0,ETO_OPAQUE,&rcClient,NULL,0,NULL);
|
||
|
SetBkColor(hdc, crSave);
|
||
|
}
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
case WM_NOTIFY:
|
||
|
if (_pweh)
|
||
|
{
|
||
|
LRESULT lres;
|
||
|
if (SUCCEEDED(_pweh->OnWinEvent(hwnd, uMsg, wParam, lParam, &lres)))
|
||
|
return lres;
|
||
|
}
|
||
|
// fall through
|
||
|
|
||
|
default:
|
||
|
return SUPERCLASS::v_WndProc(hwnd, uMsg, wParam, lParam);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
LPITEMIDLIST ChannelOC::_GetInitialPidl()
|
||
|
{
|
||
|
LPITEMIDLIST pidl = NULL;
|
||
|
|
||
|
// Figure out what directory this ChannelOC is looking at.
|
||
|
// If we're looking at a specific channel category, use it,
|
||
|
// otherwise use the top-level Channels folder.
|
||
|
//
|
||
|
if (EVAL(_pcli))
|
||
|
{
|
||
|
IOleContainer *pContainer;
|
||
|
|
||
|
if (SUCCEEDED(_pcli->GetContainer(&pContainer)))
|
||
|
{
|
||
|
IHTMLDocument2 *pDoc;
|
||
|
|
||
|
if (SUCCEEDED(pContainer->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&pDoc)))
|
||
|
{
|
||
|
IHTMLLocation *pLocation;
|
||
|
|
||
|
if (SUCCEEDED(pDoc->get_location(&pLocation)))
|
||
|
{
|
||
|
BSTR bstrURL;
|
||
|
|
||
|
if (SUCCEEDED(pLocation->get_href(&bstrURL)) && bstrURL)
|
||
|
{
|
||
|
TCHAR szPath[MAX_PATH];
|
||
|
DWORD cchT = ARRAYSIZE(szPath);
|
||
|
if (SUCCEEDED(PathCreateFromUrl(bstrURL, szPath, &cchT, 0)))
|
||
|
{
|
||
|
PathRemoveFileSpec(szPath);
|
||
|
|
||
|
// if we're not under the channels folder, then
|
||
|
// ignore this location
|
||
|
//
|
||
|
if (SUCCEEDED(IECreateFromPath(szPath, &pidl)))
|
||
|
{
|
||
|
LPITEMIDLIST pidlChannels = Channel_GetFolderPidl();
|
||
|
|
||
|
if (!pidlChannels || !ILIsParent(pidlChannels, pidl, FALSE))
|
||
|
{
|
||
|
ILFree(pidl);
|
||
|
pidl = NULL;
|
||
|
}
|
||
|
|
||
|
ILFree(pidlChannels);
|
||
|
}
|
||
|
TraceMsg(TF_BAND, "ChannelOC::_OnInPlaceActivate [%s] (%x)", szPath, pidl);
|
||
|
}
|
||
|
|
||
|
SysFreeString(bstrURL);
|
||
|
}
|
||
|
|
||
|
pLocation->Release();
|
||
|
}
|
||
|
|
||
|
pDoc->Release();
|
||
|
}
|
||
|
|
||
|
pContainer->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pidl;
|
||
|
}
|
||
|
|
||
|
void ChannelOC::_OnInPlaceActivate()
|
||
|
{
|
||
|
SUPERCLASS::_OnInPlaceActivate();
|
||
|
|
||
|
// we should never get called twice, but might as well be safe
|
||
|
//
|
||
|
if (EVAL(!_pBand))
|
||
|
{
|
||
|
LPITEMIDLIST pidl = _GetInitialPidl();
|
||
|
|
||
|
// Now create the band and initialize it properly
|
||
|
//
|
||
|
_pBand = ChannelBand_Create(pidl);
|
||
|
if (_pBand)
|
||
|
{
|
||
|
IDropTarget* pdt;
|
||
|
|
||
|
Channels_SetBandInfoSFB(_pBand);
|
||
|
_pBand->QueryInterface(IID_IWinEventHandler, (LPVOID*)&_pweh);
|
||
|
|
||
|
IUnknown_SetSite(_pBand, SAFECAST(this, IOleObject*));
|
||
|
|
||
|
// now that band is sited and init'ed, we can override defaults
|
||
|
if (_crBkgndOC != CLR_DEFAULT) {
|
||
|
BANDINFOSFB bi;
|
||
|
|
||
|
TraceMsg(TF_WARNING, "coc.oipa: BGColor=%x _pBand=%x", _crBkgndOC, _pBand);
|
||
|
bi.dwMask = ISFB_MASK_BKCOLOR;
|
||
|
bi.crBkgnd = _crBkgndOC;
|
||
|
IUnknown_SetBandInfoSFB(_pBand, &bi);
|
||
|
}
|
||
|
|
||
|
_dbi.dwMask = DBIM_MINSIZE|DBIM_MAXSIZE|DBIM_INTEGRAL|DBIM_ACTUAL|DBIM_TITLE|DBIM_MODEFLAGS|DBIM_BKCOLOR;
|
||
|
_pBand->GetBandInfo(0, DBIF_VIEWMODE_VERTICAL, &_dbi);
|
||
|
|
||
|
_pBand->GetWindow(&_hwndChild);
|
||
|
|
||
|
SetWindowPos(_hwndChild, NULL, 0, 0,
|
||
|
_rcPos.right - _rcPos.left,
|
||
|
_rcPos.bottom - _rcPos.top,
|
||
|
SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_SHOWWINDOW);
|
||
|
|
||
|
_pBand->ShowDW(TRUE);
|
||
|
|
||
|
// Register the band as a drop target
|
||
|
if (SUCCEEDED(_pBand->QueryInterface(IID_IDropTarget, (LPVOID*)&pdt)))
|
||
|
{
|
||
|
THR(RegisterDragDrop(_hwnd, pdt));
|
||
|
pdt->Release();
|
||
|
}
|
||
|
|
||
|
TraceMsg(TF_BAND, "ISFBandOC::_OnInPlaceActivate()d to cx=%d cy=%d", _size.cx, _size.cy);
|
||
|
}
|
||
|
|
||
|
ILFree(pidl);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ChannelOC::_OnInPlaceDeactivate()
|
||
|
{
|
||
|
IDeskBand * pBand = _pBand;
|
||
|
|
||
|
// set to NULL to avoid re-entrancy...
|
||
|
_pBand = NULL;
|
||
|
|
||
|
if (pBand)
|
||
|
{
|
||
|
_hwndChild = NULL;
|
||
|
|
||
|
RevokeDragDrop(_hwnd);
|
||
|
|
||
|
pBand->ShowDW(FALSE);
|
||
|
IUnknown_SetSite(pBand, NULL);
|
||
|
pBand->CloseDW(0);
|
||
|
|
||
|
TraceMsg(TF_BAND, "ISFBandOC::_OnInPlaceDeactivate()d");
|
||
|
}
|
||
|
|
||
|
// we need to keep _pweh because we need the notifies during destruction to
|
||
|
// free everything properly
|
||
|
// the _pBand = NULL above is sufficient to keep from reentrancy
|
||
|
ATOMICRELEASE(_pweh);
|
||
|
ATOMICRELEASE(pBand);
|
||
|
|
||
|
SUPERCLASS::_OnInPlaceDeactivate();
|
||
|
}
|
||
|
|
||
|
HRESULT ChannelOC::SetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect)
|
||
|
{
|
||
|
HRESULT hres = SUPERCLASS::SetObjectRects(lprcPosRect, lprcClipRect);
|
||
|
|
||
|
if (_hwndChild)
|
||
|
{
|
||
|
SetWindowPos(_hwndChild, NULL, 0,0,
|
||
|
_rcPos.right - _rcPos.left,
|
||
|
_rcPos.bottom - _rcPos.top, SWP_NOZORDER);
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
STDAPI ChannelOC_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
|
||
|
{
|
||
|
HRESULT hres = E_OUTOFMEMORY;
|
||
|
|
||
|
ChannelOC* pBand = new ChannelOC(punkOuter, poi);
|
||
|
if (pBand)
|
||
|
{
|
||
|
*ppunk = pBand->_GetInner();
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|