Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[SOLVED] Connect to DDE Server



  • Hi all,

    Is there any way I can connect to a DDE server? I know DDE is dated tech, but it's the only option I have for what I'm attempting to do.

    I've found http://permalink.gmane.org/gmane.comp.lib.qt.general/91 but it only works in Qt 3 and I'm too inexperienced to convert it forwards. Any help?

    Thanks,
    James



  • It only Qt dependency is QString. It is very easy to port it to Qt4.

    For example, instead of
    @command.ascii()@
    use
    @command.toAscii().data()@



  • That's a good start. I've also fixed some other problems by using (LPCSTR) val.utf16() which solved a couple of problems.

    That being said, can you see why this wont work?

    @DDEComm *cyDesk;
    QString result;
    cyDesk->ddeConnect("CYDESK", "Data");
    cyDesk->ddeExecute("CALL NUMBER", result);@

    I always get the following:

    @C:\Users\James.Brooks\Desktop\BLUI-BUILD-DBG..\BLUI\ddecomm.cpp:100: error: C2511: 'QString DDEComm::ddeExecute(const QString &,const QString &)' : overloaded member function not found in 'DDEComm'@



  • change function declaration in ddecomm.h from
    @QString ddeExecute(QString command, QString result); /!< Executa um comando no servidor dde/@
    to
    @QString ddeExecute(const QString &command, const QString &result) /!< Executa um comando no servidor dde/@



  • We're getting closer! Now I made the changes you said about .ascii().data() but I get 'ascii' is not a member of QString.

    Has this got something to do with the changes I made earlier?

    @hszRequest = DdeCreateStringHandleA(pidInst, (LPCSTR)item.utf16(), CP_WINANSI);@

    I added the (LPCSTR)item.utf16() part, which shut some errors up.

    So I've tried the following:

    @QString DDEComm::ddeExecute(const QString &command, const QString &result)
    {
    char *commandName = NULL;
    strcpy(commandName, (LPCSTR)command.toAscii());
    transactionData = DdeCreateDataHandle(pidInst, (LPBYTE) commandName, strlen(commandName), 0, 0L, CF_TEXT, NULL);
    DdeClientTransaction((LPBYTE) transactionData, -1, hConv, 0L, 0, XTYP_EXECUTE, 1000, NULL);

    QString returnData = ddeRequest(result);
    
    DdeFreeDataHandle(transactionData);
    
    return returnData;
    

    }@

    But now I get a hell load of errors:
    !http://dl.dropbox.com/u/7323096/QTDDE.PNG!



  • Here is patched DDEComm class:

    ddecomm.cpp
    @#include "ddecomm.h"

    DDEComm* DDEComm::_instance = NULL;

    DDEComm* DDEComm::instance()
    {
    if(_instance == NULL)
    _instance = new DDEComm();

    return _instance;
    }

    DDEComm::DDEComm()
    {
    connStatus = false;
    callback = NULL;
    pidInst = 0;
    hConv = 0L;
    }

    DDEComm::~DDEComm()
    {
    //Empty
    }

    bool DDEComm::ddeConnect(const QString &service, const QString &topic)
    {
    if(callback == NULL)
    {
    if(DdeInitializeA(&pidInst, NULL, APPCLASS_STANDARD | APPCMD_CLIENTONLY, 0L) != DMLERR_NO_ERROR)
    return false;
    }
    else
    {
    if(DdeInitializeA(&pidInst, (PFNCALLBACK) callback, APPCLASS_STANDARD | APPCMD_CLIENTONLY | MF_CONV | MF_ERRORS, 0L) != DMLERR_NO_ERROR)
    return false;
    }

    hszService = DdeCreateStringHandleA(pidInst, service.toAscii().data(), CP_WINANSI);
    hszTopic = DdeCreateStringHandleA(pidInst, topic.toAscii().data(), CP_WINANSI);
    hConv = DdeConnect(pidInst, hszService, hszTopic, NULL);

    DdeFreeStringHandle(pidInst, hszService);
    DdeFreeStringHandle(pidInst, hszTopic);

    if(!hConv)
    return false;

    connStatus = true;

    return true;
    }

    void DDEComm::ddeDisconnect()
    {
    DdeDisconnect(hConv);
    DdeUninitialize(pidInst);
    connStatus = false;
    }

    void DDEComm::setDDECallback(PFNCALLBACK ddeCallback)
    {
    callback = ddeCallback;
    }

    QString DDEComm::ddeRequest(const QString &item)
    {
    if(!connStatus)
    return NULL;

    hszRequest = DdeCreateStringHandleA(pidInst, item.toAscii().data(), CP_WINANSI);
    recData = DdeClientTransaction(NULL, 0, hConv, hszRequest, CF_TEXT, XTYP_REQUEST, 1000, NULL);
    byte = DdeAccessData(recData, &dwLength);

    char data = (char) byte;
    QString retStr = data;
    DdeFreeStringHandle(pidInst, hszRequest);
    DdeFreeDataHandle(recData);
    return retStr;
    }

    QString DDEComm::ddeExecute(const QString &command, const QString &result)
    {

    transactionData = DdeCreateDataHandle(pidInst, (LPBYTE) command.toAscii().data(), command.length(), 0, 0L, CF_TEXT, NULL);
    DdeClientTransaction((LPBYTE) transactionData, -1, hConv, 0L, 0, XTYP_EXECUTE, 1000, NULL);

    QString returnData = ddeRequest(result);

    DdeFreeDataHandle(transactionData);

    return returnData;
    } @

    ddecomm.h
    @/*

    • ddecomm.h
    • Defines the interface for DDE communication class.
    • (C) 2005 Insite Comercio e Servicos.
    • Author: Rafael Roquetto
    • Qt4 patch: AcerExtensa
    • Created on 2005-06-03.
    • This is GPL software

    */

    #ifndef DDECOMM_H
    #define DDECOMM_H

    #include <windows.h>
    #include <QString>

    /*!

    • Classe singleton que fornece métodos para comunicacao via DDE
      */

    class DDEComm
    {
    public:

    static DDEComm* instance(); /*!< retorna um ponteiro para a instancia de DDEComm */

         bool ddeConnect(const QString & service, const QString & topic); /*!< Connecta ao servico DDE, no topico desejado */
    

    void ddeDisconnect(); /!< Desconecta do servico DDE/
    void setDDECallback(PFNCALLBACK ddeCallback); /*!< Seta uma funcao de callback a ser chamada na ocorrencia de eventos DDE */

         QString ddeRequest(const QString & item); /*!< Faz um request dde para o item fornecido */
         QString ddeExecute(const QString & command, const QString & result); /*!< Executa um comando no servidor dde*/
    

    protected:
    DDEComm();
    ~DDEComm();

    private:
    bool connStatus;
    PFNCALLBACK callback; //pointer to callback

         HCONV hConv;
         HSZ hszService;
         HSZ hszTopic;
         HDDEDATA recData;
         HDDEDATA transactionData;
         HSZ hszRequest;
         LPDWORD result;
         DWORD dwLength;
         LPBYTE byte;
    

    DWORD pidInst;

    static DDEComm *_instance;

    };
    #endif /DDECOMM_H/ @



  • I've updated my sources, yet I'm now getting a lot of LNK errors.

    ddecomm.obj:-1: error: LNK2019: unresolved external symbol _DdeFreeStringHandle@8 referenced in function "public: bool __thiscall DDEComm::ddeConnect(class QString const &,class QString const &)" (?ddeConnect@DDEComm@@QAE_NABVQString@@0@Z)
    ddecomm.obj:-1: error: LNK2019: unresolved external symbol _DdeCreateStringHandleA@12 referenced in function "public: bool __thiscall DDEComm::ddeConnect(class QString const &,class QString const &)" (?ddeConnect@DDEComm@@QAE_NABVQString@@0@Z)
    ddecomm.obj:-1: error: LNK2019: unresolved external symbol _DdeCreateStringHandleA@12 referenced in function "public: bool __thiscall DDEComm::ddeConnect(class QString const &,class QString const &)" (?ddeConnect@DDEComm@@QAE_NABVQString@@0@Z)
    ddecomm.obj:-1: error: LNK2019: unresolved external symbol _DdeUninitialize@4 referenced in function "public: void __thiscall DDEComm::ddeDisconnect(void)" (?ddeDisconnect@DDEComm@@QAEXXZ)

    ... etc



  • Add
    @#pragma comment(lib,"User32.lib")@
    somewhere in header



  • Wahey! Thank you very much AcerExtensa :) No errors compiling, however:

    @DDEComm *cyDesk;
    QString result;
    cyDesk->ddeConnect("CYDESK", "Data");
    cyDesk->ddeExecute("CALL ###", result);@

    Causes my app to crash. Is this is the wrong syntax?



  • Your cyDesk ponter is not initialized and points somewhere in the universe... :)

    try something like this:

    @
    #include <QDebug>
    #include "ddecomm.h"

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    DDEComm * test = DDEComm::instance();
    const QString service = "CYDESK";
    const QString topic = "Data";
    const QString command = "CALL ###";
    QString result;

    if(test->ddeConnect(service,topic))
    {
    qDebug() << "RESULT: " << test->ddeExecute(command,result);
    }
    else qDebug() << "Can't connect to service";

    return a.exec();
    }@



  • You sir, are awesome! Thank you very, very much :)



  • Hi!

    I'ld also like to implement something with this lib. Could you please make the editted version public to download?

    Thanks very much!

    Momergil


Log in to reply