GME  13
GMEOLEColl.cpp
Go to the documentation of this file.
00001 // GMEOLEColl.cpp : implementation file
00002 //
00003 
00004 #include "stdafx.h"
00005 #include "gme.h"
00006 #include "GMEOLEColl.h"
00007 #include "EnumVar.h"
00008 
00009 #ifdef _DEBUG
00010 #define new DEBUG_NEW
00011 #undef THIS_FILE
00012 static char THIS_FILE[] = __FILE__;
00013 #endif
00014 
00015 
00017 // CStringCollect
00018 
00019 IMPLEMENT_DYNCREATE(CGMEOLEColl, CCmdTarget)
00020 
00021 CGMEOLEColl::CGMEOLEColl()
00022 {
00023         EnableAutomation();
00024 
00025         // To keep the application running as long as an OLE automation
00026         //  object is active, the constructor calls AfxOleLockApp.
00027 
00028         AfxOleLockApp();
00029 }
00030 
00031 CGMEOLEColl::~CGMEOLEColl()
00032 {
00033         // To terminate the application when all objects created with
00034         //  with OLE automation, the destructor calls AfxOleUnlockApp.
00035         RemoveAll();
00036         AfxOleUnlockApp();
00037 }
00038 
00039 void CGMEOLEColl::OnFinalRelease()
00040 {
00041         // When the last reference for an automation object is released
00042         //  OnFinalRelease is called.  This implementation deletes the
00043         //  object.  Add additional cleanup required for your object before
00044         //  deleting it from memory.
00045 
00046         delete this;
00047 }
00048 
00049 BEGIN_MESSAGE_MAP(CGMEOLEColl, CCmdTarget)
00050         //{{AFX_MSG_MAP(CGMEOLEColl)
00051                 // NOTE - the ClassWizard will add and remove mapping macros here.
00052         //}}AFX_MSG_MAP
00053 END_MESSAGE_MAP()
00054 
00055 
00056 BEGIN_DISPATCH_MAP(CGMEOLEColl, CCmdTarget)
00057         //{{AFX_DISPATCH_MAP(CGMEOLEColl)
00058         DISP_PROPERTY_EX(CGMEOLEColl, "Count", GetCount, SetNotSupported, VT_I4)
00059         DISP_FUNCTION(CGMEOLEColl, "Add", Add, VT_EMPTY, VTS_DISPATCH)
00060         DISP_FUNCTION(CGMEOLEColl, "Find", Find, VT_I4, VTS_DISPATCH)
00061         DISP_FUNCTION(CGMEOLEColl, "Remove", Remove, VT_EMPTY, VTS_VARIANT)
00062         DISP_FUNCTION(CGMEOLEColl, "RemoveAll", RemoveAll, VT_EMPTY, VTS_NONE)
00063         DISP_PROPERTY_PARAM(CGMEOLEColl, "Item", GetItem, SetItem, VT_DISPATCH, VTS_I4)
00064         //}}AFX_DISPATCH_MAP
00065         DISP_PROPERTY_EX_ID(CGMEOLEColl, "_NewEnum", DISPID_NEWENUM, GetNewEnum, SetNotSupported, VT_UNKNOWN)
00066         DISP_DEFVALUE(CGMEOLEColl, "Item")
00067 END_DISPATCH_MAP()
00068 
00069 // {36C7B797-6BDE-46d0-8870-70189000EDF9}
00070 //static const IID IID_IGMEOLEColl = 
00071 //{ 0x36c7b797, 0x6bde, 0x46d0, { 0x88, 0x70, 0x70, 0x18, 0x90, 0x0, 0xed, 0xf9 } };
00072 
00073 
00074 
00075 // Note: we add support for IID_IGMEOLEModels to support typesafe binding
00076 // from VBA.  This IID must match the GUID that is attached to the
00077 // dispinterface in the .ODL file.
00078 
00079 BEGIN_INTERFACE_MAP(CGMEOLEColl, CCmdTarget)
00080         INTERFACE_PART(CGMEOLEColl, __uuidof(IGMEOLEColl), Dual)
00081         DUAL_ERRORINFO_PART(CGMEOLEColl)
00082 END_INTERFACE_MAP()
00083 
00085 // CStringCollect message handlers
00086 
00087 void CGMEOLEColl::CheckIndex(long nIndex)
00088 {
00089         if (nIndex <= 0 || nIndex > m_ptrArray.GetSize())
00090                 AfxThrowOleException(E_INVALIDARG);
00091 }
00092 
00093 LPUNKNOWN CGMEOLEColl::GetNewEnum()
00094 {
00095         std::unique_ptr<CEnumVariant> pEnum(new CEnumVariant);
00096         int nCount = m_ptrArray.GetSize();
00097         std::unique_ptr<VARIANT[]> pContents(new VARIANT[nCount]);
00098         int i;
00099 
00100         TRY
00101         {
00102                 for (i = 0; i < nCount; ++i)
00103                 {
00104                         VariantInit(&pContents[i]);
00105                         pContents[i].pdispVal = (LPDISPATCH)(m_ptrArray.ElementAt(i));
00106                         pContents[i].pdispVal->AddRef();
00107                         pContents[i].vt = VT_DISPATCH;
00108                 }
00109         }
00110         CATCH_ALL(e)
00111         {
00112                 while (--i >= 0) {
00113                         pContents[i].pdispVal->Release();
00114                         VariantClear(&pContents[i]);
00115                 }
00116 
00117                 THROW_LAST();
00118         }
00119         END_CATCH_ALL
00120         pEnum->SetContents(pContents.release(), nCount);
00121 
00122         return pEnum.release()->GetInterface(&IID_IUnknown);
00123 }
00124 
00125 long CGMEOLEColl::GetCount()
00126 {
00127         return m_ptrArray.GetSize();
00128 }
00129 
00130 LPDISPATCH CGMEOLEColl::GetItem(long nIndex)
00131 {
00132         CheckIndex(nIndex);
00133         LPDISPATCH ret = (LPDISPATCH)(m_ptrArray.ElementAt((int)nIndex-1));
00134         ret->AddRef();
00135         return ret;
00136 }
00137 
00138 void CGMEOLEColl::SetItem(long nIndex, LPDISPATCH newValue)
00139 {
00140         CheckIndex(nIndex);
00141         m_ptrArray.ElementAt((int)nIndex-1) = newValue; 
00142         newValue->AddRef();
00143 }
00144 
00145 void CGMEOLEColl::Add(LPDISPATCH newValue)
00146 {
00147         m_ptrArray.Add(newValue);
00148         newValue->AddRef();
00149 }
00150 
00151 long CGMEOLEColl::Find(LPDISPATCH findValue)
00152 {
00153         int nCount = m_ptrArray.GetSize();
00154         for (int i = 0; i < nCount; ++i)
00155         {
00156                 if (m_ptrArray.ElementAt(i) == findValue)
00157                         return i+1;
00158         }
00159         return -1;
00160 }
00161 
00162 void CGMEOLEColl::Remove(const VARIANT FAR& removeValue)
00163 {
00164         int nIndex = -1;
00165 
00166         VARIANT varTemp;
00167         VariantInit(&varTemp);
00168         const VARIANT* pvar = &removeValue;
00169         if (removeValue.vt != VT_DISPATCH)
00170         {
00171                 if (VariantChangeType(&varTemp, (VARIANT*)&removeValue, 0, VT_I4) == NOERROR)
00172                         pvar = &varTemp;
00173                 else if (VariantChangeType(&varTemp, (VARIANT*)&removeValue, 0, VT_DISPATCH) == NOERROR)
00174                         pvar = &varTemp;
00175                 else
00176                         AfxThrowOleException(DISP_E_TYPEMISMATCH);
00177         }
00178         if (pvar->vt == VT_DISPATCH)
00179                 nIndex = (int)Find(pvar->pdispVal);
00180         else if (pvar->vt == VT_I4)
00181                 nIndex = (int)pvar->lVal;
00182         VariantClear(&varTemp);
00183 
00184         CheckIndex(nIndex);
00185 
00186         LPDISPATCH ptr = (LPDISPATCH)(m_ptrArray.ElementAt(nIndex));
00187         ptr->Release();
00188 
00189         m_ptrArray.RemoveAt(nIndex);
00190 }
00191 
00192 void CGMEOLEColl::RemoveAll()
00193 {
00194         int nCount = m_ptrArray.GetSize();
00195         for (int i = 0; i < nCount; ++i)
00196         {
00197                 LPDISPATCH ptr = (LPDISPATCH)(m_ptrArray.ElementAt(i));
00198                 ptr->Release();
00199         }
00200         m_ptrArray.RemoveAll();
00201 }
00202 
00203 
00204 DELEGATE_DUAL_INTERFACE(CGMEOLEColl, Dual)
00205 
00206 // Implement ISupportErrorInfo to indicate we support the
00207 // OLE Automation error handler.
00208 IMPLEMENT_DUAL_ERRORINFO(CGMEOLEColl, __uuidof(IGMEOLEColl))
00209 
00210 
00211 STDMETHODIMP CGMEOLEColl::XDual::get_Count(long *cnt)
00212 {
00213         METHOD_PROLOGUE(CGMEOLEColl, Dual)
00214 
00215         TRY_DUAL(__uuidof(IGMEOLEColl))
00216         {
00217                 *cnt = pThis->GetCount();
00218                 return NOERROR;
00219         }
00220         CATCH_ALL_DUAL
00221 }
00222 
00223 STDMETHODIMP CGMEOLEColl::XDual::Add(IDispatch* newValue)
00224 {
00225         METHOD_PROLOGUE(CGMEOLEColl, Dual)
00226 
00227         TRY_DUAL(__uuidof(IGMEOLEColl))
00228         {
00229                 pThis->Add(newValue);
00230                 return NOERROR;
00231         }
00232         CATCH_ALL_DUAL
00233 }
00234 
00235 STDMETHODIMP CGMEOLEColl::XDual::Find(IDispatch* findValue, long *cnt)
00236 {
00237         METHOD_PROLOGUE(CGMEOLEColl, Dual)
00238 
00239         TRY_DUAL(__uuidof(IGMEOLEColl))
00240         {
00241                 *cnt = pThis->Find(findValue);
00242                 return NOERROR;
00243         }
00244         CATCH_ALL_DUAL
00245 }
00246 
00247 STDMETHODIMP CGMEOLEColl::XDual::Remove(VARIANT removeValue)
00248 {
00249         METHOD_PROLOGUE(CGMEOLEColl, Dual)
00250 
00251         TRY_DUAL(__uuidof(IGMEOLEColl))
00252         {
00253                 pThis->Remove(removeValue);
00254                 return NOERROR;
00255         }
00256         CATCH_ALL_DUAL
00257 }
00258 
00259 STDMETHODIMP CGMEOLEColl::XDual::RemoveAll()
00260 {
00261         METHOD_PROLOGUE(CGMEOLEColl, Dual)
00262 
00263         TRY_DUAL(__uuidof(IGMEOLEColl))
00264         {
00265                 pThis->RemoveAll();
00266                 return NOERROR;
00267         }
00268         CATCH_ALL_DUAL
00269 }
00270 
00271 STDMETHODIMP CGMEOLEColl::XDual::get_Item(long nIndex, IDispatch** val)
00272 {
00273         METHOD_PROLOGUE(CGMEOLEColl, Dual)
00274 
00275         TRY_DUAL(__uuidof(IGMEOLEColl))
00276         {
00277                 *val = pThis->GetItem(nIndex);
00278                 return NOERROR;
00279         }
00280         CATCH_ALL_DUAL
00281 }
00282 
00283 STDMETHODIMP CGMEOLEColl::XDual::put_Item(long nIndex, IDispatch* newValue)
00284 {
00285         METHOD_PROLOGUE(CGMEOLEColl, Dual)
00286 
00287         TRY_DUAL(__uuidof(IGMEOLEColl))
00288         {
00289                 pThis->SetItem(nIndex, newValue);
00290                 return NOERROR;
00291         }
00292         CATCH_ALL_DUAL
00293 }
00294 
00295 STDMETHODIMP CGMEOLEColl::XDual::get__NewEnum(IUnknown** e)
00296 {
00297         METHOD_PROLOGUE(CGMEOLEColl, Dual)
00298 
00299         TRY_DUAL(__uuidof(IGMEOLEColl))
00300         {
00301                 *e = pThis->GetNewEnum();
00302                 return NOERROR;
00303         }
00304         CATCH_ALL_DUAL
00305 }