Handle ActiveX-Events with custom enum-parameters



  • I currently write an application which uses a COM-interface. To work with COM-interfaces in Qt, I want to use the ActiveX-framework of Qt. First of all, I created the wrapper-classes the the COM-interface with the Qt-tool 'dumpcpp.exe'. This tool creates a header-file and a cpp-file which contains the classes and enumerations used by the COM-interface. The tool also creates a new namespace (in my example FmTbsX) for the generated classes and enumerations. So far so good.

    I can use the generated classes to invoke methodes declared in the COM-interface. I can also receive some events, but only those which uses common Qt-data types like QVariant, QString, etc. But I want to receive an event, which uses a custom enumeration as parameter.

    The COM-interface offers an event called OnData(QString, TxDataRequestMode, QVariant&) where TxDataRequestMode is an enumeration declared in the COM-interface. I found out that the event does not use the namespace FmTbsX in its event-signature like follows: OnData(QString, FmTbsX::TxDataRequestMode, QVariant&). This can be evaluated when us register for the generic signal QAxBase:signal(...) where you can print all the event names. ("API-reference":http://harmattan-dev.nokia.com/docs/library/html/qt4/qaxbase.html)

    The dumpcpp generated such an enumeration for me:

    @
    // generated code

    namespace FmTbsX {
    ...
    enum TxDataRequestMode {
    drInsert = 0,
    drEvaluate = 1
    };
    ...
    }
    @

    Okay, I thought I can register a slot for that signal as I do as usual:

    @
    ...
    FmTbsX::XTbsSession* session = new FmTbsX::XTbsSession;
    connect(session, SIGNAL(OnData(QString, TxDataRequestMode, QVariant&)), this, SLOT(onData(QString, FmTbsX::TxDataRequestMode, QVariant&))); // in SIGNAL-signature wihout namespace FmTbsX for enum TxDataRequestMode
    @

    where the slot is:

    @
    private slots:
    void onData(QString attribName, FmTbsX::TxDataRequestMode mode, QVariant& value)
    @

    But the slot is not invoked in this case. I found out, that the slot is invoked, when I only use the first parameter in my slot (QString attribName):

    @
    private slots:
    void onData(QString attribName)
    @

    When I add the enumeration as the second parameter, it will not be invoked so this leads me to the assumption that the custom enumeration is the problem. But I don't get any compiling or runtime errors .

    From "this":http://qt-project.org/forums/viewthread/8660 thread I know that might have something to do with Qt-metadata-mapping, but all the examples do not use ActiveX-events but just "normal" events between classes. I tried to declare the enum FmTbsX::TxDataRequestMode as metatype as follows:

    @
    Q_DECLARE_METATYPE(FmTbsX::TxDataRequestMode)
    @

    and also register it with the following code in the constructor:

    @
    qRegisterMetaTypeFmTbsX::TxDataRequestMode("TxDataRequestMode");
    @

    If I understand the metadata sytem correct, Qt should recognize the parameter TxDataRequestMode and will find in the metadata mapping tables an entry for TxDataRequestMode and then maps it to the corresponding enum FmTbsX::TxDataRequestMode.

    Unfortunately that does not work and I really have no ideas what to do? I tried a lot of things but nothing helped.

    There is sometings I also found out: When I invoke

    @qRegisterMetaTypeFmTbsX::TxDataRequestMode("TxDataRequestMode");@

    then the slot is also not invoked even when I do not declare any parameters. So it must have something to do with the meta-data!?

    Does anybody have an idea?

    Thanks



  • Of course there is an alternative by receiving the events via the generic signal, but can't figure out how to get the parameters and how to return data back to the COM-interface in an output parameter. In my case, I can do this:

    @
    ...
    #include<oleauto.h> // needed for VARIANT and VARIANTARG (?)
    ...
    connect(session, SIGNAL(signal(QString &name, int argc, void *argv)),
    this, SLOT(eventHandler(QString &name, int argc, void *argv)));
    ...
    @

    I receive the event but I don't know how to go on. I only found a short implementation in the Qt Api-reference ("Qt-Api: QAxBase":http://harmattan-dev.nokia.com/docs/library/html/qt4/qaxbase.html#signal :

    @
    void Receiver::slot(const QString &name, int argc, void *argv)
    {
    VARIANTARG params = (VARIANTARG)argv;
    if (name.startsWith("BeforeNavigate2(")) {
    IDispatch *pDisp = params[argc-1].pdispVal;
    VARIANTARG URL = *params[argc-2].pvarVal;
    VARIANTARG Flags = *params[argc-3].pvarVal;
    VARIANTARG TargetFrameName = *params[argc-4].pvarVal;
    VARIANTARG PostData = *params[argc-5].pvarVal;
    VARIANTARG Headers = *params[argc-6].pvarVal;
    bool *Cancel = params[argc-7].pboolVal;
    }
    }
    @

    What to do with the VARIANTARG and how to convert the parameter to e.g. QString, etc.??? And when do I have to use VARIANT or VARIANTARG?



  • I tried to solve my problem with the generic signal QAxBase::signal.

    The signature of the event is:
    @
    OnData(QString,TxDataRequestMode,QVariant&)
    @

    ... where the first two parameters are input parameters and the last is an output parameter.

    The first parameter is a string and the second is an integer (enum). The third parameter is a variant type and is the output parameter where I have to give back a string to the COM.

    I can read the first two parameters, but I don't know how to send back the output parameter. I don't know if it is enough to just set the value or do I have to call any function? What I can say is that the implementation does not send any value back.

    @
    void FameAdapter::onFameEvent(const QString& name, int argc, void* argv)
    {
    // Check if event is 'OnData(...)'-event.
    if(name.startsWith(QString::fromLatin1("OnData(QString,TxDataRequestMode,QVariant&)")))
    {
    // Get all parameters
    VARIANTARG params = (VARIANTARG)argv;

        // Get first param of type string.
        BSTR bstrAttribName = params[argc-1].bstrVal;
        std::wstring wstrAttribName(bstrAttribName);
        const wchar_t* cstrAttribName = wstrAttribName.c_str();
        QString attribName = QString::fromWCharArray(cstrAttribName);
        QMessageBox::information(NULL, QString::fromLatin1("Attribute Name"), attribName);
    
        // Get second param of type integer.
        LONG lMode = params[argc-2].lVal;
        qint32 mode(lMode);
        QString strMode = QString::number(mode);
        QMessageBox::information(NULL, QString::fromLatin1("Mode"), strMode);
    
        // TODO: Third param is an output param of type QVariant&
        // How to pass the variant back as output param????
        VARIANTARG outputParam = params[argc-3];
        VARIANT *variant = new VARIANT;
        BSTR ms_str = SysAllocString(L"Test");
        variant->bstrVal = ms_str;
        outputParam.pvarVal = variant;
    }
    

    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.