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

Windows编程

开发平台:

Visual C++

  1. //---------------------------------------------------------------------------
  2. // Spr.cpp
  3. //---------------------------------------------------------------------------
  4. // Sprite handler
  5. //---------------------------------------------------------------------------
  6. // (C) Copyright 1992-1997 by Microsoft Corporation.  All rights reserved.
  7. //
  8. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  9. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  10. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  11. // PARTICULAR PURPOSE.
  12. //---------------------------------------------------------------------------
  13. #include "Main.h"
  14. #pragma hdrstop
  15. #include "Spr.h"
  16. #include <math.h>
  17. //---------------------------------------------------------------------------
  18. // DEBUG info
  19. //---------------------------------------------------------------------------
  20. SZTHISFILE
  21. //---------------------------------------------------------------------------
  22. // Global Variables
  23. //---------------------------------------------------------------------------
  24. ITypeInfo *g_ptinfoClsSpriteClass = NULL;
  25. ITypeInfo *g_ptinfoIntSpriteClass = NULL;
  26. ITypeInfo *g_ptinfoClsSprite      = NULL;
  27. ITypeInfo *g_ptinfoIntSprite      = NULL;
  28. HBITMAP    g_hbmpStock            = NULL;
  29. HBRUSH     g_hbrushStock          = NULL;
  30. HDC        g_hdcMem               = NULL;
  31. //***************************************************************************
  32. //***************************************************************************
  33. //**
  34. //**  Display Class
  35. //**
  36. //***************************************************************************
  37. //***************************************************************************
  38. //---------------------------------------------------------------------------
  39. // Initialize display surface for sprites
  40. //---------------------------------------------------------------------------
  41. CDisplay::CDisplay
  42. (
  43.   HINSTANCE  hinst,
  44.   HWND       hwnd,
  45.   HDC        hdc,
  46.   IUnknown  *punkParent,
  47.   PFNCOLLIDE pfnCollide,
  48.   int        cimg,
  49.   PIMG       prgimg,
  50.   UINT       idbmp
  51. )
  52. {
  53.   RECT rect;
  54.   INIT_SIGNATURE(SIG_Display);
  55.   // Create an HDC and get the stock bitmap
  56.   if (!g_hdcMem)
  57.     {
  58.     HBITMAP hbmp;
  59.     g_hdcMem = CreateCompatibleDC(NULL);
  60.     hbmp = CreateCompatibleBitmap(g_hdcMem, 1, 1);
  61.     g_hbmpStock = (HBITMAP)SelectObject(g_hdcMem, hbmp);
  62.     SelectObject(g_hdcMem, g_hbmpStock);
  63.     DeleteObject(hbmp);
  64.     g_hbrushStock = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
  65.     }
  66.   // Stash away values & init member variables
  67.   m_hinst      = hinst;
  68.   m_hdc        = hdc;
  69.   GetClientRect(hwnd, &rect);
  70.   m_cx         = rect.right;
  71.   m_cy         = rect.bottom;
  72.   m_pfnCollide = pfnCollide;
  73.   m_csc        = 0;
  74.   m_cimg       = cimg;
  75.   m_prgimg     = prgimg;
  76.   m_idbmp      = idbmp;
  77.   m_psprFirst  = NULL;
  78.   m_psprLast   = NULL;
  79.   m_punkParent = punkParent;
  80.   m_hbmp       = NULL;
  81.   m_hbrushBack = NULL;
  82.   this->SetBackColor(0x00c0c0c0);
  83.   m_hwnd       = hwnd;
  84.   // Compute animated images
  85.   for (int i=0; i<cimg; i++)
  86.     if (prgimg[i].iimgNext != iimgNONE &&
  87.         prgimg[i].iimgNext != iimgREMOVE)
  88.       prgimg[i].pimgNext = &prgimg[prgimg[i].iimgNext];
  89.   // Load in all hbmp
  90.   m_hbmp = LoadBitmap(m_hinst, MAKEINTRESOURCE(m_idbmp));
  91. }
  92. //---------------------------------------------------------------------------
  93. // Terminate Sprite Sytem
  94. //---------------------------------------------------------------------------
  95. CDisplay::~CDisplay
  96. (
  97.   void
  98. )
  99. {
  100.   CHECK_SIGNATURE(SIG_Display);
  101.   if (m_hbrushBack)
  102.     {
  103.     SelectObject(g_hdcMem, g_hbrushStock);
  104.     DeleteObject(m_hbrushBack);
  105.     m_hbrushBack = NULL;
  106.     }
  107.   if (g_hdcMem)
  108.     {
  109.     SelectObject(g_hdcMem, g_hbmpStock);
  110.     DeleteDC(g_hdcMem);
  111.     g_hdcMem = NULL;
  112.     }
  113.   if (m_hbmp)
  114.     {
  115.     // Delete all loaded bitmaps:
  116.     DeleteObject((HGDIOBJ)m_hbmp);
  117.     m_hbmp = (HBITMAP)NULL;
  118.     }
  119.   DESTROY_SIGNATURE(SIG_Display);
  120. }
  121. //---------------------------------------------------------------------------
  122. // Free all sprites on Display.
  123. //---------------------------------------------------------------------------
  124. void CDisplay::DestroyAll
  125. (
  126.   void
  127. )
  128. {
  129.   CSprite *pspr;
  130.   while (m_psprFirst)
  131.     {
  132.     pspr = m_psprFirst;
  133.     pspr->_Unlink(FALSE);
  134.     pspr->Release();
  135.     }
  136. }
  137. //---------------------------------------------------------------------------
  138. // Move all sprites on Display.
  139. //---------------------------------------------------------------------------
  140. void CDisplay::Timer
  141. (
  142.   void
  143. )
  144. {
  145.   CSprite *pspr;
  146.   CSprite *psprPrev;
  147.   for (pspr=m_psprLast; pspr; pspr=psprPrev)
  148.     {
  149.     psprPrev = pspr->m_psprPrev;
  150.     // Fire Tick event, if sprite exists
  151.     if (!pspr->m_fFree)
  152.       {
  153.       if (--pspr->m_tickEvt <= 0)
  154.         {
  155.         pspr->m_psc->FireTick(pspr);
  156.         pspr->m_tickEvt = pspr->m_tickEvtMax;
  157.         }
  158.       }
  159.     // Move sprite, if it still exits (FireTick might have killed it.)
  160.     if (!pspr->m_fFree)
  161.       {
  162.       if (--pspr->m_tickMove <= 0)
  163.         {
  164.         long xOldFull;
  165.         long yOldFull;
  166.         pspr->m_tickMove = pspr->m_tickMoveMax;
  167.         // Does this sprite have a "MoveAt" sprite attached?
  168.         if (pspr->m_psprAt)
  169.           pspr->DoMoveAt(pspr->m_psprAt, pspr->m_dMaxAt, pspr->m_scaleAt, pspr->m_flagsAt, TRUE);
  170.         xOldFull = pspr->m_xFull;
  171.         yOldFull = pspr->m_yFull;
  172.         if (HIWORD(xOldFull + pspr->m_vxFull) == HIWORD(xOldFull) &&
  173.             HIWORD(yOldFull + pspr->m_vyFull) == HIWORD(yOldFull))
  174.           {
  175.           // Movement was only fractional, so don't need to redraw sprite.
  176.           pspr->m_xFull += pspr->m_vxFull;
  177.           pspr->m_yFull += pspr->m_vyFull;
  178.           }
  179.         else
  180.           {
  181.           pspr->_Erase();
  182.           pspr->m_xFull += pspr->m_vxFull;
  183.           pspr->m_yFull += pspr->m_vyFull;
  184.           if (pspr->m_pimg->iimgNext == iimgREMOVE)
  185.             pspr->Remove();
  186.           else if (pspr->m_pimg->iimgNext != iimgNONE)
  187.             {
  188.             pspr->m_iimg = pspr->m_pimg->iimgNext;
  189.             pspr->m_pimg = pspr->m_pimg->pimgNext;
  190.             }
  191.           if (!pspr->_FDraw(TRUE))
  192.             {
  193.             pspr->m_xFull = xOldFull;
  194.             pspr->m_yFull = yOldFull;
  195.             pspr->_FDraw(FALSE);
  196.             }
  197.           }
  198.         // Calculate Friction
  199.         if (pspr->m_fFriction)
  200.           {
  201.           pspr->m_vxFull = (long)((FLOAT)pspr->m_vxFull * pspr->m_fx);
  202.           pspr->m_vyFull = (long)((FLOAT)pspr->m_vyFull * pspr->m_fy);
  203.           }
  204.         // Calculate AccelerationFriction
  205.         if (pspr->m_psc->m_fFrictionAccel)
  206.           {
  207.           pspr->m_axFull = (long)((FLOAT)pspr->m_axFull * pspr->m_psc->m_frictionAccel);
  208.           pspr->m_ayFull = (long)((FLOAT)pspr->m_ayFull * pspr->m_psc->m_frictionAccel);
  209.           }
  210.         // Calculate Acceleration
  211.         pspr->m_vxFull += pspr->m_axFull;
  212.         pspr->m_vyFull += pspr->m_ayFull;
  213.         // Ensure Vel is not over max allowed for SpriteClass
  214.         if (pspr->m_vxFull > pspr->m_psc->m_vFullMax)
  215.           pspr->m_vxFull = pspr->m_psc->m_vFullMax;
  216.         else if (pspr->m_vxFull < -pspr->m_psc->m_vFullMax)
  217.           pspr->m_vxFull = -pspr->m_psc->m_vFullMax;
  218.         if (pspr->m_vyFull > pspr->m_psc->m_vFullMax)
  219.           pspr->m_vyFull = pspr->m_psc->m_vFullMax;
  220.         else if (pspr->m_vyFull < -pspr->m_psc->m_vFullMax)
  221.           pspr->m_vyFull = -pspr->m_psc->m_vFullMax;
  222.         }
  223.       }
  224.     if (pspr->m_fFree)
  225.       {
  226.       pspr->_Unlink(TRUE);
  227.       pspr->Release();
  228.       }
  229.     }
  230. }
  231. //---------------------------------------------------------------------------
  232. // Paint all sprites.
  233. //---------------------------------------------------------------------------
  234. void CDisplay::Paint
  235. (
  236.   HDC hdc
  237. )
  238. {
  239.   CSprite *pspr;
  240.   if (hdc == NULL)
  241.     hdc = m_hdc;
  242.   for (pspr=m_psprLast; pspr; pspr=pspr->m_psprPrev)
  243.     {
  244.     if (!pspr->m_fFree && !pspr->m_fHidden)
  245.       {
  246.       SelectObject(g_hdcMem, m_hbmp);
  247.       BitBlt(hdc, pspr->m_x, pspr->m_y, pspr->m_pimg->cx, pspr->m_pimg->cy, g_hdcMem, pspr->m_pimg->x, pspr->m_pimg->y, SRCCOPY);
  248.       }
  249.     }
  250.   SelectObject(g_hdcMem, g_hbmpStock);
  251. }
  252. //---------------------------------------------------------------------------
  253. // Paint any sprites with fNeedRefresh set.
  254. //---------------------------------------------------------------------------
  255. void CDisplay::Refresh
  256. (
  257.   void
  258. )
  259. {
  260.   CSprite *pspr;
  261.   HDC    hdc = m_hdc;
  262.   for (pspr=m_psprLast; pspr; pspr=pspr->m_psprPrev)
  263.     {
  264.     if (pspr->m_fNeedRefresh && !pspr->m_fHidden)
  265.       {
  266.       pspr->m_fNeedRefresh = FALSE;
  267.       SelectObject(g_hdcMem, m_hbmp);
  268.       BitBlt(hdc, pspr->m_x, pspr->m_y, pspr->m_pimg->cx, pspr->m_pimg->cy, g_hdcMem, pspr->m_pimg->x, pspr->m_pimg->y, SRCCOPY);
  269.       }
  270.     }
  271.   SelectObject(g_hdcMem, g_hbmpStock);
  272. }
  273. //---------------------------------------------------------------------------
  274. //
  275. //---------------------------------------------------------------------------
  276. void CDisplay::SetBackColor
  277. (
  278.   COLORREF c
  279. )
  280. {
  281.   static LOGBRUSH lb = {BS_SOLID, 0x00c0c0c0, 0};
  282.   if (m_colorBack == c)
  283.     return;
  284.   m_colorBack = c;
  285.   lb.lbColor = c;
  286.   if (m_hbrushBack)
  287.     DeleteObject(m_hbrushBack);
  288.   m_hbrushBack = CreateBrushIndirect(&lb);
  289. }
  290. //---------------------------------------------------------------------------
  291. // Send Collide event back to the fn passed into the constructor.
  292. //---------------------------------------------------------------------------
  293. void CDisplay::FireCollide
  294. (
  295.   CSprite *psprLowId,
  296.   CSprite *psprHighId,
  297.   int      maskCollide
  298. )
  299. {
  300.   (*m_pfnCollide)(psprLowId, psprHighId, maskCollide);
  301. }
  302. //***************************************************************************
  303. //***************************************************************************
  304. //**
  305. //**  SpriteClass Class
  306. //**
  307. //***************************************************************************
  308. //***************************************************************************
  309. HRESULT s_hr = S_OK;
  310. //---------------------------------------------------------------------------
  311. // Create function for SpriteClass.  Use instead of "new CSpriteClass".
  312. //---------------------------------------------------------------------------
  313. HRESULT CSpriteClass::Create
  314. (
  315.   CDisplay      *pdisp,
  316.   CSpriteClass **ppscOut
  317. )
  318. {
  319.   if (!ppscOut)
  320.     return E_INVALIDARG;
  321.   *ppscOut = new CSpriteClass(pdisp);
  322.   if (!*ppscOut)
  323.     return E_OUTOFMEMORY;
  324.   return S_OK;
  325. }
  326. //---------------------------------------------------------------------------
  327. // Constructor for SpriteClass
  328. //---------------------------------------------------------------------------
  329. CSpriteClass::CSpriteClass
  330. (
  331.   CDisplay *pdisp
  332. )
  333. {
  334.   INIT_SIGNATURE(SIG_SpriteClass);
  335.   m_id              = ++(pdisp->m_csc);
  336.   m_pdisp           = pdisp;
  337.   m_brd             = SPR_brdALL;
  338.   m_maskCollide     = 0;
  339.   m_iimg            = 0;
  340.   m_cspr            = 0;
  341.   m_cref            = 1;
  342.   m_pdispBaseObject = NULL;
  343.   VariantInit(&m_varTag);
  344.   m_friction        = (FLOAT)1.0;
  345.   m_frictionAccel   = (FLOAT)1.0;
  346.   m_fFrictionAccel  = FALSE;
  347.   m_vFullMax    = 0x000a0000;
  348.   m_aFullMax    = 0x00010000;
  349. }
  350. //---------------------------------------------------------------------------
  351. // Destructor for Sprite
  352. //---------------------------------------------------------------------------
  353. void CSpriteClass::Close
  354. (
  355.   void
  356. )
  357. {
  358.   CHECK_SIGNATURE(SIG_SpriteClass);
  359.   CSprite *pspr;
  360.   CSprite *psprPrev;
  361.   // Destroy all sprites of this SpriteClass
  362.   for (pspr=m_pdisp->m_psprLast; pspr; pspr=psprPrev)
  363.     {
  364.     psprPrev = pspr->m_psprPrev;
  365.     if (pspr->m_psc == this)
  366.       {
  367.       pspr->_Unlink(FALSE);
  368.       pspr->m_psc = NULL;
  369.       pspr->Release();
  370.       }
  371.     }
  372.   // Unadvise all event sinks
  373.   m_cp.Close();
  374.   // Clear incase this is an object
  375.   VariantClear(&m_varTag);
  376. }
  377. //---------------------------------------------------------------------------
  378. // Destructor for Sprite
  379. //---------------------------------------------------------------------------
  380. CSpriteClass::~CSpriteClass
  381. (
  382.   void
  383. )
  384. {
  385.   CHECK_SIGNATURE(SIG_SpriteClass);
  386.   this->Close();
  387.   DESTROY_SIGNATURE(SIG_SpriteClass);
  388. }
  389. //***************************************************************************
  390. // IUnknown Interface
  391. //***************************************************************************
  392. //---------------------------------------------------------------------------
  393. // 
  394. //---------------------------------------------------------------------------
  395. STDMETHODIMP CSpriteClass::QueryInterface
  396. (
  397.   REFIID  iid,
  398.   LPVOID* ppvObjOut
  399. )
  400. {
  401.   if (!ppvObjOut)
  402.     return E_INVALIDARG;
  403.   *ppvObjOut = NULL;
  404.   if (iid == IID_IUnknown)
  405.     *ppvObjOut = this->GetUnknown();
  406.   else if (iid == IID_IDispatch)
  407.     *ppvObjOut = this->GetDispatch();
  408.   else if (iid == IID_ISpriteClass)
  409.     *ppvObjOut = (ISpriteClass *)this;
  410.   else if (iid == IID_IConnectionPointContainer)
  411.     *ppvObjOut = (IConnectionPointContainer *)this;
  412.   else if (iid == IID_IProvideClassInfo)
  413.     *ppvObjOut = (IProvideClassInfo *)this;
  414.   if (*ppvObjOut)
  415.     {
  416.     this->AddRef();
  417.     return S_OK;
  418.     }
  419.   return E_NOINTERFACE;
  420. }
  421. //---------------------------------------------------------------------------
  422. // 
  423. //---------------------------------------------------------------------------
  424. STDMETHODIMP_(ULONG) CSpriteClass::AddRef
  425. (
  426.   void 
  427. )
  428. {
  429.   return ++m_cref;
  430. }
  431. //---------------------------------------------------------------------------
  432. // 
  433. //---------------------------------------------------------------------------
  434. STDMETHODIMP_(ULONG) CSpriteClass::Release
  435. (
  436.   void 
  437. )
  438. {
  439.   ASSERT(m_cref, "bad m_cref");
  440.   m_cref--;
  441.   if (!m_cref)
  442.     {
  443.     this->Close();
  444.     if (!m_cref && !m_cp.m_cref)
  445.       {
  446.       delete this;
  447.       return 0;
  448.       }
  449.     }
  450.   return m_cref;
  451. }
  452. //***************************************************************************
  453. // IDispatch Interface
  454. //***************************************************************************
  455. //---------------------------------------------------------------------------
  456. // Method needed by COleAuto, so it can implement IDispatch for us.
  457. //---------------------------------------------------------------------------
  458. HRESULT CSpriteClass::GetTypeLibInfo
  459. (
  460.   HINSTANCE    *phinstOut,
  461.   const GUID  **pplibidOut, 
  462.   SHORT        *pwMajLib, 
  463.   SHORT        *pwMinLib,
  464.   const CLSID **ppclsidOut, 
  465.   const IID   **ppiidOut, 
  466.   ITypeLib   ***ppptlOut
  467. )
  468. {
  469.   *phinstOut  = g_hinst;
  470.   *pplibidOut = &LIBID_SPRUUIDS;
  471.   *pwMajLib   = 1;
  472.   *pwMinLib   = 0;
  473.   *ppclsidOut = &CLSID_SpriteClass;
  474.   *ppiidOut   = &IID_ISpriteClass;
  475.   *ppptlOut   = &g_ptlMain;
  476.   return S_OK;
  477. }
  478. //***************************************************************************
  479. // IProvideClassInfo Interface
  480. //***************************************************************************
  481. //---------------------------------------------------------------------------
  482. // 
  483. //---------------------------------------------------------------------------
  484. STDMETHODIMP CSpriteClass::GetClassInfo
  485. (
  486.   ITypeInfo** pptinfoOut
  487. )
  488. {
  489.   HRESULT hr = ((COleAuto *)this)->CheckTypeInfo(0, 0x0409);
  490.   if (hr)
  491.     return hr;
  492.   *pptinfoOut = g_ptinfoClsSpriteClass;
  493.   (*pptinfoOut)->AddRef();
  494.   return S_OK;
  495. }
  496. //---------------------------------------------------------------------------
  497. // 
  498. //---------------------------------------------------------------------------
  499. STDMETHODIMP CSpriteClass::GetGUID
  500. (
  501.   DWORD dwGuidKind,
  502.   GUID* pGUID
  503. )
  504. {
  505.   if (pGUID)
  506.     return E_INVALIDARG;
  507.   if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
  508.     return E_INVALIDARG;
  509.   *pGUID = DIID_ISpriteClassEvents;
  510.   return S_OK;
  511. }
  512. //***************************************************************************
  513. // IConnectionPointContainer Interface
  514. //***************************************************************************
  515. //---------------------------------------------------------------------------
  516. // 
  517. //---------------------------------------------------------------------------
  518. STDMETHODIMP CSpriteClass::EnumConnectionPoints
  519. (
  520.   LPENUMCONNECTIONPOINTS* ppEnum
  521. )
  522. {
  523.   return E_NOTIMPL;   // UNDONE: Implement this method
  524. }
  525. //---------------------------------------------------------------------------
  526. // 
  527. //---------------------------------------------------------------------------
  528. STDMETHODIMP CSpriteClass::FindConnectionPoint
  529. (
  530.   REFIID             iid,
  531.   LPCONNECTIONPOINT* ppCpOut
  532. )
  533. {
  534.   if (!ppCpOut)
  535.     return E_INVALIDARG;
  536.   if (iid == DIID_ISpriteClassEvents || iid == IID_IDispatch)
  537.     {
  538.     *ppCpOut = &m_cp;
  539.     (*ppCpOut)->AddRef();
  540.     return S_OK;
  541.     }
  542.     
  543.   return E_NOINTERFACE;
  544. }
  545. //***************************************************************************
  546. // Embedded IConnectionPoint Class
  547. //***************************************************************************
  548. //---------------------------------------------------------------------------
  549. // 
  550. //---------------------------------------------------------------------------
  551. CSpriteClass::XCP::XCP
  552. (
  553.   void
  554. )
  555. {
  556.   m_cref = 1;
  557.   for (int i=0; i<SC_cADVISE; i++)
  558.     m_rgpdisp[i] = NULL;
  559. }
  560. //---------------------------------------------------------------------------
  561. // 
  562. //---------------------------------------------------------------------------
  563. void CSpriteClass::XCP::Close
  564. (
  565.   void
  566. )
  567. {
  568.   for (int i=0; i<SC_cADVISE; i++)
  569.     if (m_rgpdisp[i])
  570.       {
  571.       m_rgpdisp[i]->Release();
  572.       m_rgpdisp[i] = NULL;
  573.       }
  574. }
  575. //---------------------------------------------------------------------------
  576. // 
  577. //---------------------------------------------------------------------------
  578. STDMETHODIMP CSpriteClass::XCP::QueryInterface
  579. (
  580.   REFIID  iid,
  581.   LPVOID* ppvObjOut
  582. )
  583. {
  584.   if (!ppvObjOut)
  585.     return E_INVALIDARG;
  586.   *ppvObjOut = NULL;
  587.   if (iid == IID_IUnknown)
  588.     *ppvObjOut = this->GetUnknown();
  589.   else if (iid == IID_IConnectionPoint)
  590.     *ppvObjOut = (IConnectionPoint *)this;
  591.   if (*ppvObjOut)
  592.     {
  593.     this->AddRef();
  594.     return S_OK;
  595.     }
  596.   return E_NOINTERFACE;
  597. }
  598. //---------------------------------------------------------------------------
  599. // 
  600. //---------------------------------------------------------------------------
  601. STDMETHODIMP_(ULONG) CSpriteClass::XCP::AddRef
  602. (
  603.   void 
  604. )
  605. {
  606.   return ++m_cref;
  607. }
  608. #define SCOFCP(pcp)  ((CSpriteClass *)((char *)pcp - (char *)&(((CSpriteClass *)0)->m_cp)))
  609. //---------------------------------------------------------------------------
  610. // 
  611. //---------------------------------------------------------------------------
  612. STDMETHODIMP_(ULONG) CSpriteClass::XCP::Release
  613. (
  614.   void 
  615. )
  616. {
  617.   CSpriteClass *psc = SCOFCP(this);
  618.   ASSERT(m_cref, "bad m_cref");
  619.   m_cref--;
  620.   if (!m_cref && !psc->m_cref)
  621.     {
  622.     delete psc;
  623.     return 0;
  624.     }
  625.   return m_cref;
  626. }
  627. //***************************************************************************
  628. // IConnectionPoint Interface
  629. //***************************************************************************
  630. //---------------------------------------------------------------------------
  631. // 
  632. //---------------------------------------------------------------------------
  633. STDMETHODIMP CSpriteClass::XCP::GetConnectionInterface
  634. (
  635.   IID* piid
  636. )
  637. {
  638.   if (!piid)
  639.     return E_INVALIDARG;
  640.   memcpy(piid, &DIID_ISpriteClassEvents, sizeof(IID));
  641.   return S_OK;
  642. }
  643. //---------------------------------------------------------------------------
  644. // 
  645. //---------------------------------------------------------------------------
  646. STDMETHODIMP CSpriteClass::XCP::GetConnectionPointContainer
  647. (
  648.   IConnectionPointContainer** ppCpcOut
  649. )
  650. {
  651.   if (!ppCpcOut)
  652.     return E_INVALIDARG;
  653.   *ppCpcOut = SCOFCP(this);
  654.   (*ppCpcOut)->AddRef();
  655.   return S_OK;
  656. }
  657. //---------------------------------------------------------------------------
  658. // 
  659. //---------------------------------------------------------------------------
  660. STDMETHODIMP CSpriteClass::XCP::Advise
  661. (
  662.   IUnknown* punkSink,
  663.   DWORD*    pdwCookie
  664. )
  665. {
  666.   IDispatch  *psce = NULL;
  667.   IDispatch **ppdisp;
  668.   HRESULT     hr;
  669.   if (!punkSink || !pdwCookie)
  670.     return E_INVALIDARG;
  671.   *pdwCookie = 0;
  672.   // Look for empty slot
  673.   for (ppdisp=m_rgpdisp; *ppdisp && ppdisp<&m_rgpdisp[SC_cADVISE]; ppdisp++)
  674.     ;
  675.   // Did we find one?
  676.   if (ppdisp >= &m_rgpdisp[SC_cADVISE])
  677.     return E_FAIL;          // UNDONE: Error?
  678.   // Now see if sink supports correct interface
  679.   hr = punkSink->QueryInterface(DIID_ISpriteClassEvents, (void **)&psce);
  680.   if (hr == E_NOINTERFACE)
  681.     {
  682.     hr = punkSink->QueryInterface(IID_IDispatch, (void **)&psce);
  683.     if (hr)
  684.       return hr;
  685.     }
  686.   ASSERT(psce, "QI but no ptr");
  687.   // Finish advise by stashing punkSink QI'd to our interface
  688.   *ppdisp = psce;       // AddRef'd from QI
  689.   *pdwCookie = (ppdisp - m_rgpdisp) + 1;
  690.   return S_OK;
  691. }
  692. //---------------------------------------------------------------------------
  693. // 
  694. //---------------------------------------------------------------------------
  695. STDMETHODIMP CSpriteClass::XCP::Unadvise
  696. (
  697.   DWORD dwCookie
  698. )
  699. {
  700.   if (!dwCookie || dwCookie > SC_cADVISE)
  701.     return E_INVALIDARG;
  702.   m_rgpdisp[dwCookie-1]->Release();
  703.   m_rgpdisp[dwCookie-1] = NULL;
  704.   return S_OK;
  705. }
  706. //---------------------------------------------------------------------------
  707. // 
  708. //---------------------------------------------------------------------------
  709. STDMETHODIMP CSpriteClass::XCP::EnumConnections
  710. (
  711.   LPENUMCONNECTIONS* ppEnum
  712. )
  713. {
  714.   return E_NOTIMPL;   // UNDONE: Implement this method
  715. }
  716. //***************************************************************************
  717. //***************************************************************************
  718. //**
  719. //**  Sprite Class
  720. //**
  721. //***************************************************************************
  722. //***************************************************************************
  723. //---------------------------------------------------------------------------
  724. // Constructor for Sprite
  725. //---------------------------------------------------------------------------
  726. CSprite::CSprite
  727. (
  728.   CSpriteClass *psc,
  729.   int           x,
  730.   int           y,
  731.   CSprite      *psprPrev,   // NULL==1st, -1==Last
  732.   VARIANT      *pvarUser
  733. )
  734. {
  735.   INIT_SIGNATURE(SIG_Sprite);
  736.   m_pdisp        = psc->m_pdisp;
  737.   m_psprNext     = NULL;
  738.   m_psprPrev     = psprPrev;
  739.   m_xFull        = 0;
  740.   m_x            = x;
  741.   m_yFull        = 0;
  742.   m_y            = y;
  743.   m_vxFull       = 0;
  744.   m_vyFull       = 0;
  745.   m_axFull       = 0;
  746.   m_ayFull       = 0;
  747.   m_fx           = psc->m_friction;
  748.   m_fy           = psc->m_friction;
  749.   m_fFriction    = (psc->m_friction != 1.0);
  750.   m_tickEvt      = 0x7fffffff;
  751.   m_tickEvtMax   = 0x7fffffff;
  752.   m_tickMove     = 1;
  753.   m_tickMoveMax  = 1;
  754.   m_iimg         = psc->m_iimg;
  755.   m_pimg         = &m_pdisp->m_prgimg[m_iimg];
  756.   m_psc          = psc;
  757.   m_fNeedRefresh = TRUE;
  758.   m_fFree        = FALSE;
  759.   m_fIgnoreMove  = FALSE;
  760.   m_fLinked      = FALSE;
  761.   m_fHidden      = 2;     // Set to 2 instead of TRUE to detect if user explicitly hides it during _Init event
  762.   m_cref         = 1;
  763.   m_psprAt       = NULL;
  764.   m_pdispBaseObject = NULL;
  765.   VariantInit(&m_varTag);
  766.   this->_Link();
  767.   m_psc->FireInit(this, pvarUser);
  768.   if (m_fHidden == 2) 
  769.     m_fHidden = FALSE;    // If not explicitly hidden in event, show it
  770. }
  771. //---------------------------------------------------------------------------
  772. // Destructor for Sprite
  773. //---------------------------------------------------------------------------
  774. CSprite::~CSprite
  775. (
  776.   void
  777. )
  778. {
  779.   CHECK_SIGNATURE(SIG_Sprite);
  780.   VariantClear(&m_varTag);
  781.   if (m_psprAt)
  782.     {
  783.     m_psprAt->Release();
  784.     m_psprAt = NULL;
  785.     }
  786.   this->_Unlink(TRUE);
  787.   DESTROY_SIGNATURE(SIG_Sprite);
  788. }
  789. //---------------------------------------------------------------------------
  790. // Change the class of an existing pspr
  791. //---------------------------------------------------------------------------
  792. CSprite *CSprite::PsprMutate
  793. (
  794.   CSpriteClass *psc,
  795.   VARIANT      *pvarUser
  796. )
  797. {
  798.   m_x          += m_pimg->cx >> 1;
  799.   m_y          += m_pimg->cy >> 1;
  800.   m_iimg        = psc->m_iimg;
  801.   m_pimg        = &m_pdisp->m_prgimg[m_iimg];
  802.   m_x          -= m_pimg->cx >> 1;
  803.   m_y          -= m_pimg->cy >> 1;
  804.   m_psc->m_cspr--;
  805.   m_psc         = psc;
  806.   m_psc->m_cspr++;
  807.   m_tickEvt     = 0x7fffffff;
  808.   m_tickEvtMax  = 0x7fffffff;
  809.   m_tickMove    = 0;
  810.   m_tickMoveMax = 1;
  811.   m_fHidden     = 2;     // Set to 2 instead of TRUE to detect if user explicitly hides it during _Init event
  812.   
  813.   m_psc->FireInit(this, pvarUser);
  814.   if (m_fHidden == 2) 
  815.     m_fHidden = FALSE;    // If not explicitly hidden in event, show it
  816.   return this;
  817. }
  818. //---------------------------------------------------------------------------
  819. // Free a SPR structure
  820. //---------------------------------------------------------------------------
  821. void CSprite::MarkFree
  822. (
  823.   void
  824. )
  825. {
  826.   if (m_psprAt)
  827.     {
  828.     m_psprAt->Release();
  829.     m_psprAt = NULL;
  830.     }
  831.   m_psc->FireTerm(this);
  832.   m_fFree = TRUE;
  833. }
  834. //---------------------------------------------------------------------------
  835. // Link a sprite into the display list
  836. //---------------------------------------------------------------------------
  837. void CSprite::_Link
  838. (
  839.   void
  840. )
  841. {
  842.   if (!m_psprPrev)
  843.     {
  844.     m_psprNext = m_pdisp->m_psprFirst;
  845.     m_pdisp->m_psprFirst = this;
  846.     if (m_psprNext)
  847.       m_psprNext->m_psprPrev = this;
  848.     if (!m_pdisp->m_psprLast)
  849.       m_pdisp->m_psprLast = this;
  850.     }
  851.   else if (m_psprPrev == (CSprite *)-1)
  852.     {
  853.     m_psprNext = NULL;
  854.     m_psprPrev = m_pdisp->m_psprLast;
  855.     if (m_pdisp->m_psprLast)
  856.       m_pdisp->m_psprLast->m_psprNext = this;
  857.     else
  858.       m_pdisp->m_psprFirst = this;
  859.     m_pdisp->m_psprLast = this;
  860.     }
  861.   else
  862.     {
  863.     // UNDONE: Fix this up.
  864.     m_psprNext = m_pdisp->m_psprLast->m_psprNext;
  865.     m_pdisp->m_psprLast->m_psprNext = this;
  866.     m_psprNext->m_psprPrev = this;
  867.     if (m_pdisp->m_psprLast == m_pdisp->m_psprLast)
  868.       m_pdisp->m_psprLast = this;
  869.     }
  870.   m_fLinked = TRUE;
  871.   m_psc->m_cspr++;
  872.   //this->_FDraw(FALSE);      // Require "s.Refresh" to avoid spurious paint before img set
  873. }
  874. //---------------------------------------------------------------------------
  875. // Unlink a sprite into the display list
  876. //---------------------------------------------------------------------------
  877. void CSprite::_Unlink
  878. (
  879.   BOOL fFireEvt
  880. )
  881. {
  882.   if (!m_fLinked)
  883.     return;
  884.   this->_Erase();
  885.   if (m_pdisp->m_psprFirst == this)
  886.     m_pdisp->m_psprFirst = m_psprNext;
  887.   if (m_pdisp->m_psprLast  == this)
  888.     m_pdisp->m_psprLast  = m_psprPrev;
  889.   if (m_psprPrev)
  890.     m_psprPrev->m_psprNext = m_psprNext;
  891.   if (m_psprNext)
  892.     m_psprNext->m_psprPrev = m_psprPrev;
  893.   m_fLinked = FALSE;
  894.   m_fHidden = TRUE;
  895.   // Track # of sprites of this kind.  If there are no more, then
  896.   // fire the _LastTerm event.
  897.   m_psc->m_cspr--;
  898.   if (fFireEvt && !m_psc->m_cspr)
  899.     m_psc->FireLastTerm();
  900.   if (m_psprAt)
  901.     {
  902.     m_psprAt->Release();
  903.     m_psprAt = NULL;
  904.     }
  905. }
  906. //---------------------------------------------------------------------------
  907. // Draw the given sprite
  908. //---------------------------------------------------------------------------
  909. BOOL CSprite::_FDraw
  910. (
  911.   BOOL fCollide
  912. )
  913. {
  914.   CSprite *psprT;
  915.   CSprite *psprNext;
  916.   int x   = m_x;
  917.   int y   = m_y;
  918.   int cx  = m_pimg->cx;
  919.   int cy  = m_pimg->cy;
  920.   HDC hdc = m_pdisp->m_hdc;
  921.   if (fCollide && !m_fFree)
  922.     {
  923.     int maskCollide = m_psc->m_maskCollide;
  924.     if (m_fHidden)
  925.       goto DoneWithColl;
  926.     for (psprT=m_pdisp->m_psprFirst; psprT; psprT=psprNext)
  927.       {
  928.       psprNext = psprT->m_psprNext;
  929.       if (psprT != this &&                                    // Never collide w/self
  930.           ((psprT->m_psc != m_psc) || (maskCollide & 1)) &&   // Coll w/like kind only if bit 1 set
  931.           (maskCollide & psprT->m_psc->m_maskCollide & ~1) && // Coll w/other kinds only if masks overlap
  932.           x <= psprT->m_x+psprT->m_pimg->cx && x+cx >= psprT->m_x && // Coll only if actually touch
  933.           y <= psprT->m_y+psprT->m_pimg->cy && y+cy >= psprT->m_y)
  934.         {
  935.         m_fIgnoreMove = FALSE;
  936.         if (m_psc->m_id <= psprT->m_psc->m_id)
  937.           m_pdisp->FireCollide(this, psprT, maskCollide & psprT->m_psc->m_maskCollide);
  938.         else
  939.           m_pdisp->FireCollide(psprT, this, maskCollide & psprT->m_psc->m_maskCollide);
  940.         if (m_fFree)
  941.           return TRUE;
  942.         if (m_fIgnoreMove)
  943.           return FALSE;
  944.         if (psprT->m_fFree)
  945.           goto DoneWithColl;
  946.         }
  947.       }
  948. DoneWithColl:;
  949.     if ((m_psc->m_brd & SPR_brdALL))
  950.       {
  951.       BRD brd = 0;
  952.       if (m_psc->m_brd & SPR_brdIN)
  953.         {
  954.         if (x < 0) brd = SPR_brdINLEFT;
  955.         if (y < 0) brd |= SPR_brdINTOP;
  956.         if (x+cx > m_pdisp->m_cx) brd |= SPR_brdINRIGHT;
  957.         if (y+cy > m_pdisp->m_cy) brd |= SPR_brdINBOTTOM;
  958.         }
  959.       if (m_psc->m_brd & SPR_brdOUT)
  960.         {
  961.         if (x+cx < 0) brd  = SPR_brdOUTLEFT;
  962.         if (y+cy < 0) brd |= SPR_brdOUTTOP;
  963.         if (x > m_pdisp->m_cx) brd |= SPR_brdOUTRIGHT;
  964.         if (y > m_pdisp->m_cy) brd |= SPR_brdOUTBOTTOM;
  965.         }
  966.       if (brd)
  967.         {
  968.         m_fIgnoreMove = FALSE;
  969.         m_psc->FireBorder(this, brd);
  970.         if (m_fFree)
  971.           return TRUE;
  972.         if (m_fIgnoreMove)
  973.           return FALSE;
  974.         }
  975.       }
  976.     }
  977.   // Don't draw if not visible
  978.   if (m_fHidden)
  979.     return TRUE;
  980.   SelectObject(g_hdcMem, m_pdisp->m_hbmp);
  981.   BitBlt(hdc, m_x, m_y, cx, cy, g_hdcMem, m_pimg->x, m_pimg->y, SRCCOPY);
  982.   m_fNeedRefresh = FALSE;
  983.   for (psprT=m_psprPrev; psprT; psprT=psprT->m_psprPrev)
  984.     {
  985.     if (!psprT->m_fNeedRefresh &&
  986.         x <= psprT->m_x+psprT->m_pimg->cx && x+cx >= psprT->m_x &&
  987.         y <= psprT->m_y+psprT->m_pimg->cy && y+cy >= psprT->m_y)
  988.       {
  989.       psprT->m_fNeedRefresh = TRUE;
  990.       }
  991.     }
  992.   SelectObject(g_hdcMem, g_hbmpStock);
  993.   return TRUE;
  994. }
  995. //---------------------------------------------------------------------------
  996. // Erase the given sprite
  997. //---------------------------------------------------------------------------
  998. void CSprite::_Erase
  999. (
  1000.   void
  1001. )
  1002. {
  1003.   int      x   = m_x;
  1004.   int      y   = m_y;
  1005.   int      cx  = m_pimg->cx;
  1006.   int      cy  = m_pimg->cy;
  1007.   HDC      hdc = m_pdisp->m_hdc;
  1008.   CSprite *psprT;
  1009.   SelectObject(hdc, (HGDIOBJ)(m_pdisp->m_hbrushBack ? m_pdisp->m_hbrushBack : g_hbrushStock));
  1010.   PatBlt(hdc, m_x, m_y, cx, cy, PATCOPY);
  1011.   for (psprT=m_pdisp->m_psprLast; psprT; psprT=psprT->m_psprPrev)
  1012.     {
  1013.     if (psprT != this && !psprT->m_fNeedRefresh &&
  1014.         x <= psprT->m_x+psprT->m_pimg->cx && x+cx >= psprT->m_x &&
  1015.         y <= psprT->m_y+psprT->m_pimg->cy && y+cy >= psprT->m_y)
  1016.       psprT->m_fNeedRefresh = TRUE;
  1017.     }
  1018.   SelectObject(g_hdcMem, g_hbrushStock);
  1019. }
  1020. //---------------------------------------------------------------------------
  1021. // Move the given sprite to new location
  1022. //---------------------------------------------------------------------------
  1023. BOOL CSprite::MoveToFull
  1024. (
  1025.   long xFull,
  1026.   long yFull,
  1027.   BOOL fCollide
  1028. )
  1029. {
  1030.   long xOldFull = m_xFull;
  1031.   long yOldFull = m_yFull;
  1032.   this->_Erase();
  1033.   m_xFull = xFull;
  1034.   m_yFull = yFull;
  1035.   if (m_pimg->iimgNext == iimgREMOVE)
  1036.     this->Remove();
  1037.   else if (m_pimg->iimgNext != iimgNONE)
  1038.     {
  1039.     m_iimg = m_pimg->iimgNext;
  1040.     m_pimg = m_pimg->pimgNext;
  1041.     }
  1042.   if (!this->_FDraw(fCollide))
  1043.     {
  1044.     m_xFull = xOldFull;
  1045.     m_yFull = yOldFull;
  1046.     this->_FDraw(FALSE);
  1047.     return FALSE;
  1048.     }
  1049.   return TRUE;
  1050. }
  1051. //---------------------------------------------------------------------------
  1052. // Move the given sprite to new location
  1053. //---------------------------------------------------------------------------
  1054. BOOL CSprite::MoveByFull
  1055. (
  1056.   long dxFull,
  1057.   long dyFull,
  1058.   BOOL fCollide
  1059. )
  1060. {
  1061.   long xOldFull = m_xFull;
  1062.   long yOldFull = m_yFull;
  1063.   if (HIWORD(xOldFull + dxFull) == HIWORD(xOldFull) &&
  1064.       HIWORD(yOldFull + dyFull) == HIWORD(yOldFull))
  1065.     {
  1066.     m_xFull += dxFull;
  1067.     m_yFull += dyFull;
  1068.     return TRUE;
  1069.     }
  1070.   this->_Erase();
  1071.   m_xFull += dxFull;
  1072.   m_yFull += dyFull;
  1073.   if (m_pimg->iimgNext == iimgREMOVE)
  1074.     this->Remove();
  1075.   else if (m_pimg->iimgNext != iimgNONE)
  1076.     {
  1077.     m_iimg = m_pimg->iimgNext;
  1078.     m_pimg = m_pimg->pimgNext;
  1079.     }
  1080.   if (!this->_FDraw(fCollide))
  1081.     {
  1082.     m_xFull = xOldFull;
  1083.     m_yFull = yOldFull;
  1084.     this->_FDraw(FALSE);
  1085.     return FALSE;
  1086.     }
  1087.   return TRUE;
  1088. }
  1089. //---------------------------------------------------------------------------
  1090. // flags: 1=X, 2=Y;
  1091. //        4=Pos, 8=Vel, 16=Accel;
  1092. //        32=Less With Distance (default=More);
  1093. //        128=Remember
  1094. //---------------------------------------------------------------------------
  1095. BOOL CSprite::DoMoveAt
  1096. (
  1097.   CSprite *psprAt,
  1098.   float    scale,
  1099.   float    dMax,
  1100.   long     flags,
  1101.   BOOL     fCollide
  1102. )
  1103.   {
  1104.   long dx = psprAt->m_xFull - m_xFull;
  1105.   long dy = psprAt->m_yFull - m_yFull;
  1106.   if (flags & MAS_RECIPDIST)
  1107.     {
  1108.     dx = FULLOFFLOAT((FLOAT)1.0 / FLOATOFFULL(dx | 0xffff));
  1109.     dy = FULLOFFLOAT((FLOAT)1.0 / FLOATOFFULL(dy | 0xffff));
  1110.     }
  1111.   float d = FLOATOFFULL(dx) * scale;
  1112.   if (d > dMax)
  1113.     d = dMax;
  1114.   else if (d < -dMax)
  1115.     d = -dMax;
  1116.   dx = FULLOFFLOAT(d);
  1117.   d = FLOATOFFULL(dy) * scale;
  1118.   if (d > dMax)
  1119.     d = dMax;
  1120.   else if (d < -dMax)
  1121.     d = -dMax;
  1122.   dy = FULLOFFLOAT(d);
  1123.   if (flags & MAS_X)
  1124.     {
  1125.     if (flags & MAS_VEL)
  1126.       {
  1127.       m_vxFull += dx;
  1128.       if (m_vxFull > m_psc->m_vFullMax)
  1129.         m_vxFull = m_psc->m_vFullMax;
  1130.       else if (m_vxFull < -m_psc->m_vFullMax)
  1131.         m_vxFull = -m_psc->m_vFullMax;
  1132.       }
  1133.     if (flags & MAS_ACCEL)
  1134.       {
  1135.       m_axFull += dx;
  1136.       if (m_axFull > m_psc->m_aFullMax)
  1137.         m_axFull = m_psc->m_aFullMax;
  1138.       else if (m_axFull < -m_psc->m_aFullMax)
  1139.         m_axFull = -m_psc->m_aFullMax;
  1140.       }
  1141.     if (!(flags & MAS_POS))
  1142.       dx = 0;
  1143.     }
  1144.   else 
  1145.     dx = 0;
  1146.   if (flags & MAS_Y)
  1147.     {
  1148.     if (flags & MAS_VEL)
  1149.       {
  1150.       m_vyFull += dy;
  1151.       if (m_vyFull > m_psc->m_vFullMax)
  1152.         m_vyFull = m_psc->m_vFullMax;
  1153.       else if (m_vyFull < -m_psc->m_vFullMax)
  1154.         m_vyFull = -m_psc->m_vFullMax;
  1155.       }
  1156.     if (flags & MAS_ACCEL)
  1157.       {
  1158.       m_ayFull += dy;
  1159.       if (m_ayFull > m_psc->m_aFullMax)
  1160.         m_ayFull = m_psc->m_aFullMax;
  1161.       else if (m_ayFull < -m_psc->m_aFullMax)
  1162.         m_ayFull = -m_psc->m_aFullMax;
  1163.       }
  1164.     if (!(flags & MAS_POS))
  1165.       dy = 0;
  1166.     }
  1167.   else 
  1168.     dy = 0;
  1169.   if (dx || dy)
  1170.     return this->MoveByFull(dx, dy, fCollide);
  1171.   return TRUE;
  1172.   }
  1173. //***************************************************************************
  1174. // IUnknown Interface
  1175. //***************************************************************************
  1176. //---------------------------------------------------------------------------
  1177. // 
  1178. //---------------------------------------------------------------------------
  1179. STDMETHODIMP CSprite::QueryInterface
  1180. (
  1181.   REFIID  iid,
  1182.   LPVOID* ppvObjOut
  1183. )
  1184. {
  1185.   if (!ppvObjOut)
  1186.     return E_INVALIDARG;
  1187.   *ppvObjOut = NULL;
  1188.   if (iid == IID_IUnknown)
  1189.     *ppvObjOut = this->GetUnknown();
  1190.   else if (iid == IID_IDispatch)
  1191.     *ppvObjOut = this->GetDispatch();
  1192.   else if (iid == IID_ISprite)
  1193.     *ppvObjOut = (ISprite *)this;
  1194.   if (*ppvObjOut)
  1195.     {
  1196.     this->AddRef();
  1197.     return S_OK;
  1198.     }
  1199.   return E_NOINTERFACE;
  1200. }
  1201. //---------------------------------------------------------------------------
  1202. // 
  1203. //---------------------------------------------------------------------------
  1204. STDMETHODIMP_(ULONG) CSprite::AddRef
  1205. (
  1206.   void 
  1207. )
  1208. {
  1209.   return ++m_cref;
  1210. }
  1211. //---------------------------------------------------------------------------
  1212. // 
  1213. //---------------------------------------------------------------------------
  1214. STDMETHODIMP_(ULONG) CSprite::Release
  1215. (
  1216.   void 
  1217. )
  1218. {
  1219.   ASSERT(m_cref, "bad m_cref");
  1220.   m_cref--;
  1221.   if (!m_cref)
  1222.     {
  1223.     delete this;
  1224.     return 0;
  1225.     }
  1226.   return m_cref;
  1227. }
  1228. //***************************************************************************
  1229. // IDispatch Interface
  1230. //***************************************************************************
  1231. //---------------------------------------------------------------------------
  1232. // Method needed by COleAuto, so it can implement IDispatch for us.
  1233. //---------------------------------------------------------------------------
  1234. HRESULT CSprite::GetTypeLibInfo
  1235. (
  1236.   HINSTANCE    *phinstOut,
  1237.   const GUID  **pplibidOut, 
  1238.   SHORT        *pwMajLib, 
  1239.   SHORT        *pwMinLib,
  1240.   const CLSID **ppclsidOut, 
  1241.   const IID   **ppiidOut, 
  1242.   ITypeLib   ***ppptlOut
  1243. )
  1244. {
  1245.   *phinstOut  = g_hinst;
  1246.   *pplibidOut = &LIBID_SPRUUIDS;
  1247.   *pwMajLib   = 1;
  1248.   *pwMinLib   = 0;
  1249.   *ppclsidOut = &CLSID_Sprite;
  1250.   *ppiidOut   = &IID_ISprite;
  1251.   *ppptlOut   = &g_ptlMain;
  1252.   return S_OK;
  1253. }
  1254. //--- EOF -------------------------------------------------------------------