' com/vbobject.ab #require Namespace ActiveBasic Namespace COM Class VBObject Public Sub VBObject() pdisp = 0 End Sub Sub VBObject(className As String, pOuter As *IUnknown, clsContext As DWord) VBObject(ToWCStr(className), pOuter, clsContext) End Sub Sub VBObject(className As PCSTR, pOuter As *IUnknown, clsContext As DWord) VBObject(ToWCStr(className), pOuter, clsContext) End Sub Sub VBObject(className As PCWSTR, pOuter As *IUnknown, clsContext As DWord) pdisp = 0 Dim clsid As CLSID Dim hr = _System_CLSIDFromString(className, clsid) VBObject(clsid, pOuter, clsContext) End Sub Sub VBObject(ByRef clsid As CLSID, pOuter As *IUnknown, clsContext As DWord) Dim hr = CoCreateInstance(clsid, pOuter, clsContext, IID_IDispatch, pdisp) End Sub Sub VBObject(ByRef obj As VBObject) pdisp = obj.pdisp pdisp->AddRef() End Sub Sub ~VBObject() Clear() End Sub Sub Clear() If pdisp <> 0 Then pdisp->Release() pdisp = 0 End If End Sub Function Operator [](name As PCWSTR) As DispatchCaller Return GetCaller(name) End Function Function Operator [](name As String) As DispatchCaller Return GetCaller(ToWCStr(name)) End Function Function Equals(y As VBObject) As Boolean Return _System_COMReferenceEquals(pdisp, y.pdisp) End Function /* Override Function GetHashCode() As Long Dim punk = _System_GetUnknown(pdisp) GetHashCode = _System_HashFromPtr(punk) punk->Release() End Function */ Function Operator ==(y As VBObject) As Boolean Return Equals(y) End Function Function Operator <>(y As VBObject) As Boolean Return Not Equals(y) End Function Sub Assign(p As *IDispatch) Clear() VBObject.Copy(pdisp, p) End Sub Function Copy() As *IDispatch VBObject.Copy(GetDispatch, pdisp) End Function Sub Attach(ByRef p As *IDispatch) Clear() VBObject.Move(pdisp, p) End Sub Function Detach() As *IDispatch VBObject.Move(Detach, pdisp) End Function Function Dispatch() As *IDispatch Dispatch = pdisp End Function Private Function GetCaller(name As PCWSTR) As DispatchCaller Dim dispid As DISPID Dim hr = pdisp->GetIDsOfNames(GUID_NULL, VarPtr(name), 1, LOCALE_USER_DEFAULT, VarPtr(dispid)) Return New DispatchCaller(pdisp, dispid) End Function pdisp As *IDispatch Static Sub Copy(ByRef dst As *IDispatch, ByVal src As *IDispatch) dst = src dst->AddRef() End Sub Static Sub Move(ByRef dst As *IDispatch, ByRef src As *IDispatch) dst = src src = 0 End Sub End Class Class DispatchCaller Public Sub DispatchCaller() End Sub Sub DispatchCaller(pDispatch As *IDispatch, dispatchId As DISPID) pdisp = pDispatch pdisp->AddRef() dispid = dispatchId End Sub Sub DispatchCaller(ByRef dc As DispatchCaller) pdisp = dc.pdisp pdisp->AddRef() dispid = dc.dispid End Sub Sub Operator =(ByRef dc As DispatchCaller) Dispose() DispatchCaller(dc) End Sub Sub Dispose() If pdisp <> 0 Then pdisp->Release() pdisp = 0 End If End Sub Sub ~DispatchCaller() Dispose() End Sub Function Prop() As Variant Dim dispParams As DISPPARAMS With dispParams .rgvarg = 0 .rgdispidNamedArgs = 0 .cArgs = 0 .cNamedArgs = 0 End With Dim ret As VARIANT Dim hr = pdisp->Invoke(dispid, GUID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, dispParams, ret, 0, 0) Dispose() Prop = New Variant v.Attach(ret) Return v End Function Sub Prop(arg As Variant) Prop(ByVal arg.PtrToVariant) End Sub Sub Prop(ByRef arg As VARIANT) setProp(arg, DISPATCH_PROPERTYPUT) End Sub Sub PropRef(arg As Variant) PropRef(ByVal arg.PtrToVariant) End Sub Sub PropRef(ByRef arg As VARIANT) setProp(arg, DISPATCH_PROPERTYPUTREF) End Sub Function Call(cArgs As Long, args As *VARIANT) As Variant Dim dispParams As DISPPARAMS With dispParams .rgvarg = args .rgdispidNamedArgs = 0 .cArgs = cArgs .cNamedArgs = 0 End With Dim ret As VARIANT Dim hr = pdisp->Invoke(dispid, GUID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, dispParams, ret, ByVal 0, 0) Dispose() Dim v = New Variant v.Attach(ret) Return v End Function ' Function Call(cArgs As Long, args As *Variant) As Variant ' End Function Function Call() As Variant Return Call(0, 0) End Function Function Call(arg0 As Variant) As Variant Return Call(1, arg0.PtrToVariant) End Function Function Call(arg0 As Variant, arg1 As Variant) As Variant Dim arg[ELM(2)] As VARIANT arg[0] = arg0.Copy() arg[1] = arg1.Copy() Return Call(2, arg) End Function Function Call(arg0 As Variant, arg1 As Variant, arg2 As Variant) As Variant Dim arg[ELM(3)] As VARIANT arg[0] = arg0.Copy() arg[1] = arg1.Copy() arg[2] = arg2.Copy() Return Call(3, arg) End Function Function Call(arg0 As Variant, arg1 As Variant, arg2 As Variant, arg3 As Variant) As Variant Dim arg[ELM(4)] As VARIANT arg[0] = arg0.Copy() arg[1] = arg1.Copy() arg[2] = arg2.Copy() arg[3] = arg3.Copy() Return Call(4, arg) End Function /* Function Call(arg0 = Variant.OptionalParam As Variant, arg1 = Variant.OptionalParam As Variant, arg2 = Variant.OptionalParam As Variant, arg3 = Variant.OptionalParam As Variant, arg4 = Variant.OptionalParam As Variant, arg5 = Variant.OptionalParam As Variant, arg6 = Variant.OptionalParam As Variant, arg7 = Variant.OptionalParam As Variant, arg8 = Variant.OptionalParam As Variant, arg9 = Variant.OptionalParam As Variant) As Variant Dim arg[ELM(10)] As VARIANT arg[0] = arg0.Copy() arg[1] = arg1.Copy() arg[2] = arg2.Copy() arg[3] = arg3.Copy() arg[4] = arg3.Copy() arg[5] = arg4.Copy() arg[6] = arg5.Copy() arg[7] = arg6.Copy() arg[8] = arg7.Copy() arg[9] = arg8.Copy() Return Call(10, arg) End Function */ Private Sub setProp(ByRef arg As VARIANT, callType As Word) Dim dispidNamed = DISPID_PROPERTYPUT As DISPID Dim dispParams As DISPPARAMS With dispParams .rgvarg = VarPtr(arg) .rgdispidNamedArgs = VarPtr(dispidNamed) .cArgs = 1 .cNamedArgs = 1 End With Dim hr = pdisp->Invoke(dispid, GUID_NULL, LOCALE_USER_DEFAULT, callType, dispParams, ByVal 0, ByVal 0, 0) Dispose() End Sub pdisp As *IDispatch dispid As DISPID End Class Function CallByName(obj As VBObject, procName As String, callType As Word, cArgs As Long, args As *VARIANT) As Variant Return CallByName(obj.Dispatch, ToWCStr(procName), callType, cArgs, args) End Function Function CallByName(obj As VBObject, procName As PCWSTR, callType As Word, cArgs As Long, args As *VARIANT) As Variant Return CallByName(obj.Dispatch, procName, callType, cArgs, args) End Function Function CallByName(obj As *IDispatch, name As PCWSTR, callType As Word, cArgs As Long, args As *VARIANT) As Variant Dim dispid As DISPID Dim hr = obj->GetIDsOfNames(GUID_NULL, VarPtr(name), 1, LOCALE_USER_DEFAULT, VarPtr(dispid)) Dim dispParams As DISPPARAMS With dispParams .rgvarg = args .rgdispidNamedArgs = 0 .cArgs = cArgs .cNamedArgs = 0 End With Dim ret As VARIANT hr = obj->Invoke(dispid, GUID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, dispParams, ret, ByVal 0, 0) CallByName = New Variant CallByName.Attach(ret) Return CallByName End Function /* Function CreateObject(className As PCWSTR) As VBObject Return New VBObject(className, 0, CLSCTX_ALL) End Function Function CreateObject(className As String) As VBObject Return New VBObject(ToWCStr(className), 0, CLSCTX_ALL) End Function /* #ifdef _WIN32_DCOM Function CreateObject(className As PCWSTR, serverName As PCWSTR) As VBObject Dim clsid As CLSID Dim si As COSERVERINFO Dim context As DWord If /*Server = 0 OrElse* / Server[0] = 0 Then context = CLSCTX_SERVER Else context = CLSCTX_REMOTE_SERVER si.pwszName = serverName End If Dim hr = _System_CLSIDFromString(className, clsid) Dim mqi As MULTI_QI mqi.pIID = VarPtr(IID_IUnknown) hr = CoCreateInstanceEx(clsid, 0, context, si, 1, VarPtr(mqi)) If SUCCEEDED(hr) Then Dim obj As VBObject obj.Attach(mqi.pItf As IDispatch) Return obj Else 'Throw Return Nothing End If End Function Function CreateObject(className As String, serverName As String) As VBObject Return CreateObject(ToWCStr(className), ToWCStr(serverName)) End Function #endif */ Function _System_CLSIDFromString(pwString As PCWSTR, ByRef guid As GUID) As HRESULT If pwString[0] = &h007b As WCHAR Then ' 1文字目が { ならクラスIDの文字列表現と見なしCLSIDFromStringで変換。 _System_CLSIDFromString = CLSIDFromString(pwString, guid) Else _System_CLSIDFromString = CLSIDFromProgID(pwString, guid) End If End Function Function _System_COMReferenceEquals(p As *IUnknown, q As *IUnknown) As Boolean If p = q Then Return True Else If p = 0 Or q = 0 Then Return False End If Dim punkX = _System_GetUnknown(p) Dim punkY = _System_GetUnknown(q) If punkX = punkY Then _System_COMReferenceEquals = True Else _System_COMReferenceEquals = False End If punkX->Release() punkY->Release() End Function Function _System_GetUnknown(p As *IUnknown) As *IUnknown 'pは任意のCOMインタフェース If FAILDED(pdisp->QueryInterface(IID_Unknown, _System_GetUnknown)) Then GetUnknown = 0 End If End Function End Namespace 'COM End Namespace 'ActiveBasic