1

Тема: Кто поможет с созданием сервера DDE на C++

Господа, возможно у кого то есть готовый код на C++ для создания DDE сервера, чтобы забирать данные из Quik?

2 (2018-11-19 09:52:05 отредактировано Awako)

Re: Кто поможет с созданием сервера DDE на C++

// ConsoleApplication1.cpp: определяет точку входа для консольного приложения.
//

#include "stdafx.h"
#include <Dde.h>
#include "ddeml.h"
#include "ConsoleApplication1.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


DWORD inst = 0;
HSZ ServiceHSZ;
BOOL WORK = true;
// Единственный объект приложения
//DDE константы
#define DDE_FLOAT_BLK  0x0001 //Тип tdtFloat
#define DDE_STRING_BLK 0x0002 //Тип tdtString
#define DDE_TABLE_BLK  0x0010 //Тип tdtTable

#define WORD_SIZE sizeof(WORD)
#define WORD_DIM 0xFFFF
#define DOUBLE_SIZE sizeof(double)
#define STRUCT_COL_SIZE 24
#define NUM_LEN 32
#define INI_LEN 256
#define MAX_THREADS 64


HSZ hszApp, hszTopic;


CWinApp theApp;

using namespace std;


void ParseXLTable(LPBYTE lpbBufData, DWORD dwBufLen)
{
    WORD i;
    WORD wSize = 0;
    void *out_ctx = NULL;
    WORD *wTypeBlock = NULL;  
    WORD *wDataCnt;             
    WORD wRowsNum;              
    WORD wColNum;             
    char *chDataBlock = NULL; 
    DWORD dwIdx = 0;              
    double dNum = 0;          
    WORD ctx_num = 0;          
    WORD ctx_num_full = 0;      
    WORD w_commit_num = 0;    
    WORD w_ctx_num_rows = 0;  
    void *pImpStruct = NULL;
    WORD wRealCntRows = 0;

    int DataNum;

    DataNum = 0;
    while (dwIdx < dwBufLen)
    {
        wTypeBlock = (WORD *)&lpbBufData[dwIdx];
        if (*wTypeBlock == DDE_TABLE_BLK) {
            //cout << "wTypeBlock = " << "DDE_TABLE" << endl;
            dwIdx += (DWORD)WORD_SIZE;
            wDataCnt = (WORD *)&lpbBufData[dwIdx];
            dwIdx += (DWORD)WORD_SIZE;
            wRowsNum = (WORD) *((WORD *)&lpbBufData[dwIdx]);// Rows count
            dwIdx += (DWORD)WORD_SIZE;
            wColNum = (WORD) *((WORD *)&lpbBufData[dwIdx]);// Columns count
            dwIdx += (DWORD)WORD_SIZE;
            cout << "RowsNum = " << wRowsNum << " ColNum = " << wColNum - 1 << endl;

        } else  if (*wTypeBlock == DDE_STRING_BLK) {
            //cout << "wTypeBlock = " << "DDE_STRING" << endl;
            dwIdx += (DWORD)WORD_SIZE;
            wDataCnt = (WORD *)&lpbBufData[dwIdx]; //ќбща¤ длина строки            
            dwIdx += (DWORD)WORD_SIZE;
            i = 0;
            while (i < *wDataCnt) {
                wSize = (WORD) *(BYTE *)&lpbBufData[dwIdx];
                chDataBlock = (char *)malloc(wSize + 1);
                memset(chDataBlock, 0, wSize + 1);

                if (wSize != 0) {
                    memcpy(chDataBlock, &lpbBufData[dwIdx + 1], wSize);
                }
                i += wSize + 1;
                dwIdx += wSize + 1;

                div_t x = div(DataNum, wColNum);
                if (x.rem > 0) {
                    cout << "[" << x.quot << "," << x.rem << "] = " << chDataBlock << endl;
                }
                DataNum = DataNum + 1;
            }
        } else if (*wTypeBlock == DDE_FLOAT_BLK) {
            //cout << "wTypeBlock = " << "DDE_FLOAT" << endl;
            dwIdx += (DWORD)WORD_SIZE;
            wDataCnt = (WORD *)&lpbBufData[dwIdx];    
            dwIdx += (DWORD)WORD_SIZE;
            i = 0;
            wSize = DOUBLE_SIZE;
            while (i < *wDataCnt) {
                chDataBlock = (char *)malloc(wSize + 1);
                memset(chDataBlock, 0, wSize + 1);
                memcpy(chDataBlock, &lpbBufData[dwIdx], wSize);
                dNum = *((double *)chDataBlock); //OK!!


                chDataBlock = (char *)malloc(NUM_LEN + 1);
                memset(chDataBlock, 0, NUM_LEN + 1);
                sprintf_s(chDataBlock, NUM_LEN + 1, "%f", dNum);

                i += wSize;
                dwIdx += wSize;

                div_t x = div(DataNum, wColNum);
                if (x.rem > 0) {
                    cout << "[" << x.quot << "," << x.rem << "] = " << chDataBlock << endl;
                }
                DataNum = DataNum + 1;
            }
        }else {
            //cout << "wTypeBlock = " << *wTypeBlock << endl;
        }
    }
}


