VB和C++ActiveX控件以不同的方式保存其信息,如何实现C++ActiveX控件来代替VB ActiveX

VB and C++ ActiveX control persist its information in different way, how can I implement C++ ActiveX control to replace VB ActiveX?

本文关键字:VB C++ActiveX 控件 何实现 实现 ActiveX 信息 保存 方式      更新时间:2023-10-16

背景

有一个由VB创建的旧ActiveX控件。我将此ActiveX控件添加到Excel工作簿中,并设置了一些属性。这些属性是在保存书本时保存的。具体来说,它们是使用VB代码中的PropertyBag保存在UserControl_WriteProperties函数中的。因此,这些属性一直存在于工作簿中,直到现在。

我的任务

我必须使用C++创建一个新的ActiveX控件,以便与旧控件向后兼容。我需要所有信息都保存在ActiveX控件中,它在我的旧Excel工作簿中。因此,我在ActiveX控件中实现了IPersistPropertyBag。

我的期望是,当我打开旧的Excel工作簿时,所有信息都必须通过PropertyBag正确检索。

问题

我发现保存在Excel工作簿中的信息是流格式的。我可以将IPersistStreamInit实现到我的新ActiveX控件,但我不理解Excel工作簿中保留的流中的格式。因此,我无法检索保存在Excel工作簿中的信息。

我想知道为什么信息是以流格式保存的,尽管它们是通过VB代码中的Propertybag保存的。

问题

在这种情况下,是否有方法将所有信息持久化到ActiveX控件中?我已经找到它两天了,但我找不到办法。

属性包保存到流中,仅此而已。

我希望您的C++控件实现IPersistStream,所以Excel正在尝试使用它。我建议您首先尝试从C++控件中剥离IPersistStream、IPersistStreamInit和IPersistStorage,只留下IPersistPropertyBag。

我通过创建一个VB6 COM dll来处理此任务。

Option Explicit
Dim objMyPropertyBag As PropertyBag
Public Sub Contents(a_content As Variant)
    objMyPropertyBag.Contents = a_content
End Sub
Public Function Read(key As String) As String
On Error GoTo Error_Handler
    Read = objMyPropertyBag.ReadProperty(key)
Error_Handler:
    MsgBox Err.Source & Err.Number
End Function
Private Sub Class_Initialize()
    Set objMyPropertyBag = New PropertyBag
End Sub

当我打开包含旧ActiveX对象的旧Excel工作簿时。我做以下步骤:

  1. 它将进入IPersistStreamInit::Load函数,它给我一个IStream
  2. 我读取了这个流,并解析为VT_UI1的SAFEARRAY的VARIANT(等于BYTE的数组(,称为"content">
  3. 我创建了一个VB6 COM dll的实例,名为"contentReader">
  4. 我调用contentReader->Contents(content((将我创建的SAFEARRAY传递给它(

现在我可以通过contentReader->read([in]key,[out]value(读取PropertyBag中的任何键。