How do I fire events from a QAxServer executable?
Hi guys, I'm currently adding an OLE layer to my app using ActiveQt. It went great so far except that I can't understand why my signals are not passed to the OLE.
I'm using Qt's testcon to monitor the events.
After hours trying to debug my app and going nowhere, I tried to start from an official Qt example and modify it to suit my need.
I started with the AxBouncer example from the well know book C++ GUI Programming with Qt4, 2nd Edition.
The souce code is available freely here: http://www.informit.com/content/images/9780132354165/examples/qt-book-examples.zip
I just added a signal, a QTimer in the constructor that fires the event every second. testcon shows it works very well.
But that example produces a dll. As soon as I turn it into an executable, the signal stops from being detected by testcon.
I then gave a look an official example from Qt named simple.
This example already comes with some signals that are emitted whenever you move a QSlider.
Tested it with testcon and, again, the signals are not shown.
I'm now wondering if this is a known limitation or something like that.
Unfortunately the online help is really quiet on these kind of platform specific topics so any help will be much much appreciated.
(I can share minimal source code to reproduce the working and non working configurations if needed)
Hi, the limitation is that there are basically 2 ways of doing OLE here, one is by building an ActiveX control .dll (many years ago also the extension .ocx was used).
Those .dlls is what you can play with in testcon.
The other way is by building an .exe file into something called an OLE Automation Server or Active X server (this is what the Qt example simple is), and that flavor is not supported by testcon. But it's quite easy to test anyway, if you have Visual Studio around you can test it from there, I just did that in Visual Basic:
The ActiveQt framework consists of two modules:
- The QAxContainer module is a static library implementing QObject and QWidget subclasses, QAxObject and QAxWidget, that act as containers for COM objects and ActiveX controls.
- The QAxServer module is a static library that implements functionality for in-process and executable COM servers. This module provides the QAxAggregated, QAxBindable and QAxFactory classes.
Is it the same thing you are talking about? Or do you mean that the second module QAxServer comes in 2 different flavors? (control .dll/server .exe)
How can you tell testcon can only work with control.dll? Documention says it's for containers, but text above says containers are created with QAxContainer module.
However the bouncer example works fine in testcon and relies on the QAxServer module.
Last question: can you show me how to hook an OLE event with your vb example?
Thanks again for your help
Hi, the QAXserver I think can be used for both types of OLE (.dll and .exe), but for creating .exe files you only need QAXFactory.
The bouncer example most likely only comes as a ActiveX.dll, that's why testcon is ok with it.
(But testcon might be happy loading .exe files also, I suspect it does not but I don't know, to test I need to download Qt's sources and build it :-(
Finally. about that vb example, to sink an event (ancient Microsoft terminology) you add another Sub (and change from Dim to WithEvents when declaring the OLE server):
Hi, you can also sink that event from Qt quite easy: build a vanilla Qt widgets app, add a QAXWidget to the form, add a reference to the simpleax.exe file (i.e. the QSimpleAX class) and then add the event (similar as in Visual Studio), here's some pictures:
Edit: this should work in testcon as well, it's pretty straightforward.
*Edit #2: Indeed, I was most likely wrong in my previous post (saying that testcon doesn't like OLE .exe files). When looking at testcon's source code: it uses an QAXWidget, same as my simple test program, so that simple example should work like a charm...
Thanks for your detailed answer. I'm now debuging with a VB application and it seems to be able to hook events from my exe application. Will report later.
Still not clear why testcon fails.
Agreed, testcon should work. Hmm maybe later I'll find the time to build it.
But if you instead can proceed testing via a Visual Basic program, then testcon might not be needed :-)
@hskoglund Well I stopped using testcon and I'm now able to fire my events and catch them with the VB client.
I still have a couple question, hope you can help!
CreateObject("MyApp.MyComController")from VB it returns quite early. Lots of my subobject are still un-initialized (looks like I'm still in the middle of my main).
How do I deal with this?
I'm exposing two object to the OLE layer, one is a subclass of QGraphicsView. From the documentation it should shows as an ActiveX control:
If the object returned is a QWidget it will be exposed as an ActiveX control, otherwise the returned object will be exposed as a simple COM object.
How can I integrate this control in my VB app? It is not listed in the Toolbox > COM components
I'm thinking it's because you're doing OLE between 2 apps, the OLE traffic will be asynchronous, so VB will not wait for your app to finish processing.
To qualify as an ActiveX control (i.e. a control that you can paste on your VB form) I'm pretty sure it has to be a .dll, not an .exe.
Thank you, although I'm left without solution on those 2 questions :(
Hmmm, problem #1 I think you can solve by introducing additional handshaking, like setting a property "InitDone" to true when all your subobjects are up and running, and having VB wait for that.
But anyway, both issues I think will vanish if you switch from building an .exe to a .dll.
An ActiveX control normally does not have any other UI or functionality besides being an embedded control in someone else's program, so perhaps your shoehorning too much into your app. I mean trying both to be a normal app with a GUI and at the same time being an ActiveX control. Perhaps you could refactor out the OLE stuff into a ActiveX control .dll and use it from your normal app as well? Just my 2 cents :-)
Finally found that the early return (problem #1) was due to the way QSplashScreen works.
Since you have to call qApp->processEvents() to refresh the display, the event loop was processing the request for creating the OLE objects much earlier than expected.
- To qualify as an ActiveX control (i.e. a control that you can paste on your VB form) I'm pretty sure it has to be a .dll, not an .exe.
Do you think that if my server (exe) exposes a QWidget, it won't be possible to use it as a Control in VB (I don't care about drag and drop, what I wonder is if it will be impossible to insert the widget in a VB Form)
Hi, well the simpleax.exe example above works in VB and it exposes its widgets, so it should work for you as well. And when I tested it from my simple Widgets app above, I had simpleax.exe's widgets running inside my app's form (you see the window title: MainWindow).
However when I tested simpleax.exe from VB, I couldn't paste its widgets onto VB's form, only create that additional window instance with the title simpleax.exe.
When I looked at the existing COM components already listed I see half of them are .ocx and the half are .dlls. But actually there are 2 instances of .exe files present: both for Outlook.exe:
So that means it should be possible :-)
So, from VB you can't have simpleax widget in your own Form (event calling it programatically, no drag and drop) is that what you mean?
But with C++ QAXWidget, you can embed it in your app GUI?
Yes that's about it.
In VB, if I don't issue the x.show() statement at startup, then no simpleax widgets will be visible, and when I do the x.show() they are visible alright, but in their own, separate form.
In Qt, I dont' need to do any ui->axwidget()->show(), simpleax's widgets will show themselves anyway, and in Qt's window. In other words, Qt eats VB's lunch here :-)
So is this anomaly due to VB's inability to handle in-form .exe files, or due to Qt not adhering to some ancient Microsoft OLE specification? My guess is that in-form .exe files are sort of verboten (i.e. alternative 2) and Qt manages to sneak around it..
Dear @hskoglund , do you have any idea how to use custom types in the OLE client?
For instance QRect is declared by default in any tlb created with ActiveQt. However when trying to retrieve properties with this type from VB, I get this error:
The specified record cannot be mapped to a managed value class.