Make an ActiveX control work without a form?

4.6k views Asked by At

We are using Topaz Signature pads. They provide their APIs in the from of an ActiveX control which is to be put on a Winform control. Well, the way our project will work we do not want to have a form(at least not visible). We just want for the signature ActiveX control to get an image in the background.

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;
}

Ok so I get an error at the marked line. The exception is

Exception of type 'System.Windows.Forms.AxHost+InvalidActiveXStateException' was thrown.

What do I do to solve this problem? Would it just be easier to create a new hidden form and put the control on it so it's invisible?

4

There are 4 answers

1
Earlz On BEST ANSWER

Actually it ended up that Topaz provided an ActiveX control and a .Net wrapper around it. I switched to the .Net wrapper and it doesn't require being placed on a form or anything. I will leave the question up though because had it not been for that wrapper I would actually be dealing with it.

0
jaros On

This is what I did (basically added invisible Ax control and invoked its methods thereafter):

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);
}
0
tyranid On

You might be able to just use the COM object directly (it really depends how they implemented the control). Normally when you import the COM object into your references it will create a wrapper AxHost but it should also import the basic class objects. Find which that is then just create it as any normal class, do not use the AxHost version. If there doesn't seem to be any base class objects you can create the object using the Activator and either the CLSID or ProgID of the control. Something like:

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

0
Hans Passant On

Yes, that can't work this way. The AxHost wrapper requires its Handle to be created before it is usable. Which requires it to be a child control on a form whose Show() method is called.

You normally get two interop wrappers from an ActiveX control, an AxBlah.dll which contains the AxHost wrapper and a Blah.dll which wraps the COM interfaces. You'd only need to reference Blah.dll. Whether that will work is an open question, many ActiveX controls require a window handle to deal with thread synchronization.

If that doesn't work out, you'll need a host form. You can keep it invisible by pasting this code into the form class:

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

You have to call Application.Run() to pump the message loop.