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

Windows编程

开发平台:

Visual C++

  1. /*************************************************************************
  2. **
  3. **  This is a part of the Microsoft Source Code Samples.
  4. **
  5. **  Copyright (C) 1992-1997 Microsoft Corporation. All rights reserved.
  6. **
  7. **  This source code is only intended as a supplement to Microsoft Development
  8. **  Tools and/or WinHelp documentation.  See these sources for detailed
  9. **  information regarding the Microsoft samples programs.
  10. **
  11. **  OLE Automation Lines object
  12. **
  13. **  lines.cpp
  14. **
  15. **  CLines collection implementation
  16. **
  17. **  Written by Microsoft Product Support Services, Windows Developer Support
  18. **
  19. *************************************************************************/
  20. #include <windows.h>
  21. #include <windowsx.h>
  22. #ifdef WIN16   
  23.   #include <ole2.h>
  24.   #include <compobj.h>    
  25.   #include <dispatch.h> 
  26.   #include <variant.h>
  27.   #include <olenls.h>  
  28. #endif      
  29. #include "lines.h"   
  30. /*
  31.  * CLines::Create
  32.  *
  33.  * Purpose:
  34.  *  Creates an instance of a Lines collection object and initializes it.
  35.  *
  36.  * Parameters:
  37.  *  lMaxSize   Maximum number of items that can added to collection.
  38.  *  lLBound    Lower bound of index of collection.  
  39.  *  pPane      Pointer to pane that contains this collection. Required because the pane coordinates 
  40.  *             the lines and points collection.
  41.  *  ppLines    Returns Lines collection object.
  42.  *
  43.  * Return Value:
  44.  *  HRESULT
  45.  *
  46.  */
  47. HRESULT
  48. CLines::Create(ULONG lMaxSize, long lLBound, CPane FAR* pPane, CLines FAR* FAR* ppLines) 
  49. {   
  50.     HRESULT hr;
  51.     CLines FAR* pLines = NULL;
  52.     SAFEARRAYBOUND sabound[1];
  53.      
  54.     *ppLines = NULL;
  55.     
  56.     // Create new collection
  57.     pLines = new CLines();
  58.     if (pLines == NULL)
  59.         goto error;
  60.     pLines->m_cMax = lMaxSize;
  61.     pLines->m_cElements = 0; 
  62.     pLines->m_lLBound = lLBound;
  63.     pLines->m_pPane = pPane;      
  64.     
  65.     // Load type information for the Lines collection from type library. 
  66.     hr = LoadTypeInfo(&pLines->m_ptinfo, IID_ILines);
  67.     if (FAILED(hr))
  68.         goto error;
  69.     
  70.     // Create a safe array of variants which is used to implement the collection.            
  71.     sabound[0].cElements = lMaxSize;
  72.     sabound[0].lLbound = lLBound;        
  73.     pLines->m_psa = SafeArrayCreate(VT_VARIANT, 1, sabound);
  74.     if (pLines->m_psa == NULL)
  75.     {
  76.         hr = E_OUTOFMEMORY;
  77.         goto error;
  78.     }             
  79.     *ppLines = pLines;
  80.     return NOERROR;
  81.     
  82. error: 
  83.     if (pLines == NULL)
  84.         return E_OUTOFMEMORY;
  85.     if (pLines->m_ptinfo)
  86.         pLines->m_ptinfo->Release();                            
  87.     if (pLines->m_psa) 
  88.         SafeArrayDestroy(pLines->m_psa); 
  89.   
  90.     pLines->m_psa = NULL;
  91.     pLines->m_ptinfo = NULL; 
  92.     
  93.     delete pLines;
  94.     return hr;
  95. }
  96. /*
  97.  * CLines::CLines
  98.  *
  99.  * Purpose:
  100.  *  Constructor for CLines object. Initializes members to NULL.
  101.  *
  102.  */
  103. #pragma warning (disable : 4355)
  104. CLines::CLines() : m_SupportErrorInfo(this, IID_ILines)
  105. #pragma warning (default : 4355)
  106. {    
  107.     m_cRef = 0;
  108.     m_psa = NULL;
  109.     m_ptinfo = NULL; 
  110. }
  111. /*
  112.  * CLines::~CLines
  113.  *
  114.  * Purpose:
  115.  *  Destructor for CLines object. 
  116.  *
  117.  */
  118. CLines::~CLines()
  119. {    
  120.      if (m_ptinfo) m_ptinfo->Release();                   
  121.      if (m_psa) SafeArrayDestroy(m_psa);
  122. }
  123. /*
  124.  * CLines::QueryInterface, AddRef, Release
  125.  *
  126.  * Purpose:
  127.  *  Implements IUnknown::QueryInterface, AddRef, Release
  128.  *
  129.  */
  130. STDMETHODIMP
  131. CLines::QueryInterface(REFIID iid, void FAR* FAR* ppv) 
  132. {    
  133.     *ppv = NULL;
  134.         
  135.     if (iid == IID_IUnknown || iid == IID_ILines || iid == IID_IDispatch)
  136.         *ppv = this;     
  137.     else if (iid == IID_ISupportErrorInfo)
  138.         *ppv = &m_SupportErrorInfo;
  139.     else return E_NOINTERFACE; 
  140.     AddRef();
  141.     return NOERROR;    
  142. }
  143. STDMETHODIMP_(ULONG)
  144. CLines::AddRef(void)
  145. #ifdef _DEBUG  
  146.     TCHAR ach[50];
  147.     wsprintf(ach, TEXT("Ref = %ld, Linesrn"), m_cRef+1); 
  148.     OutputDebugString(ach); 
  149. #endif  
  150.     
  151.     return ++m_cRef;
  152. }
  153. STDMETHODIMP_(ULONG)
  154. CLines::Release(void)
  155. #ifdef _DEBUG  
  156.     TCHAR ach[50];
  157.     wsprintf(ach, TEXT("Ref = %ld, Linesrn"), m_cRef-1); 
  158.     OutputDebugString(ach);   
  159. #endif
  160.     
  161.     if(--m_cRef == 0)
  162.     {
  163.         delete this;
  164.         return 0;
  165.     }
  166.     return m_cRef;
  167. /*
  168.  * CLines::GetTypeInfoCount
  169.  *
  170.  * Purpose:
  171.  *  Implements IDispatch::GetTypeInfoCount.
  172.  *
  173.  */
  174. STDMETHODIMP
  175. CLines::GetTypeInfoCount(UINT FAR* pctinfo)
  176. {
  177.     *pctinfo = 1;
  178.     return NOERROR;
  179. }
  180. /*
  181.  * CLines::GetTypeInfo
  182.  *
  183.  * Purpose:
  184.  *  Implements IDispatch::GetTypeInfo. 
  185.  *
  186.  */
  187. STDMETHODIMP
  188. CLines::GetTypeInfo(
  189.       UINT itinfo,
  190.       LCID lcid,
  191.       ITypeInfo FAR* FAR* pptinfo)
  192. {    
  193.     *pptinfo = NULL;
  194.      
  195.     if(itinfo != 0)
  196.         return DISP_E_BADINDEX;
  197.     
  198.     m_ptinfo->AddRef(); 
  199.     *pptinfo = m_ptinfo;
  200.     
  201.     return NOERROR;
  202. }
  203. /*
  204.  * CLines::GetIDsOfNames
  205.  *
  206.  * Purpose:
  207.  *  Implements IDispatch::GetIDsOfNames.  The standard implementation, DispGetIDsOfNames,
  208.  *  is used.
  209.  *
  210.  */
  211. STDMETHODIMP 
  212. CLines::GetIDsOfNames(
  213.       REFIID riid,
  214.       OLECHAR FAR* FAR* rgszNames,
  215.       UINT cNames,
  216.       LCID lcid,
  217.       DISPID FAR* rgdispid)
  218. {
  219.     return DispGetIDsOfNames(m_ptinfo, rgszNames, cNames, rgdispid);
  220. }
  221. /*
  222.  * CLines::Invoke
  223.  *
  224.  * Purpose:
  225.  *  Implements IDispatch::Invoke.  The standard implementation, DispInvoke,
  226.  *  is used.
  227.  *
  228.  */
  229. STDMETHODIMP
  230. CLines::Invoke(
  231.       DISPID dispidMember,
  232.       REFIID riid,
  233.       LCID lcid,
  234.       WORD wFlags,
  235.       DISPPARAMS FAR* pdispparams,
  236.       VARIANT FAR* pvarResult,
  237.       EXCEPINFO FAR* pexcepinfo,
  238.       UINT FAR* puArgErr)
  239. {  
  240.     return DispInvoke(
  241.         this, m_ptinfo,
  242.         dispidMember, wFlags, pdispparams,
  243.         pvarResult, pexcepinfo, puArgErr); 
  244. }
  245. /*  
  246.  * 
  247.  * Properties and methods exposed through automation.
  248.  *
  249.  */
  250. /*
  251.  * CLines::Add
  252.  *
  253.  * Purpose:
  254.  *  Adds a line to the lines collection. 
  255.  *
  256.  * Parameters:
  257.  *  pLineNew    IDispatch of line to be added to collection.
  258.  *
  259.  */
  260. STDMETHODIMP  
  261. CLines::Add(ILine FAR* pLineNew)
  262.     HRESULT hr;   
  263.     LONG l;
  264.     CLine FAR* pLine = NULL;
  265.     VARIANT v;       
  266.     HDC hdc;
  267.     
  268.     // Is the collection full?
  269.     if (m_cElements == m_cMax) 
  270.         return RaiseException(IDS_CollectionFull, IID_ILines);
  271.     hr = pLineNew->QueryInterface(IID_ILine, (void FAR* FAR*)&pLine);
  272.     if (FAILED(hr))
  273.         return RaiseException(IDS_LineFromOtherInstance, IID_ILines);
  274.     
  275.     // Add end points of line to the pane's point collection    
  276.     if (FALSE == pLine->AddEndPointsToPane(m_pPane))     
  277.         {hr = RaiseException(IDS_CantAddEndPoints, IID_ILines); goto error;}  
  278.     
  279.     // Add new line to collection
  280.     l = m_lLBound+m_cElements; 
  281.     VariantInit(&v);
  282.     V_VT(&v) = VT_DISPATCH;
  283.     V_DISPATCH(&v) = pLineNew;    
  284.     hr = SafeArrayPutElement(m_psa, &l, &v);
  285.     if (FAILED(hr))
  286.         {hr = RaiseException(IDS_Unexpected, IID_ILines); goto error;}  
  287.     m_cElements++;   
  288.     
  289.     // Draw the new line
  290.     hdc = m_pPane->GetDC();    
  291.     pLine->Draw(hdc);
  292.     m_pPane->ReleaseDC(hdc);  
  293.     
  294.     pLine->Release();                    
  295.     return NOERROR;    
  296.     
  297. error:  
  298.     if (pLine)
  299.         pLine->Release();      
  300.     return hr;   
  301. }
  302. /*
  303.  * CLines::get_Count
  304.  *
  305.  * Purpose:
  306.  *  Returns number of items in collection.
  307.  *
  308.  */
  309. STDMETHODIMP    
  310. CLines::get_Count(long FAR* lCount)  
  311. {
  312.     *lCount = m_cElements;
  313.     return NOERROR;             
  314. }
  315. /*
  316.  * CLines::get_Item
  317.  *
  318.  * Purpose:
  319.  *  Retrieves item from collection, given an index. 
  320.  *
  321.  * Parameters:   
  322.  *   lIndex   Index of item to be retrieved. 
  323.  *   ppLine   Returns IDispatch of item retrieved from collection.
  324.  *
  325.  */
  326. STDMETHODIMP
  327. CLines::get_Item(long lIndex, ILine FAR* FAR* ppLine)
  328.     HRESULT hr;                                            
  329.     VARIANT v;
  330.    
  331.     // Check if index is within range         
  332.     if (lIndex < m_lLBound || lIndex >= (long)(m_lLBound+m_cElements)) 
  333.         return RaiseException(IDS_InvalidIndex, IID_ILines); 
  334.     
  335.     // Retrieve and return item. Note that SafeArrayGetElement AddRefs, so an additional AddRef
  336.     // is not required.
  337.     VariantInit(&v);
  338.     hr = SafeArrayGetElement(m_psa, &lIndex, &v);
  339.     if (FAILED(hr))
  340.         return RaiseException(IDS_Unexpected, IID_ILines);
  341.     *ppLine = (ILine FAR*) V_DISPATCH(&v);  
  342.     return NOERROR;
  343. }
  344. /*
  345.  * CLines::get_NewEnum
  346.  *
  347.  * Purpose:
  348.  *  Returns an enumerator (IEnumVARIANT) for the items curently in the collection. 
  349.  *  The NewEnum property is restricted and so is invisible to users of an 
  350.  *  automation controller's scripting language. Automation controllers that support
  351.  *  a 'For Each' statement to iterate through the elements of a collection will use
  352.  *  the enumerator returned by NewEnum. The enumerator creates a snapshot of the
  353.  *  the current state of the collection.
  354.  *
  355.  */
  356. STDMETHODIMP
  357. CLines::get__NewEnum(IUnknown FAR* FAR* ppunkEnum)
  358. {
  359.     CEnumVariant FAR* penum = NULL;;
  360.     HRESULT hr;
  361.     
  362.     *ppunkEnum = NULL;
  363.     
  364.     // Create new enumerator for items currently in collection and QI for IUnknown
  365.     hr = CEnumVariant::Create(m_psa, m_cElements, &penum);
  366.     if (FAILED(hr))
  367.         {hr = RaiseException(IDS_OutOfMemory, IID_ILines); goto error;}        
  368.     hr = penum->QueryInterface(IID_IUnknown, (VOID FAR* FAR*)ppunkEnum);    
  369.     if (FAILED(hr)) 
  370.         {hr = RaiseException(IDS_Unexpected, IID_ILines); goto error;}  
  371.     return NOERROR; 
  372.     
  373. error:
  374.     if (penum)
  375.         delete penum;   
  376.     return hr;              
  377. }
  378. /*
  379.  * CLines::Remove
  380.  *
  381.  * Purpose:
  382.  *  Removes specified item from collection. 
  383.  *
  384.  * Parameters:   
  385.  *   lIndex   Index of item to be removed. 
  386.  *
  387.  */
  388. STDMETHODIMP
  389. CLines::Remove(long lIndex)
  390. {
  391.     HRESULT hr;
  392.     long l;
  393.     VARIANT HUGEP *pvar;
  394.     CLine FAR* pLine = NULL;  
  395.     RECT rc;
  396.     
  397.     // Check if integer index is within range. 
  398.     if (lIndex < m_lLBound || lIndex >= (long)(m_lLBound+m_cElements))
  399.         return RaiseException(IDS_InvalidIndex, IID_ILines);    
  400.     hr = SafeArrayAccessData(m_psa, (void HUGEP* FAR*)&pvar);
  401.     if (FAILED(hr))
  402.         return RaiseException(IDS_Unexpected, IID_ILines); 
  403.     V_DISPATCH(&pvar[lIndex-m_lLBound])->QueryInterface(IID_ILine, (void FAR* FAR*)&pLine);         
  404.      
  405.     // Ask the pane to invalidate the area where the line is drawn.
  406.     pLine->GetInvalidateRect(&rc);
  407.     m_pPane->InvalidateRect(&rc);
  408.     
  409.     // Remove end points of line from the pane's point collection.   
  410.     pLine->RemoveEndPointsFromPane(m_pPane);    
  411.     // Remove Line  
  412.     V_DISPATCH(&pvar[lIndex-m_lLBound])->Release();    
  413.     // Move up the array elements, after the element to be removed.        
  414.     for (l=lIndex-m_lLBound; l<(long)(m_cElements-1); l++)  
  415.         pvar[l] = pvar[l+1];    
  416.     // Remove last element.    
  417.     V_VT(&pvar[l]) = VT_EMPTY;
  418.     
  419.     pLine->Release();        
  420.     hr = SafeArrayUnaccessData(m_psa);
  421.     if (FAILED(hr))
  422.        return RaiseException(IDS_Unexpected, IID_ILines); 
  423.        
  424.     m_cElements--;  
  425.     m_pPane->Update();     // Ask the pane to repaint invalidated areas caused by removal of line.
  426.     return NOERROR;
  427. }
  428. /* 
  429.  *
  430.  * The following methods are not exposed through Automation
  431.  *
  432.  */  
  433.  
  434. /*
  435.  * CLines::Draw
  436.  *
  437.  * Purpose:
  438.  *  Draws all lines in collection.
  439.  *
  440.  */
  441. STDMETHODIMP_(void)
  442. CLines::Draw(HDC hdc)
  443. {
  444.     HRESULT hr;
  445.     long l;
  446.     CLine FAR* pLine = NULL;
  447.     VARIANT HUGEP *pvar;
  448.     
  449.     // Draw each line in the Lines collection
  450.     hr = SafeArrayAccessData(m_psa, (void HUGEP* FAR*)&pvar);
  451.     if (FAILED(hr))
  452.        return;           
  453.     for (l=0; l<(long)m_cElements; l++)
  454.     {        
  455.         hr = V_DISPATCH(&pvar[l])->QueryInterface(IID_ILine, (void FAR* FAR*)&pLine);
  456.         if (FAILED(hr))
  457.             continue;          
  458.         pLine->Draw(hdc);
  459.         pLine->Release();        
  460.     }   
  461.     hr = SafeArrayUnaccessData(m_psa);
  462.     if (FAILED(hr))
  463.         return;
  464.     return;
  465. }
  466. /*
  467.  * CLines::Clear
  468.  *
  469.  * Purpose:
  470.  *  Removes all items from collection.
  471.  *
  472.  */
  473. STDMETHODIMP_(void)
  474. CLines::Clear(void)
  475. {
  476.     SafeArrayDestroyData(m_psa);   
  477.     SafeArrayAllocData(m_psa);
  478.     m_cElements = 0;
  479. }