D3DATL.H
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:9k
源码类别:

Windows编程

开发平台:

Visual C++

  1. // D3D.h : Declaration of the CDirect3D
  2. //
  3. // This is a part of the Active Template Library.
  4. // Copyright (C) 1996-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Active Template Library Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Active Template Library product.
  12. #include <objsafe.h>
  13. #include "resource.h"       // main symbols
  14. #include "D3DWnd.h"
  15. //////////////////////////////////////////////////////////////////////////////////////////////////
  16. // CTimer
  17. template <class Derived, class T, const IID* piid>
  18. class CTimer
  19. {
  20. public:
  21. CTimer()
  22. {
  23. m_bTimerOn = FALSE;
  24. }
  25. HRESULT TimerOn(DWORD dwTimerInterval)
  26. {
  27. Derived* pDerived = ((Derived*)this);
  28. m_dwTimerInterval = dwTimerInterval;
  29. if (m_bTimerOn) // already on, just change interval
  30. return S_OK;
  31. m_bTimerOn = TRUE;
  32. m_dwTimerInterval = dwTimerInterval;
  33. m_pStream = NULL;
  34. HRESULT hRes;
  35. hRes = CoMarshalInterThreadInterfaceInStream(*piid, (T*)pDerived, &m_pStream);
  36. // Create thread and pass the thread proc the this ptr
  37. m_hThread = CreateThread(NULL, 0, &_Apartment, (void*)this, 0, &m_dwThreadID);
  38. return S_OK;
  39. }
  40. void TimerOff()
  41. {
  42. if (m_bTimerOn)
  43. {
  44. m_bTimerOn = FALSE;
  45. AtlWaitWithMessageLoop(m_hThread);
  46. }
  47. }
  48. // Implementation
  49. private:
  50. static DWORD WINAPI _Apartment(void* pv)
  51. {
  52. CTimer<Derived, T, piid>* pThis = (CTimer<Derived, T, piid>*) pv;
  53. pThis->Apartment();
  54. return 0;
  55. }
  56. DWORD Apartment()
  57. {
  58. CoInitialize(NULL);
  59. HRESULT hRes;
  60. m_spT.Release();
  61. if (m_pStream)
  62. hRes = CoGetInterfaceAndReleaseStream(m_pStream, *piid, (void**)&m_spT);
  63. while(m_bTimerOn)
  64. {
  65. Sleep(m_dwTimerInterval);
  66. if (!m_bTimerOn)
  67. break;
  68. m_spT->DisplayScene();
  69. }
  70. m_spT.Release();
  71. CoUninitialize();
  72. return 0;
  73. }
  74. // Attributes
  75. public:
  76. DWORD m_dwTimerInterval;
  77. // Implementation
  78. private:
  79. HANDLE m_hThread;
  80. DWORD m_dwThreadID;
  81. LPSTREAM m_pStream;
  82. CComPtr<T> m_spT;
  83. BOOL m_bTimerOn;
  84. };
  85. /////////////////////////////////////////////////////////////////////////////
  86. // CDirect3D
  87. class CDirect3D :
  88. public CComObjectRoot,
  89. public CComCoClass<CDirect3D, &CLSID_CDirect3DCtl>,
  90. public CComControl<CDirect3D>,
  91. public CTimer<CDirect3D, IDirect3DCtl, &IID_IDirect3DCtl>,
  92. public IDispatchImpl<IDirect3DCtl, &IID_IDirect3DCtl, &LIBID_DIRECT3DLib>,
  93. public IPersistStreamInitImpl<CDirect3D>,
  94. public IPersistStorageImpl<CDirect3D>,
  95. public IQuickActivateImpl<CDirect3D>,
  96. public IProvideClassInfo2Impl<&CLSID_CDirect3DCtl, NULL, &LIBID_DIRECT3DLib>,
  97. public IOleControlImpl<CDirect3D>,
  98. public IOleObjectImpl<CDirect3D>,
  99. public IOleInPlaceActiveObjectImpl<CDirect3D>,
  100. public IViewObjectExImpl<CDirect3D>,
  101. public IOleInPlaceObjectWindowlessImpl<CDirect3D>,
  102. public IDataObjectImpl<CDirect3D>,
  103. public IObjectSafetyImpl<CDirect3D, INTERFACESAFE_FOR_UNTRUSTED_CALLER>,
  104. public ISupportErrorInfo
  105. {
  106. public:
  107. CDirect3D()
  108. {
  109. m_hOurWnd   = NULL;
  110. m_p3DWindow = NULL;
  111. m_dwSafety  = 0;
  112. }
  113. ~CDirect3D()
  114. {
  115. // Stop, if we haven't stopped already
  116. if (m_p3DWindow)
  117. Stop3D();
  118. }
  119. DECLARE_REGISTRY_RESOURCEID(IDR_Direct3D)
  120. DECLARE_GET_CONTROLLING_UNKNOWN()
  121. BEGIN_COM_MAP(CDirect3D)
  122. COM_INTERFACE_ENTRY(IDirect3DCtl)
  123. COM_INTERFACE_ENTRY(IDispatch)
  124. COM_INTERFACE_ENTRY_IMPL(IViewObjectEx)
  125. COM_INTERFACE_ENTRY_IMPL_IID(IID_IViewObject2, IViewObjectEx)
  126. COM_INTERFACE_ENTRY_IMPL_IID(IID_IViewObject, IViewObjectEx)
  127. COM_INTERFACE_ENTRY_IMPL(IOleInPlaceObjectWindowless)
  128. COM_INTERFACE_ENTRY_IMPL_IID(IID_IOleInPlaceObject, IOleInPlaceObjectWindowless)
  129. COM_INTERFACE_ENTRY_IMPL_IID(IID_IOleWindow, IOleInPlaceObjectWindowless)
  130. COM_INTERFACE_ENTRY_IMPL(IOleInPlaceActiveObject)
  131. COM_INTERFACE_ENTRY_IMPL(IOleControl)
  132. COM_INTERFACE_ENTRY_IMPL(IOleObject)
  133. COM_INTERFACE_ENTRY_IMPL(IQuickActivate)
  134. COM_INTERFACE_ENTRY_IMPL(IPersistStorage)
  135. COM_INTERFACE_ENTRY_IMPL(IPersistStreamInit)
  136. COM_INTERFACE_ENTRY_IMPL(IDataObject)
  137. COM_INTERFACE_ENTRY(IObjectSafety)
  138. COM_INTERFACE_ENTRY(IProvideClassInfo)
  139. COM_INTERFACE_ENTRY(IProvideClassInfo2)
  140. COM_INTERFACE_ENTRY(ISupportErrorInfo)
  141. END_COM_MAP()
  142. BEGIN_MSG_MAP(CDirect3D)
  143. MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
  144. MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
  145. END_MSG_MAP()
  146. BEGIN_PROPERTY_MAP(CDirect3D)
  147. END_PROPERTY_MAP()
  148. // ISupportsErrorInfo
  149. STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
  150. STDMETHOD(OnFrameWindowActivate)(BOOL fActivate)
  151. {
  152. ATLTRACE(_T("OnFrameWindowActivaten"));
  153. if (fActivate && m_p3DWindow)
  154. m_p3DWindow->SetPalette();
  155. return S_OK;
  156. }
  157. // IDirect3DCtl
  158. public:
  159. // Implementation
  160. public:
  161. // The drawing is done through CDirect3DWindow, so we need
  162. // to do nothing here.
  163. LRESULT OnEraseBackground(UINT, WPARAM, LPARAM, BOOL& bHandled)
  164. {
  165. return 0;
  166. }
  167. LRESULT OnLButtonDown(UINT, WPARAM, LPARAM, BOOL& bHandled)
  168. {
  169. m_p3DWindow->SetPalette();
  170. return 0;
  171. }
  172. HRESULT OnDraw(ATL_DRAWINFO&)
  173. {
  174. // We're not doing any drawing using GDI, so there is nothing to do here.
  175. // We still need to have this function so we don't bring in the default ATL
  176. // drawing code.
  177. return TRUE;
  178. }
  179. HRESULT InPlaceActivate(LONG iVerb, const RECT* prcPosRect = NULL)
  180. {
  181. HRESULT hr;
  182. hr = CComControlBase::InPlaceActivate(iVerb, prcPosRect);
  183. if (!m_p3DWindow)   // Start if we haven't started yet
  184. Start3D();
  185. return hr;
  186. }
  187. STDMETHOD(InPlaceDeactivate)(void)
  188. {
  189. if (m_p3DWindow)
  190. Stop3D();
  191. return IOleInPlaceObjectWindowlessImpl<CDirect3D>::InPlaceDeactivate();
  192. }
  193. STDMETHOD(Start3D)()
  194. {
  195. // Find out what window we need to use
  196. GetOurWindow();
  197. // If we haven't got a window yet, then there's nothing we can do
  198. if (m_hOurWnd == NULL)
  199. return E_FAIL;
  200. m_p3DWindow = new CDirect3DWindow;
  201. if (!m_p3DWindow)
  202. {
  203. return E_OUTOFMEMORY;
  204. }
  205. RECT rcInitialPos = m_rcPos;
  206. RectToDesktop(&rcInitialPos);
  207. HRESULT hr = m_p3DWindow->OnCreate(m_hOurWnd, rcInitialPos);
  208. // The OnSize method creates the initial scene
  209. if (SUCCEEDED(hr))
  210. m_p3DWindow->OnSize(m_hOurWnd, m_rcPos.right-m_rcPos.left,
  211. m_rcPos.bottom-m_rcPos.top);
  212. TimerOn(5);
  213. return hr;
  214. }
  215. STDMETHOD(Stop3D)()
  216. {
  217. TimerOff();
  218. delete m_p3DWindow;
  219. m_p3DWindow = NULL;
  220. return S_OK;
  221. }
  222. STDMETHOD(SetObjectRects)(LPCRECT prcPos,LPCRECT prcClip)
  223. {
  224. if (prcPos == NULL)
  225. {
  226. // I've seen VB5 send this
  227. ATLTRACE(_T("WARNING: SetObjects called with NULL prcPosn"));
  228. return S_OK;
  229. }
  230. HRESULT hr = IOleInPlaceObjectWindowlessImpl<CDirect3D>::SetObjectRects(prcPos, prcClip);
  231. return hr;
  232. }
  233. STDMETHOD(DisplayScene)()
  234. {
  235. if (m_p3DWindow)
  236. {
  237. //          m_p3DWindow->SetPalette();
  238. m_p3DWindow->TickScene();
  239. Draw3DWindow();
  240. }
  241. return S_OK;
  242. }
  243. private:
  244. void Draw3DWindow()
  245. {
  246. static RECT rcOldPos;
  247. if (m_p3DWindow)
  248. {
  249. RECT rcPos = m_rcPos;
  250. RectToDesktop(&rcPos);
  251. // Has the size changed
  252. if ((rcPos.right-rcPos.left != rcOldPos.right-rcOldPos.left) ||
  253. (rcPos.bottom-rcPos.top != rcOldPos.bottom-rcOldPos.top))
  254. {
  255. ATLTRACE(_T("Draw(%d,%d,%d,%d)n"),rcPos.left,rcPos.top,rcPos.right,rcPos.bottom);
  256. m_p3DWindow->OnSize(m_hOurWnd, m_rcPos.right-m_rcPos.left,
  257. m_rcPos.bottom-m_rcPos.top);
  258. ATLTRACE(_T("EndDrawn"));
  259. }
  260. // Has it moved
  261. if (rcPos.left!=rcOldPos.left || rcPos.top!=rcOldPos.top)
  262. m_p3DWindow->OnMove(m_hOurWnd, rcPos.left, rcPos.top);
  263. rcOldPos = rcPos;
  264. m_p3DWindow->DoFrame();
  265. }
  266. }
  267. // Get the window we need to use. This will either be the window that has already
  268. // been created if we are window. If we are windowless the HWND of the client
  269. // will be retrieved from the HDC.
  270. void GetOurWindow()
  271. {
  272. // If we're windowless we still need an HWND for Direct3d
  273. if (m_bWndLess)
  274. {
  275. HDC hDC;
  276. // Get the HDC from the client
  277. m_spInPlaceSite->GetDC(NULL, OLEDC_NODRAW, &hDC);
  278. m_hOurWnd = WindowFromDC(hDC);
  279. #if 1
  280. // Code to make VB5 paint properly now it has clipped it's own hDC
  281. RECT rect;
  282. ::GetClientRect(m_hOurWnd,&rect);
  283. HRGN hRegion = CreateRectRgn(rect.left,rect.top,rect.right,rect.bottom);
  284. SelectClipRgn(hDC,hRegion);
  285. #endif
  286. m_spInPlaceSite->ReleaseDC(hDC);
  287. }
  288. else
  289. m_hOurWnd = m_hWnd;
  290. }
  291. // Convert RECT so that it is relative to the desktop.
  292. void RectToDesktop(RECT* pRect)
  293. {
  294. POINT pt;
  295. pt.x = 0;
  296. pt.y = 0;
  297. ::ClientToScreen(m_hOurWnd, &pt);
  298. if (m_bWndLess)
  299. ::OffsetRect(pRect, pt.x, pt.y);
  300. else
  301. // If we're not windowless, cater for the fact that pRect will not necessarily be at (0,0)
  302. ::OffsetRect(pRect, pt.x-pRect->left, pt.y-pRect->top);
  303. }
  304. HWND                m_hOurWnd;
  305. CDirect3DWindow*    m_p3DWindow;    // Pointer to Direct3D window if we have one
  306. DWORD               m_dwSafety;     // Current safety settings
  307. };