home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap14 / cosmo / autofigs.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  14.9 KB  |  652 lines

  1. /*
  2.  * AUTOFIGS.CPP
  3.  * Cosmo Chapter 14
  4.  *
  5.  * "Figures" collection object for Cosmo's OLE Automation support,
  6.  * derived from CAutoBase.
  7.  *
  8.  * Copyright (c)1993-1995 Microsoft Corporation, All Right Reserved.
  9.  *
  10.  * Kraig Brockschmidt, Microsoft
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  INTERNET>kraigb@microsoft.com
  13.  */
  14.  
  15.  
  16. #include "cosmo.h"
  17.  
  18.  
  19. /*
  20.  * CAutoFigures::CAutoFigures
  21.  * CAutoFigures::~CAutoFigures
  22.  *
  23.  * Constructor Parameters:
  24.  *  pCL             PCCosmoClient to the client object that we use
  25.  *                  to implement much of this interface.
  26.  */
  27.  
  28. CAutoFigures::CAutoFigures(PCCosmoClient pCL)
  29.     : CAutoBase(pCL, pCL->m_hInst, IID_ICosmoFigures
  30.     , DIID_DICosmoFigures, NULL)
  31.     {
  32.     return;
  33.     }
  34.  
  35.  
  36. CAutoFigures::~CAutoFigures(void)
  37.     {
  38.     return;
  39.     }
  40.  
  41.  
  42.  
  43.  
  44. /*
  45.  * CAutoFigures::QueryInterface
  46.  * CAutoFigures::AddRef
  47.  * CAutoFigures::Release
  48.  */
  49.  
  50. STDMETHODIMP CAutoFigures::QueryInterface(REFIID riid, PPVOID ppv)
  51.     {
  52.     *ppv=NULL;
  53.  
  54.     if (IID_IUnknown==riid || IID_ICosmoFigures==riid)
  55.         *ppv=(IUnknown *)this;
  56.  
  57.     if (IID_IDispatch==riid || m_diid==riid)
  58.         *ppv=m_pImpIDispatch;
  59.  
  60.     if (NULL!=*ppv)
  61.         {
  62.         ((LPUNKNOWN)*ppv)->AddRef();
  63.         return NOERROR;
  64.         }
  65.  
  66.     return ResultFromScode(E_NOINTERFACE);
  67.     }
  68.  
  69. STDMETHODIMP_(ULONG) CAutoFigures::AddRef(void)
  70.     {
  71.     return ++m_cRef;
  72.     }
  73.  
  74. STDMETHODIMP_(ULONG) CAutoFigures::Release(void)
  75.     {
  76.     //CCosmoClient deletes this object during shutdown
  77.     if (0==--m_cRef)
  78.         {
  79.         /*
  80.          * Note:  This early release is to avoid a bug in
  81.          * Beta Windows NT 3.51 at the time this code was
  82.          * finalized.  Technically it should be fine to leave
  83.          * the Release call in CImpIDispatch::~CImpIDispatch
  84.          * (see autobase.cpp), but making the call here
  85.          * avoids a crash on a null pointer.
  86.          */
  87.         ReleaseInterface(m_pImpIDispatch->m_pITypeInfo);
  88.         }
  89.     return m_cRef;
  90.     }
  91.  
  92.  
  93.  
  94.  
  95. /*
  96.  * CAutoFigures::VTableInterface
  97.  *
  98.  * Purpose:
  99.  *  Returns the right vtable pointer to use when calling
  100.  *  ITypeInfo::Invoke (see CImpIDispatch::Invoke in AUTOBASE.CPP).
  101.  */
  102. void *CAutoFigures::VTableInterface(void)
  103.     {
  104.     return (ICosmoFigures *)this;
  105.     }
  106.  
  107.  
  108.  
  109. //The ICosmoFigures implementation
  110.  
  111. /*
  112.  * CAutoFigures::Application
  113.  * CAutoFigures::Parent
  114.  * Properties, read-only
  115.  *
  116.  * The application object (CAutoApp) in which we're contained,
  117.  * which is stored in the frame object.  Basically we walk
  118.  * up from the client to the frame to it's application object
  119.  * to get the IDispatch we need.
  120.  */
  121.  
  122. STDMETHODIMP_(IDispatch *) CAutoFigures::get_Application(void)
  123.     {
  124.     PCCosmoFrame    pFR;
  125.  
  126.     pFR=(PCCosmoFrame)m_pCL->Frame();
  127.     return pFR->AutoApp()->get_Application();
  128.     }
  129.  
  130. STDMETHODIMP_(IDispatch *) CAutoFigures::get_Parent(void)
  131.     {
  132.     return get_Application();
  133.     }
  134.  
  135.  
  136.  
  137. /*
  138.  * CAutoFigures::Count
  139.  * Property, read-only
  140.  *
  141.  * The number of figures in this collection
  142.  */
  143.  
  144. STDMETHODIMP_(long) CAutoFigures::get_Count(void)
  145.     {
  146.     //This is easy:  just the number of items in the listbox.
  147.     return m_pCL->m_cDoc;
  148.     }
  149.  
  150.  
  151.  
  152. /*
  153.  * CAutoFigures::Item
  154.  * Method
  155.  *
  156.  * This is essentially an array lookup operator for the collection.
  157.  * Collection.Item by itself the same as the collection itself.
  158.  * Otherwise you can refer to the item by index or by path, which
  159.  * shows up in the VARIANT parameter.  We have to check the type
  160.  * of the variant to see if it's VT_I4 (an index) or VT_BSTR (a
  161.  * path) and do the right thing.
  162.  */
  163.  
  164. STDMETHODIMP_(IDispatch *) CAutoFigures::Item(VARIANT index)
  165.     {
  166.     IDispatch  *pIDispatch=NULL;
  167.     PCCosmoDoc  pDoc;
  168.     const int   cch=512;
  169.     TCHAR       szPath[cch];
  170.     UINT        i;
  171.     HWND        hList=m_pCL->m_hListDocs;
  172.  
  173.     /*
  174.      * Each case in this switch gets at a different pointer
  175.      * and stores it in pIDispatch for return.
  176.      */
  177.     switch (index.vt)
  178.         {
  179.         case VT_ERROR:
  180.             /*
  181.              * No parameters, get the "Figures" collection
  182.              * IDispatch, which we can easily retrieve with
  183.              * our own QueryInterface.
  184.              */
  185.             QueryInterface(IID_IDispatch, (PPVOID)&pIDispatch);
  186.             break;
  187.  
  188.         case VT_I4:
  189.             if (LB_ERR!=SendMessage(hList, LB_GETTEXT
  190.                 , (int)index.lVal, (LONG)&pDoc))
  191.                 {
  192.                 //Sets pIDispatch to NULL on failure.
  193.                 pDoc->AutoFigure()->QueryInterface(IID_IDispatch
  194.                     , (PPVOID)&pIDispatch);
  195.                 }
  196.  
  197.             break;
  198.  
  199.         case VT_BSTR:
  200.             /*
  201.              * First we'll iterate over the pages and check
  202.              * for full path matches.  If that doesn't yield
  203.              * anything, then we'll see if index.bstrVal is
  204.              * just a filename inside one of the paths.
  205.              */
  206.             for (i=0; i < m_pCL->m_cDoc; i++)
  207.                 {
  208.                 if (LB_ERR!=SendMessage(hList, LB_GETTEXT
  209.                     , i, (LONG)&pDoc))
  210.                     {
  211.                     pDoc->FilenameGet(szPath, cch);
  212.  
  213.                    #ifdef WIN32ANSI
  214.                     char    szTemp[512];
  215.  
  216.                     WideCharToMultiByte(CP_ACP, 0, index.bstrVal, -1
  217.                         , szTemp, 512, NULL, NULL);
  218.  
  219.                     if (0==lstrcmpi(szPath, szTemp))
  220.                    #else
  221.                     if (0==lstrcmpi(szPath, index.bstrVal))
  222.                    #endif
  223.                         {
  224.                         //Found it...
  225.                         pDoc->AutoFigure()->QueryInterface
  226.                             (IID_IDispatch, (PPVOID)&pIDispatch);
  227.                         }
  228.                     }
  229.                 }
  230.  
  231.             //Stop now if we found anything.
  232.             if (NULL!=pIDispatch)
  233.                 break;
  234.  
  235.             //Now look for portions of the path
  236.             for (i=0; i < m_pCL->m_cDoc; i++)
  237.                 {
  238.                 if (LB_ERR!=SendMessage(hList, LB_GETTEXT
  239.                     , i, (LONG)&pDoc))
  240.                     {
  241.                     LPTSTR  psz;
  242.  
  243.                     pDoc->FilenameGet(szPath, cch);
  244.  
  245.                    #ifdef WIN32ANSI
  246.                     char    szTemp[512];
  247.  
  248.                     WideCharToMultiByte(CP_ACP, 0, index.bstrVal, -1
  249.                         , szTemp, 512, NULL, NULL);
  250.                     psz=_tcsstr(szPath, szTemp);
  251.                    #else
  252.                     psz=_tcsstr(szPath, index.bstrVal);
  253.                    #endif
  254.  
  255.                     if (NULL!=psz)
  256.                         {
  257.                         //Found it...
  258.                         pDoc->AutoFigure()->QueryInterface
  259.                             (IID_IDispatch, (PPVOID)&pIDispatch);
  260.                         }
  261.                     }
  262.                 }
  263.  
  264.  
  265.             break;
  266.  
  267.         default:
  268.             return NULL;
  269.         }
  270.  
  271.     return pIDispatch;
  272.     }
  273.  
  274.  
  275.  
  276. /*
  277.  * CAutoFigures::Add
  278.  * CAutoFigures::Open
  279.  * Methods
  280.  *
  281.  * Creates a new figure window with an empty figure (Add) or one
  282.  * with the contents of a file (Open), and adds it to the collection.
  283.  */
  284.  
  285. STDMETHODIMP_(IDispatch *) CAutoFigures::Add(void)
  286.     {
  287.     return NewFigure(NULL);
  288.     }
  289.  
  290. STDMETHODIMP_(IDispatch *) CAutoFigures::Open(BSTR bstrPath)
  291.     {
  292.    #ifdef WIN32ANSI
  293.     char        szTemp[512];
  294.  
  295.     WideCharToMultiByte(CP_ACP, 0, bstrPath, -1, szTemp
  296.         , 512, NULL, NULL);
  297.     return NewFigure(szTemp);
  298.    #else
  299.     return NewFigure(bstrPath);
  300.    #endif
  301.     }
  302.  
  303.  
  304.  
  305. /*
  306.  * CAutoFigures:NewFigure
  307.  *
  308.  * Purpose:
  309.  *  Internal helper function to centralize figure creation for
  310.  *  Add and Open.
  311.  *
  312.  * Parameters:
  313.  *  pszPath         LPTSTR to a file to open if this is an open.
  314.  *                  Should be NULL for Add.
  315.  *
  316.  * Return Value:
  317.  *  IDispatch *     Return value for Add and Open
  318.  */
  319.  
  320. IDispatch * CAutoFigures::NewFigure(LPTSTR pszPath)
  321.     {
  322.     PCCosmoDoc  pDoc;
  323.     IDispatch  *pIDispatch=NULL;
  324.     HRESULT     hr;
  325.  
  326.     //Try creating a hidden document, which creates the object.
  327.     pDoc=(PCCosmoDoc)m_pCL->NewDocument(FALSE);
  328.  
  329.     if (NULL==pDoc)
  330.         return NULL;
  331.  
  332.     hr=ResultFromScode(E_FAIL);
  333.  
  334.     //Try to load the file and get the IDispatch for the document
  335.     if (DOCERR_NONE==pDoc->Load(TRUE, pszPath))
  336.         {
  337.         hr=pDoc->AutoFigure()->QueryInterface(IID_IDispatch
  338.             , (PPVOID)&pIDispatch);
  339.         }
  340.  
  341.     if (FAILED(hr))
  342.         m_pCL->CloseDocument(pDoc);
  343.     else
  344.         g_cObj++;
  345.  
  346.     return pIDispatch;
  347.     }
  348.  
  349.  
  350.  
  351.  
  352.  
  353. /*
  354.  * CAutoFigures::Close
  355.  * Method
  356.  *
  357.  * Closes all figure windows in the collection
  358.  */
  359.  
  360. STDMETHODIMP_(void) CAutoFigures::Close(void)
  361.     {
  362.     m_pCL->QueryCloseAllDocuments(TRUE, FALSE);
  363.     return;
  364.     }
  365.  
  366.  
  367.  
  368.  
  369.  
  370. /*
  371.  * CAutoFigures::_NewEnum
  372.  * Method
  373.  *
  374.  * Creates and returns an enumerator of the current list of
  375.  * figures in this collection.
  376.  */
  377.  
  378. STDMETHODIMP_(IUnknown *) CAutoFigures::_NewEnum(void)
  379.     {
  380.     PCEnumFigures   pNew=NULL;
  381.     BOOL            fRet=TRUE;
  382.  
  383.     pNew=new CEnumFigures(m_pCL->Instance());
  384.  
  385.     if (NULL!=pNew)
  386.         {
  387.         if (!pNew->Init(m_pCL->m_hListDocs, FALSE))
  388.             {
  389.             delete pNew;
  390.             pNew=NULL;
  391.             }
  392.         else
  393.             pNew->AddRef();
  394.         }
  395.  
  396.     return (IUnknown *)pNew;
  397.     }
  398.  
  399.  
  400.  
  401.  
  402. //CEnumFigures implementation of IEnumVARIANT
  403.  
  404.  
  405. /*
  406.  * CEnumFigures::CEnumFigures
  407.  * CEnumFigures::~CEnumFigures
  408.  *
  409.  * Parameters (Constructor):
  410.  *  hInst           HINSTANCE of the application.
  411.  */
  412.  
  413. CEnumFigures::CEnumFigures(HINSTANCE hInst)
  414.     {
  415.     m_cRef=0;
  416.     m_hList=NULL;
  417.     m_hInst=hInst;
  418.     m_iCur=0;
  419.     m_cItems=0;
  420.     return;
  421.     }
  422.  
  423.  
  424. CEnumFigures::~CEnumFigures(void)
  425.     {
  426.     if (NULL!=m_hList)
  427.         DestroyWindow(m_hList);
  428.  
  429.     return;
  430.     }
  431.  
  432.  
  433.  
  434. /*
  435.  * CEnumFigures::Init
  436.  *
  437.  * Purpose:
  438.  *  Initializes the enumeration with any operations that might fail.
  439.  *
  440.  * Parameters:
  441.  *  hListPDoc       HWND of the listbox containing the current
  442.  *                  set of document pointers.
  443.  *  fClone          BOOL indicating if this is a clone creation
  444.  *                  in which case hListPDoc already has what we want
  445.  *                  and we can just copy it directly.
  446.  *
  447.  * Return Value:
  448.  *  BOOL            TRUE if initialization succeeded,
  449.  *                  FALSE otherwise.
  450.  */
  451. BOOL CEnumFigures::Init(HWND hListPDoc, BOOL fClone)
  452.     {
  453.     UINT        i;
  454.     UINT        cDoc;
  455.     PCDocument  pDoc;
  456.  
  457.     //Create our own list
  458.     m_hList=CreateWindow(TEXT("listbox"), TEXT("EnumList")
  459.         , WS_POPUP | LBS_OWNERDRAWFIXED, 0, 0, 100, 100
  460.         , HWND_DESKTOP, NULL, m_hInst, NULL);
  461.  
  462.     if (NULL==m_hList)
  463.         return FALSE;
  464.  
  465.     /*
  466.      * An enumeration should not be attached to any sort of
  467.      * dynamic list, so we have to initialize our own list here.
  468.      * Furthermore, the hList we get here has document object
  469.      * pointers which could possibly become invalid and we have
  470.      * no way of knowing it.  So we take each pointer and copy
  471.      * the window handle of that document into our own list.  If
  472.      * the window is destroyed, then we have a way of checking
  473.      * that condition and failing to return a valid pointer
  474.      * in other partsof this enumerator.
  475.      */
  476.  
  477.     cDoc=(UINT)SendMessage(hListPDoc, LB_GETCOUNT, 0, 0L);
  478.  
  479.     for (i=0; i < cDoc; i++)
  480.         {
  481.         if (LB_ERR!=SendMessage(hListPDoc, LB_GETTEXT, i
  482.             , (LONG)&pDoc))
  483.             {
  484.             HWND    hWndDoc;
  485.  
  486.             //When cloning we have the window handle already.
  487.             if (fClone)
  488.                 hWndDoc=(HWND)(UINT)(LONG)pDoc;
  489.             else
  490.                 hWndDoc=pDoc->Window();
  491.  
  492.             if (LB_ERR!=SendMessage(m_hList, LB_ADDSTRING, 0
  493.                 , (LONG)(UINT)hWndDoc))
  494.                 m_cItems++;
  495.             }
  496.         }
  497.  
  498.     return TRUE;
  499.     }
  500.  
  501.  
  502.  
  503. /*
  504.  * CEnumFigures::QueryInterface
  505.  * CEnumFigures::AddRef
  506.  * CEnumFigures::Release
  507.  */
  508.  
  509. STDMETHODIMP CEnumFigures::QueryInterface(REFIID riid, PPVOID ppv)
  510.     {
  511.     *ppv=NULL;
  512.  
  513.     if (IID_IUnknown==riid || IID_IEnumVARIANT==riid)
  514.         *ppv=this;
  515.  
  516.     if (NULL!=*ppv)
  517.         {
  518.         ((LPUNKNOWN)*ppv)->AddRef();
  519.         return NOERROR;
  520.         }
  521.  
  522.     return ResultFromScode(E_NOINTERFACE);
  523.     }
  524.  
  525.  
  526. STDMETHODIMP_(ULONG) CEnumFigures::AddRef(void)
  527.     {
  528.     ++m_cRef;
  529.     return m_cRef;
  530.     }
  531.  
  532. STDMETHODIMP_(ULONG) CEnumFigures::Release(void)
  533.     {
  534.     ULONG       cRefT;
  535.  
  536.     cRefT=--m_cRef;
  537.  
  538.     if (0L==m_cRef)
  539.         delete this;
  540.  
  541.     return cRefT;
  542.     }
  543.  
  544.  
  545. /*
  546.  * CEnumFigures::Next
  547.  * CEnumFigures::Skip
  548.  * CEnumFigures::Reset
  549.  * CEnumFigures::Clone
  550.  *
  551.  * Standard enumerator members for IEnumVARIANT
  552.  */
  553.  
  554. STDMETHODIMP CEnumFigures::Next(ULONG cVar, VARIANT *pVar
  555.     , ULONG *pulVar)
  556.     {
  557.     ULONG       cReturn=0L;
  558.     PCCosmoDoc  pDoc;
  559.     HRESULT     hr;
  560.     void       *pv;
  561.     LONG        l;
  562.  
  563.     if (NULL==pulVar)
  564.         {
  565.         if (1L!=cVar)
  566.             return ResultFromScode(E_POINTER);
  567.         }
  568.     else
  569.         *pulVar=0L;
  570.  
  571.     if (NULL==pVar || m_iCur >= m_cItems)
  572.         return ResultFromScode(S_FALSE);
  573.  
  574.     while (m_iCur < m_cItems && cVar > 0)
  575.         {
  576.         if (LB_ERR==SendMessage(m_hList, LB_GETTEXT, (UINT)m_iCur++
  577.             , (LONG)&l))
  578.             continue;
  579.  
  580.         /*
  581.          * Try getting the document pointer.  If this fails
  582.          * then the window is invalid (document is destroyed)
  583.          * so remove it from the list for future enumerations.
  584.          */
  585.         pDoc=(PCCosmoDoc)SendMessage((HWND)(UINT)l
  586.             , DOCM_PDOCUMENT, 0, 0L);
  587.  
  588.         if (NULL==pDoc)
  589.             {
  590.             SendMessage(m_hList, LB_DELETESTRING, (UINT)--m_iCur, 0L);
  591.             continue;
  592.             }
  593.  
  594.         hr=pDoc->AutoFigure()->QueryInterface(IID_IDispatch, &pv);
  595.  
  596.         if (SUCCEEDED(hr))
  597.             {
  598.             *pVar->ppdispVal=(IDispatch *)pv;
  599.             pVar++;
  600.             cReturn++;
  601.             cVar--;
  602.             }
  603.         }
  604.  
  605.  
  606.     if (NULL!=pulVar)
  607.         *pulVar=cReturn;
  608.  
  609.     return NOERROR;
  610.     }
  611.  
  612.  
  613. STDMETHODIMP CEnumFigures::Skip(ULONG cSkip)
  614.     {
  615.     if ((m_iCur+cSkip) >= m_cItems)
  616.         return ResultFromScode(S_FALSE);
  617.  
  618.     m_iCur+=cSkip;
  619.     return NOERROR;
  620.     }
  621.  
  622.  
  623. STDMETHODIMP CEnumFigures::Reset(void)
  624.     {
  625.     m_iCur=0;
  626.     return NOERROR;
  627.     }
  628.  
  629.  
  630. STDMETHODIMP CEnumFigures::Clone(LPENUMVARIANT *ppEnum)
  631.     {
  632.     PCEnumFigures   pNew;
  633.  
  634.     *ppEnum=NULL;
  635.  
  636.     pNew=new CEnumFigures(m_hInst);
  637.  
  638.     if (NULL!=pNew)
  639.         {
  640.         if (!pNew->Init(m_hList, TRUE))
  641.             {
  642.             delete pNew;
  643.             pNew=NULL;
  644.             }
  645.         else
  646.             pNew->AddRef();
  647.         }
  648.  
  649.     *ppEnum=(IEnumVARIANT *)pNew;
  650.     return (NULL!=pNew) ? NOERROR : ResultFromScode(E_OUTOFMEMORY);
  651.     }
  652.