home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / atl / direct3d / d3datl.h < prev    next >
C/C++ Source or Header  |  1998-03-26  |  9KB  |  362 lines

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