HDDEDATA CALLBACK DdeCallback(
    UINT uType,  // Transaction type. 
    UINT uFmt,  // Clipboard data format. 
    HCONV hconv, // Handle to the conversation. 
    HSZ hsz1,  // Handle to a string. 
    HSZ hsz2,  // Handle to a string. 
    HDDEDATA hdata, // Handle to a global memory object. 
    DWORD dwData1, // Transaction-specific data. 
    DWORD dwData2) // Transaction-specific data. 
{
    char* buf;
    int iCount;
    CString sTopic;
    CString sCells;
    CString STR;
    LPBYTE lpbBufData = NULL;

    //cout << "DdeCallback uType = " << uType << endl;
    //cout << "DdeCallback uFmt = " << uFmt << endl;

    if (uType == XTYP_CONNECT)
    {
        return (HDDEDATA)TRUE;
    }
    if (uType == XTYP_POKE) {
        //входящие параметры DDE соединения
        iCount = DdeQueryStringA(inst, hsz1, NULL, 0, CP_WINANSI)+1; 
        buf = new char[iCount];
        DdeQueryStringA(inst, hsz1, buf, iCount, CP_WINANSI);
        sTopic = (CString)buf;
        cout << "sTopic = " << sTopic << endl;

        //входящие параметры листа соединения
        iCount = DdeQueryStringA(inst, hsz2, NULL, 0, CP_WINANSI) + 1;
        buf = new char[iCount];
        DdeQueryStringA(inst, hsz2, buf, iCount, CP_WINANSI);
        sCells = (CString)buf;
        
        cout << "sCells = " << sCells << endl;

        iCount = DdeGetData(hdata, NULL, 0, 0);
        lpbBufData = (LPBYTE)malloc(iCount);
        memset(lpbBufData, 0, iCount);
        cout << "iCount = " << iCount << endl;

        DdeGetData(hdata, lpbBufData, iCount, 0);

        ParseXLTable(lpbBufData, iCount);
        return((HDDEDATA)DDE_FACK);
    }

    return (HDDEDATA)NULL;
}

int main()
{
    int nRetCode = 0;

    HMODULE hModule = ::GetModuleHandle(nullptr);

    if (hModule != nullptr)
    {
        if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
        {
            wprintf(L"Критическая ошибка: сбой при инициализации MFC\n");
            nRetCode = 1;
        }
        else
        {
            system("chcp 1251");
            cout << "START TESTDDE Server" << endl;
            if (DdeInitializeA(&inst, (PFNCALLBACK) DdeCallback, APPCLASS_STANDARD, 0) == DMLERR_NO_ERROR) {
                //cout << "DdeInitializeA " << DdeGetLastError(inst) << endl;
                ServiceHSZ = DdeCreateStringHandleA(inst, "TESTDDE", CP_WINANSI); //имя DDE сервера 
                //cout << "DdeCreateStringHandleA " << DdeGetLastError(inst) << endl;
                HDDEDATA srr;
                srr = DdeNameService(inst, ServiceHSZ, 0, DNS_REGISTER);
                //cout << "DdeNameService " << srr << endl;
                if (srr == 0) {
                    //cout << "DdeNameService " << DdeGetLastError(inst) << endl;
                }
            }
            MSG msg;
            while (GetMessage(&msg, NULL, 0, 0)) {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }

            DdeUninitialize(inst);
            system("pause");
        }
    }
    else
    {
        wprintf(L"Критическая ошибка: неудачное завершение GetModuleHandle\n");
        nRetCode = 1;
    }

    return nRetCode;
}