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.

610 lines
14 KiB

  1. //////////////////////////////////////////////////////////////////////////
  2. //
  3. // container.cpp
  4. //
  5. // This file contains the complete implementation of an ActiveX
  6. // control container. This purpose of this container is to test
  7. // a single control being hosted.
  8. //
  9. // (C) Copyright 1997 by Microsoft Corporation. All rights reserved.
  10. //
  11. //////////////////////////////////////////////////////////////////////////
  12. #include <windows.h>
  13. #include <commctrl.h>
  14. #include "container.h"
  15. /**
  16. * This method is the constructor for the Container object.
  17. */
  18. Container::Container()
  19. {
  20. m_cRefs = 1;
  21. m_hwnd = NULL;
  22. m_punk = NULL;
  23. memset(&m_rect, 0, sizeof(m_rect));
  24. }
  25. /**
  26. * This method is the destructor for the Container object.
  27. */
  28. Container::~Container()
  29. {
  30. if (m_punk)
  31. {
  32. m_punk->Release();
  33. m_punk=NULL;
  34. }
  35. }
  36. /**
  37. * This method is called when the caller wants an interface pointer.
  38. *
  39. * @param riid The interface being requested.
  40. * @param ppvObject The resultant object pointer.
  41. *
  42. * @return HRESULT S_OK, E_POINTER, E_NOINTERFACE
  43. */
  44. STDMETHODIMP Container::QueryInterface(REFIID riid, PVOID *ppvObject)
  45. {
  46. if (!ppvObject)
  47. return E_POINTER;
  48. if (IsEqualIID(riid, IID_IOleClientSite))
  49. *ppvObject = (IOleClientSite *)this;
  50. else if (IsEqualIID(riid, IID_IOleInPlaceSite))
  51. *ppvObject = (IOleInPlaceSite *)this;
  52. else if (IsEqualIID(riid, IID_IOleInPlaceFrame))
  53. *ppvObject = (IOleInPlaceFrame *)this;
  54. else if (IsEqualIID(riid, IID_IOleInPlaceUIWindow))
  55. *ppvObject = (IOleInPlaceUIWindow *)this;
  56. else if (IsEqualIID(riid, IID_IOleControlSite))
  57. *ppvObject = (IOleControlSite *)this;
  58. else if (IsEqualIID(riid, IID_IOleWindow))
  59. *ppvObject = this;
  60. else if (IsEqualIID(riid, IID_IDispatch))
  61. *ppvObject = (IDispatch *)this;
  62. else if (IsEqualIID(riid, IID_IUnknown))
  63. *ppvObject = this;
  64. else
  65. {
  66. *ppvObject = NULL;
  67. return E_NOINTERFACE;
  68. }
  69. AddRef();
  70. return S_OK;
  71. }
  72. /**
  73. * This method increments the current object count.
  74. *
  75. * @return ULONG The new reference count.
  76. */
  77. ULONG Container::AddRef(void)
  78. {
  79. return ++m_cRefs;
  80. }
  81. /**
  82. * This method decrements the object count and deletes if necessary.
  83. *
  84. * @return ULONG Remaining ref count.
  85. */
  86. ULONG Container::Release(void)
  87. {
  88. if (--m_cRefs)
  89. return m_cRefs;
  90. delete this;
  91. return 0;
  92. }
  93. // ***********************************************************************
  94. // IOleClientSite
  95. // ***********************************************************************
  96. HRESULT Container::SaveObject()
  97. {
  98. return E_NOTIMPL;
  99. }
  100. HRESULT Container::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER * ppMk)
  101. {
  102. return E_NOTIMPL;
  103. }
  104. HRESULT Container::GetContainer(LPOLECONTAINER * ppContainer)
  105. {
  106. return E_NOINTERFACE;
  107. }
  108. HRESULT Container::ShowObject()
  109. {
  110. return S_OK;
  111. }
  112. HRESULT Container::OnShowWindow(BOOL fShow)
  113. {
  114. return S_OK;
  115. }
  116. HRESULT Container::RequestNewObjectLayout()
  117. {
  118. return E_NOTIMPL;
  119. }
  120. // ***********************************************************************
  121. // IOleWindow
  122. // ***********************************************************************
  123. HRESULT Container::GetWindow(HWND * lphwnd)
  124. {
  125. if (!IsWindow(m_hwnd))
  126. return S_FALSE;
  127. *lphwnd = m_hwnd;
  128. return S_OK;
  129. }
  130. HRESULT Container::ContextSensitiveHelp(BOOL fEnterMode)
  131. {
  132. return E_NOTIMPL;
  133. }
  134. // ***********************************************************************
  135. // IOleInPlaceSite
  136. // ***********************************************************************
  137. HRESULT Container::CanInPlaceActivate(void)
  138. {
  139. return S_OK;
  140. }
  141. HRESULT Container::OnInPlaceActivate(void)
  142. {
  143. return S_OK;
  144. }
  145. HRESULT Container::OnUIActivate(void)
  146. {
  147. return S_OK;
  148. }
  149. HRESULT Container::GetWindowContext (IOleInPlaceFrame ** ppFrame, IOleInPlaceUIWindow ** ppIIPUIWin,
  150. LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
  151. {
  152. *ppFrame = (IOleInPlaceFrame *)this;
  153. *ppIIPUIWin = NULL;
  154. RECT rect;
  155. GetClientRect(m_hwnd, &rect);
  156. lprcPosRect->left = 0;
  157. lprcPosRect->top = 0;
  158. lprcPosRect->right = rect.right;
  159. lprcPosRect->bottom = rect.bottom;
  160. CopyRect(lprcClipRect, lprcPosRect);
  161. lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
  162. lpFrameInfo->fMDIApp = FALSE;
  163. lpFrameInfo->hwndFrame = m_hwnd;
  164. lpFrameInfo->haccel = 0;
  165. lpFrameInfo->cAccelEntries = 0;
  166. (*ppFrame)->AddRef();
  167. return S_OK;
  168. }
  169. HRESULT Container::Scroll(SIZE scrollExtent)
  170. {
  171. return E_NOTIMPL;
  172. }
  173. HRESULT Container::OnUIDeactivate(BOOL fUndoable)
  174. {
  175. return E_NOTIMPL;
  176. }
  177. HRESULT Container::OnInPlaceDeactivate(void)
  178. {
  179. return S_OK;
  180. }
  181. HRESULT Container::DiscardUndoState(void)
  182. {
  183. return E_NOTIMPL;
  184. }
  185. HRESULT Container::DeactivateAndUndo(void)
  186. {
  187. return E_NOTIMPL;
  188. }
  189. HRESULT Container::OnPosRectChange(LPCRECT lprcPosRect)
  190. {
  191. return S_OK;
  192. }
  193. // ***********************************************************************
  194. // IOleInPlaceUIWindow
  195. // ***********************************************************************
  196. HRESULT Container::GetBorder(LPRECT lprectBorder)
  197. {
  198. return E_NOTIMPL;
  199. }
  200. HRESULT Container::RequestBorderSpace(LPCBORDERWIDTHS lpborderwidths)
  201. {
  202. return E_NOTIMPL;
  203. }
  204. HRESULT Container::SetBorderSpace(LPCBORDERWIDTHS lpborderwidths)
  205. {
  206. return E_NOTIMPL;
  207. }
  208. HRESULT Container::SetActiveObject(IOleInPlaceActiveObject * pActiveObject, LPCOLESTR lpszObjName)
  209. {
  210. return E_NOTIMPL;
  211. }
  212. // ***********************************************************************
  213. // IOleInPlaceFrame
  214. // ***********************************************************************
  215. HRESULT Container::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  216. {
  217. return E_NOTIMPL;
  218. }
  219. HRESULT Container::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
  220. {
  221. return E_NOTIMPL;
  222. }
  223. HRESULT Container::RemoveMenus(HMENU hmenuShared)
  224. {
  225. return E_NOTIMPL;
  226. }
  227. HRESULT Container::SetStatusText(LPCOLESTR pszStatusText)
  228. {
  229. char status[MAX_PATH]; // ansi version of status text
  230. if (NULL == pszStatusText)
  231. return E_POINTER;
  232. WideCharToMultiByte(CP_ACP, 0, pszStatusText, -1, status, MAX_PATH, NULL, NULL);
  233. if (IsWindow(m_hwndStatus))
  234. SendMessage(m_hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)status);
  235. return (S_OK);
  236. }
  237. HRESULT Container::EnableModeless(BOOL fEnable)
  238. {
  239. return E_NOTIMPL;
  240. }
  241. HRESULT Container::TranslateAccelerator(LPMSG lpmsg, WORD wID)
  242. {
  243. return S_OK;
  244. }
  245. // ***********************************************************************
  246. // IOleControlSite
  247. // ***********************************************************************
  248. HRESULT Container::OnControlInfoChanged()
  249. {
  250. return E_NOTIMPL;
  251. }
  252. HRESULT Container::LockInPlaceActive(BOOL fLock)
  253. {
  254. return E_NOTIMPL;
  255. }
  256. HRESULT Container::GetExtendedControl(IDispatch **ppDisp)
  257. {
  258. if (ppDisp == NULL)
  259. return E_INVALIDARG;
  260. *ppDisp = (IDispatch *)this;
  261. (*ppDisp)->AddRef();
  262. return S_OK;
  263. }
  264. HRESULT Container::TransformCoords(POINTL *pptlHimetric, POINTF *pptfContainer, DWORD dwFlags)
  265. {
  266. return E_NOTIMPL;
  267. }
  268. HRESULT Container::TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers)
  269. {
  270. return S_FALSE;
  271. }
  272. HRESULT Container::OnFocus(BOOL fGotFocus)
  273. {
  274. return E_NOTIMPL;
  275. }
  276. HRESULT Container::ShowPropertyFrame(void)
  277. {
  278. return E_NOTIMPL;
  279. }
  280. // ***********************************************************************
  281. // IDispatch
  282. // ***********************************************************************
  283. HRESULT Container::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
  284. {
  285. *rgdispid = DISPID_UNKNOWN;
  286. return DISP_E_UNKNOWNNAME;
  287. }
  288. HRESULT Container::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  289. {
  290. return E_NOTIMPL;
  291. }
  292. HRESULT Container::GetTypeInfoCount(unsigned int FAR * pctinfo)
  293. {
  294. return E_NOTIMPL;
  295. }
  296. HRESULT Container::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
  297. {
  298. return DISP_E_MEMBERNOTFOUND;
  299. }
  300. // ***********************************************************************
  301. // Public (non-interface) Methods
  302. // ***********************************************************************
  303. /**
  304. * This method will add an ActiveX control to the container. Note, for
  305. * now, this container can only have one control.
  306. *
  307. * @param bstrClsid The CLSID or PROGID of the control.
  308. *
  309. * @return No return value.
  310. */
  311. void Container::add(BSTR bstrClsid)
  312. {
  313. CLSID clsid; // CLSID of the control object
  314. HRESULT hr; // return code
  315. CLSIDFromString(bstrClsid, &clsid);
  316. CoCreateInstance(clsid,
  317. NULL,
  318. CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  319. IID_IUnknown,
  320. (PVOID *)&m_punk);
  321. if (!m_punk)
  322. return;
  323. IOleObject *pioo;
  324. hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
  325. if (FAILED(hr))
  326. return;
  327. pioo->SetClientSite(this);
  328. pioo->Release();
  329. IPersistStreamInit *ppsi;
  330. hr = m_punk->QueryInterface(IID_IPersistStreamInit, (PVOID *)&ppsi);
  331. if (SUCCEEDED(hr))
  332. {
  333. ppsi->InitNew();
  334. ppsi->Release();
  335. }
  336. }
  337. /**
  338. * This method will remove the control from the container.
  339. *
  340. * @return No return value.
  341. */
  342. void Container::remove()
  343. {
  344. if (!m_punk)
  345. return;
  346. HRESULT hr;
  347. IOleObject *pioo;
  348. IOleInPlaceObject *pipo;
  349. hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
  350. if (SUCCEEDED(hr))
  351. {
  352. pioo->Close(OLECLOSE_NOSAVE);
  353. pioo->SetClientSite(NULL);
  354. pioo->Release();
  355. }
  356. hr = m_punk->QueryInterface(IID_IOleInPlaceObject, (PVOID *)&pipo);
  357. if (SUCCEEDED(hr))
  358. {
  359. pipo->UIDeactivate();
  360. pipo->InPlaceDeactivate();
  361. pipo->Release();
  362. }
  363. m_punk->Release();
  364. m_punk = NULL;
  365. }
  366. /**
  367. * This method sets the parent window. This is used by the container
  368. * so the control can parent itself.
  369. *
  370. * @param hwndParent The parent window handle.
  371. *
  372. * @return No return value.
  373. */
  374. void Container::setParent(HWND hwndParent)
  375. {
  376. m_hwnd = hwndParent;
  377. }
  378. /**
  379. * This method will set the location of the control.
  380. *
  381. * @param x The top left.
  382. * @param y The top right.
  383. * @param width The width of the control.
  384. * @param height The height of the control.
  385. */
  386. void Container::setLocation(int x, int y, int width, int height)
  387. {
  388. m_rect.left = x;
  389. m_rect.top = y;
  390. m_rect.right = width;
  391. m_rect.bottom = height;
  392. if (!m_punk)
  393. return;
  394. HRESULT hr;
  395. IOleInPlaceObject *pipo;
  396. hr = m_punk->QueryInterface(IID_IOleInPlaceObject, (PVOID *)&pipo);
  397. if (FAILED(hr))
  398. return;
  399. pipo->SetObjectRects(&m_rect, &m_rect);
  400. pipo->Release();
  401. }
  402. /**
  403. * Sets the visible state of the control.
  404. *
  405. * @param fVisible TRUE=visible, FALSE=hidden
  406. * @return No return value.
  407. */
  408. void Container::setVisible(BOOL fVisible)
  409. {
  410. if (!m_punk)
  411. return;
  412. HRESULT hr;
  413. IOleObject *pioo;
  414. hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
  415. if (FAILED(hr))
  416. return;
  417. if (fVisible)
  418. {
  419. pioo->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, 0, m_hwnd, &m_rect);
  420. pioo->DoVerb(OLEIVERB_SHOW, NULL, this, 0, m_hwnd, &m_rect);
  421. }
  422. else
  423. pioo->DoVerb(OLEIVERB_HIDE, NULL, this, 0, m_hwnd, NULL);
  424. pioo->Release();
  425. }
  426. /**
  427. * This sets the focus to the control (a.k.a. UIActivate)
  428. *
  429. * @param fFocus TRUE=set, FALSE=remove
  430. *
  431. * @return No return value.
  432. */
  433. void Container::setFocus(BOOL fFocus)
  434. {
  435. if (!m_punk)
  436. return;
  437. HRESULT hr;
  438. IOleObject *pioo;
  439. if (fFocus)
  440. {
  441. hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
  442. if (FAILED(hr))
  443. return;
  444. pioo->DoVerb(OLEIVERB_UIACTIVATE, NULL, this, 0, m_hwnd, &m_rect);
  445. pioo->Release();
  446. }
  447. }
  448. /**
  449. * If the container has an HWND for the status window (must be
  450. * common control), then this method is used to tell the container.
  451. *
  452. * @param hwndStatus Window handle of the status bar.
  453. *
  454. * @return No return value.
  455. */
  456. void Container::setStatusWindow(HWND hwndStatus)
  457. {
  458. m_hwndStatus = hwndStatus;
  459. }
  460. /**
  461. * This method gives the control the opportunity to translate and use
  462. * key strokes.
  463. *
  464. * @param msg Key message.
  465. *
  466. * @return No return value.
  467. */
  468. void Container::translateKey(MSG msg)
  469. {
  470. if (!m_punk)
  471. return;
  472. HRESULT hr;
  473. IOleInPlaceActiveObject *pao;
  474. hr = m_punk->QueryInterface(IID_IOleInPlaceActiveObject, (PVOID *)&pao);
  475. if (FAILED(hr))
  476. return;
  477. pao->TranslateAccelerator(&msg);
  478. pao->Release();
  479. }
  480. /**
  481. * Returns the IDispatch pointer of the contained control. Note, the
  482. * caller is responsible for calling IDispatch::Release().
  483. *
  484. * @return Controls dispatch interface.
  485. */
  486. IDispatch * Container::getDispatch()
  487. {
  488. if (!m_punk)
  489. return NULL;
  490. HRESULT hr;
  491. IDispatch *pdisp;
  492. hr = m_punk->QueryInterface(IID_IDispatch, (PVOID *)&pdisp);
  493. return pdisp;
  494. }
  495. /**
  496. * Returns the IUnknown interface pointer for the containd control. Note,
  497. * the caller is responsible for calling IUnknown::Release().
  498. *
  499. * @return Controls unknown interface.
  500. */
  501. IUnknown * Container::getUnknown()
  502. {
  503. if (!m_punk)
  504. return NULL;
  505. m_punk->AddRef();
  506. return m_punk;
  507. }