Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

383 lines
11 KiB

  1. //
  2. // This Channel OC code was copied from browseui. Once it is reenabled in
  3. // browseui it can be removed from shdocvw.
  4. //
  5. #include "priv.h"
  6. #include "cobjsafe.h"
  7. STDAPI ChannelOC_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi);
  8. HRESULT IUnknown_SetBandInfoSFB(IUnknown *punkBand, BANDINFOSFB *pbi);
  9. IDeskBand * ChannelBand_Create(LPCITEMIDLIST pidlDefault);
  10. //LPITEMIDLIST Channel_GetFolderPidl();
  11. void Channels_SetBandInfoSFB(IUnknown* punkBand);
  12. //////////////////////////////////////////////////
  13. //
  14. // ChannelOC
  15. //
  16. // This is an OC that wraps the above band for
  17. // inclusion in the Active Desktop.
  18. //
  19. // TODO:
  20. // - listen to ISFBand for resizes and request them
  21. // from our container
  22. //
  23. // Do we need to register as a drop target?
  24. #undef SUPERCLASS
  25. #define SUPERCLASS CShellEmbedding
  26. #undef THISCLASS
  27. #define THISCLASS ChannelOC
  28. class ChannelOC : public SUPERCLASS
  29. , public IServiceProvider
  30. , public IPersistPropertyBag
  31. , public CObjectSafety
  32. {
  33. public:
  34. // *** IUnknown ***
  35. virtual STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj) { return SUPERCLASS::QueryInterface(riid, ppvObj); };
  36. virtual STDMETHODIMP_(ULONG) AddRef(void) { return SUPERCLASS::AddRef(); }
  37. virtual STDMETHODIMP_(ULONG) Release(void) { return SUPERCLASS::Release(); }
  38. // *** CAggregatedUnknown ***
  39. virtual HRESULT v_InternalQueryInterface(REFIID riid, LPVOID * ppvObj);
  40. // *** IServiceProvider ***
  41. virtual STDMETHODIMP QueryService(REFGUID guidService,
  42. REFIID riid, void **ppvObj);
  43. // *** IPersistPropertyBag ***
  44. virtual STDMETHODIMP Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog);
  45. virtual STDMETHODIMP Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties);
  46. virtual STDMETHODIMP InitNew();
  47. virtual STDMETHODIMP GetClassID(CLSID *pClassID) { return SUPERCLASS::GetClassID(pClassID); };
  48. // *** IOleInPlaceObject ***
  49. virtual STDMETHODIMP SetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect);
  50. protected:
  51. ChannelOC(IUnknown* punkOuter, LPCOBJECTINFO poi);
  52. ~ChannelOC();
  53. friend HRESULT ChannelOC_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi);
  54. virtual LRESULT v_WndProc(HWND, UINT, WPARAM, LPARAM);
  55. LPITEMIDLIST _GetInitialPidl(void);
  56. virtual void _OnInPlaceActivate(void); // called when we actually go in-place-active
  57. virtual void _OnInPlaceDeactivate(void); // called when we actually deactivate
  58. IDeskBand* _pBand;
  59. IWinEventHandler* _pweh;
  60. COLORREF _crBkgndOC;
  61. COLORREF _crBorder;
  62. // for GetBandInfo, not currently used
  63. DESKBANDINFO _dbi;
  64. };
  65. ChannelOC::ChannelOC(IUnknown* punkOuter, LPCOBJECTINFO poi) :
  66. CShellEmbedding(punkOuter, poi, NULL)
  67. {
  68. TraceMsg(TF_SHDLIFE, "ctor ChannelOC %x", this);
  69. _crBkgndOC = CLR_DEFAULT;
  70. _crBorder = CLR_DEFAULT;
  71. }
  72. ChannelOC::~ChannelOC()
  73. {
  74. TraceMsg(TF_SHDLIFE, "dtor ChannelOC %x", this);
  75. }
  76. HRESULT ChannelOC::v_InternalQueryInterface(REFIID riid, void **ppvObj)
  77. {
  78. static const QITAB qit[] = {
  79. QITABENT(THISCLASS, IServiceProvider),
  80. QITABENT(THISCLASS, IPersistPropertyBag),
  81. QITABENT(THISCLASS, IObjectSafety),
  82. { 0 },
  83. };
  84. HRESULT hres = QISearch(this, qit, riid, ppvObj);
  85. if (FAILED(hres))
  86. hres = SUPERCLASS::v_InternalQueryInterface(riid, ppvObj);
  87. return hres;
  88. }
  89. HRESULT ChannelOC::QueryService(REFGUID guidService, REFIID riid, void **ppvObj)
  90. {
  91. return IUnknown_QueryService(_pcli, guidService, riid, ppvObj);
  92. }
  93. //*** ChannelOC::IPersistPropertyBag::* {
  94. //
  95. HRESULT THISCLASS::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
  96. {
  97. ASSERT(_crBkgndOC == CLR_DEFAULT); // paranoia
  98. _crBkgndOC = PropBag_ReadInt4(pPropBag, L"BGColor", CLR_DEFAULT);
  99. TraceMsg(TF_WARNING, "coc.l: BGColor=%x", _crBkgndOC);
  100. _crBorder = PropBag_ReadInt4(pPropBag, L"BorderColor", CLR_DEFAULT);
  101. return S_OK;
  102. }
  103. HRESULT THISCLASS::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
  104. {
  105. ASSERT(0);
  106. return E_NOTIMPL;
  107. }
  108. HRESULT THISCLASS::InitNew()
  109. {
  110. ASSERT(_crBkgndOC == CLR_DEFAULT);
  111. ASSERT(_crBorder == CLR_DEFAULT);
  112. return E_NOTIMPL;
  113. }
  114. // }
  115. LRESULT ChannelOC::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  116. {
  117. LRESULT lres = 0;
  118. switch(uMsg)
  119. {
  120. case WM_CONTEXTMENU:
  121. return 1;
  122. case WM_WINDOWPOSCHANGED:
  123. if (_hwndChild)
  124. {
  125. LPWINDOWPOS lpwp = (LPWINDOWPOS)lParam;
  126. if (!(lpwp->flags & SWP_NOSIZE))
  127. {
  128. SetWindowPos(_hwndChild, NULL,
  129. 0,0,
  130. lpwp->cx, lpwp->cy,
  131. SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE|
  132. (lpwp->flags&(SWP_NOREDRAW|SWP_NOCOPYBITS)));
  133. }
  134. }
  135. return 0;
  136. case WM_ERASEBKGND:
  137. if ( _crBorder == CLR_DEFAULT )
  138. {
  139. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  140. }
  141. else
  142. {
  143. HDC hdc = (HDC) wParam;
  144. RECT rcClient;
  145. GetClientRect( hwnd, &rcClient );
  146. COLORREF crSave = SetBkColor(hdc, _crBorder);
  147. ExtTextOut(hdc,0,0,ETO_OPAQUE,&rcClient,NULL,0,NULL);
  148. SetBkColor(hdc, crSave);
  149. }
  150. case WM_COMMAND:
  151. case WM_NOTIFY:
  152. if (_pweh)
  153. {
  154. LRESULT lres;
  155. if (SUCCEEDED(_pweh->OnWinEvent(hwnd, uMsg, wParam, lParam, &lres)))
  156. return lres;
  157. }
  158. // fall through
  159. default:
  160. return SUPERCLASS::v_WndProc(hwnd, uMsg, wParam, lParam);
  161. }
  162. }
  163. LPITEMIDLIST ChannelOC::_GetInitialPidl()
  164. {
  165. LPITEMIDLIST pidl = NULL;
  166. // Figure out what directory this ChannelOC is looking at.
  167. // If we're looking at a specific channel category, use it,
  168. // otherwise use the top-level Channels folder.
  169. //
  170. if (EVAL(_pcli))
  171. {
  172. IOleContainer *pContainer;
  173. if (SUCCEEDED(_pcli->GetContainer(&pContainer)))
  174. {
  175. IHTMLDocument2 *pDoc;
  176. if (SUCCEEDED(pContainer->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&pDoc)))
  177. {
  178. IHTMLLocation *pLocation;
  179. if (SUCCEEDED(pDoc->get_location(&pLocation)))
  180. {
  181. BSTR bstrURL;
  182. if (SUCCEEDED(pLocation->get_href(&bstrURL)) && bstrURL)
  183. {
  184. TCHAR szPath[MAX_PATH];
  185. DWORD cchT = ARRAYSIZE(szPath);
  186. if (SUCCEEDED(PathCreateFromUrl(bstrURL, szPath, &cchT, 0)))
  187. {
  188. PathRemoveFileSpec(szPath);
  189. // if we're not under the channels folder, then
  190. // ignore this location
  191. //
  192. if (SUCCEEDED(IECreateFromPath(szPath, &pidl)))
  193. {
  194. LPITEMIDLIST pidlChannels = Channel_GetFolderPidl();
  195. if (!pidlChannels || !ILIsParent(pidlChannels, pidl, FALSE))
  196. {
  197. ILFree(pidl);
  198. pidl = NULL;
  199. }
  200. ILFree(pidlChannels);
  201. }
  202. TraceMsg(TF_BAND, "ChannelOC::_OnInPlaceActivate [%s] (%x)", szPath, pidl);
  203. }
  204. SysFreeString(bstrURL);
  205. }
  206. pLocation->Release();
  207. }
  208. pDoc->Release();
  209. }
  210. pContainer->Release();
  211. }
  212. }
  213. return pidl;
  214. }
  215. void ChannelOC::_OnInPlaceActivate()
  216. {
  217. SUPERCLASS::_OnInPlaceActivate();
  218. // we should never get called twice, but might as well be safe
  219. //
  220. if (EVAL(!_pBand))
  221. {
  222. LPITEMIDLIST pidl = _GetInitialPidl();
  223. // Now create the band and initialize it properly
  224. //
  225. _pBand = ChannelBand_Create(pidl);
  226. if (_pBand)
  227. {
  228. IDropTarget* pdt;
  229. Channels_SetBandInfoSFB(_pBand);
  230. _pBand->QueryInterface(IID_IWinEventHandler, (LPVOID*)&_pweh);
  231. IUnknown_SetSite(_pBand, SAFECAST(this, IOleObject*));
  232. // now that band is sited and init'ed, we can override defaults
  233. if (_crBkgndOC != CLR_DEFAULT) {
  234. BANDINFOSFB bi;
  235. TraceMsg(TF_WARNING, "coc.oipa: BGColor=%x _pBand=%x", _crBkgndOC, _pBand);
  236. bi.dwMask = ISFB_MASK_BKCOLOR;
  237. bi.crBkgnd = _crBkgndOC;
  238. IUnknown_SetBandInfoSFB(_pBand, &bi);
  239. }
  240. _dbi.dwMask = DBIM_MINSIZE|DBIM_MAXSIZE|DBIM_INTEGRAL|DBIM_ACTUAL|DBIM_TITLE|DBIM_MODEFLAGS|DBIM_BKCOLOR;
  241. _pBand->GetBandInfo(0, DBIF_VIEWMODE_VERTICAL, &_dbi);
  242. _pBand->GetWindow(&_hwndChild);
  243. SetWindowPos(_hwndChild, NULL, 0, 0,
  244. _rcPos.right - _rcPos.left,
  245. _rcPos.bottom - _rcPos.top,
  246. SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_SHOWWINDOW);
  247. _pBand->ShowDW(TRUE);
  248. // Register the band as a drop target
  249. if (SUCCEEDED(_pBand->QueryInterface(IID_IDropTarget, (LPVOID*)&pdt)))
  250. {
  251. THR(RegisterDragDrop(_hwnd, pdt));
  252. pdt->Release();
  253. }
  254. TraceMsg(TF_BAND, "ISFBandOC::_OnInPlaceActivate()d to cx=%d cy=%d", _size.cx, _size.cy);
  255. }
  256. ILFree(pidl);
  257. }
  258. }
  259. void ChannelOC::_OnInPlaceDeactivate()
  260. {
  261. IDeskBand * pBand = _pBand;
  262. // set to NULL to avoid re-entrancy...
  263. _pBand = NULL;
  264. if (pBand)
  265. {
  266. _hwndChild = NULL;
  267. RevokeDragDrop(_hwnd);
  268. pBand->ShowDW(FALSE);
  269. IUnknown_SetSite(pBand, NULL);
  270. pBand->CloseDW(0);
  271. TraceMsg(TF_BAND, "ISFBandOC::_OnInPlaceDeactivate()d");
  272. }
  273. // we need to keep _pweh because we need the notifies during destruction to
  274. // free everything properly
  275. // the _pBand = NULL above is sufficient to keep from reentrancy
  276. ATOMICRELEASE(_pweh);
  277. ATOMICRELEASE(pBand);
  278. SUPERCLASS::_OnInPlaceDeactivate();
  279. }
  280. HRESULT ChannelOC::SetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect)
  281. {
  282. HRESULT hres = SUPERCLASS::SetObjectRects(lprcPosRect, lprcClipRect);
  283. if (_hwndChild)
  284. {
  285. SetWindowPos(_hwndChild, NULL, 0,0,
  286. _rcPos.right - _rcPos.left,
  287. _rcPos.bottom - _rcPos.top, SWP_NOZORDER);
  288. }
  289. return hres;
  290. }
  291. STDAPI ChannelOC_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  292. {
  293. HRESULT hres = E_OUTOFMEMORY;
  294. ChannelOC* pBand = new ChannelOC(punkOuter, poi);
  295. if (pBand)
  296. {
  297. *ppunk = pBand->_GetInner();
  298. hres = S_OK;
  299. }
  300. return hres;
  301. }