Better_Software_Header_Mobile Better_Software_Header_Web

Find what you need - explore our website and developer resources

OLE-Dispatch When Doing MFC/Qt Migration

Bridging OLE and Qt

// This is the widget we're working with:
QWidget* someWidget = ...;

// Lets' create our dispatcher:
// You have to delete it yourself or let COM do it for you via IUnknown::AddRef/Release
QObjectDispatcher* dispatcher = new QObjectDispatcher(someWidget);

// The code until this point is the only part which is new in your application, as
// far as dispatching the calls/properties is involved. From here, it's exactly the same;
// from the OLE MFC application's perspective we often only have an IUnknown:
IUnknown* pUnknown = dispatcher;

// Now get the interface and start playing with it:
CComQIPtr<IDispatch> pDispatch(pUnknown);

// First we have to retrieve the index of the property we change
LPOLESTR name = "windowTitle";
DISPID dispId = -1;
pDispatch->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT, &dispId);

// Now that we have the index, we change the property
VARIANT varTitle = CComVariant("New window title");
DISPSPARAMS dispParams = { nullptr, nullptr, 0, 0 };
dispParams.rgvarg = &varTitle;
dispParams.cArgs = 1;
pDispatch->Invoke(dispId, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT,
    &dispParams, nullptr, nullptr, nullptr);
HRESULT QObjectDispatcher::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cnames, LCID, DISPID* rgDispId)
{
    // GetIdsOfNames supports requesting several at the same time
    for (uint i = 0; i < cNames; ++i) {
        // note you cannot use QMetaObject::indexOfMethod directly, 
        // since it expects the fully qualified name
        auto indexOfMethod = []() { /* ... */ };
        const int methodIndex = indexOfMethod(rgszNames[i]);
        if (methodIndex != -1) {
          rgDispId[i] = methodIndex;
          continue;
        }
    }
    // now do the same for the properties...
    // [...]
    return S_OK;
}
HRESULT QObjectDispatcher::Invoke(DISPID dispIdMember, REFIID riid, LCID, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO*, UINT*)
{
    if (wFlags == DISPATCH_METHOD) {
        const QMetaMethod method = metaObject->method(dispIdMember);

        // translate return argument
        auto returnArgument = translateReturnArgument(method, pVarResult);

        // then call the method, translating all the arguments
        invokeMethod(method, m_object, returnArgument, translateArgument(0), ...);

        return S_OK;
    }

    // [...]
}

About KDAB

01_NoPhoto

Christoph Schleifenbaum

Senior Software Engineer

Sign up for the KDAB Newsletter