可以在运行时以程序方式生成ActiveX属性(从Visual Basic访问)吗?

时间:2009-02-27 11:22:19

标签: c++ vba vb6 activex

有谁知道是否可以在运行时生成ActiveX属性?

我只需要能够从Visual Basic中获取和设置这些属性。

我的ActiveX控件是用C ++编写的,我已经知道如何通过实现硬编码的C ++ get和put函数来创建属性。但是,我可能为此ActiveX控件提供了大量属性,理想情况下,公开的属性集将根据ActiveX控件的内部状态而更改。

我希望有一种方法可以从数据生成属性,例如以下XML:

<Properties>
    <Property>
        <Name>SomeProperty</Name>
        <Type>Int</Type>
        <DefaultValue>10</DefaultValue>
    </Property>

    ...

<Properties>

由于

2 个答案:

答案 0 :(得分:1)

根据您需要的语法,这可能非常简单或有些困难。

一种方法是在ActiveX控件中创建自己的名称/值集合。 您只需添加两种方法:

HRESULT GetPropery([in] BSTR name, [out,retval] VARIANT value);
HRESULT SetPropery([in] BSTR name, [in] VARIANT value);

基本上你会在控件上有一个属性,它包含所有其他属性的集合。这是最直截了当的方式。

您可以改为创建com collection (链接假定ATL,但有关com集合的通用信息)属性。对集合的Item()调用接受字符串。访问它就像(该集合名为“Properties”):

myValue = myControl.Properties("Name")

我不确定如何设置这样的值?

myControl.Properties("Name") = newValue

这可能要求集合不返回变体,而是返回具有“default”属性的COM对象。我甚至不记得默认属性的大部分细节 - 但我认为VB6客户端很好地支持它们,所有你必须在IDL / ODL文件中设置一些属性。

这两种想法都要求调用者具有方法(Get / SetProperty)的一点间接或使用集合属性(myobject.Properties.XXXX)。如果你必须有这样的语法:

x = myControl.MyDynamticProperty

您需要编写自己的实现IDispatch 的GetIDsOfName和Invoke。我前一段时间做过这件事,很丑陋。值得庆幸的是,由于我们对应用程序的这一部分采取了不同的方向,因此全部删除了。您必须强制调用者使用非vtable IDispatch接口(并且是后期绑定) - 我认为这可能很容易或很难,具体取决于调用语言。我的调用者总是VB 脚本所以这不是问题。

答案 1 :(得分:0)

首先,它在技术上是可行的,但涉及到内存和vtable。不是因为内心的微弱而且绝对不是你想长期保持的任何东西。 COM的设计使得一旦定义了接口,它对于该修订是不变的。这就是为什么在添加到界面时更新修订号是至关重要的。

我们必须在为金属切割软件创建成本计算模块时处理同样的问题。 Microsoft Scripting的Dictonary太不灵活,所以我们创建了一组类似的属性对象。它允许动态地向我们的类添加属性。

Option Explicit

Private priName As String
Private priValue As Variant

Private priProperties As PropertyList

Public Property Get Properties() As PropertyLis
    Set Properties = priProperties
End Property

Public Function Assign(ByVal RHS As Property)
    priName = RHS.Name
    priValue = RHS.Value
    priProperties.Assign RHS.Properties
End Function

Public Function Clone() As Property
    Dim nObject As Property

    Set nObject = New Property

    nObject.Name = priName
    nObject.Value = priValue

    If Not priProperties Is Nothing Then
        nObject.Properties.Assign priProperties
    End If

    Set Clone = nObject

    Set nObject = Nothing
End Function

Public Property Get Name() As String
    Name = priName
End Property

Public Property Let Name(ByVal RHS As String)
    priName = RHS
End Property

Public Property Get Value() As Variant
    Value = priValue
End Property

Public Property Let Value(ByVal RHS As Variant)
    priValue = RHS
End Property

Private Sub Class_Initialize()
    mPropertyType = PropertyTypeEnum.ptVariant
    mPropertyList = New PropertyList
End Sub

对propertyList。将Item定义为默认属性,将NewEnum定义为枚举属性。

Option Explicit

Private mCol As Collection

Public Sub Assign(nObject As PropertyList)
    Dim I As Long

    Me.Clear
    For I = 1 To nObject.Count
        Me.AddMember nObject(I).Clone
    Next

End Sub

Public Function Clone() As PropertyList
    Dim nObject As PropertyList
    Dim I As Long

    Set nObject = New PropertyList

    For I = 1 To Count
        nObject.AddMember Me(I).Clone
    Next I

    Set Clone = nObject

    Set nObject = Nothing
End Function

Public Sub AddMember(Item As Property)
    mCol.Add Item, Item.Name
End Sub

Public Sub Add(Name As String, Optional Value As Variant)
    Dim Item As Property
    If Not Defined(Name) Then
        Set Item = New Property

        Item.Name = Name

        If Not IsMissing(Value) Then N.Value = Value
        AddMember N
    Else
        If Not IsMissing(Value) Then Me(Name).Value = Value
    End If
End Sub

Private Sub Class_Initialize()
    Set mCol = New Collection
End Sub

Private Sub Class_Terminate()
    Set mCol = Nothing
End Sub

Public Sub Clear()
    Set mCol = New Collection
End Sub

Public Property Get Count()
    Count = mCol.Count
End Property

Public Property Get Defined(Index As Variant) As Boolean
    Dim Item As Property

    On Error Resume Next

    If IsNumeric(Index) Then
        Set Item = mCol(Index)
    Else
        Set Item = mCol(UCase(Index))
    End If

    If Err.Number <> 0 Then
        Defined = False
    Else
        Defined = True
    End If

End Property

Public Property Get Item(Index As Variant) As Property
    If IsNumeric(Index) Then
        Set Item = mCol(Index)
    Else
        Set Item = mCol(UCase(Index))
    End If
End Property

Public Property Get NewEnum() As IUnknown
    Set NewEnum = mCol.[_NewEnum]
End Property

我们的版本比排序和格式化功能更复杂,这就是我们不使用Microsoft Scripting Dictonary的原因。这允许我们动态创建一组分层属性。事实证明,这对我们的软件实施成本核算模块非常有用。因为我们不断添加或更改字段以响应客户输入。

这对于处理XML字段的灵活性非常有用。您可以使用Vartype函数获取变体的确切类型。您可以选择将字符串存储为VB6,就像大多数BASIC变体一样,可以在数字和字符串之间自由转换。