Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED] Handling COM event Qt/C++
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] Handling COM event Qt/C++

Scheduled Pinned Locked Moved General and Desktop
22 Posts 4 Posters 12.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Maxbester
    wrote on 4 Feb 2013, 09:21 last edited by
    #1

    Hi there,

    I am porting an Excel macro to Qt4/C++.

    This macro uses ActiveX to command and receive data from another application.

    I need to receive events from this application and I don't know how to do it. Currently, the Excel macro uses the 'WithEvents' keyword to do so.

    Is there any equivalent with Qt? How to do it?

    Thanks

    1 Reply Last reply
    0
    • G Offline
      G Offline
      giesbert
      wrote on 4 Feb 2013, 09:40 last edited by
      #2

      Hi Maxbester,

      I do not really get what you do.
      You say you port an excel macro, an excel macro is something written in VBA within Excel.
      How does Qt come into the game here? How do you use Qt here? And where? inprocess?

      Nokia Certified Qt Specialist.
      Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

      1 Reply Last reply
      0
      • M Offline
        M Offline
        Maxbester
        wrote on 4 Feb 2013, 09:50 last edited by
        #3

        [quote author="Gerolf" date="1359970851"]Hi Maxbester,

        I do not really get what you do.
        You say you port an excel macro, an excel macro is something written in VBA within Excel.
        How does Qt come into the game here? How do you use Qt here? And where? inprocess?[/quote]

        I am sorry for the misunderstanding. Actually, I am not really porting the macro. I am re-developing it with Qt.

        Is it clearer?

        1 Reply Last reply
        0
        • G Offline
          G Offline
          giesbert
          wrote on 4 Feb 2013, 10:18 last edited by
          #4

          So you are are out of the excel process?
          WithEvents is a VB macro.

          Nokia Certified Qt Specialist.
          Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

          1 Reply Last reply
          0
          • A Offline
            A Offline
            andre
            wrote on 4 Feb 2013, 11:03 last edited by
            #5

            To me, it looks as if Maxbester is trying to automate Excel using a Qt application that interfaces with Excel through ActiveX. That application is to replace an older Excel macro. Right?

            Perhaps you should study the QAx* examples, especially the one automating Outlook.

            1 Reply Last reply
            0
            • M Offline
              M Offline
              Maxbester
              wrote on 4 Feb 2013, 12:08 last edited by
              #6

              [quote author="Andre" date="1359975781"]To me, it looks as if Maxbester is trying to automate Excel using a Qt application that interfaces with Excel through ActiveX. That application is to replace an older Excel macro. Right?[/quote]

              Yes you are right.

              [quote author="Andre" date="1359975781"]Perhaps you should study the QAx* examples, especially the one automating Outlook.[/quote]

              I studied the Outlook example but, maybe I'm wrong, I didn't see any information about COM event handling.

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andre
                wrote on 4 Feb 2013, 13:22 last edited by
                #7

                I didn't try it myself, but it looked to me like COM events are exposed as (dynamically generated) signals.

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  Maxbester
                  wrote on 4 Feb 2013, 13:50 last edited by
                  #8

                  [quote author="Andre" date="1359984176"]I didn't try it myself, but it looked to me like COM events are exposed as (dynamically generated) signals.[/quote]

                  Yes, I think it would be a good thing. However, Qt generated a header file from a .tlb file and it doesn't have any signal at all.

                  So I am stuck...

                  1 Reply Last reply
                  0
                  • G Offline
                    G Offline
                    giesbert
                    wrote on 4 Feb 2013, 14:07 last edited by
                    #9

                    Hi,

                    You mean COM events (I expect you mean callbacks?) which you subscribe?
                    Those are callback methods implemented in a callback interface. If that is done correctly with COM, the ActiveQt creates a class with signals which you can connect to.

                    You should check, whether the tlb file really contains outgoing interfaces for the class.

                    Nokia Certified Qt Specialist.
                    Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                    1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      Maxbester
                      wrote on 4 Feb 2013, 14:33 last edited by
                      #10

                      Thanks for your reply.
                      I don't know how to check the tlb file (I'm new to Windows and COM programming). What I know is that ActiveQt didn't generate any signal...

                      1 Reply Last reply
                      0
                      • A Offline
                        A Offline
                        andre
                        wrote on 4 Feb 2013, 14:43 last edited by
                        #11

                        Did you try to just connect to a signal with the appropriate name at runtime? I think it needs to be something like this:
                        @
                        connect(activeXObject, SIGNAL(ItemAdd(IDispatch*)), this, SLOT(whatever()));
                        @
                        Where ItemAdd is the name of the ActiveX event. The documentation of QAxObject states:
                        [quote]You can subclass QAxObject, but you cannot use the Q_OBJECT macro in the subclass (the generated moc-file will not compile), so you cannot add further signals, slots or properties. This limitation is due to the metaobject information generated in runtime. To work around this problem, aggregate the QAxObject as a member of the QObject subclass.[/quote]
                        That makes me think that QAxObject does some magic behind the scenes where it dynamically, at runtime, creates the interface in terms of signals. So, there is nothing to inspect at design time.

                        1 Reply Last reply
                        0
                        • M Offline
                          M Offline
                          Maxbester
                          wrote on 4 Feb 2013, 14:52 last edited by
                          #12

                          Al right, this is not a bad idea. I am going to try that.
                          Thanks!

                          1 Reply Last reply
                          0
                          • G Offline
                            G Offline
                            giesbert
                            wrote on 4 Feb 2013, 15:54 last edited by
                            #13

                            Hi Maxbester,

                            to read the content of a Tlb (or a OCM dll, ocx file) you can use Oleview from Microsoft.
                            It extracts all information of a type library.

                            Nokia Certified Qt Specialist.
                            Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                            1 Reply Last reply
                            0
                            • M Offline
                              M Offline
                              Maxbester
                              wrote on 4 Feb 2013, 16:04 last edited by
                              #14

                              It doesn't seem to work. I've got the message:
                              @
                              QObject::connect: No such signal QAxBase::INotify2(...)
                              @

                              I found a document about the software I try to interact with. It is "Pulse Labshop":http://homel.vsb.cz/~tum52/download/PULSEAutomation.pdf from "BrĂ¼el & Kjaer":http://www.bksv.com.

                              This link leads to a pdf with some basic information. Page 56 is an explanation about how to work with its notification system (to me, it just looks like events).

                              1 Reply Last reply
                              0
                              • A Offline
                                A Offline
                                andre
                                wrote on 4 Feb 2013, 16:46 last edited by
                                #15

                                INotify2 doesn't look like the actual name of the event. However, what you could try is to use QMetaObject to just list the signals from your QAxObject at runtime.

                                @
                                const QMetaObject* mo = myQAxObject->metaObject();
                                int i(0);
                                while (i < mo->methodCount()) {
                                QMetaMethod mm = mo->metaMethod(i++);

                                QString typeString;
                                switch (mm.type()) {
                                case QMetaMethod::Method: typeString = QString("Method"); break;
                                case QMetaMethod::Signal: typeString = QString("Signal"); break;
                                case QMetaMethod::Slot: typeString = QString("Slot"); break;
                                case QMetaMethod::Constructor: typeString = QString("Constructor"); break;
                                }

                                QString accessString;
                                switch (mm.access()) {
                                case QMetaMethod::Private: typeString = QString("Private"); break;
                                case QMetaMethod::Protected: typeString = QString("Protected"); break;
                                case QMetaMethod::Public: typeString = QString("Public"); break;
                                }

                                qDebug() << accessString << typeString << mm.signature();
                                }
                                @

                                Something like the above can be used to get a good view of all the methods, signals and slots of your object. It should also list any dynamically generated ones, if there are any. Perhaps you can use it to find out the exact signature of the signals you're after, instead of guessing what they might be called and what arguments you need for them...

                                1 Reply Last reply
                                0
                                • M Offline
                                  M Offline
                                  Maxbester
                                  wrote on 4 Feb 2013, 17:07 last edited by
                                  #16

                                  Thanks a lot! I didn't know a such thing was possible.

                                  I changed a little bit your code because there are some mistakes:

                                  @
                                  PulseLabShop::IPulseLabShop2* app = new PulseLabShop::IPulseLabShop2();
                                  const QMetaObject* mo = app->metaObject();
                                  for (int i=0; i<mo->methodCount(); i++) {
                                  QMetaMethod mm = mo->method(i);

                                    QString typeString;
                                    switch (mm.methodType()) {
                                    case QMetaMethod::Method: typeString = QString("Method"); break;
                                    case QMetaMethod::Signal: typeString = QString("Signal"); break;
                                    case QMetaMethod::Slot: typeString = QString("Slot"); break;
                                    case QMetaMethod::Constructor: typeString = QString("Constructor"); break;
                                    }
                                  
                                    QString accessString;
                                    switch (mm.access()) {
                                    case QMetaMethod::Private: typeString = QString("Private"); break;
                                    case QMetaMethod::Protected: typeString = QString("Protected"); break;
                                    case QMetaMethod::Public: typeString = QString("Public"); break;
                                    }
                                  
                                    qDebug() << accessString << typeString << mm.signature();
                                  }
                                  

                                  @

                                  I found one signal for this class. I will try to connect it.

                                  1 Reply Last reply
                                  0
                                  • M Offline
                                    M Offline
                                    Maxbester
                                    wrote on 5 Feb 2013, 07:26 last edited by
                                    #17

                                    Finally, all classes and interfaces return the same signals and slots:

                                    @
                                    "Protected" "signal" destroyed(QObject*)
                                    "Protected" "signal" destroyed()
                                    "Public" "slot" deleteLater()
                                    "Public" "slot" _q_reregisterTimers(void*)
                                    "Protected" "signal" signal(QString,int,void*)
                                    "Protected" "signal" propertyChanged(QString)
                                    "Protected" "signal" exception(int,QString,QString,QString)
                                    @

                                    I cannot connect a protected signal. I am still stuck... Any idea?

                                    1 Reply Last reply
                                    0
                                    • A Offline
                                      A Offline
                                      andre
                                      wrote on 5 Feb 2013, 07:50 last edited by
                                      #18

                                      All of these are standard QObject signals and slots, nothing specific to QAxObject. Are you sure the QAxObject is properly initialized before you do this? That is, that it represents a valid COM object? If so, then I have no clue, and I am afraid I led you down a dead end. My apologies for that.

                                      1 Reply Last reply
                                      0
                                      • M Offline
                                        M Offline
                                        Maxbester
                                        wrote on 5 Feb 2013, 08:06 last edited by
                                        #19

                                        [quote author="Andre" date="1360050606"]Are you sure the QAxObject is properly initialized before you do this?[/quote]

                                        It should be. However, the program license may be expired. I have to work on this and try to reinstall Pulse Labshop.
                                        I will come back here after.

                                        Anyway, thanks for your help ;)

                                        1 Reply Last reply
                                        0
                                        • M Offline
                                          M Offline
                                          Maxbester
                                          wrote on 10 Apr 2013, 16:17 last edited by
                                          #20

                                          [quote author="Maxbester" date="1359997679"]Thanks a lot! I didn't know a such thing was possible.

                                          I changed a little bit your code because there are some mistakes:

                                          @
                                          PulseLabShop::IPulseLabShop2* app = new PulseLabShop::IPulseLabShop2();
                                          const QMetaObject* mo = app->metaObject();
                                          for (int i=0; i<mo->methodCount(); i++) {
                                          QMetaMethod mm = mo->method(i);

                                            QString typeString;
                                            switch (mm.methodType()) {
                                            case QMetaMethod::Method: typeString = QString("Method"); break;
                                            case QMetaMethod::Signal: typeString = QString("Signal"); break;
                                            case QMetaMethod::Slot: typeString = QString("Slot"); break;
                                            case QMetaMethod::Constructor: typeString = QString("Constructor"); break;
                                            }
                                          
                                            QString accessString;
                                            switch (mm.access()) {
                                            case QMetaMethod::Private: typeString = QString("Private"); break;
                                            case QMetaMethod::Protected: typeString = QString("Protected"); break;
                                            case QMetaMethod::Public: typeString = QString("Public"); break;
                                            }
                                          
                                            qDebug() << accessString << typeString << mm.signature();
                                          }
                                          

                                          @

                                          I found one signal for this class. I will try to connect it.[/quote]

                                          Better than that:

                                          @
                                          QString filename="Doc.html";
                                          QFile file( filename );
                                          if ( file.open(QIODevice::Write) )
                                          {
                                          QTextStream stream( &file );
                                          stream << app->generateDocumentation();
                                          }
                                          @

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved