1

我们使用的是 Topaz Signature 垫。它们在要放在 Winform 控件上的 ActiveX 控件中提供其 API。好吧,我们项目的工作方式我们不希望有一个表单(至少不可见)。我们只希望签名 ActiveX 控件在背景中获取图像。

static AxSigPlus sig = new AxSIGPLUSLib.AxSigPlus();

public static void Begin()
{
    ((System.ComponentModel.ISupportInitialize)(sig)).BeginInit();
    sig.Name = "sig";
    sig.Location = new System.Drawing.Point(0, 0);
    sig.Size = new System.Drawing.Size(0, 0);
    sig.Enabled = true;

    sig.TabletState = 1; //error here
    sig.SigCompressionMode = 0;
}

好的,所以我在标记的行出现错误。例外是

引发了“System.Windows.Forms.AxHost+InvalidActiveXStateException”类型的异常。

我该怎么做才能解决这个问题?创建一个新的隐藏表单并将控件放在它上面使其不可见会更容易吗?

4

4 回答 4

2

是的,这样不行。AxHost 包装器需要在可用之前创建其句柄。这要求它是调用 Show() 方法的窗体上的子控件。

您通常会从 ActiveX 控件获得两个互操作包装器,一个包含 AxHost 包装器的 AxBlah.dll 和一个包装 COM 接口的 Blah.dll。您只需要引用 Blah.dll。这是否可行是一个悬而未决的问题,许多 ActiveX 控件需要一个窗口句柄来处理线程同步。

如果这不起作用,您将需要一个主机表单。您可以通过将此代码粘贴到表单类中来使其不可见:

    protected override void SetVisibleCore(bool value) {
        if (!IsHandleCreated) CreateHandle();
        value = false;
        base.SetVisibleCore(value);
    }

您必须调用 Application.Run() 来泵送消息循环。

于 2010-05-25T19:19:04.567 回答
1

您也许可以直接使用 COM 对象(这实际上取决于他们如何实现控件)。通常,当您将 COM 对象导入引用时,它会创建一个包装器 AxHost,但它也应该导入基本类对象。找到那个,然后像任何普通类一样创建它,不要使用 AxHost 版本。如果似乎没有任何基类对象,您可以使用 Activator 和控件的 CLSID 或 ProgID 创建对象。就像是:

object o = Activator.CreateInstance(Type.GetTypeFromProgID("prog.id"))

于 2010-05-25T19:18:34.227 回答
1

这就是我所做的(基本上添加了不可见的 Ax 控件并随后调用了它的方法):

using (AxRUNNERXLib.AxRunnerX crm = new AxRUNNERXLib.AxRunnerX ()) {
    Controls.Add (crm);
    crm.Visible = false;

    crm.CustomerPrefix = m_SelCall.CustomerPrefix;
    crm.LoadDefaultDescription ();
    crm.SearchByID (m_SelCall.CustomerID);
    crm.OperatorID = Form1.operatorID.ToString ();
    crm.ShowHistory ();

    Controls.Remove (crm);
}
于 2011-08-16T15:41:13.617 回答
0

实际上,Topaz 最终提供了一个 ActiveX 控件和一个围绕它的 .Net 包装器。我切换到 .Net 包装器,它不需要放在表单或任何东西上。不过,我会留下这个问题,因为如果不是那个包装器,我实际上会处理它。

于 2010-05-25T22:00:50.887 回答