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.

539 lines
19 KiB

  1. /*--------------------------------------------------------------------------*
  2. *
  3. * Microsoft Windows
  4. * Copyright (C) Microsoft Corporation, 1999
  5. *
  6. * File: AxHostWindow2.h
  7. *
  8. * Contents: Header file for CAxHostWindow2T. Refer to MSJ, December 1999.
  9. *
  10. * History: 30-Nov-99 VivekJ Created
  11. *
  12. *--------------------------------------------------------------------------*/
  13. #pragma once
  14. #ifndef __AXHOSTWINDOW2_H_
  15. #define __AXHOSTWINDOW2_H_
  16. template <typename TFrameWindow> class CSimpleFrameSite;
  17. //------------------------------------------------------------------------------------------------------------------
  18. //
  19. //
  20. //------------------------------------------------------------------------------------------------------------------
  21. template<typename TFrameWindow>
  22. class ATL_NO_VTABLE CAxHostWindow2T : public CAxHostWindow/*,
  23. public IPersistPropertyBagImpl<CAxHostWindow2T>,
  24. public IPersistStreamInitImpl<CAxHostWindow2T>*/
  25. {
  26. public:
  27. CAxHostWindow2T()
  28. {
  29. m_bUserMode = false;
  30. m_bMessageReflect = false;
  31. m_ContainerPages.cElems = 0;
  32. m_ContainerPages.pElems = 0;
  33. }
  34. ~CAxHostWindow2T()
  35. {
  36. if(m_ContainerPages.cElems >=1)
  37. CoTaskMemFree(m_ContainerPages.pElems);
  38. }
  39. DECLARE_GET_CONTROLLING_UNKNOWN()
  40. DECLARE_PROTECT_FINAL_CONSTRUCT()
  41. typedef CAxHostWindow2T<TFrameWindow> thisClass;
  42. typedef CSimpleFrameSite<TFrameWindow> simpleFrameClass;
  43. BEGIN_COM_MAP(thisClass)
  44. //COM_INTERFACE_ENTRY(IPersistPropertyBag)
  45. //COM_INTERFACE_ENTRY(IPersistStreamInit)
  46. COM_INTERFACE_ENTRY_CACHED_TEAR_OFF(IID_ISimpleFrameSite,simpleFrameClass, m_spUnkSimpleFrameSite.p)
  47. COM_INTERFACE_ENTRY_NOINTERFACE(IOleContainer) //yes!!
  48. COM_INTERFACE_ENTRY_CHAIN(CAxHostWindow)
  49. END_COM_MAP()
  50. public:
  51. BEGIN_PROP_MAP(thisClass)
  52. PROP_ENTRY("AllowWindowlessActivation" , 0x60020000, CLSID_NULL)
  53. PROP_ENTRY("BackColor" , DISPID_AMBIENT_BACKCOLOR, CLSID_NULL)
  54. PROP_ENTRY("ForeColor" , DISPID_AMBIENT_FORECOLOR, CLSID_NULL)
  55. PROP_ENTRY("LocaleID" , DISPID_AMBIENT_LOCALEID, CLSID_NULL)
  56. PROP_ENTRY("UserMode" , DISPID_AMBIENT_USERMODE, CLSID_NULL)
  57. PROP_ENTRY("DisplayAsDefault" , DISPID_AMBIENT_DISPLAYASDEFAULT, CLSID_NULL)
  58. PROP_ENTRY("Font" , DISPID_AMBIENT_FONT, CLSID_NULL)
  59. PROP_ENTRY("MessageReflect" , DISPID_AMBIENT_MESSAGEREFLECT, CLSID_NULL)
  60. PROP_ENTRY("ShowGrabHandles" , DISPID_AMBIENT_SHOWGRABHANDLES, CLSID_NULL)
  61. PROP_ENTRY("ShowHatching" , DISPID_AMBIENT_SHOWHATCHING, CLSID_NULL)
  62. PROP_ENTRY("DocHostFlags" , 0x60020012, CLSID_NULL)
  63. PROP_ENTRY("DocHostDoubleClickFlags" , 0x60020014, CLSID_NULL)
  64. PROP_ENTRY("AllowContextMenu" , 0x60020016, CLSID_NULL)
  65. PROP_ENTRY("AllowShowUI" , 0x60020018, CLSID_NULL)
  66. PROP_ENTRY("OptionKeyPath" , 0x6002001a, CLSID_NULL)
  67. END_PROP_MAP()
  68. public:
  69. STDMETHOD(CreateControlEx)(LPCOLESTR lpszTricsData, HWND hWnd, IStream* pStream, IUnknown** ppUnk, REFIID iidAdvise, IUnknown* punkSink)
  70. {
  71. HRESULT hr = S_FALSE;
  72. ReleaseAll();
  73. if (m_hWnd != NULL)
  74. {
  75. RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);
  76. ReleaseWindow();
  77. }
  78. if (::IsWindow(hWnd))
  79. {
  80. USES_CONVERSION;
  81. SubclassWindow(hWnd);
  82. if (m_clrBackground == NULL)
  83. {
  84. if (IsParentDialog())
  85. m_clrBackground = GetSysColor(COLOR_BTNFACE);
  86. else
  87. m_clrBackground = GetSysColor(COLOR_WINDOW);
  88. }
  89. bool bWasHTML;
  90. hr = CreateNormalizedObjectEx(lpszTricsData, IID_IUnknown, (void**)ppUnk, bWasHTML);
  91. bool bInited = hr == S_FALSE;
  92. if (SUCCEEDED(hr))
  93. hr = ActivateAx(*ppUnk, bInited, pStream);
  94. //Try to hook up any sink the user might have given us.
  95. m_iidSink = iidAdvise;
  96. if(SUCCEEDED(hr) && *ppUnk && punkSink)
  97. AtlAdvise(*ppUnk, punkSink, m_iidSink, &m_dwAdviseSink);
  98. if (SUCCEEDED(hr) && bWasHTML && *ppUnk != NULL)
  99. {
  100. if ((GetStyle() & (WS_VSCROLL | WS_HSCROLL)) == 0)
  101. m_dwDocHostFlags |= DOCHOSTUIFLAG_SCROLL_NO;
  102. else
  103. {
  104. DWORD dwStyle = GetStyle();
  105. SetWindowLong(GWL_STYLE, dwStyle & ~(WS_VSCROLL | WS_HSCROLL));
  106. SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_DRAWFRAME);
  107. }
  108. CComPtr<IUnknown> spUnk(*ppUnk);
  109. // Is it just plain HTML?
  110. USES_CONVERSION;
  111. if ((lpszTricsData[0] == OLECHAR('M') || lpszTricsData[0] == OLECHAR('m')) &&
  112. (lpszTricsData[1] == OLECHAR('S') || lpszTricsData[1] == OLECHAR('s')) &&
  113. (lpszTricsData[2] == OLECHAR('H') || lpszTricsData[2] == OLECHAR('h')) &&
  114. (lpszTricsData[3] == OLECHAR('T') || lpszTricsData[3] == OLECHAR('t')) &&
  115. (lpszTricsData[4] == OLECHAR('M') || lpszTricsData[4] == OLECHAR('m')) &&
  116. (lpszTricsData[5] == OLECHAR('L') || lpszTricsData[5] == OLECHAR('l')) &&
  117. (lpszTricsData[6] == OLECHAR(':')))
  118. {
  119. // Just HTML, eh?
  120. CComPtr<IPersistStreamInit> spPSI;
  121. hr = spUnk->QueryInterface(IID_IPersistStreamInit, (void**)&spPSI);
  122. spPSI->InitNew();
  123. bInited = TRUE;
  124. CComPtr<IHTMLDocument2> spHTMLDoc2;
  125. hr = spUnk->QueryInterface(IID_IHTMLDocument2, (void**)&spHTMLDoc2);
  126. if (SUCCEEDED(hr))
  127. {
  128. CComPtr<IHTMLElement> spHTMLBody;
  129. hr = spHTMLDoc2->get_body(&spHTMLBody);
  130. if (SUCCEEDED(hr))
  131. hr = spHTMLBody->put_innerHTML(CComBSTR(lpszTricsData + 7));
  132. }
  133. }
  134. else
  135. {
  136. CComPtr<IWebBrowser2> spBrowser;
  137. spUnk->QueryInterface(IID_IWebBrowser2, (void**)&spBrowser);
  138. if (spBrowser)
  139. {
  140. CComVariant ve;
  141. CComVariant vurl(lpszTricsData);
  142. #pragma warning(disable: 4310) // cast truncates constant value
  143. spBrowser->put_Visible(VARIANT_TRUE);
  144. #pragma warning(default: 4310) // cast truncates constant value
  145. spBrowser->Navigate2(&vurl, &ve, &ve, &ve, &ve);
  146. }
  147. }
  148. }
  149. if (FAILED(hr) || m_spUnknown == NULL)
  150. {
  151. // We don't have a control or something failed so release
  152. ReleaseAll();
  153. if (m_hWnd != NULL)
  154. {
  155. RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);
  156. if (FAILED(hr))
  157. ReleaseWindow();
  158. }
  159. }
  160. }
  161. return hr;
  162. }
  163. //We support licensing
  164. virtual HRESULT CreateLicensedControl(REFCLSID clsid,REFIID riid, void** ppvObj,bool& bIsItLicensed)
  165. {
  166. CComPtr<IClassFactory2> spCF2;
  167. bIsItLicensed = false;
  168. HRESULT hr = CoGetClassObject(clsid,CLSCTX_SERVER,0,IID_IClassFactory2,(void**)&spCF2);
  169. if(FAILED(hr)) return hr;
  170. bIsItLicensed = true;
  171. LICINFO licInfo;
  172. licInfo.cbLicInfo = sizeof(LICINFO);
  173. hr = spCF2->GetLicInfo(&licInfo);
  174. if(FAILED(hr))
  175. {
  176. ::MessageBox(NULL,_T("License Key for this component not found. You do not have the appropriate license to use this component in the design environment"),_T("Licensing Error"),MB_OK);
  177. return hr;
  178. }
  179. BSTR strKey = 0;
  180. if(licInfo.fRuntimeKeyAvail)
  181. {
  182. hr = spCF2->RequestLicKey(0,&strKey);
  183. }
  184. if(SUCCEEDED(hr) || licInfo.fLicVerified)
  185. {
  186. hr = spCF2->CreateInstanceLic(NULL,NULL,riid,strKey,ppvObj);
  187. if(strKey) { ::SysFreeString(strKey); }
  188. return hr;
  189. }
  190. ::MessageBox(NULL,_T("License Key for this component not found. You do not have the appropriate license to use this component in the design environment"),_T("Licensing Error"),MB_OK);
  191. return hr;
  192. }
  193. virtual HRESULT CreateNormalizedObjectEx(LPCOLESTR lpszTricsData, REFIID riid, void** ppvObj, bool& bWasHTML)
  194. {
  195. ATLASSERT(ppvObj);
  196. CLSID clsid;
  197. HRESULT hr = E_FAIL;
  198. bWasHTML = false;
  199. *ppvObj = NULL;
  200. if (lpszTricsData == NULL || lpszTricsData[0] == 0){ return S_OK; }
  201. // Is it HTML ?
  202. USES_CONVERSION;
  203. if ((lpszTricsData[0] == OLECHAR('M') || lpszTricsData[0] == OLECHAR('m')) &&
  204. (lpszTricsData[1] == OLECHAR('S') || lpszTricsData[1] == OLECHAR('s')) &&
  205. (lpszTricsData[2] == OLECHAR('H') || lpszTricsData[2] == OLECHAR('h')) &&
  206. (lpszTricsData[3] == OLECHAR('T') || lpszTricsData[3] == OLECHAR('t')) &&
  207. (lpszTricsData[4] == OLECHAR('M') || lpszTricsData[4] == OLECHAR('m')) &&
  208. (lpszTricsData[5] == OLECHAR('L') || lpszTricsData[5] == OLECHAR('l')) &&
  209. (lpszTricsData[6] == OLECHAR(':')))
  210. {
  211. // It's HTML, so let's create mshtml
  212. hr = CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_SERVER, riid, ppvObj);
  213. bWasHTML = true;
  214. }
  215. if (FAILED(hr))
  216. {
  217. // Can't be clsid, or progid if length is grater than 255
  218. if (ocslen(lpszTricsData) < 255)
  219. {
  220. if (lpszTricsData[0] == '{') // Is it a CLSID?
  221. hr = CLSIDFromString((LPOLESTR)lpszTricsData, &clsid);
  222. else
  223. hr = CLSIDFromProgID((LPOLESTR)lpszTricsData, &clsid); // How about a ProgID?
  224. if (SUCCEEDED(hr)) // Aha, it was one of those two
  225. {
  226. //check if its a licensed control
  227. //TODO: The usermode and binary persistence needs to act here
  228. bool bLicensed = false;
  229. hr = CreateLicensedControl(clsid,riid,ppvObj,bLicensed);
  230. if(SUCCEEDED(hr) || ( bLicensed && FAILED(hr) ) )
  231. return hr;
  232. //create the control in a normal way - it does not support licensing
  233. hr = CoCreateInstance(clsid, NULL, CLSCTX_SERVER, riid, ppvObj);
  234. }
  235. }
  236. if (FAILED(hr))
  237. {
  238. // Last guess - it must be either a URL so let's create shdocvw
  239. hr = CoCreateInstance(CLSID_WebBrowser, NULL, CLSCTX_SERVER, riid, ppvObj);
  240. bWasHTML = true;
  241. }
  242. }
  243. return hr;
  244. }
  245. public:
  246. virtual void OnFinalMessage(HWND hWnd)
  247. {
  248. FinalRelease();
  249. GetControllingUnknown()->Release();
  250. }
  251. public: //modified methods
  252. STDMETHOD(GetContainer)(IOleContainer** ppContainer)
  253. {
  254. if(!ppContainer) return E_POINTER;
  255. if(m_spOleContainer)
  256. return (*ppContainer = m_spOleContainer)->AddRef(), S_OK;
  257. *ppContainer = 0;
  258. return E_NOINTERFACE;
  259. }
  260. STDMETHOD(GetExtendedControl)(IDispatch** ppDisp)
  261. {
  262. if(!ppDisp) return E_POINTER;
  263. if(m_spExtendedDispatch)
  264. return (*ppDisp = m_spExtendedDispatch)->AddRef(), S_OK;
  265. *ppDisp = 0;
  266. return E_NOTIMPL;
  267. }
  268. STDMETHOD(GetWindowContext)(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo)
  269. {
  270. if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL || lprcClipRect == NULL || !m_spInPlaceFrame || !m_spInPlaceUIWindow || !m_pContainerFrame)
  271. {
  272. return E_POINTER;
  273. }
  274. m_spInPlaceFrame.CopyTo(ppFrame);
  275. m_spInPlaceUIWindow.CopyTo(ppDoc);
  276. GetClientRect(lprcPosRect);
  277. GetClientRect(lprcClipRect);
  278. pFrameInfo = m_pContainerFrame->GetInPlaceFrameInfo();
  279. return S_OK;
  280. }
  281. STDMETHOD(ShowPropertyFrame)()
  282. {
  283. HRESULT hr = E_FAIL;
  284. if(m_ContainerPages.cElems <= 0) return hr;
  285. CComPtr<ISpecifyPropertyPages> spSpecifyPages;
  286. hr = QueryControl(IID_ISpecifyPropertyPages,(void**)&spSpecifyPages);
  287. if(FAILED(hr)) return hr;
  288. CAUUID pages;
  289. hr = spSpecifyPages->GetPages(&pages);
  290. if(FAILED(hr)) return hr;
  291. CComQIPtr<IOleObject> spObj(spSpecifyPages);
  292. CComPtr<IUnknown> spUnk = spSpecifyPages;
  293. if(!spObj || !spUnk) return E_NOINTERFACE;
  294. UINT nOldElems = pages.cElems;
  295. pages.cElems += m_ContainerPages.cElems;
  296. pages.pElems = (GUID *)::CoTaskMemRealloc(pages.pElems, pages.cElems * sizeof(CLSID));
  297. for(UINT n = 0; n < m_ContainerPages.cElems; n++)
  298. {
  299. pages.pElems[nOldElems + n] = m_ContainerPages.pElems[n];
  300. }
  301. LPOLESTR szTitle = NULL;
  302. spObj->GetUserType(USERCLASSTYPE_SHORT, &szTitle);
  303. RECT rcPos;
  304. ::GetClientRect(m_hWnd,&rcPos);
  305. m_pContainerFrame->SetDirty(true);
  306. hr = OleCreatePropertyFrame(m_pContainerFrame->m_hWnd, rcPos.top, rcPos.left, szTitle,
  307. 1, &spUnk.p, pages.cElems, pages.pElems, LOCALE_USER_DEFAULT, 0, 0);
  308. CoTaskMemFree(szTitle);
  309. CoTaskMemFree(pages.pElems);
  310. return hr;
  311. }
  312. void ReleaseAll()
  313. {
  314. if (m_bReleaseAll)
  315. return;
  316. m_bReleaseAll = TRUE;
  317. if (m_spViewObject != NULL)
  318. m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, NULL);
  319. if(m_dwAdviseSink != 0xCDCDCDCD)
  320. {
  321. AtlUnadvise(m_spUnknown, m_iidSink, m_dwAdviseSink);
  322. m_dwAdviseSink = 0xCDCDCDCD;
  323. }
  324. if (m_spOleObject)
  325. {
  326. m_spOleObject->Unadvise(m_dwOleObject);
  327. m_spOleObject->Close(OLECLOSE_NOSAVE);
  328. m_spOleObject->SetClientSite(NULL);
  329. }
  330. if (m_spUnknown != NULL)
  331. {
  332. CComPtr<IObjectWithSite> spSite;
  333. m_spUnknown->QueryInterface(IID_IObjectWithSite, (void**)&spSite);
  334. if (spSite != NULL)
  335. spSite->SetSite(NULL);
  336. }
  337. m_spViewObject.Release();
  338. m_dwViewObjectType = 0;
  339. m_spInPlaceObjectWindowless.Release();
  340. m_spOleObject.Release();
  341. m_spUnknown.Release();
  342. m_bInPlaceActive = FALSE;
  343. m_bWindowless = FALSE;
  344. m_bInPlaceActive = FALSE;
  345. m_bUIActive = FALSE;
  346. m_bCapture = FALSE;
  347. m_bReleaseAll = FALSE;
  348. }
  349. STDMETHOD(AttachControl)(IUnknown* pUnkControl, HWND hWnd)
  350. {
  351. HRESULT hr = S_FALSE;
  352. ReleaseAll();
  353. if (m_hWnd != NULL)
  354. {
  355. RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);
  356. ReleaseWindow();
  357. }
  358. if (::IsWindow(hWnd))
  359. {
  360. SubclassWindow(hWnd);
  361. hr = ActivateAx(pUnkControl, TRUE, NULL);
  362. if (FAILED(hr))
  363. {
  364. ReleaseAll();
  365. if (m_hWnd != NULL)
  366. {
  367. RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);
  368. ReleaseWindow();
  369. }
  370. }
  371. }
  372. return hr;
  373. }
  374. void FinalRelease()
  375. {
  376. CAxHostWindow::FinalRelease();
  377. }
  378. public:
  379. unsigned m_bRequiresSave:1;
  380. CComPtr<IUnknown> m_spUnkSimpleFrameSite;
  381. CComPtr<IOleContainer> m_spOleContainer;
  382. CComPtr<IDispatch> m_spExtendedDispatch;
  383. CAUUID m_ContainerPages;
  384. TFrameWindow *m_pContainerFrame;
  385. };
  386. //--------------------------------------------------------------------------------------------------------------------
  387. //*Very Very* Simple SimpleFrameSite impl
  388. //SimpleFrameSite tear-off atop the Site - very basic message routing
  389. //one Known control that implements it for our test cases is(sad we cant use VB's intrinsic ones) - MS tabbed Dialog(Sheridan's)
  390. //(not to be confused with MS tabstrip control)
  391. //------------------------------------------------------------------------------------------------------------------
  392. template <typename TFrameWindow>
  393. class ATL_NO_VTABLE CSimpleFrameSite: public ISimpleFrameSite,
  394. public CComTearOffObjectBase<CAxHostWindow2T<TFrameWindow> >
  395. {
  396. public:
  397. CSimpleFrameSite(){}
  398. ~CSimpleFrameSite(){}
  399. typedef CSimpleFrameSite<TFrameWindow> thisClass;
  400. BEGIN_COM_MAP(thisClass)
  401. COM_INTERFACE_ENTRY(ISimpleFrameSite)
  402. END_COM_MAP()
  403. DECLARE_PROTECT_FINAL_CONSTRUCT()
  404. public:
  405. //ISimpleFrameSite
  406. STDMETHODIMP PreMessageFilter(/* [in] */ HWND hWnd,/* [in] */ UINT msg,/* [in] */ WPARAM wp,
  407. /* [in] */ LPARAM lp,/* [out] */ LRESULT *plResult,
  408. /* [out] */ DWORD *pdwCookie)
  409. {
  410. if(!plResult || !pdwCookie) { return E_POINTER; }
  411. HWND hWndChild = GetAxWindow(hWnd);
  412. if(hWndChild && ((msg == WM_PAINT)||(msg == WM_KEYDOWN)) )
  413. {
  414. ATLTRACE("\nPreMessageFilter called !!\n");
  415. *plResult = 0;
  416. ::SendMessage(hWndChild,msg,wp,lp);
  417. }
  418. return S_OK;
  419. }
  420. STDMETHODIMP PostMessageFilter(/* [in] */ HWND hWnd,/* [in] */ UINT msg,/* [in] */ WPARAM wp,
  421. /* [in] */ LPARAM lp,/* [out] */ LRESULT *plResult,/* [in] */ DWORD dwCookie)
  422. {
  423. if(!plResult) { return E_POINTER; }
  424. HWND hWndChild = GetAxWindow(hWnd);
  425. if(hWndChild && ((msg == WM_PAINT)||(msg == WM_KEYDOWN)) )
  426. {
  427. ATLTRACE("\nPostMessageFilter called !!\n");
  428. *plResult = 0;
  429. }
  430. return S_OK;
  431. }
  432. protected:
  433. HWND GetAxWindow(HWND& hWnd)
  434. {
  435. HWND hWndChild = GetWindow(hWnd,GW_CHILD);
  436. TCHAR pszClassName[100];
  437. if(hWndChild)
  438. {
  439. for(;;)
  440. {
  441. GetClassName(hWndChild,pszClassName,100);
  442. if(lstrcmp(pszClassName, _T("AtlAxWinEx") ) ==0 )
  443. {
  444. return ::GetWindow(hWndChild,GW_CHILD);
  445. }
  446. else
  447. {
  448. return hWndChild;
  449. }
  450. }
  451. }
  452. return 0;
  453. }
  454. };
  455. #endif
  456. //--------------------------------------------------------------------------------------------------------------------