// // 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; }