Skip to content

Instantly share code, notes, and snippets.

@sunjerry019
Last active November 9, 2022 09:08
Show Gist options
  • Save sunjerry019/e51504317f523c21ef12da5155c1354f to your computer and use it in GitHub Desktop.
Save sunjerry019/e51504317f523c21ef12da5155c1354f to your computer and use it in GitHub Desktop.
Using an (GUI) ActiveX Control in Python

Using an (GUI) ActiveX Control in Python (Minimal Example)

I was trying to use a GUI-only ActiveX Control in Python (using an OCX File) and I managed to get it working using PyQt5 as an intermediary.

See the below minimal example code using the ActiveX Control DATARAOCX.GetDataCtrl.1.

I found this way more elegant than using comtypes, wxpython or similar, especially since comtypes kept throwing a "Catastropic Error" whenever I try to access the ActiveX Control.

Hope this helps someone also stuck in this problem.

from PyQt5 import QtWidgets, QAxContainer
dummyapp = QtWidgets.QApplication(['']) # Makes a dummy app
datactrl = QAxContainer.QAxWidget("DATARAYOCX.GetDataCtrl.1")
# A method StartDriver() is provided in the OCX
ret = datactrl.dynamicCall("StartDriver")
# Returns the value as returned by the ActiveX Control
@Yongbooo
Copy link

Hi, I also use GUI-only ActiveX and OCX file to drive DataRay Beam profile analyzer . Now, I can start the device successfully, but I don't know how to read the raw data from the device , In wxpython example supplied from DataRay, There's this piece of code:

self.px = wx.lib.activex.ActiveXCtrl(parent=self.frame,size=(300,200),axID='DATARAYOCX.ProfilesCtrl.1',pos=(0,270))
self.px.ctrl.ProfileID=4
self.py = wx.lib.activex.ActiveXCtrl(parent=self.frame,size=(300,200),axID='DATARAYOCX.ProfilesCtrl.1',pos=(320,270))
self.py.ctrl.ProfileID =5

I don't know how to write to realize the same function .

@sunjerry019
Copy link
Author

@Yongbooo Check out

The trick here is that you want to bind a given axID to a QAxWidget as in line 4 of the gist. In your case, the axID is DATARAYOCX.ProfilesCtrl.1. You can then call the appropriate OCX dynamical call method of that ActiveX Control (like the StartDriver in the above gist).

Hope this helps!

@Yongbooo
Copy link

Yongbooo commented Nov 9, 2022

@sunjerry019 Thanks for your reply. I tried all OCX dynamical call methods of that ActiveX Control , but only the StartDriver( ) worked.
Take your method 'getAxisProfile(self, axis: WinCamAxes) 'as example, below is myself code.

import numpy as np
from PyQt5 import QtWidgets, QAxContainer
from collections import namedtuple
import time
dummyapp = QtWidgets.QApplication([''])  # Makes a dummy app
datactrl = QAxContainer.QAxWidget("DATARAYOCX.GetDataCtrl.1")
ret = datactrl.dynamicCall("StartDriver")
axis = {
    "x": QAxContainer.QAxWidget("DATARAYOCX.ProfilesCtrl.1"),
    "y": QAxContainer.QAxWidget("DATARAYOCX.ProfilesCtrl.1")
}
axis = namedtuple("Axis", axis.keys())(*axis.values())

axis.x.setProperty("ProfileID", 4)
axis.y.setProperty("ProfileID", 5)
prof_data = None
data = {
    "x": np.array(axis.x.dynamicCall("GetProfileDataAsVariant")),
    "y": np.array(axis.y.dynamicCall("GetProfileDataAsVariant"))
}
time.sleep(1)
prof_data = [0, 0]
prof_data[0] = data["x"]
prof_data[1] = data["y"]
print(prof_data)

The content output is always zero:
[array([0, 0, 0, ..., 0, 0, 0]), array([0, 0, 0, ..., 0, 0, 0])]

Could you tell me what's wrong with my script.
Looking forward to your reply.

@sunjerry019
Copy link
Author

  1. Python has lazy evaluation, which means that the dynamicCallwas likely only executed when the print() function is called
  2. In my version, I used a queue and waited for the DataReady event before retrieving the data.
  3. In my version, I did not manage to get "GetProfileDataAsVariant" to work. It could be because of other limitations/reasons etc. However, since I do not have access to a WinCamD camera anymore, I am unable to debug this.
  4. If this issue that you are facing is specifically for the WinCamD, I recommend moving this conversation to my nanosquared repo instead of having it here. If you do manage to fix it, I would like to encourage you to create a pull request on my repository so that it could be used as a reference for others should they find this thread again.

Sorry I can't be of much help, but I hope this somewhat answers your question :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment