Leaked source code of windows server 2003
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.

935 lines
27 KiB

  1. /*--------------------------------------------------------------------------*
  2. *
  3. * Microsoft Windows
  4. * Copyright (C) Microsoft Corporation, 1992 - 1999
  5. *
  6. * File: ocxview.cpp
  7. *
  8. * Contents: Implementation file for COCXHostView
  9. *
  10. * History: 12-Dec-97 JeffRo Created
  11. *
  12. * This class is required to host OCX controls to fix focus problems.
  13. * The MDI child frame window keeps track of its currently active view.
  14. * When we're hosting OCX controls without this view and the OCX get the
  15. * focus, the MDI child frame thinks the previously active view, usually
  16. * the scope tree, is still the active view. So if the user Alt-Tabs
  17. * away from MMC and back, for instance, the scope tree will get the focus
  18. * even though the OCX had the focus before.
  19. *
  20. * We need this view to represent the OCX, which isn't a view, to the MDI
  21. * child frame.
  22. *
  23. *--------------------------------------------------------------------------*/
  24. #include "stdafx.h"
  25. #include "amc.h"
  26. #include "ocxview.h"
  27. #include "amcview.h"
  28. #ifdef DBG
  29. CTraceTag tagOCXActivation (_T("OCX"), _T("Activation"));
  30. CTraceTag tagOCXTranslateAccel (_T("OCX"), _T("TranslateAccelerator"));
  31. #endif
  32. /*+-------------------------------------------------------------------------*
  33. * class COCXCtrlWrapper
  34. *
  35. *
  36. * PURPOSE: Maintains a pointer to a CMMCAxWindow as well as to the OCX in
  37. * the window.
  38. *
  39. *+-------------------------------------------------------------------------*/
  40. class COCXCtrlWrapper : public CComObjectRoot, public IUnknown
  41. {
  42. typedef COCXCtrlWrapper ThisClass;
  43. public:
  44. COCXCtrlWrapper() : m_pOCXWindow(NULL)
  45. {
  46. }
  47. ~COCXCtrlWrapper()
  48. {
  49. if(m_pOCXWindow && m_pOCXWindow->IsWindow())
  50. m_pOCXWindow->DestroyWindow();
  51. delete m_pOCXWindow;
  52. }
  53. BEGIN_COM_MAP(ThisClass)
  54. COM_INTERFACE_ENTRY(IUnknown)
  55. END_COM_MAP()
  56. DECLARE_NOT_AGGREGATABLE(ThisClass);
  57. SC ScInitialize(CMMCAxWindow *pWindowOCX, IUnknown *pUnkCtrl) // initialize with the window that hosts the control
  58. {
  59. DECLARE_SC(sc, TEXT("COCXCtrlWrapper::ScInitialize"));
  60. sc = ScCheckPointers(pWindowOCX, pUnkCtrl);
  61. if(sc)
  62. return sc;
  63. m_pOCXWindow = pWindowOCX;
  64. m_spUnkCtrl = pUnkCtrl;
  65. return sc;
  66. }
  67. SC ScGetControl(IUnknown **ppUnkCtrl)
  68. {
  69. DECLARE_SC(sc, TEXT("COCXCtrlWrapper::ScGetData"));
  70. sc = ScCheckPointers(ppUnkCtrl);
  71. if(sc)
  72. return sc;
  73. *ppUnkCtrl = m_spUnkCtrl;
  74. if(*ppUnkCtrl)
  75. (*ppUnkCtrl)->AddRef();
  76. return sc;
  77. }
  78. CMMCAxWindow * GetAxWindow() {return m_pOCXWindow;}
  79. private:
  80. CMMCAxWindow * m_pOCXWindow; // handle to the window.
  81. CComPtr<IUnknown> m_spUnkCtrl; // the IUnknown of the control
  82. };
  83. /////////////////////////////////////////////////////////////////////////////
  84. // COCXHostView
  85. IMPLEMENT_DYNCREATE(COCXHostView, CView)
  86. COCXHostView::COCXHostView() : m_pAMCView(NULL)
  87. {
  88. }
  89. COCXHostView::~COCXHostView()
  90. {
  91. m_pAMCView = NULL;
  92. }
  93. /*+-------------------------------------------------------------------------*
  94. *
  95. * COCXHostView::PreCreateWindow
  96. *
  97. * PURPOSE: Adds the WS_CLIPCHILDREN bit. This prevents the host window
  98. * from overwriting the OCX.
  99. *
  100. * PARAMETERS:
  101. * CREATESTRUCT& cs :
  102. *
  103. * RETURNS:
  104. * BOOL
  105. *
  106. *+-------------------------------------------------------------------------*/
  107. BOOL
  108. COCXHostView::PreCreateWindow(CREATESTRUCT& cs)
  109. {
  110. cs.style |= WS_CLIPCHILDREN;
  111. // give base class a chance to do own job
  112. BOOL bOK = (CView::PreCreateWindow(cs));
  113. // register view class
  114. LPCTSTR pszViewClassName = g_szOCXViewWndClassName;
  115. // try to register window class which does not cause the repaint
  116. // on resizing (do it only once)
  117. static bool bClassRegistered = false;
  118. if ( !bClassRegistered )
  119. {
  120. WNDCLASS wc;
  121. if (::GetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wc))
  122. {
  123. // Clear the H and V REDRAW flags
  124. wc.style &= ~(CS_HREDRAW | CS_VREDRAW);
  125. wc.lpszClassName = pszViewClassName;
  126. // Register this new class;
  127. bClassRegistered = AfxRegisterClass(&wc);
  128. }
  129. }
  130. // change window class to one which does not cause the repaint
  131. // on resizing if we successfully registered such
  132. if ( bClassRegistered )
  133. cs.lpszClass = pszViewClassName;
  134. return bOK;
  135. }
  136. /*+-------------------------------------------------------------------------*
  137. *
  138. * COCXHostView::GetAxWindow
  139. *
  140. * PURPOSE: Returns a pointer to the current AxWindow.
  141. *
  142. * RETURNS:
  143. * CMMCAxWindow *
  144. *
  145. *+-------------------------------------------------------------------------*/
  146. CMMCAxWindow *
  147. COCXHostView::GetAxWindow()
  148. {
  149. COCXCtrlWrapper *pOCXCtrlWrapper = dynamic_cast<COCXCtrlWrapper *>(m_spUnkCtrlWrapper.GetInterfacePtr());
  150. if(!pOCXCtrlWrapper)
  151. return (NULL);
  152. return pOCXCtrlWrapper->GetAxWindow();
  153. }
  154. CAMCView *
  155. COCXHostView::GetAMCView()
  156. {
  157. return m_pAMCView;
  158. }
  159. BEGIN_MESSAGE_MAP(COCXHostView, CView)
  160. //{{AFX_MSG_MAP(COCXHostView)
  161. ON_WM_SIZE()
  162. ON_WM_SETFOCUS()
  163. ON_WM_MOUSEACTIVATE()
  164. ON_WM_SETTINGCHANGE()
  165. ON_WM_CREATE()
  166. ON_WM_DESTROY()
  167. //}}AFX_MSG_MAP
  168. END_MESSAGE_MAP()
  169. /////////////////////////////////////////////////////////////////////////////
  170. // COCXHostView drawing
  171. void COCXHostView::OnDraw(CDC* pDC)
  172. {
  173. // this view should always be totally obscured by the OCX it is hosting
  174. }
  175. /////////////////////////////////////////////////////////////////////////////
  176. // COCXHostView diagnostics
  177. #ifdef _DEBUG
  178. void COCXHostView::AssertValid() const
  179. {
  180. CView::AssertValid();
  181. }
  182. void COCXHostView::Dump(CDumpContext& dc) const
  183. {
  184. CView::Dump(dc);
  185. }
  186. #endif //_DEBUG
  187. /////////////////////////////////////////////////////////////////////////////
  188. // COCXHostView message handlers
  189. void COCXHostView::OnSize(UINT nType, int cx, int cy)
  190. {
  191. ASSERT_VALID (this);
  192. CView::OnSize(nType, cx, cy);
  193. if (nType != SIZE_MINIMIZED)
  194. {
  195. if(GetAxWindow() != NULL)
  196. GetAxWindow()->MoveWindow (0, 0, cx, cy, FALSE /*bRepaint*/);
  197. }
  198. }
  199. void COCXHostView::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
  200. {
  201. SetAmbientFont (NULL);
  202. CView::OnSettingChange(uFlags, lpszSection);
  203. if(GetAxWindow() != NULL)
  204. GetAxWindow()->SendMessage (WM_SETTINGCHANGE, uFlags, (LPARAM) lpszSection);
  205. }
  206. void COCXHostView::OnSetFocus(CWnd* pOldWnd)
  207. {
  208. DECLARE_SC(sc, TEXT("COCXHostView::OnSetFocus"));
  209. ASSERT_VALID (this);
  210. // delegate the focus to the control we're hosting, if we have one
  211. if(GetAxWindow() != NULL)
  212. GetAxWindow()->SetFocus();
  213. // check if someone cared to take the focus.
  214. // default handling else.
  215. if (this == GetFocus())
  216. {
  217. CView::OnSetFocus (pOldWnd);
  218. }
  219. }
  220. int COCXHostView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
  221. {
  222. /*---------------------------------------------------------*/
  223. /* this code came from CView::OnMouseActivate; we do it */
  224. /* here to bypass sending WM_MOUSEACTIVATE on the the */
  225. /* parent window, avoiding focus churn in the parent frame */
  226. /*---------------------------------------------------------*/
  227. CFrameWnd* pParentFrame = GetParentFrame();
  228. if (pParentFrame != NULL)
  229. {
  230. // eat it if this will cause activation
  231. ASSERT(pParentFrame == pDesktopWnd || pDesktopWnd->IsChild(pParentFrame));
  232. // either re-activate the current view, or set this view to be active
  233. CView* pView = pParentFrame->GetActiveView();
  234. HWND hWndFocus = ::GetFocus();
  235. if (pView == this &&
  236. m_hWnd != hWndFocus && !::IsChild(m_hWnd, hWndFocus))
  237. {
  238. // re-activate this view
  239. OnActivateView(TRUE, this, this);
  240. }
  241. else
  242. {
  243. // activate this view
  244. pParentFrame->SetActiveView(this);
  245. }
  246. }
  247. return (MA_ACTIVATE);
  248. }
  249. BOOL COCXHostView::OnCmdMsg( UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo )
  250. {
  251. // Do normal command routing
  252. if (CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  253. return TRUE;
  254. // if view didn't handle it, give parent view a chance
  255. CWnd* pParentView = GetParent ();
  256. if ((pParentView != NULL) &&
  257. pParentView->IsKindOf (RUNTIME_CLASS (CAMCView)) &&
  258. pParentView->OnCmdMsg (nID, nCode, pExtra, pHandlerInfo))
  259. return (TRUE);
  260. // not handled
  261. return FALSE;
  262. }
  263. void COCXHostView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
  264. {
  265. DECLARE_SC(sc, TEXT("COCXHostView::OnActivateView"));
  266. CView::OnActivateView(bActivate,pActivateView,pDeactiveView);
  267. // If pActivateView and pDeactiveView are same then this app has lost
  268. // or gained focus without changing the active view within the app.
  269. // So do nothing.
  270. if (pActivateView == pDeactiveView)
  271. return;
  272. if (bActivate)
  273. {
  274. sc = ScFireEvent(COCXHostActivationObserver::ScOnOCXHostActivated);
  275. if (sc)
  276. sc.TraceAndClear();
  277. }
  278. else
  279. /*
  280. * If this view's no longer active, then the in-place object should
  281. * no longer be UI active. This is important for the WebBrowser control
  282. * because if you move from one "Link to Web Address" node to another, or
  283. * from one taskpad to another, it won't allow tabbing to links on the
  284. * new hosted page if it's not deactivated and reactivated in the
  285. * appropriate sequence.
  286. */
  287. {
  288. IOleInPlaceObjectPtr spOleIPObj = GetIUnknown();
  289. /*
  290. * app hack for SQL snapin. Do not UIDeactivate the DaVinci control.
  291. * See bugs 175586, 175756, 193673 & 258109.
  292. */
  293. CAMCView *pAMCView = GetAMCView();
  294. sc = ScCheckPointers(pAMCView, E_UNEXPECTED);
  295. if (sc)
  296. return;
  297. SViewData *pViewData = pAMCView->GetViewData();
  298. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  299. if (sc)
  300. return;
  301. // If DaVinci control do not UIDeactivate.
  302. LPCOLESTR lpszOCXClsid = pViewData->GetOCX();
  303. if ( (_wcsicmp(lpszOCXClsid, L"{464EE255-FDC7-11D2-9743-00105A994F8D}") == 0) ||
  304. (_wcsicmp(lpszOCXClsid, L"{97240642-F896-11D0-B255-006097C68E81}") == 0) )
  305. return;
  306. /*
  307. * app hack for SQL snapin ends here.
  308. */
  309. if (spOleIPObj != NULL)
  310. {
  311. Trace (tagOCXActivation, _T("Deactivating in-place object"));
  312. spOleIPObj->UIDeactivate();
  313. }
  314. else
  315. Trace (tagOCXActivation, _T("No in-place object to deactivate"));
  316. }
  317. }
  318. int COCXHostView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  319. {
  320. if (CView::OnCreate(lpCreateStruct) == -1)
  321. return -1;
  322. // initialize the AxWin class just once.
  323. static bool bIsAxWinInitialized = false;
  324. if(!bIsAxWinInitialized)
  325. {
  326. AtlAxWinInit();
  327. bIsAxWinInitialized = true;
  328. }
  329. // get a pointer to the AMCView.
  330. m_pAMCView = dynamic_cast<CAMCView*>(GetParent());
  331. return 0;
  332. }
  333. LPUNKNOWN COCXHostView::GetIUnknown(void)
  334. {
  335. DECLARE_SC(sc, TEXT("COCXHostView::GetIUnknown"));
  336. COCXCtrlWrapper *pOCXCtrlWrapper = dynamic_cast<COCXCtrlWrapper *>((IUnknown *)m_spUnkCtrlWrapper);
  337. if(!pOCXCtrlWrapper)
  338. {
  339. sc = E_UNEXPECTED;
  340. return NULL;
  341. }
  342. IUnknownPtr spUnkCtrl;
  343. sc = pOCXCtrlWrapper->ScGetControl(&spUnkCtrl);
  344. if(sc)
  345. return NULL;
  346. return (LPUNKNOWN)spUnkCtrl;
  347. }
  348. /*+-------------------------------------------------------------------------*
  349. *
  350. * COCXHostView::ScSetControl
  351. *
  352. * PURPOSE: Hosts the specified control in the OCX view. Delegates to one of
  353. * the two other overloaded versions of this function.
  354. *
  355. * PARAMETERS:
  356. * HNODE hNode : The node that owns the view.
  357. * CResultViewType& rvt: The result view information
  358. * INodeCallback * pNodeCallback :
  359. *
  360. * RETURNS:
  361. * SC
  362. *
  363. *+-------------------------------------------------------------------------*/
  364. SC
  365. COCXHostView::ScSetControl(HNODE hNode, CResultViewType& rvt, INodeCallback *pNodeCallback)
  366. {
  367. DECLARE_SC(sc, TEXT("COCXHostView::ScSetControl"));
  368. USES_CONVERSION;
  369. // make sure that we're trying to set up the right type of view.
  370. if(rvt.GetType() != MMC_VIEW_TYPE_OCX)
  371. return E_UNEXPECTED;
  372. // either BOTH rvt.IsPersistableViewDescriptionValid() and rvt.GetOCXUnknown() should be valid (the GetResultViewType2 case)
  373. // or BOTH should be invalid and just GetOCX() should be valid.
  374. if(rvt.IsPersistableViewDescriptionValid() && (rvt.GetOCXUnknown() != NULL) )
  375. {
  376. // the GetResultViewType2 case
  377. sc = ScSetControl1(hNode, rvt.GetOCXUnknown(), rvt.GetOCXOptions(), pNodeCallback);
  378. if(sc)
  379. return sc;
  380. }
  381. else if(rvt.GetOCX() != NULL)
  382. {
  383. sc = ScSetControl2(hNode, rvt.GetOCX(), rvt.GetOCXOptions(), pNodeCallback);
  384. if(sc)
  385. return sc;
  386. }
  387. else
  388. {
  389. // should never happen.
  390. return (sc = E_UNEXPECTED);
  391. }
  392. // must have a legal Ax Window at this point.
  393. sc = ScCheckPointers(GetAxWindow());
  394. if(sc)
  395. return sc;
  396. // the OCX should fill the entirety of the OCX host view
  397. CRect rectHost;
  398. GetClientRect (rectHost);
  399. GetAxWindow()->SetWindowPos(HWND_TOP, rectHost.left, rectHost.top, rectHost.Width(), rectHost.Height(), SWP_NOACTIVATE | SWP_SHOWWINDOW);
  400. return sc;
  401. }
  402. /*+-------------------------------------------------------------------------*
  403. *
  404. * COCXHostView::ScSetControl1
  405. *
  406. * PURPOSE: Hosts the control specified by pUnkCtrl in the OCX view. Takes
  407. * care of caching the control
  408. *
  409. * PARAMETERS:
  410. * HNODE hNode :
  411. * LPUNKNOWN pUnkCtrl :
  412. * DWORD dwOCXOptions :
  413. * INodeCallback * pNodeCallback :
  414. *
  415. * RETURNS:
  416. * SC
  417. *
  418. *+-------------------------------------------------------------------------*/
  419. SC
  420. COCXHostView::ScSetControl1(HNODE hNode, LPUNKNOWN pUnkCtrl, DWORD dwOCXOptions, INodeCallback *pNodeCallback)
  421. {
  422. DECLARE_SC(sc, TEXT("COCXHostView::ScSetControl1"));
  423. // validate parameters.
  424. sc = ScCheckPointers((void *)hNode, pUnkCtrl, pNodeCallback);
  425. if(sc)
  426. return sc;
  427. CComPtr<IUnknown> spUnkCtrl;
  428. // 1. Hide existing window, if any.
  429. sc = ScHideWindow();
  430. if(sc)
  431. return sc;
  432. // 2. Get a cached window if one exists - NOTE that in this overload we do not look at RVTI_OCX_OPTIONS_CACHE_OCX at this point.
  433. sc = pNodeCallback->GetControl(hNode, pUnkCtrl, &m_spUnkCtrlWrapper); // the overloaded form of GetControl
  434. if (sc)
  435. return sc;
  436. // 3. if no cached window, create one.
  437. if(m_spUnkCtrlWrapper == NULL) /*no cached window, create one*/
  438. {
  439. CMMCAxWindow * pWndAx = NULL;
  440. sc = ScCreateAxWindow(pWndAx);
  441. if(sc)
  442. return sc;
  443. CComPtr<IUnknown> spUnkContainer;
  444. // attach the container to the AxWindow
  445. sc = pWndAx->AttachControl(pUnkCtrl, &spUnkContainer);
  446. if(sc)
  447. return sc;
  448. // create a wrapper for the control
  449. CComObject<COCXCtrlWrapper> *pOCXCtrlWrapper = NULL;
  450. sc = CComObject<COCXCtrlWrapper>::CreateInstance(&pOCXCtrlWrapper);
  451. if(sc)
  452. return sc;
  453. spUnkCtrl = pUnkCtrl;
  454. // initialize the wrapper.
  455. // The pointer to the control and the CMMCAxWindow is now owned by the wrapper.
  456. sc = pOCXCtrlWrapper->ScInitialize(pWndAx, spUnkCtrl);
  457. if(sc)
  458. return sc;
  459. m_spUnkCtrlWrapper = pOCXCtrlWrapper; // does the addref.
  460. // cache only if the snapin asked us to. NOTE that this logic is different from the other version of SetControl
  461. if(dwOCXOptions & RVTI_OCX_OPTIONS_CACHE_OCX)
  462. {
  463. // This is cached by the static node and used for all nodes of the snapin.
  464. sc = pNodeCallback->SetControl(hNode, pUnkCtrl, m_spUnkCtrlWrapper); // this call passes the wrapper
  465. if(sc)
  466. return sc;
  467. }
  468. // Do not send MMCN_INITOCX, the snapin created this control it should have initialized it.
  469. }
  470. else
  471. {
  472. // The next call sets m_spUnkCtrlWrapper, which is used to get a pointer to the Ax window.
  473. COCXCtrlWrapper *pOCXCtrlWrapper = dynamic_cast<COCXCtrlWrapper *>((IUnknown *)m_spUnkCtrlWrapper);
  474. if(!pOCXCtrlWrapper)
  475. return (sc = E_UNEXPECTED); // this should never happen.
  476. sc = pOCXCtrlWrapper->ScGetControl(&spUnkCtrl);
  477. if(sc)
  478. return sc;
  479. sc = ScCheckPointers(GetAxWindow(), (LPUNKNOWN)spUnkCtrl);
  480. if(sc)
  481. return sc;
  482. // un-hide the window.
  483. GetAxWindow()->ShowWindow(SW_SHOWNORMAL);
  484. }
  485. return sc;
  486. }
  487. /*+-------------------------------------------------------------------------*
  488. *
  489. * COCXHostView::ScSetControl2
  490. *
  491. * PURPOSE: Hosts the specified control in the OCX view. This is the
  492. * OCX returned by GetResultViewType. Also takes care of
  493. * caching the control if needed and sending the MMCN_INITOCX
  494. * notification to snap-ins. The caching is done by hiding the
  495. * OCX window and passing nodemgr a COM object that holds a pointer
  496. * to the window as well as the control. The nodemgr side determines
  497. * whether or not to cache the control. If the control is not
  498. * cached, nodemgr merely releases the object passed to it.
  499. *
  500. * PARAMETERS:
  501. * HNODE hNode :
  502. * LPCWSTR szOCXClsid :
  503. * DWORD dwOCXOptions :
  504. * INodeCallback * pNodeCallback :
  505. *
  506. * RETURNS:
  507. * SC
  508. *
  509. *+-------------------------------------------------------------------------*/
  510. SC
  511. COCXHostView::ScSetControl2(HNODE hNode, LPCWSTR szOCXClsid, DWORD dwOCXOptions, INodeCallback *pNodeCallback)
  512. {
  513. DECLARE_SC(sc, TEXT("COCXHostView::ScSetControl2"));
  514. // validate parameters.
  515. sc = ScCheckPointers((void *)hNode, szOCXClsid, pNodeCallback);
  516. if(sc)
  517. return sc;
  518. // create the OCX if needed
  519. CLSID clsid;
  520. sc = CLSIDFromString (const_cast<LPWSTR>(szOCXClsid), &clsid);
  521. if(sc)
  522. return sc;
  523. CComPtr<IUnknown> spUnkCtrl;
  524. sc = ScHideWindow();
  525. if(sc)
  526. return sc;
  527. // check whether there is a cached control for this node.
  528. if (dwOCXOptions & RVTI_OCX_OPTIONS_CACHE_OCX)
  529. {
  530. sc = pNodeCallback->GetControl(hNode, clsid, &m_spUnkCtrlWrapper);
  531. if (sc)
  532. return sc;
  533. }
  534. // nope, create a control and set this control for the node.
  535. if (m_spUnkCtrlWrapper == NULL)
  536. {
  537. CMMCAxWindow * pWndAx = NULL;
  538. sc = ScCreateAxWindow(pWndAx);
  539. if(sc)
  540. return sc;
  541. sc = pWndAx->CreateControlEx(szOCXClsid, NULL /*pStream*/,
  542. NULL /*ppUnkContainer*/, &spUnkCtrl);
  543. if(sc)
  544. return sc;
  545. // spUnkCtrl should be valid at this point.
  546. sc = ScCheckPointers(spUnkCtrl);
  547. if(sc)
  548. return sc;
  549. CComObject<COCXCtrlWrapper> *pOCXCtrlWrapper = NULL;
  550. sc = CComObject<COCXCtrlWrapper>::CreateInstance(&pOCXCtrlWrapper);
  551. if(sc)
  552. return sc;
  553. sc = ScCheckPointers(pOCXCtrlWrapper);
  554. if(sc)
  555. return sc;
  556. // initialize the wrapper.
  557. // The pointer to the control and the CMMCAxWindow is now owned by the wrapper.
  558. sc = pOCXCtrlWrapper->ScInitialize(pWndAx, spUnkCtrl);
  559. if(sc)
  560. return sc;
  561. m_spUnkCtrlWrapper = pOCXCtrlWrapper; // does the addref.
  562. // This is cached by the static node and used for all nodes of the snapin.
  563. if (dwOCXOptions & RVTI_OCX_OPTIONS_CACHE_OCX)
  564. {
  565. sc = pNodeCallback->SetControl(hNode, clsid, m_spUnkCtrlWrapper); // this call passes the wrapper
  566. if(sc)
  567. return sc;
  568. }
  569. // send the MMCN_INITOCX notification.
  570. sc = pNodeCallback->InitOCX(hNode, spUnkCtrl); // this passes the actual IUnknown of the control.
  571. if(sc)
  572. return sc;
  573. }
  574. else
  575. {
  576. // The next call sets m_spUnkCtrlWrapper, which is used to get a pointer to the Ax window.
  577. COCXCtrlWrapper *pOCXCtrlWrapper = dynamic_cast<COCXCtrlWrapper *>((IUnknown *)m_spUnkCtrlWrapper);
  578. if(!pOCXCtrlWrapper)
  579. return (sc = E_UNEXPECTED); // this should never happen.
  580. sc = pOCXCtrlWrapper->ScGetControl(&spUnkCtrl);
  581. if(sc)
  582. return sc;
  583. sc = ScCheckPointers(GetAxWindow(), (LPUNKNOWN)spUnkCtrl);
  584. if(sc)
  585. return sc;
  586. // un-hide the window.
  587. GetAxWindow()->ShowWindow(SW_SHOWNORMAL);
  588. }
  589. return sc;
  590. }
  591. /*+-------------------------------------------------------------------------*
  592. *
  593. * COCXHostView::ScHideWindow
  594. *
  595. * PURPOSE: Hides the existing window, if any.
  596. *
  597. * RETURNS:
  598. * SC
  599. *
  600. *+-------------------------------------------------------------------------*/
  601. SC
  602. COCXHostView::ScHideWindow()
  603. {
  604. DECLARE_SC(sc, TEXT("COCXCtrlWrapper::ScHideWindow"));
  605. // if there is an existing window, hide it.
  606. if(GetAxWindow())
  607. {
  608. GetAxWindow()->ShowWindow(SW_HIDE);
  609. m_spUnkCtrlWrapper.Release(); // this deletes the unneeded window if the reference count is zero.
  610. }
  611. return sc;
  612. }
  613. /*+-------------------------------------------------------------------------*
  614. *
  615. * COCXHostView::ScCreateAxWindow
  616. *
  617. * PURPOSE: Creates a new Ax window
  618. *
  619. * PARAMETERS:
  620. * PMMCAXWINDOW pWndAx :
  621. *
  622. * RETURNS:
  623. * SC
  624. *
  625. *+-------------------------------------------------------------------------*/
  626. SC
  627. COCXHostView::ScCreateAxWindow(PMMCAXWINDOW &pWndAx)
  628. {
  629. DECLARE_SC(sc, TEXT("COCXHostView::ScCreateAxWindow"));
  630. // create a new window
  631. pWndAx = new CMMCAxWindow;
  632. if(!pWndAx)
  633. return (sc = E_OUTOFMEMORY);
  634. // create the OCX host window
  635. // BUG: 418921 always create the host window with (0,0,0,0) which is what used first time
  636. // as client rect is not created.
  637. // This fixes resize problem for some of the OCX (HP ManageX snapin).
  638. HWND hwndAx = pWndAx->Create(m_hWnd, (RECT&)g_rectEmpty, _T(""), (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS) );
  639. if (hwndAx == NULL)
  640. {
  641. sc.FromLastError();
  642. return (sc);
  643. }
  644. /*
  645. * Bug 451981: By default, the ATL OCX host window supports hosting
  646. * windowless controls. This differs from the MMC 1.2 implementation
  647. * of the OCX host window (which used MFC), which did not. Some controls
  648. * (e.g. Disk Defragmenter OCX) claim to support windowless instantiation
  649. * but do not.
  650. *
  651. * For compatibility, we must only instantiate result pane OCX's as
  652. * windowed controls.
  653. */
  654. CComPtr<IAxWinAmbientDispatch> spHostDispatch;
  655. sc = pWndAx->QueryHost(IID_IAxWinAmbientDispatch, (void**)&spHostDispatch);
  656. if (sc)
  657. sc.Clear(); // ignore this failure
  658. else
  659. {
  660. spHostDispatch->put_AllowWindowlessActivation (VARIANT_FALSE); // disallow windowless activation
  661. SetAmbientFont (spHostDispatch);
  662. }
  663. return sc;
  664. }
  665. void COCXHostView::OnDestroy()
  666. {
  667. CView::OnDestroy();
  668. if(GetAxWindow())
  669. GetAxWindow()->DestroyWindow();
  670. }
  671. /*+-------------------------------------------------------------------------*
  672. * COCXHostView::SetAmbientFont
  673. *
  674. * This function sets the font that any OCX that uses the DISPID_AMBIENT_FONT
  675. * ambient property will inherit.
  676. *--------------------------------------------------------------------------*/
  677. void COCXHostView::SetAmbientFont (IAxWinAmbientDispatch* pHostDispatch)
  678. {
  679. DECLARE_SC (sc, _T("COCXHostView::SetAmbientFont"));
  680. CComPtr<IAxWinAmbientDispatch> spHostDispatch;
  681. /*
  682. * no host dispatch interface supplied? get it from the AxWindow
  683. */
  684. if (pHostDispatch == NULL)
  685. {
  686. CMMCAxWindow* pWndAx = GetAxWindow();
  687. if (pWndAx == NULL)
  688. return;
  689. sc = pWndAx->QueryHost(IID_IAxWinAmbientDispatch, (void**)&spHostDispatch);
  690. if (sc)
  691. return;
  692. pHostDispatch = spHostDispatch;
  693. sc = ScCheckPointers (pHostDispatch, E_UNEXPECTED);
  694. if (sc)
  695. return;
  696. }
  697. /*
  698. * get the icon title font
  699. */
  700. LOGFONT lf;
  701. SystemParametersInfo (SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, false);
  702. /*
  703. * get the desktop resolution
  704. */
  705. CWindowDC dcDesktop (CWnd::GetDesktopWindow());
  706. int ppi = dcDesktop.GetDeviceCaps (LOGPIXELSY);
  707. long lfHeight = (lf.lfHeight >= 0) ? lf.lfHeight : -lf.lfHeight;
  708. /*
  709. * create an IFontDisp interface around the icon title font
  710. */
  711. USES_CONVERSION;
  712. FONTDESC fd;
  713. fd.cbSizeofstruct = sizeof (fd);
  714. fd.lpstrName = T2OLE (lf.lfFaceName);
  715. fd.sWeight = (short) lf.lfWeight;
  716. fd.sCharset = lf.lfCharSet;
  717. fd.fItalic = lf.lfItalic;
  718. fd.fUnderline = lf.lfUnderline;
  719. fd.fStrikethrough = lf.lfStrikeOut;
  720. fd.cySize.Lo = lfHeight * 720000 / ppi;
  721. fd.cySize.Hi = 0;
  722. CComPtr<IFontDisp> spFontDisp;
  723. sc = OleCreateFontIndirect (&fd, IID_IFontDisp, (void**) &spFontDisp);
  724. if (sc)
  725. return;
  726. /*
  727. * set the Font property on the AxHostWindow
  728. */
  729. pHostDispatch->put_Font (spFontDisp);
  730. }
  731. /*+-------------------------------------------------------------------------*
  732. *
  733. * COCXHostView::PreTranslateMessage
  734. *
  735. * PURPOSE: Sends accelerator messages to the OCX.
  736. *
  737. * PARAMETERS:
  738. * MSG* pMsg :
  739. *
  740. * RETURNS:
  741. * BOOL
  742. *
  743. *+-------------------------------------------------------------------------*/
  744. BOOL
  745. COCXHostView::PreTranslateMessage(MSG* pMsg)
  746. {
  747. DECLARE_SC(sc, TEXT("COCXHostView::PreTranslateMessage"));
  748. if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
  749. {
  750. IOleInPlaceActiveObjectPtr spOleIPAObj = GetIUnknown();
  751. #ifdef DBG
  752. TCHAR szTracePrefix[32];
  753. sc = StringCchPrintf(szTracePrefix, countof(szTracePrefix), _T("msg=0x%04x, vkey=0x%04x:"), pMsg->message, pMsg->wParam);
  754. if (sc)
  755. sc.TraceAndClear(); // Ignore return;
  756. #endif
  757. if (spOleIPAObj != NULL)
  758. {
  759. bool fHandled = (spOleIPAObj->TranslateAccelerator(pMsg) == S_OK);
  760. Trace (tagOCXTranslateAccel, _T("%s %s handled"), szTracePrefix, fHandled ? _T(" ") : _T("not"));
  761. if (fHandled)
  762. return TRUE;
  763. }
  764. else
  765. Trace (tagOCXTranslateAccel, _T("%s not handled (no IOleInPlaceActiveObject*)"), szTracePrefix);
  766. }
  767. return BC::PreTranslateMessage(pMsg);
  768. }