OccEx.cpp
上传用户:hstrip
上传日期:2007-01-02
资源大小:42k
文件大小:37k
源码类别:

ActiveX/DCOM/ATL

开发平台:

Visual C++

  1. // OccEx.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include <afxconv.h>
  5. #include "OccEx.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. // HACK #1: 
  12. // COleControlContainerEx cannot access pWnd->m_pCtrlCont and 
  13. // pWnd->m_pCtrlSite since these are protected members of CWnd. 
  14. // The original COleControlContainer is a friend of CWnd, so the
  15. // orginal implementation has access to these members. A clean
  16. // solution would be to derive a class from CWnd, granting this
  17. // access; but we would have to derive from CDialog, CView, 
  18. // CFormView etc too...
  19. // The following two functions access the members via offsets
  20. // to the last public member. This is version dependent, so check.
  21. #if _MFC_VER < 0x0421 || _MFC_VER > 0x0600
  22. #error These hacks are for MFC 4.21 ... 6.0. Please check.
  23. #endif
  24. static inline COleControlContainer*& GetControlContainer(CWnd* pWnd)
  25. {
  26. return *(COleControlContainer**)((void**)&pWnd->m_nFlags + 4);
  27. }
  28. static inline COleControlSite*& GetControlSite(CWnd* pWnd)
  29. {
  30. return *(COleControlSite**)((void**)&pWnd->m_nFlags + 5);
  31. }
  32. /////////////////////////////////////////////////////////////////////////////
  33. // COccManagerEx
  34. COccManagerEx::COccManagerEx(CRuntimeClass* pContainerClass, CRuntimeClass* pSiteClass)
  35. : m_pContainerClass(pContainerClass)
  36. , m_pSiteClass(pSiteClass)
  37. {
  38. if (pContainerClass)
  39. ASSERT(pContainerClass->IsDerivedFrom(RUNTIME_CLASS(COleControlContainerEx))
  40. && pContainerClass->m_pfnCreateObject != NULL);
  41. if (pSiteClass)
  42. ASSERT(pSiteClass->IsDerivedFrom(RUNTIME_CLASS(COleControlSiteEx))
  43. && pSiteClass->m_pfnCreateObject != NULL);
  44. }
  45. COleControlContainer* COccManagerEx::CreateContainer(CWnd* pWnd)
  46. {
  47. if (m_pContainerClass == NULL)
  48. return COccManager::CreateContainer(pWnd);
  49. COleControlContainerEx* pContainer = STATIC_DOWNCAST(COleControlContainerEx, m_pContainerClass->CreateObject());
  50. pContainer->m_pWnd = pWnd;
  51. pContainer->Init();
  52. return pContainer;
  53. }
  54. COleControlSite* COccManagerEx::CreateSite(COleControlContainer* pCtrlCont)
  55. {
  56. if (m_pSiteClass == NULL)
  57. return COccManager::CreateSite(pCtrlCont);
  58. COleControlSiteEx* pSite = STATIC_DOWNCAST(COleControlSiteEx, m_pSiteClass->CreateObject());
  59. pSite->m_pCtrlCont = pCtrlCont;
  60. pSite->Init();
  61. return pSite;
  62. }
  63. /////////////////////////////////////////////////////////////////////////////
  64. // COleControlContainerEx
  65. IMPLEMENT_DYNCREATE(COleControlContainerEx, 
  66. CCmdTarget) // COleControlContainer has no type info
  67. COleControlContainerEx::COleControlContainerEx()
  68. : COleControlContainer(NULL)
  69. , m_pCapture(NULL)
  70. , m_pFocus(NULL)
  71. , m_bSupportWindowlessActivation(true)
  72. , m_pfnContWndProc(NULL)
  73. {
  74. }
  75. void COleControlContainerEx::Init()
  76. {
  77. }
  78. COleControlContainerEx::~COleControlContainerEx()
  79. {
  80. }
  81. // HACK #2: 
  82. // There seems to be an error in the MFC 4.21 import library: 
  83. // COleControlContainer::interfaceMap (and COleControlSite::interfaceMap)
  84. // is wrong!!!
  85. // The Macro BEGIN_INTERFACE_MAP(COleControlContainerEx, COleControlContainer)
  86. // expands (among others) to 
  87. // const AFX_INTERFACEMAP* PASCAL COleControlContainerEx::_GetBaseInterfaceMap() 
  88. // {
  89. // return &COleControlContainer::interfaceMap; 
  90. // }
  91. // which returns the wrong value and causes the program to crash.
  92. // To workaround the bug, I use COleControlContainer::GetInterfaceMap() to get
  93. // the correct pointer, storing it in a static variable.
  94. // Since COleControlContainer::GetInterfaceMap() is protected, I access it
  95. // via an inline function COleControlContainerEx::GetBaseInterfaceMap().
  96. //BEGIN_INTERFACE_MAP(COleControlContainerEx, COleControlContainer)
  97. const AFX_INTERFACEMAP* PASCAL COleControlContainerEx::_GetBaseInterfaceMap() 
  98. {
  99. // return &COleControlContainer::interfaceMap; 
  100. static const AFX_INTERFACEMAP* pBaseMap = NULL;
  101. if (pBaseMap == NULL)
  102. {
  103. COleControlContainerEx temp;
  104. pBaseMap = temp.GetBaseInterfaceMap();
  105. }
  106. return pBaseMap;
  107. const AFX_INTERFACEMAP* COleControlContainerEx::GetInterfaceMap() const 
  108. { return &COleControlContainerEx::interfaceMap; } 
  109. const AFX_DATADEF AFX_INTERFACEMAP COleControlContainerEx::interfaceMap = 
  110. { &COleControlContainerEx::_GetBaseInterfaceMap, &COleControlContainerEx::_interfaceEntries[0], }; 
  111. const AFX_DATADEF AFX_INTERFACEMAP_ENTRY COleControlContainerEx::_interfaceEntries[] = 
  112. INTERFACE_PART(COleControlContainerEx, IID_IOleInPlaceFrame, OleInPlaceFrame)
  113. END_INTERFACE_MAP()
  114. BOOL COleControlContainerEx::CreateControl(CWnd* pWndCtrl, REFCLSID clsid,
  115. LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, UINT nID,
  116. CFile* pPersist, BOOL bStorage, BSTR bstrLicKey,
  117. COleControlSite** ppNewSite)
  118. {
  119. ASSERT_VALID(this);
  120. ASSERT(pWndCtrl->m_hWnd == NULL);
  121. // This is copied from COleControlContainer::CreateControl
  122. // Changes:
  123. // - use COleControlSiteEx::CreateControl instead of COleControlSite::CreateControl
  124. // - automatically subclass the container window to forward keyboard and mouse
  125. //   input messages.
  126. COleControlSite* pSite = NULL;
  127. TRY
  128. {
  129. pSite = afxOccManager->CreateSite(this);
  130. }
  131. CATCH_ALL(e)
  132. {
  133. return FALSE;
  134. }
  135. END_CATCH_ALL
  136. if (pSite == NULL)
  137. return FALSE;
  138. // HACK #3: 
  139. // COleControlSite::CreateControl is not virtual, so I check the type of the site
  140. // object and simulate the virtual call by an appropriate cast.
  141. COleControlSiteEx* pSiteEx = DYNAMIC_DOWNCAST(COleControlSiteEx, pSite);
  142. BOOL bCreated;
  143. if (pSiteEx)
  144. bCreated = SUCCEEDED(pSiteEx->CreateControl(pWndCtrl, clsid,
  145. lpszWindowName, dwStyle, rect, nID, pPersist, bStorage, bstrLicKey));
  146. else
  147. bCreated = SUCCEEDED(pSite->CreateControl(pWndCtrl, clsid,
  148. lpszWindowName, dwStyle, rect, nID, pPersist, bStorage, bstrLicKey));
  149. if (bCreated)
  150. {
  151. // Note that COleControlSiteEx::CreateControl creates a "pseudo" m_hWnd, i.e.
  152. // a unique value wich can never collide with a real HWND.
  153. // This is necessary for the m_siteMap mechanism used in COleControlContainer.
  154. // See comments in COleControlSiteEx::CreateControl
  155. ASSERT(pSite->m_hWnd != NULL);
  156. m_siteMap.SetAt(pSite->m_hWnd, pSite);
  157. if (ppNewSite != NULL)
  158. *ppNewSite = pSite;
  159. if (pSiteEx && pSiteEx->IsWindowlessActive() && m_pfnContWndProc == NULL)
  160. {
  161. // subclass container window to handle UI messages
  162. TRACE0("Subclassing container windown");
  163. m_pfnContWndProc = (WNDPROC)SetWindowLong(m_pWnd->m_hWnd, GWL_WNDPROC, (LONG)ContWndProc);
  164. }
  165. }
  166. else
  167. {
  168. delete pSite;
  169. }
  170. return bCreated;
  171. }
  172. // This window proc is used for the subclassed container window
  173. LRESULT CALLBACK COleControlContainerEx::ContWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
  174. {
  175. AFX_MANAGE_STATE(AfxGetAppModuleState());
  176. CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
  177. ASSERT(pWnd != NULL);
  178. ASSERT(pWnd->m_hWnd == hWnd);
  179. COleControlContainerEx* pContainer = STATIC_DOWNCAST(COleControlContainerEx, GetControlContainer(pWnd));
  180. if (pContainer == NULL)
  181. return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
  182. ASSERT_VALID(pContainer);
  183. ASSERT(pContainer->m_pWnd == pWnd);
  184. LRESULT lResult;
  185. if (pContainer->OnWindowMessage(nMsg, wParam, lParam, lResult))
  186. return lResult;
  187. return CallWindowProc(pContainer->m_pfnContWndProc, hWnd, nMsg, wParam, lParam);
  188. }
  189. bool COleControlContainerEx::OnWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
  190. {
  191. COleControlSiteEx* pTarget = NULL;
  192. if ((msg >= WM_KEYFIRST && msg <= WM_IME_KEYLAST)
  193. || msg == WM_HELP
  194. || msg == WM_CANCELMODE)
  195. {
  196. // pass keyboard messages to pseudo focus
  197. pTarget = m_pFocus;
  198. }
  199. else if ((msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST)
  200. || msg == WM_SETCURSOR)
  201. {
  202. if (m_pCapture)
  203. {
  204. // pass keyboard messages to pseudo capture
  205. pTarget = m_pCapture;
  206. }
  207. else
  208. {
  209. // check if the mouse is over a windowless control
  210. CPoint pt; GetCursorPos(&pt);
  211. m_pWnd->ScreenToClient(&pt);
  212. pTarget = WindowlessSiteFromPoint(pt);
  213. }
  214. }
  215. if (pTarget == NULL)
  216. return false;
  217. return pTarget->OnWindowMessage(msg, wParam, lParam, lResult);
  218. }
  219. COleControlSiteEx* COleControlContainerEx::WindowlessSiteFromPoint(CPoint pt)
  220. {
  221. HWND hWnd;
  222. COleControlSite* pSite;
  223. POSITION pos = m_siteMap.GetStartPosition();
  224. while (pos != NULL)
  225. {
  226. m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  227. if ((DWORD)hWnd & 1)
  228. {
  229. ASSERT_KINDOF(COleControlSiteEx, pSite);
  230. if ((pSite->m_dwStyle & WS_VISIBLE) != 0 && pSite->m_rect.PtInRect(pt))
  231. {
  232. // TODO: use IViewObjectEx::QueryHitPoint to support non-rectangular controls
  233. return static_cast<COleControlSiteEx*>(pSite);
  234. }
  235. }
  236. }
  237. return NULL;
  238. }
  239. void COleControlContainerEx::OnDraw(CDC* pDC)
  240. {
  241. HWND hWnd;
  242. COleControlSite* pSite;
  243. POSITION pos = m_siteMap.GetStartPosition();
  244. while (pos != NULL)
  245. {
  246. m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  247. if ((DWORD)hWnd & 1)
  248. {
  249. ASSERT_KINDOF(COleControlSiteEx, pSite);
  250. if ((pSite->m_dwStyle & WS_VISIBLE) != 0)
  251. static_cast<COleControlSiteEx*>(pSite)->Draw(pDC);
  252. }
  253. }
  254. }
  255. void COleControlContainerEx::AmbientPropertyChanged(DISPID dispid)
  256. {
  257. POSITION pos = m_siteMap.GetStartPosition();
  258. while (pos != NULL)
  259. {
  260. HWND hWnd;
  261. COleControlSiteEx* pSite;
  262. m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  263. ASSERT_KINDOF(COleControlSiteEx, pSite);
  264. ASSERT_VALID(pSite);
  265. pSite->AmbientPropertyChanged(dispid);
  266. }
  267. }
  268. /////////////////////////////////////////////////////////////////////////////
  269. // COleControlContainerEx::XOleInPlaceFrame
  270. // This replaces the IOleInPlaceFrame implementation in COleControlContainer.
  271. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::QueryInterface(
  272. REFIID iid, LPVOID* ppvObj)
  273. {
  274. METHOD_PROLOGUE_EX_(COleControlContainerEx, OleInPlaceFrame)
  275. return (HRESULT)pThis->InternalQueryInterface(&iid, ppvObj);
  276. }
  277. STDMETHODIMP_(ULONG) COleControlContainerEx::XOleInPlaceFrame::AddRef()
  278. {
  279. METHOD_PROLOGUE_EX_(COleControlContainerEx, OleInPlaceFrame)
  280. return (ULONG)pThis->InternalAddRef();
  281. }
  282. STDMETHODIMP_(ULONG) COleControlContainerEx::XOleInPlaceFrame::Release()
  283. {
  284. METHOD_PROLOGUE_EX_(COleControlContainerEx, OleInPlaceFrame)
  285. return (ULONG)pThis->InternalRelease();
  286. }
  287. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::GetWindow(HWND* phWnd)
  288. {
  289. METHOD_PROLOGUE_EX_(COleControlContainerEx, OleInPlaceFrame)
  290. *phWnd = pThis->m_pWnd->m_hWnd;
  291. return S_OK;
  292. }
  293. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::ContextSensitiveHelp(BOOL)
  294. {
  295. return E_NOTIMPL;
  296. }
  297. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::GetBorder(LPRECT)
  298. {
  299. return E_NOTIMPL;
  300. }
  301. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::RequestBorderSpace(
  302. LPCBORDERWIDTHS)
  303. {
  304. return E_NOTIMPL;
  305. }
  306. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::SetBorderSpace(
  307. LPCBORDERWIDTHS)
  308. {
  309. return E_NOTIMPL;
  310. }
  311. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::SetActiveObject(
  312. LPOLEINPLACEACTIVEOBJECT pActiveObject, LPCOLESTR pszObjName)
  313. {
  314. METHOD_PROLOGUE_EX_(COleControlContainerEx, OleInPlaceFrame)
  315. return pThis->m_xOleIPFrame.SetActiveObject(pActiveObject, pszObjName);
  316. }
  317. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::InsertMenus(HMENU,
  318. LPOLEMENUGROUPWIDTHS)
  319. {
  320. return E_NOTIMPL;
  321. }
  322. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::SetMenu(HMENU, HOLEMENU, HWND)
  323. {
  324. return E_NOTIMPL;
  325. }
  326. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::RemoveMenus(HMENU)
  327. {
  328. return E_NOTIMPL;
  329. }
  330. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::SetStatusText(
  331. LPCOLESTR lpszStatusText)
  332. {
  333. METHOD_PROLOGUE_EX_(COleControlContainerEx, OleInPlaceFrame)
  334. USES_CONVERSION;
  335. CFrameWnd* pFrame = pThis->m_pWnd->GetParentFrame();
  336. ASSERT_VALID(pFrame);
  337. pFrame->SetMessageText(OLE2CT(lpszStatusText));
  338. return S_OK;
  339. }
  340. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::EnableModeless(BOOL fEnable)
  341. {
  342. METHOD_PROLOGUE_EX(COleControlContainerEx, OleInPlaceFrame)
  343. ASSERT_VALID(pThis);
  344. SCODE sc = E_UNEXPECTED;
  345. TRY
  346. {
  347. CFrameWnd* pFrame = pThis->m_pWnd->GetParentFrame();
  348. ASSERT_VALID(pFrame);
  349. if (!fEnable)
  350. pFrame->BeginModalState();
  351. else
  352. pFrame->EndModalState();
  353. sc = S_OK;
  354. }
  355. END_TRY
  356. return sc;
  357. }
  358. STDMETHODIMP COleControlContainerEx::XOleInPlaceFrame::TranslateAccelerator(
  359. LPMSG lpmsg, WORD wID)
  360. {
  361. UNUSED_ALWAYS(lpmsg);
  362. UNUSED_ALWAYS(wID);
  363. return E_NOTIMPL;
  364. }
  365. /////////////////////////////////////////////////////////////////////////////
  366. // COleControlSiteEx
  367. IMPLEMENT_DYNCREATE(COleControlSiteEx, CCmdTarget) // COleControlSite is not DYNAMIC
  368. // See comment "HACK #2" 
  369. //BEGIN_INTERFACE_MAP(COleControlSiteEx, COleControlSite)
  370. const AFX_INTERFACEMAP* PASCAL COleControlSiteEx::_GetBaseInterfaceMap() 
  371. {
  372. // return &COleControlSite::interfaceMap; 
  373. static const AFX_INTERFACEMAP* pBaseMap = NULL;
  374. if (pBaseMap == NULL)
  375. {
  376. COleControlSiteEx temp;
  377. pBaseMap = temp.GetBaseInterfaceMap();
  378. }
  379. return pBaseMap;
  380. const AFX_INTERFACEMAP* COleControlSiteEx::GetInterfaceMap() const 
  381. { return &COleControlSiteEx::interfaceMap; } 
  382. const AFX_DATADEF AFX_INTERFACEMAP COleControlSiteEx::interfaceMap = 
  383. { &COleControlSiteEx::_GetBaseInterfaceMap, &COleControlSiteEx::_interfaceEntries[0], }; 
  384. const AFX_DATADEF AFX_INTERFACEMAP_ENTRY COleControlSiteEx::_interfaceEntries[] = 
  385. INTERFACE_PART(COleControlSiteEx, IID_IOleInPlaceSite, OleInPlaceSiteWindowless)
  386. INTERFACE_PART(COleControlSiteEx, IID_IOleInPlaceSiteEx, OleInPlaceSiteWindowless)
  387. INTERFACE_PART(COleControlSiteEx, IID_IOleInPlaceSiteWindowless, OleInPlaceSiteWindowless)
  388. END_INTERFACE_MAP()
  389. COleControlSiteEx::COleControlSiteEx()
  390. : COleControlSite(NULL)
  391. , m_dwActivateFlags(0)
  392. , m_pIPOW(NULL)
  393. {
  394. TRACE0("COleControlSiteEx object createdn");
  395. }
  396. void COleControlSiteEx::Init()
  397. {
  398. }
  399. COleControlSiteEx::~COleControlSiteEx()
  400. {
  401. COleControlContainerEx* pContainer = DYNAMIC_DOWNCAST(COleControlContainerEx, m_pCtrlCont);
  402. if (pContainer)
  403. {
  404. if (pContainer->m_pFocus == this)
  405. pContainer->m_pFocus = NULL;
  406. if (pContainer->m_pCapture == this)
  407. pContainer->m_pCapture = NULL;
  408. }
  409. if (m_pIPOW)
  410. {
  411. m_pIPOW->Release();
  412. m_pIPOW = NULL;
  413. }
  414. TRACE0("COleControlSiteEx object destroyedn");
  415. }
  416. void COleControlSiteEx::AmbientPropertyChanged(DISPID dispid)
  417. {
  418. LPOLECONTROL pOleCtl = NULL;
  419. if (SUCCEEDED(m_pObject->QueryInterface(IID_IOleControl, (LPVOID*)&pOleCtl)))
  420. {
  421. ASSERT(pOleCtl != NULL);
  422. pOleCtl->OnAmbientPropertyChange(dispid);
  423. pOleCtl->Release();
  424. }
  425. }
  426. HRESULT COleControlSiteEx::CreateControl(CWnd* pWndCtrl, REFCLSID clsid,
  427. LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, UINT nID,
  428. CFile* pPersist, BOOL bStorage, BSTR bstrLicKey)
  429. {
  430. // This is a copy of COleControlSite::CreateControl
  431. // Changes:
  432. // - Allow windowless activation.
  433. HRESULT hr = E_FAIL;
  434. m_hWnd = NULL;
  435. // Connect the OLE Control with its proxy CWnd object
  436. if (pWndCtrl != NULL)
  437. {
  438. ASSERT(GetControlSite(pWndCtrl) == NULL);
  439. m_pWndCtrl = pWndCtrl;
  440. GetControlSite(pWndCtrl) = this;
  441. }
  442. // Initialize OLE, if necessary
  443. _AFX_THREAD_STATE* pState = AfxGetThreadState();
  444. if (!pState->m_bNeedTerm && !AfxOleInit())
  445. return hr;
  446. if (SUCCEEDED(hr = CreateOrLoad(clsid, pPersist, bStorage, bstrLicKey)))
  447. {
  448. ASSERT(m_pObject != NULL);
  449. m_nID = nID;
  450. m_rect = rect;
  451. m_dwStyleMask = WS_GROUP | WS_TABSTOP;
  452. if (m_dwMiscStatus & OLEMISC_ACTSLIKEBUTTON)
  453. m_dwStyleMask |= BS_DEFPUSHBUTTON;
  454. if (m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)
  455. dwStyle &= ~WS_VISIBLE;
  456. m_dwStyle = dwStyle & m_dwStyleMask;
  457. // If control wasn't quick-activated, then connect sinks now.
  458. if (hr != S_FALSE)
  459. {
  460. m_dwEventSink = ConnectSink(m_iidEvents, &m_xEventSink);
  461. m_dwPropNotifySink = ConnectSink(IID_IPropertyNotifySink,
  462. &m_xPropertyNotifySink);
  463. }
  464. m_dwNotifyDBEvents = ConnectSink(IID_INotifyDBEvents, &m_xNotifyDBEvents);
  465. // Now that the object has been created, attempt to
  466. // in-place activate it.
  467. if (!SetExtent())
  468. TRACE1("Warning: SetExtent on OLE control (dialog ID %d) failed.n",
  469. nID);
  470. if (SUCCEEDED(hr = m_pObject->QueryInterface(IID_IOleInPlaceObject,
  471. (LPVOID*)&m_pInPlaceObject)))
  472. {
  473. if (dwStyle & WS_VISIBLE)
  474. {
  475. // control is visible: just activate it
  476. hr = DoVerb(OLEIVERB_INPLACEACTIVATE);
  477. }
  478. else
  479. {
  480. // control is not visible: activate off-screen, hide, then move
  481. m_rect.OffsetRect(-32000, -32000);
  482. if (SUCCEEDED(hr = DoVerb(OLEIVERB_INPLACEACTIVATE)) &&
  483. SUCCEEDED(hr = DoVerb(OLEIVERB_HIDE)))
  484. {
  485. m_rect.OffsetRect(32000, 32000);
  486. hr = m_pInPlaceObject->SetObjectRects(m_rect, m_rect);
  487. }
  488. }
  489. }
  490. else
  491. {
  492. TRACE1("IOleInPlaceObject not supported on OLE control (dialog ID %d).n", nID);
  493. TRACE1(">>> Result code: 0x%08lxn", hr);
  494. }
  495. if (SUCCEEDED(hr))
  496. GetControlInfo();
  497. // if QueryInterface or activation failed, cleanup everything
  498. if (FAILED(hr))
  499. {
  500. if (m_pInPlaceObject != NULL)
  501. {
  502. m_pInPlaceObject->Release();
  503. m_pInPlaceObject = NULL;
  504. }
  505. if (m_pIPOW)
  506. {
  507. m_pIPOW->Release();
  508. m_pIPOW = NULL;
  509. }
  510. DisconnectSink(m_iidEvents, m_dwEventSink);
  511. DisconnectSink(IID_IPropertyNotifySink, m_dwPropNotifySink);
  512. DisconnectSink(IID_INotifyDBEvents, m_dwNotifyDBEvents);
  513. m_dwEventSink = 0;
  514. m_dwPropNotifySink = 0;
  515. m_dwNotifyDBEvents = 0;
  516. m_pObject->Release();
  517. m_pObject = NULL;
  518. }
  519. }
  520. if (SUCCEEDED(hr))
  521. {
  522. // --- Begin modification ---
  523. ASSERT((m_dwActivateFlags & ACTIVATE_WINDOWLESS) != 0 || m_hWnd != NULL);
  524. // HACK#4:
  525. // Lots of functions in CWnd and COleControlContainer rely on the fact that all active
  526. // contained controls are in the HWND->COleControlSite map m_siteMap.
  527. // Since windowless controls have no HWND, we just create a pseude HWND, i.e. a number
  528. // which is guaranteed to be unique and which cannot be a valid window handle.
  529. // We use (HWND)((DWORD)pSite | 1) for this (window handles are always even).
  530. // The only places in MFC where the hwnd info from the map is really used as window handle
  531. // are in the following functions:
  532. // - CWnd::OnWndMsg for WM_CTLCOLOR
  533. // - CWnd::ReflectLastMsg
  534. // - some virtual functions in COleControlSite.
  535. // The first two are never called for windowless controls, the COleControlSite functions
  536. // are overridden here.
  537. if (m_hWnd == NULL)
  538. {
  539. m_hWnd = (HWND)((DWORD)this | 1);
  540. m_dwStyleMask |= WS_VISIBLE;
  541. m_dwStyle |= (dwStyle & WS_VISIBLE);
  542. VERIFY(SUCCEEDED(m_pInPlaceObject->QueryInterface(
  543. IID_IOleInPlaceObjectWindowless, (void**)&m_pIPOW)));
  544. }
  545. else
  546. {
  547. ASSERT(((DWORD)m_hWnd & 1) == 0);
  548. }
  549. // --- End modification ---
  550. AttachWindow();
  551. // Initialize the control's Caption or Text property, if any
  552. if (lpszWindowName != NULL)
  553. SetWindowText(lpszWindowName);
  554. // Initialize styles
  555. ModifyStyle(0, m_dwStyle | (dwStyle & (WS_DISABLED|WS_BORDER)), 0);
  556. }
  557. return hr;
  558. }
  559. void COleControlSiteEx::Draw(CDC* pDC)
  560. {
  561. if (!IsWindowlessActive() || (m_dwStyle & WS_VISIBLE) == 0)
  562. return;
  563. LPVIEWOBJECT lpViewObject = NULL;
  564. if (FAILED(m_pObject->QueryInterface(IID_IViewObject, (void**)&lpViewObject)))
  565. return;
  566. // get RECTL describing window extents and origin
  567. RECTL rclWBounds;
  568. CPoint ptOrg = pDC->GetWindowOrg();
  569. CSize sizeExt = pDC->GetWindowExt();
  570. rclWBounds.left = ptOrg.x;
  571. rclWBounds.top = ptOrg.y;
  572. rclWBounds.right = sizeExt.cx;
  573. rclWBounds.bottom = sizeExt.cy;
  574. lpViewObject->Draw(DVASPECT_CONTENT, -1, NULL,
  575. NULL, NULL, pDC->m_hDC,
  576. (RECTL*)&m_rect, &rclWBounds, NULL, 0);
  577. lpViewObject->Release();
  578. }
  579. DWORD COleControlSiteEx::GetStyle() const
  580. {
  581. DWORD dwStyle = m_dwStyle;
  582. if (!IsWindowlessActive())
  583. dwStyle |= (::GetWindowLong(m_hWnd, GWL_STYLE) & WS_VISIBLE);
  584. TRY
  585. {
  586. BOOL bEnabled = TRUE;
  587. GetProperty(DISPID_ENABLED, VT_BOOL, &bEnabled);
  588. if (!bEnabled)
  589. dwStyle |= WS_DISABLED;
  590. }
  591. END_TRY
  592. TRY
  593. {
  594. short sBorderStyle = 0;
  595. GetProperty(DISPID_BORDERSTYLE, VT_I2, &sBorderStyle);
  596. if (sBorderStyle == 1)
  597. dwStyle |= WS_BORDER;
  598. }
  599. END_TRY
  600. return dwStyle;
  601. }
  602. DWORD COleControlSiteEx::GetExStyle() const
  603. {
  604. DWORD dwExStyle = 0;
  605. if (!IsWindowlessActive())
  606. dwExStyle |= ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
  607. TRY
  608. {
  609. short sAppearance = 0;
  610. GetProperty(DISPID_APPEARANCE, VT_I2, &sAppearance);
  611. if (sAppearance == 1)
  612. dwExStyle |= WS_EX_CLIENTEDGE;
  613. }
  614. END_TRY
  615. return dwExStyle;
  616. }
  617. BOOL COleControlSiteEx::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  618. {
  619. m_dwStyle = ((m_dwStyle & ~dwRemove) | dwAdd) & m_dwStyleMask;
  620. // Enabled property
  621. if ((dwRemove & WS_DISABLED) || (dwAdd & WS_DISABLED))
  622. {
  623. if (SafeSetProperty(DISPID_ENABLED, VT_BOOL, (~dwAdd & WS_DISABLED)))
  624. {
  625. dwRemove &= ~WS_DISABLED;
  626. dwAdd &= ~WS_DISABLED;
  627. }
  628. }
  629. // BorderStyle property
  630. if ((dwRemove & WS_BORDER) || (dwAdd & WS_BORDER))
  631. {
  632. if (SafeSetProperty(DISPID_BORDERSTYLE, VT_I2, (dwAdd & WS_BORDER)))
  633. {
  634. dwRemove &= ~WS_BORDER;
  635. dwAdd &= ~WS_BORDER;
  636. }
  637. }
  638. if (!IsWindowlessActive())
  639. {
  640. return CWnd::ModifyStyle(m_hWnd, dwRemove, dwAdd, nFlags);
  641. }
  642. else
  643. {
  644. if ((dwRemove & WS_VISIBLE) || (dwAdd & WS_VISIBLE))
  645. {
  646. //.TODO: Visible property changed
  647. }
  648. return TRUE;
  649. }
  650. }
  651. BOOL COleControlSiteEx::ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  652. {
  653. // BorderStyle property
  654. if ((dwRemove & WS_EX_CLIENTEDGE) || (dwAdd & WS_EX_CLIENTEDGE))
  655. {
  656. if (SafeSetProperty(DISPID_APPEARANCE, VT_I2, (dwAdd & WS_EX_CLIENTEDGE)))
  657. {
  658. dwRemove &= ~WS_EX_CLIENTEDGE;
  659. dwAdd &= ~WS_EX_CLIENTEDGE;
  660. }
  661. }
  662. if (!IsWindowlessActive())
  663. {
  664. return CWnd::ModifyStyleEx(m_hWnd, dwRemove, dwAdd, nFlags);
  665. }
  666. else
  667. {
  668. return TRUE;
  669. }
  670. }
  671. #ifdef _DEBUG
  672. // The original implementations of the following two functions work
  673. // perfectly with windowless controls, but both have an ASSERT(::IsWindow(m_hWnd))
  674. // which will fire for a windowless control.
  675. // We override these functions only in the _DEBUG version to get rid of the ASSERT.
  676. void COleControlSiteEx::SetWindowText(LPCTSTR lpszString)
  677. {
  678. // ASSERT(::IsWindow(m_hWnd));
  679. if (!SafeSetProperty(DISPID_CAPTION, VT_BSTR, lpszString))
  680. SafeSetProperty(DISPID_TEXT, VT_BSTR, lpszString);
  681. }
  682. void COleControlSiteEx::GetWindowText(CString& str) const
  683. {
  684. // ASSERT(::IsWindow(m_hWnd));
  685. TRY
  686. {
  687. GetProperty(DISPID_CAPTION, VT_BSTR, &str);
  688. }
  689. CATCH_ALL(e)
  690. {
  691. TRY
  692. {
  693. GetProperty(DISPID_TEXT, VT_BSTR, &str);
  694. }
  695. END_TRY
  696. }
  697. END_CATCH_ALL
  698. }
  699. #endif
  700. BOOL COleControlSiteEx::SetWindowPos(const CWnd* pWndInsertAfter, int x, int y, int cx,
  701. int cy, UINT nFlags)
  702. {
  703. if (nFlags & SWP_HIDEWINDOW)
  704. ShowWindow(SW_HIDE);
  705. if ((nFlags & (SWP_NOMOVE|SWP_NOSIZE)) != (SWP_NOMOVE|SWP_NOSIZE))
  706. {
  707. int xNew;
  708. int yNew;
  709. if (nFlags & SWP_NOMOVE)
  710. {
  711. xNew = m_rect.left;
  712. yNew = m_rect.top;
  713. }
  714. else
  715. {
  716. xNew = x;
  717. yNew = y;
  718. }
  719. int cxNew;
  720. int cyNew;
  721. if (nFlags & SWP_NOSIZE)
  722. {
  723. cxNew = m_rect.Width();
  724. cyNew = m_rect.Height();
  725. }
  726. else
  727. {
  728. cxNew = cx;
  729. cyNew = cy;
  730. }
  731. MoveWindow(xNew, yNew, cxNew, cyNew, !(nFlags & SWP_NOREDRAW));
  732. }
  733. if (nFlags & SWP_SHOWWINDOW)
  734. ShowWindow(SW_SHOW);
  735. // we've handled hide, move, size, and show; let Windows do the rest
  736. nFlags &= ~(SWP_HIDEWINDOW|SWP_SHOWWINDOW);
  737. nFlags |= (SWP_NOMOVE|SWP_NOSIZE);
  738. if (!IsWindowlessActive())
  739. {
  740. return ::SetWindowPos(m_hWnd, pWndInsertAfter->GetSafeHwnd(),
  741. x, y, cx, cy, nFlags);
  742. }
  743. else
  744. {
  745. return TRUE;
  746. }
  747. }
  748. BOOL COleControlSiteEx::ShowWindow(int nCmdShow)
  749. {
  750. BOOL bReturn;
  751. if (IsWindowlessActive())
  752. bReturn = (m_dwStyle & WS_VISIBLE) != 0;
  753. else
  754. bReturn = ::IsWindowVisible(m_hWnd);
  755. int iVerb = 0;
  756. switch (nCmdShow)
  757. {
  758. case SW_SHOW:
  759. case SW_SHOWNORMAL:
  760. case SW_SHOWNOACTIVATE:
  761. iVerb = OLEIVERB_SHOW;
  762. if (IsWindowlessActive())
  763. m_dwStyle |= WS_VISIBLE;
  764. break;
  765. case SW_HIDE:
  766. iVerb = OLEIVERB_HIDE;
  767. if (IsWindowlessActive())
  768. m_dwStyle &= ~WS_VISIBLE;
  769. break;
  770. }
  771. if (iVerb != 0)
  772. DoVerb(iVerb);
  773. return bReturn;
  774. }
  775. CWnd* COleControlSiteEx::SetFocus()
  776. {
  777. CWnd* pWndPrev = CWnd::GetFocus();
  778. if (IsWindowlessActive())
  779. {
  780. DoVerb(OLEIVERB_UIACTIVATE);
  781. }
  782. else
  783. {
  784. if (m_dwMiscStatus & OLEMISC_NOUIACTIVATE)
  785. ::SetFocus(m_hWnd);
  786. else
  787. DoVerb(OLEIVERB_UIACTIVATE);
  788. }
  789. return pWndPrev;
  790. }
  791. bool COleControlSiteEx::OnWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
  792. {
  793. if (m_pIPOW == NULL)
  794. return false;
  795. HRESULT hr = m_pIPOW->OnWindowMessage(msg, wParam, lParam, &lResult);
  796. return hr == S_OK;
  797. }
  798. /////////////////////////////////////////////////////////////////////////////
  799. // COleControlSiteEx::XOleInPlaceSiteWindowless
  800. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::QueryInterface(
  801. REFIID iid, LPVOID* ppvObj)
  802. {
  803. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  804. return (HRESULT)pThis->InternalQueryInterface(&iid, ppvObj);
  805. }
  806. STDMETHODIMP_(ULONG) COleControlSiteEx::XOleInPlaceSiteWindowless::AddRef()
  807. {
  808. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  809. return (ULONG)pThis->InternalAddRef();
  810. }
  811. STDMETHODIMP_(ULONG) COleControlSiteEx::XOleInPlaceSiteWindowless::Release()
  812. {
  813. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  814. return (ULONG)pThis->InternalRelease();
  815. }
  816. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::GetWindow(HWND* phWnd)
  817. {
  818. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  819. *phWnd = pThis->m_pCtrlCont->m_pWnd->GetSafeHwnd();
  820. return *phWnd != NULL ? S_OK : E_FAIL;
  821. }
  822. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::ContextSensitiveHelp(BOOL fEnterMode)
  823. {
  824. UNUSED_ALWAYS(fEnterMode);
  825. return E_NOTIMPL;
  826. }
  827. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::CanInPlaceActivate()
  828. {
  829. return S_OK;
  830. }
  831. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::OnInPlaceActivate()
  832. {
  833. return OnInPlaceActivateEx(NULL, 0);
  834. }
  835. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::OnUIActivate()
  836. {
  837. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  838. pThis->m_pCtrlCont->OnUIActivate(pThis);
  839. return S_OK;
  840. }
  841. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::GetWindowContext(LPOLEINPLACEFRAME* ppFrame,
  842. LPOLEINPLACEUIWINDOW* ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
  843. {
  844. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  845. // pass to default implementation
  846. return pThis->m_xOleIPSite.GetWindowContext(ppFrame, ppDoc, lprcPosRect, lprcClipRect, lpFrameInfo);
  847. }
  848. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::Scroll(SIZE scrollExtent)
  849. {
  850. UNUSED_ALWAYS(scrollExtent);
  851. return S_FALSE;
  852. }
  853. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::OnUIDeactivate(BOOL fUndoable)
  854. {
  855. UNUSED_ALWAYS(fUndoable);
  856. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  857. pThis->m_pCtrlCont->OnUIDeactivate(pThis);
  858. return S_OK;
  859. }
  860. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::OnInPlaceDeactivate()
  861. {
  862. return OnInPlaceDeactivateEx(TRUE);
  863. }
  864. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::DiscardUndoState()
  865. {
  866. return S_OK;
  867. }
  868. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::DeactivateAndUndo()
  869. {
  870. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  871. pThis->m_pInPlaceObject->UIDeactivate();
  872. return S_OK;
  873. }
  874. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::OnPosRectChange(LPCRECT lprcPosRect)
  875. {
  876. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  877. CRect rectClip;
  878. pThis->m_pCtrlCont->m_pWnd->GetClientRect(rectClip);
  879. pThis->m_rect = lprcPosRect;
  880. return pThis->m_pInPlaceObject->SetObjectRects(pThis->m_rect, rectClip);
  881. }
  882. // IOleInPlaceSiteEx
  883. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::OnInPlaceActivateEx(BOOL* pfNoRedraw, DWORD dwFlags)
  884. {
  885. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  886. pThis->m_dwActivateFlags = dwFlags;
  887. if (pfNoRedraw)
  888. {
  889. // TODO: look closer
  890. *pfNoRedraw = FALSE;
  891. }
  892. return S_OK;
  893. }
  894. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::OnInPlaceDeactivateEx(BOOL fNoRedraw)    
  895. {
  896. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  897. pThis->DetachWindow();
  898. pThis->m_dwActivateFlags = 0;
  899. return S_OK;
  900. }
  901. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::RequestUIActivate()
  902. {
  903. return S_OK;
  904. }
  905. // IOleInPlaceSiteWindowless
  906. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::CanWindowlessActivate()
  907. {
  908. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  909. if (STATIC_DOWNCAST(COleControlContainerEx, pThis->m_pCtrlCont)->m_bSupportWindowlessActivation)
  910. return S_OK;
  911. else
  912. return E_FAIL; // use E_FAIL instead of S_FALSE, since the latter does not work with ATL controls
  913. }
  914. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::GetCapture()
  915. {
  916. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  917. HWND hwndCapture = ::GetCapture();
  918. if (hwndCapture == NULL)
  919. return S_FALSE;
  920. else if (!pThis->IsWindowlessActive() && hwndCapture == pThis->m_hWnd)
  921. return S_OK;
  922. else if (hwndCapture == pThis->m_pCtrlCont->m_pWnd->GetSafeHwnd()
  923. && STATIC_DOWNCAST(COleControlContainerEx, pThis->m_pCtrlCont)->m_pCapture == pThis)
  924. return S_OK;
  925. else
  926. return S_FALSE;
  927. }
  928. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::SetCapture(BOOL fCapture)
  929. {
  930. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  931. if (!fCapture)
  932. {
  933. if (GetCapture() == S_OK)
  934. ::ReleaseCapture();
  935. STATIC_DOWNCAST(COleControlContainerEx, pThis->m_pCtrlCont)->m_pCapture = NULL;
  936. }
  937. else if (!pThis->IsWindowlessActive())
  938. {
  939. ::SetCapture(pThis->m_hWnd);
  940. }
  941. else
  942. {
  943. STATIC_DOWNCAST(COleControlContainerEx, pThis->m_pCtrlCont)->m_pCapture = pThis;
  944. ::SetCapture(pThis->m_pCtrlCont->m_pWnd->GetSafeHwnd());
  945. }
  946. return S_OK;
  947. }
  948. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::GetFocus()
  949. {
  950. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  951. HWND hwndFocus = ::GetFocus();
  952. if (hwndFocus == NULL)
  953. return S_FALSE;
  954. else if (!pThis->IsWindowlessActive() && hwndFocus == pThis->m_hWnd)
  955. return S_OK;
  956. else if (hwndFocus == pThis->m_pCtrlCont->m_pWnd->GetSafeHwnd()
  957. && STATIC_DOWNCAST(COleControlContainerEx, pThis->m_pCtrlCont)->m_pFocus == pThis)
  958. return S_OK;
  959. else
  960. return S_FALSE;
  961. }
  962. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::SetFocus(BOOL fFocus)
  963. {
  964. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  965. if (!fFocus)
  966. {
  967. if (GetFocus() == S_OK)
  968. ::SetFocus(NULL);
  969. STATIC_DOWNCAST(COleControlContainerEx, pThis->m_pCtrlCont)->m_pFocus = NULL;
  970. }
  971. else if (!pThis->IsWindowlessActive())
  972. {
  973. ::SetFocus(pThis->m_hWnd);
  974. }
  975. else
  976. {
  977. STATIC_DOWNCAST(COleControlContainerEx, pThis->m_pCtrlCont)->m_pFocus = pThis;
  978. ::SetFocus(pThis->m_pCtrlCont->m_pWnd->GetSafeHwnd());
  979. }
  980. return S_OK;
  981. }
  982. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::GetDC(LPCRECT pRect, DWORD grfFlags, HDC* phDC)
  983. {
  984. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  985. *phDC = pThis->WindowlessGetDC(pRect, grfFlags);
  986. return *phDC ? S_OK : E_FAIL;
  987. }
  988. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::ReleaseDC(HDC hDC)
  989. {
  990. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  991. pThis->WindowlessReleaseDC(hDC);
  992. return S_OK;
  993. }
  994. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::InvalidateRect(LPCRECT pRect, BOOL fErase)
  995. {
  996. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  997. pThis->WindowlessInvalidateRect(pRect, fErase);
  998. return S_OK;
  999. }
  1000. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::InvalidateRgn(HRGN hRGN, BOOL fErase)
  1001. {
  1002. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  1003. pThis->WindowlessInvalidateRgn(hRGN, fErase);
  1004. return S_OK;
  1005. }
  1006. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip)
  1007. {
  1008. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  1009. pThis->WindowlessScrollRect(dx, dy, pRectScroll, pRectClip);
  1010. return S_OK;
  1011. }
  1012. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::AdjustRect(LPRECT prc)
  1013. {
  1014. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  1015. pThis->WindowlessAdjustRect(prc);
  1016. return S_OK;
  1017. }
  1018. STDMETHODIMP COleControlSiteEx::XOleInPlaceSiteWindowless::OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
  1019. {
  1020. METHOD_PROLOGUE(COleControlSiteEx, OleInPlaceSiteWindowless)
  1021. if (pThis->WindowlessOnDefWindowMessage(msg, wParam, lParam, *plResult))
  1022. return S_OK;
  1023. else
  1024. return S_FALSE;
  1025. }
  1026. HDC COleControlSiteEx::WindowlessGetDC(LPCRECT pRect, DWORD grfFlags)
  1027. {
  1028. HWND hwndContainer = m_pCtrlCont->m_pWnd->GetSafeHwnd();
  1029. if (grfFlags & OLEDC_NODRAW)
  1030. return ::GetDC(hwndContainer);
  1031. if (grfFlags & OLEDC_OFFSCREEN)
  1032. return NULL;
  1033. HDC hDC = ::GetDC(hwndContainer);
  1034. ::IntersectClipRect(hDC, m_rect.left, m_rect.top, m_rect.right, m_rect.bottom);
  1035. if (pRect)
  1036. ::IntersectClipRect(hDC, pRect->left, pRect->top, pRect->right, pRect->bottom);
  1037. if (grfFlags & OLEDC_PAINTBKGND)
  1038. {
  1039. ::SendMessage(hwndContainer, WM_ERASEBKGND, (WPARAM)hDC, 0);
  1040. // TODO: draw objects behind this one
  1041. }
  1042. return hDC;
  1043. }
  1044. void COleControlSiteEx::WindowlessReleaseDC(HDC hDC)
  1045. {
  1046. // TODO: draw object on top of this
  1047. HWND hwndContainer = m_pCtrlCont->m_pWnd->GetSafeHwnd();
  1048. ::ReleaseDC(hwndContainer, hDC);
  1049. }
  1050. void COleControlSiteEx::WindowlessInvalidateRect(LPCRECT pRect, BOOL fErase)
  1051. {
  1052. CRect rect = m_rect;
  1053. if (pRect)
  1054. rect &= *pRect;
  1055. m_pCtrlCont->m_pWnd->InvalidateRect(rect, fErase);
  1056. }
  1057. void COleControlSiteEx::WindowlessInvalidateRgn(HRGN hRGN, BOOL fErase)
  1058. {
  1059. if (hRGN == NULL)
  1060. {
  1061. m_pCtrlCont->m_pWnd->InvalidateRect(m_rect, fErase);
  1062. }
  1063. else
  1064. {
  1065. CRgn rgnRect;
  1066. rgnRect.CreateRectRgnIndirect(m_rect);
  1067. CRgn rgn;
  1068. rgn.CombineRgn(&rgnRect, CRgn::FromHandle(hRGN), RGN_AND);
  1069. m_pCtrlCont->m_pWnd->InvalidateRgn(&rgn, fErase);
  1070. }
  1071. }
  1072. void COleControlSiteEx::WindowlessScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip)
  1073. {
  1074. WindowlessInvalidateRect(pRectScroll, TRUE);
  1075. m_pCtrlCont->m_pWnd->UpdateWindow();
  1076. // TODO: make smarter
  1077. }
  1078. void COleControlSiteEx::WindowlessAdjustRect(LPRECT prc)
  1079. {
  1080. UNUSED_ALWAYS(prc);
  1081. }
  1082. BOOL COleControlSiteEx::WindowlessOnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
  1083. {
  1084. HWND hwndContainer = m_pCtrlCont->m_pWnd->GetSafeHwnd();
  1085. switch (msg)
  1086. {
  1087. case WM_LBUTTONDOWN:
  1088. // TODO: check if the control can be UI activated
  1089. // (corresponds to (SendMesage(WM_GETDLGCODE) & DLGC_STATIC) == 0)
  1090. SetFocus();
  1091. return TRUE;
  1092. case WM_SETCURSOR:
  1093. case WM_CONTEXTMENU:
  1094. case WM_HELP:
  1095. // TODO: pass on to the container window's original window proc
  1096. return FALSE;
  1097. default:
  1098. // TODO: pass on to the container window's original window proc
  1099. lResult = ::DefWindowProc(hwndContainer, msg, wParam, lParam);
  1100. return TRUE;
  1101. }
  1102. }
  1103. /////////////////////////////////////////////////////////////////////////////
  1104. // CWindowlessControl
  1105. IMPLEMENT_DYNCREATE(CWindowlessControl, CWnd)
  1106. CWindowlessControl::CWindowlessControl()
  1107. {
  1108. }
  1109. BOOL CWindowlessControl::CreateControl(LPCTSTR lpszClass, LPCTSTR lpszWindowName,
  1110. DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID,
  1111. CFile* pPersist, BOOL bStorage, BSTR bstrLicKey)
  1112. {
  1113. ASSERT(lpszClass != NULL);
  1114. CLSID clsid;
  1115. HRESULT hr = AfxGetClassIDFromString(lpszClass, &clsid);
  1116. if (FAILED(hr))
  1117. return FALSE;
  1118. return CreateControl(clsid, lpszWindowName, dwStyle, rect, pParentWnd, nID,
  1119. pPersist, bStorage, bstrLicKey);
  1120. }
  1121. BOOL CWindowlessControl::CreateControl(REFCLSID clsid, LPCTSTR lpszWindowName, DWORD dwStyle,
  1122. const RECT& rect, CWnd* pParentWnd, UINT nID, CFile* pPersist,
  1123. BOOL bStorage, BSTR bstrLicKey)
  1124. {
  1125. ASSERT(pParentWnd != NULL);
  1126. #ifdef _DEBUG
  1127. if (afxOccManager == NULL)
  1128. {
  1129. TRACE0("Warning: AfxEnableControlContainer has not been called yet.n");
  1130. TRACE0(">>> You should call it in your app's InitInstance function.n");
  1131. }
  1132. #endif
  1133. if (pParentWnd == NULL)
  1134. return FALSE;
  1135. // if (!pParentWnd->InitControlContainer())
  1136. // return FALSE;
  1137. // This does not work since InitControlContainer is protected;
  1138. // so we have to copy the implementation.
  1139. COleControlContainer*& pCtrlCont = GetControlContainer(pParentWnd);
  1140. TRY
  1141. {
  1142. if (pCtrlCont == NULL)
  1143. pCtrlCont = afxOccManager->CreateContainer(pParentWnd);
  1144. }
  1145. END_TRY
  1146. // Mark all ancestor windows as containing OLE controls.
  1147. if (pCtrlCont != NULL)
  1148. {
  1149. CWnd* pWnd = pParentWnd;
  1150. while ((pWnd != NULL) && !(pWnd->m_nFlags & WF_OLECTLCONTAINER))
  1151. {
  1152. pWnd->m_nFlags |= WF_OLECTLCONTAINER;
  1153. pWnd = pWnd->GetParent();
  1154. if (! (GetWindowLong(pWnd->GetSafeHwnd(), GWL_STYLE) & WS_CHILD))
  1155. break;
  1156. }
  1157. }
  1158. if (pCtrlCont == NULL)
  1159. return FALSE;
  1160. // HACK #5: 
  1161. // COleControlContainer::CreateControl is not virtual, so I check the type of the 
  1162. // container object and simulate the virtual call by an appropriate cast.
  1163. COleControlContainer* pContainer = GetControlContainer(pParentWnd);
  1164. if (pContainer->IsKindOf(RUNTIME_CLASS(COleControlContainerEx)))
  1165. return static_cast<COleControlContainerEx*>(pContainer)->CreateControl(this, clsid, lpszWindowName,
  1166. dwStyle, rect, nID, pPersist, bStorage, bstrLicKey);
  1167. else
  1168. return pContainer->CreateControl(this, clsid, lpszWindowName,
  1169. dwStyle, rect, nID, pPersist, bStorage, bstrLicKey);
  1170. }