Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Реализация DDE сервера


Автор: JavaCraft 4.3.2009, 20:41
Покажите пожалуйста на примере, как на стороне DDE-сервера
Получить hszItem, посланный клиентом

В параметрах функции обратного вызова нет такого параметра
HDDEDATA __stdcall DDEServer::Callback(UINT wType, UINT wFmt, HCONV hConv,
    HSZ hsz1, HSZ hsz2, HDDEDATA hData,ULONG_PTR dwData1, ULONG_PTR dwData2)

hConv - канал
hsz1 - раздел
hsz2 - сервис

Поиск по гуглу и докам пока не помог, там этот вопрос почему-то стороной обходят.

Автор: sergshabal 14.3.2009, 21:24
Вот пытался реализовать дде сервер который бы принимал данные в формате xlTable и выводил их в StringGrid... но увы мои познания в программировании огорчили мня. есть также живой, работающий пример на делфи. Если у когото есть предложения как это все можно собрать на с++ builder буду рад выслушатьsmile

Код

main.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#include <ddeml.h>
#pragma hdrstop

#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
HWND hDde;
unsigned long idInst;
AnsiString sTopic;
TPokeAction action;
PDdeQueItem p=new TDdeQueItem;
static const Word WM_DDE_ADDQUE = 0x402;
HSZ ServiceHSz,TopicHSz;
TThreadList *fDdeQue=new TThreadList;
int dataSize;
unsigned char szDDEData;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
HDDEDATA CALLBACK CallbackProc(UINT uType, UINT uFmt,HCONV hconv,HSZ hsz1,HSZ hsz2,
   HDDEDATA hdata,DWORD dwData1,DWORD dwData2)
{   /* TODO : Дописать фунцию обратного вызова */
    char buf[256];

    switch (uType) {
        case XTYP_CONNECT: {
          return (HDDEDATA)1;
        }
        case XTYP_POKE:{
          DdeQueryString(idInst,hsz1,buf,sizeof(buf),CP_WINANSI);
          sTopic=buf;
          //action=paPass;
          Form1->Memo1->Lines->Add("XTYP_POKE");
          if (&Form1->OnDdePoke) Form1->OnDdePoke(&sTopic,&action);
          //ShowMessage(action);
          switch (action){
              case paAccept: {
                 DdeQueryString(idInst,hsz2,buf,sizeof(buf),CP_WINANSI);
                 p->sTopic=sTopic;
                 p->sCells=buf;
                 p->size=DdeGetData(hdata,NULL,4,0);
                 DdeGetData(hdata,(unsigned char*)p->data,p->size,0);
                 try {
                   fDdeQue->LockList();
                   fDdeQue->Add(p);
                   Form1->Memo1->Lines->Add(p->sTopic+" "+p->sCells+" "+p->size);
                 }
                 __finally {
                   fDdeQue->UnlockList();
                 }
                 if (Form1->Handle!=0) {
                   PostMessageA(Form1->Handle,WM_DDE_ADDQUE,0,0);
                   Form1->AddQ();
                 }
                 return (HDDEDATA)dde_Ack;
              };
              case paPass: {
                 return (HDDEDATA)dde_Ack;
              };
              case paReject: {
                 return (HDDEDATA)dde_Busy;
              };
          }
        }
    }
    return (HDDEDATA)0;
};
void __fastcall TForm1::FormCreate(TObject *Sender)
{  Memo2->Lines->Add("in FormCreate");
   idInst=0;
   if (DdeInitializeA(&idInst,(PFNCALLBACK)CallbackProc,APPCLASS_STANDARD,0)==
       DMLERR_NO_ERROR) {
     ServiceHSz=DdeCreateStringHandleA(idInst,"rob",CP_WINANSI);
     TopicHSz=DdeCreateStringHandleA(idInst,"Topic",CP_WINANSI);
     if (DdeNameService(idInst,ServiceHSz,0,DNS_REGISTER)==0)
       ShowMessage("Не удалось зарегестрировать имя DDE сервера.");
   }
   else
     ShowMessage("Не удалось выполнить инициализацию DDE.");
   //fOnPoke=OnDdePoke;
   //fOnData=OnDdeData;

}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
   DdeNameService(idInst,ServiceHSz,0,DNS_UNREGISTER);
   fDdeQue->Free();
   DdeFreeStringHandle(idInst,ServiceHSz);
   DdeUninitialize(idInst);
}
//---------------------------------------------------------------------------
TVariantTable __fastcall TForm1::XLTDecodeV(void * data, int datasize)
{ Memo2->Lines->Add("in XLTDecodeV");
  TVariantTable vtResult;
  int i;
  Pointer curr;
  Word BlockType, BlockSize;
  Byte StringSize;
  float RealData;
  ShortString StringData;
  int DataNum=0;
  AnsiString s;

  curr=addp(data, 4);
  vtResult.RowCount=(int)curr;
  curr=addp(curr, 2);
  vtResult.ColCount=(int)curr;
  vtResult.Cells.Length=vtResult.RowCount;
  for (i=0;vtResult.RowCount;i++){
    vtResult.Cells[i].Length=vtResult.ColCount;
  }
  while((int)subp(curr,data)<datasize) {
    BlockType=(int)curr;
    curr=addp(curr, 2);
    BlockSize=(int)curr;
    curr=addp(curr, 2);
    switch (BlockType){
      case 1: { //число
        while(BlockSize>0) {
          RealData=(int)curr;
          curr=addp(curr,8);
          BlockSize-=8;
          vtResult.Cells[DataNum/vtResult.ColCount][DataNum%vtResult.ColCount]=RealData;
          DataNum++;
        } ;
      } break;
      case 2: { //текст
        while(BlockSize>0) {
          StringSize=(Byte)curr;
          curr=addp(curr);
          StringData[0]=(char)StringSize;
          for (i=1;i<StringSize;i++){
            StringData[i]=(char)curr;
            curr=addp(curr);
          }
          vtResult.Cells[DataNum/vtResult.ColCount][DataNum%vtResult.ColCount]=StringData;
          DataNum++;
          BlockSize-=(StringSize+1);
        } ;
      } break;
    }
  };
  s.SetLength(datasize);
  for (i=0;i<datasize;i++){
    s[i+1]=(char)addp(data,i);
  }
  return vtResult;
}
//------------------------------------------------------------------------------
extern PACKAGE void * __fastcall addp(void * p, int increment = 0x1)/* overload */
{
  return (Pointer)((int)p+increment);
}
extern PACKAGE void * __fastcall addp(void * p, void * increment)/* overload */
{
  return (Pointer)((int)p+(int)increment);
}
extern PACKAGE void * __fastcall subp(void * p, int decrement = 0x1)/* overload */
{
  return (Pointer)((int)p-decrement);
}
extern PACKAGE void * __fastcall subp(void * p, void * decrement)/* overload */
{
  return (Pointer)((int)p-(int)decrement);
}
//--------------------------------------------------------------------------
Types::TRect __fastcall TForm1::DecodeCellAddr(AnsiString CellAddr)
{ Memo2->Lines->Add("in DecodeCellAddr");
  TRect rResult;
  int tmp1,tmp2;
  CellAddr=UpperCase(CellAddr);
  tmp1=PosEx("R", CellAddr, 1);
  tmp2=PosEx("C", CellAddr,tmp1);
  try {
    rResult.Top=StrToInt(CellAddr.SubString(tmp1+1,tmp2-tmp1-1))-1;
  }
  catch(...)
  { exit; }
  tmp1=PosEx("R", CellAddr, tmp2);
  try {
    rResult.Left=StrToInt(CellAddr.SubString(tmp2+1,tmp1-tmp2-1-1))-1;
  }
  catch(...)
  { exit; }
  tmp2=PosEx("C", CellAddr,tmp1);
  try {
    rResult.Bottom=StrToInt(CellAddr.SubString(tmp1+1,tmp2-tmp1-1))-1;
    rResult.Right=StrToInt(CellAddr.SubString(tmp2+1,CellAddr.Length()-tmp2))-1;
  }
  catch(...)
  { exit; }
  return rResult;
}
//--------------------------------------------------------------------------
extern PACKAGE int __fastcall PosEx(AnsiString SubStr, AnsiString MainString, int i)
{
  if (i == 1) return AnsiPos(SubStr, MainString);
  else {
    int LenSubStr=SubStr.Length();
    int Len = MainString.Length() - LenSubStr + 1;
    while (i <= Len) {
      if (MainString[i] == SubStr[1]){
        int X = 1;
        while ((X < LenSubStr)&&(MainString[i + X] == SubStr[X + 1])) X++;
        if (X == LenSubStr) return i;
      }
      i++;
    }
    return 0;
  }
}
//--------------------------------------------------------------------------
MESSAGE void __fastcall TForm1::AddQue(Messages::TWMSysCommand & Message)
{  Memo2->Lines->Add("in AddQue");
   TVariantTable vt;
   TRect Cells;
   int i;
   try {
     p=(TDdeQueItem*)fDdeQue->LockList()->Items[fDdeQue->LockList()->Count-1];
     Cells=DecodeCellAddr(p->sCells);
     vt=XLTDecodeV(p->data,p->size);
     if (fOnData) {
       fOnData(p->sTopic,Cells, vt);
     }
     for (i=fDdeQue->LockList()->Count-1;i>0;i--) {
       p->data=fDdeQue->LockList()->Items[i];
       memset(p->data,0,p->size);
     }
   }
   __finally {
     fDdeQue->UnlockList();
   }
}
//------------------------------------------------------------------------------
void __fastcall TForm1::OnDdePoke(AnsiString * Topic, TPokeAction * action)
{
  action=paAccept;
  Memo2->Lines->Add("in OnDdePoke");
}
//------------------------------------------------------------------------------
void __fastcall TForm1::OnDdeData(AnsiString Topic, TRect Cells, TVariantTable Data)
{
  Memo2->Lines->Add("in OnDdeData");
  int i, j;
  // фиксируем для какой таблицы и какие ячейки обновлены
  Memo1->Lines->Add(TimeToStr(Now())+ ": Данные для темы "+Topic+", в ячейки R"+IntToStr(Cells.Top)+
      "C"+IntToStr(Cells.Left)+":R"+IntToStr(Cells.Bottom)+"C"+IntToStr(Cells.Right));
  // меняем размер сетки
  StringGrid1->RowCount = max(StringGrid1->RowCount, Cells.Bottom+1);
  StringGrid1->ColCount = max(StringGrid1->ColCount, Cells.Right+1);
  // заполняем сетку значенями не равными 0
  for (i=Cells.Top; i<Cells.Bottom;i++){
    for (j=Cells.Left;j<Cells.Right;j++){
        StringGrid1->Cells[j][i] = Data.Cells[i-Cells.Top][j-Cells.Left];
    }
  }
}
//----------------------------------------------------------------------------


void __fastcall TForm1::AddQ()
{
   Memo2->Lines->Add("in AddQ");
   TVariantTable vt;
   TRect Cells;
   int i;
   try {
     p=(TDdeQueItem*)fDdeQue->LockList()->Items[fDdeQue->LockList()->Count-1];
     Cells=DecodeCellAddr(p->sCells);
     vt=XLTDecodeV(p->data,p->size);
     if (fOnData) {
       fOnData(p->sTopic,Cells, vt);
     }
     for (i=fDdeQue->LockList()->Count-1;i>0;i--) {
       p->data=fDdeQue->LockList()->Items[i];
       memset(p->data,0,p->size);
     }
   }
   __finally {
     fDdeQue->UnlockList();
   }
}



Код

main.h
//---------------------------------------------------------------------------
#ifdef __cplusplus
   int max (int value1, int value2);
   int max(int value1, int value2)
   {return ( (value1 > value2) ? value1 : value2);}
#endif

#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <Grids.hpp>
//---------------------------------------------------------------------------
enum TPokeAction {paAccept, paPass, paReject};
typedef DynamicArray< DynamicArray< Variant > >  TDoubleVariant;


struct TVariantTable
{
   TDoubleVariant Cells;
   int RowCount;
   int ColCount;
};

typedef void __fastcall (__closure *TDdePokeEvent)(AnsiString *Topic, TPokeAction *Action);
typedef void __fastcall (__closure *TDdeDataEvent)(AnsiString Topic, TRect Cells, const TVariantTable Data);


struct TDdeQueItem;
typedef TDdeQueItem *PDdeQueItem;
struct TDdeQueItem
{
   void * data;
   int size;
   AnsiString sTopic;
   AnsiString sCells;
} ;

class TForm1 : public TForm
{
__published:    // IDE-managed Components
        TStringGrid *StringGrid1;
        TSplitter *Splitter1;
        TMemo *Memo1;
        TMemo *Memo2;
        void __fastcall FormCreate(TObject *Sender);
        void __fastcall FormDestroy(TObject *Sender);
        //__property TDdePokeEvent OnPoke = {read=fOnPoke, write=fOnPoke};
    //__property TDdeDataEvent OnData = {read=fOnData, write=fOnData};
private:    // User declarations
public:
             // User declarations
        __fastcall TForm1(TComponent* Owner);
        TVariantTable __fastcall XLTDecodeV(void * data, int datasize);
        Types::TRect __fastcall DecodeCellAddr(AnsiString CellAddr);
        MESSAGE void __fastcall AddQue(Messages::TWMSysCommand & Message);
        TDdePokeEvent fOnPoke;
        TDdeDataEvent fOnData;
        void __fastcall OnDdePoke(AnsiString * Topic, TPokeAction * action);
        void __fastcall OnDdeData(AnsiString Topic, TRect Cells, TVariantTable Data);
        void __fastcall AddQ();

};
//---------------------------------------------------------------------------
namespace Ddeexlunt
{
extern PACKAGE void * __fastcall addp(void * p, int increment = 0x1);
extern PACKAGE void * __fastcall addp(void * p, void * increment);
extern PACKAGE void * __fastcall subp(void * p, int decrement = 0x1);
extern PACKAGE void * __fastcall subp(void * p, void * decrement);
extern PACKAGE int __fastcall PosEx(AnsiString SubStr, AnsiString MainString, int i);

}
using namespace Ddeexlunt;

extern PACKAGE TForm1 *Form1;

//---------------------------------------------------------------------------
#endif



Автор: true25 6.12.2009, 02:45
Ты нашел ошибку??? получилось??? просто я что-то подобное пишу, и ничего не получается(((

Автор: MasterLom 21.9.2010, 17:02
Цитата(sergshabal @ 14.3.2009,  21:24)
Вот пытался реализовать дде сервер который бы принимал данные в формате xlTable и выводил их в StringGrid... но увы мои познания в программировании огорчили мня. есть также живой, работающий пример на делфи. Если у когото есть предложения как это все можно собрать на с++ builder буду рад выслушатьsmile

Код

main.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#include <ddeml.h>
#pragma hdrstop

#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
HWND hDde;
unsigned long idInst;
AnsiString sTopic;
TPokeAction action;
PDdeQueItem p=new TDdeQueItem;
static const Word WM_DDE_ADDQUE = 0x402;
HSZ ServiceHSz,TopicHSz;
TThreadList *fDdeQue=new TThreadList;
int dataSize;
unsigned char szDDEData;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
HDDEDATA CALLBACK CallbackProc(UINT uType, UINT uFmt,HCONV hconv,HSZ hsz1,HSZ hsz2,
   HDDEDATA hdata,DWORD dwData1,DWORD dwData2)
{   /* TODO : Дописать фунцию обратного вызова */
    char buf[256];

    switch (uType) {
        case XTYP_CONNECT: {
          return (HDDEDATA)1;
        }
        case XTYP_POKE:{
          DdeQueryString(idInst,hsz1,buf,sizeof(buf),CP_WINANSI);
          sTopic=buf;
          //action=paPass;
          Form1->Memo1->Lines->Add("XTYP_POKE");
          if (&Form1->OnDdePoke) Form1->OnDdePoke(&sTopic,&action);
          //ShowMessage(action);
          switch (action){
              case paAccept: {
                 DdeQueryString(idInst,hsz2,buf,sizeof(buf),CP_WINANSI);
                 p->sTopic=sTopic;
                 p->sCells=buf;
                 p->size=DdeGetData(hdata,NULL,4,0);
                 DdeGetData(hdata,(unsigned char*)p->data,p->size,0);
                 try {
                   fDdeQue->LockList();
                   fDdeQue->Add(p);
                   Form1->Memo1->Lines->Add(p->sTopic+" "+p->sCells+" "+p->size);
                 }
                 __finally {
                   fDdeQue->UnlockList();
                 }
                 if (Form1->Handle!=0) {
                   PostMessageA(Form1->Handle,WM_DDE_ADDQUE,0,0);
                   Form1->AddQ();
                 }
                 return (HDDEDATA)dde_Ack;
              };
              case paPass: {
                 return (HDDEDATA)dde_Ack;
              };
              case paReject: {
                 return (HDDEDATA)dde_Busy;
              };
          }
        }
    }
    return (HDDEDATA)0;
};
void __fastcall TForm1::FormCreate(TObject *Sender)
{  Memo2->Lines->Add("in FormCreate");
   idInst=0;
   if (DdeInitializeA(&idInst,(PFNCALLBACK)CallbackProc,APPCLASS_STANDARD,0)==
       DMLERR_NO_ERROR) {
     ServiceHSz=DdeCreateStringHandleA(idInst,"rob",CP_WINANSI);
     TopicHSz=DdeCreateStringHandleA(idInst,"Topic",CP_WINANSI);
     if (DdeNameService(idInst,ServiceHSz,0,DNS_REGISTER)==0)
       ShowMessage("Не удалось зарегестрировать имя DDE сервера.");
   }
   else
     ShowMessage("Не удалось выполнить инициализацию DDE.");
   //fOnPoke=OnDdePoke;
   //fOnData=OnDdeData;

}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
   DdeNameService(idInst,ServiceHSz,0,DNS_UNREGISTER);
   fDdeQue->Free();
   DdeFreeStringHandle(idInst,ServiceHSz);
   DdeUninitialize(idInst);
}
//---------------------------------------------------------------------------
TVariantTable __fastcall TForm1::XLTDecodeV(void * data, int datasize)
{ Memo2->Lines->Add("in XLTDecodeV");
  TVariantTable vtResult;
  int i;
  Pointer curr;
  Word BlockType, BlockSize;
  Byte StringSize;
  float RealData;
  ShortString StringData;
  int DataNum=0;
  AnsiString s;

  curr=addp(data, 4);
  vtResult.RowCount=(int)curr;
  curr=addp(curr, 2);
  vtResult.ColCount=(int)curr;
  vtResult.Cells.Length=vtResult.RowCount;
  for (i=0;vtResult.RowCount;i++){
    vtResult.Cells[i].Length=vtResult.ColCount;
  }
  while((int)subp(curr,data)<datasize) {
    BlockType=(int)curr;
    curr=addp(curr, 2);
    BlockSize=(int)curr;
    curr=addp(curr, 2);
    switch (BlockType){
      case 1: { //число
        while(BlockSize>0) {
          RealData=(int)curr;
          curr=addp(curr,8);
          BlockSize-=8;
          vtResult.Cells[DataNum/vtResult.ColCount][DataNum%vtResult.ColCount]=RealData;
          DataNum++;
        } ;
      } break;
      case 2: { //текст
        while(BlockSize>0) {
          StringSize=(Byte)curr;
          curr=addp(curr);
          StringData[0]=(char)StringSize;
          for (i=1;i<StringSize;i++){
            StringData[i]=(char)curr;
            curr=addp(curr);
          }
          vtResult.Cells[DataNum/vtResult.ColCount][DataNum%vtResult.ColCount]=StringData;
          DataNum++;
          BlockSize-=(StringSize+1);
        } ;
      } break;
    }
  };
  s.SetLength(datasize);
  for (i=0;i<datasize;i++){
    s[i+1]=(char)addp(data,i);
  }
  return vtResult;
}
//------------------------------------------------------------------------------
extern PACKAGE void * __fastcall addp(void * p, int increment = 0x1)/* overload */
{
  return (Pointer)((int)p+increment);
}
extern PACKAGE void * __fastcall addp(void * p, void * increment)/* overload */
{
  return (Pointer)((int)p+(int)increment);
}
extern PACKAGE void * __fastcall subp(void * p, int decrement = 0x1)/* overload */
{
  return (Pointer)((int)p-decrement);
}
extern PACKAGE void * __fastcall subp(void * p, void * decrement)/* overload */
{
  return (Pointer)((int)p-(int)decrement);
}
//--------------------------------------------------------------------------
Types::TRect __fastcall TForm1::DecodeCellAddr(AnsiString CellAddr)
{ Memo2->Lines->Add("in DecodeCellAddr");
  TRect rResult;
  int tmp1,tmp2;
  CellAddr=UpperCase(CellAddr);
  tmp1=PosEx("R", CellAddr, 1);
  tmp2=PosEx("C", CellAddr,tmp1);
  try {
    rResult.Top=StrToInt(CellAddr.SubString(tmp1+1,tmp2-tmp1-1))-1;
  }
  catch(...)
  { exit; }
  tmp1=PosEx("R", CellAddr, tmp2);
  try {
    rResult.Left=StrToInt(CellAddr.SubString(tmp2+1,tmp1-tmp2-1-1))-1;
  }
  catch(...)
  { exit; }
  tmp2=PosEx("C", CellAddr,tmp1);
  try {
    rResult.Bottom=StrToInt(CellAddr.SubString(tmp1+1,tmp2-tmp1-1))-1;
    rResult.Right=StrToInt(CellAddr.SubString(tmp2+1,CellAddr.Length()-tmp2))-1;
  }
  catch(...)
  { exit; }
  return rResult;
}
//--------------------------------------------------------------------------
extern PACKAGE int __fastcall PosEx(AnsiString SubStr, AnsiString MainString, int i)
{
  if (i == 1) return AnsiPos(SubStr, MainString);
  else {
    int LenSubStr=SubStr.Length();
    int Len = MainString.Length() - LenSubStr + 1;
    while (i <= Len) {
      if (MainString[i] == SubStr[1]){
        int X = 1;
        while ((X < LenSubStr)&&(MainString[i + X] == SubStr[X + 1])) X++;
        if (X == LenSubStr) return i;
      }
      i++;
    }
    return 0;
  }
}
//--------------------------------------------------------------------------
MESSAGE void __fastcall TForm1::AddQue(Messages::TWMSysCommand & Message)
{  Memo2->Lines->Add("in AddQue");
   TVariantTable vt;
   TRect Cells;
   int i;
   try {
     p=(TDdeQueItem*)fDdeQue->LockList()->Items[fDdeQue->LockList()->Count-1];
     Cells=DecodeCellAddr(p->sCells);
     vt=XLTDecodeV(p->data,p->size);
     if (fOnData) {
       fOnData(p->sTopic,Cells, vt);
     }
     for (i=fDdeQue->LockList()->Count-1;i>0;i--) {
       p->data=fDdeQue->LockList()->Items[i];
       memset(p->data,0,p->size);
     }
   }
   __finally {
     fDdeQue->UnlockList();
   }
}
//------------------------------------------------------------------------------
void __fastcall TForm1::OnDdePoke(AnsiString * Topic, TPokeAction * action)
{
  action=paAccept;
  Memo2->Lines->Add("in OnDdePoke");
}
//------------------------------------------------------------------------------
void __fastcall TForm1::OnDdeData(AnsiString Topic, TRect Cells, TVariantTable Data)
{
  Memo2->Lines->Add("in OnDdeData");
  int i, j;
  // фиксируем для какой таблицы и какие ячейки обновлены
  Memo1->Lines->Add(TimeToStr(Now())+ ": Данные для темы "+Topic+", в ячейки R"+IntToStr(Cells.Top)+
      "C"+IntToStr(Cells.Left)+":R"+IntToStr(Cells.Bottom)+"C"+IntToStr(Cells.Right));
  // меняем размер сетки
  StringGrid1->RowCount = max(StringGrid1->RowCount, Cells.Bottom+1);
  StringGrid1->ColCount = max(StringGrid1->ColCount, Cells.Right+1);
  // заполняем сетку значенями не равными 0
  for (i=Cells.Top; i<Cells.Bottom;i++){
    for (j=Cells.Left;j<Cells.Right;j++){
        StringGrid1->Cells[j][i] = Data.Cells[i-Cells.Top][j-Cells.Left];
    }
  }
}
//----------------------------------------------------------------------------


void __fastcall TForm1::AddQ()
{
   Memo2->Lines->Add("in AddQ");
   TVariantTable vt;
   TRect Cells;
   int i;
   try {
     p=(TDdeQueItem*)fDdeQue->LockList()->Items[fDdeQue->LockList()->Count-1];
     Cells=DecodeCellAddr(p->sCells);
     vt=XLTDecodeV(p->data,p->size);
     if (fOnData) {
       fOnData(p->sTopic,Cells, vt);
     }
     for (i=fDdeQue->LockList()->Count-1;i>0;i--) {
       p->data=fDdeQue->LockList()->Items[i];
       memset(p->data,0,p->size);
     }
   }
   __finally {
     fDdeQue->UnlockList();
   }
}



Код

main.h
//---------------------------------------------------------------------------
#ifdef __cplusplus
   int max (int value1, int value2);
   int max(int value1, int value2)
   {return ( (value1 > value2) ? value1 : value2);}
#endif

#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <Grids.hpp>
//---------------------------------------------------------------------------
enum TPokeAction {paAccept, paPass, paReject};
typedef DynamicArray< DynamicArray< Variant > >  TDoubleVariant;


struct TVariantTable
{
   TDoubleVariant Cells;
   int RowCount;
   int ColCount;
};

typedef void __fastcall (__closure *TDdePokeEvent)(AnsiString *Topic, TPokeAction *Action);
typedef void __fastcall (__closure *TDdeDataEvent)(AnsiString Topic, TRect Cells, const TVariantTable Data);


struct TDdeQueItem;
typedef TDdeQueItem *PDdeQueItem;
struct TDdeQueItem
{
   void * data;
   int size;
   AnsiString sTopic;
   AnsiString sCells;
} ;

class TForm1 : public TForm
{
__published:    // IDE-managed Components
        TStringGrid *StringGrid1;
        TSplitter *Splitter1;
        TMemo *Memo1;
        TMemo *Memo2;
        void __fastcall FormCreate(TObject *Sender);
        void __fastcall FormDestroy(TObject *Sender);
        //__property TDdePokeEvent OnPoke = {read=fOnPoke, write=fOnPoke};
    //__property TDdeDataEvent OnData = {read=fOnData, write=fOnData};
private:    // User declarations
public:
             // User declarations
        __fastcall TForm1(TComponent* Owner);
        TVariantTable __fastcall XLTDecodeV(void * data, int datasize);
        Types::TRect __fastcall DecodeCellAddr(AnsiString CellAddr);
        MESSAGE void __fastcall AddQue(Messages::TWMSysCommand & Message);
        TDdePokeEvent fOnPoke;
        TDdeDataEvent fOnData;
        void __fastcall OnDdePoke(AnsiString * Topic, TPokeAction * action);
        void __fastcall OnDdeData(AnsiString Topic, TRect Cells, TVariantTable Data);
        void __fastcall AddQ();

};
//---------------------------------------------------------------------------
namespace Ddeexlunt
{
extern PACKAGE void * __fastcall addp(void * p, int increment = 0x1);
extern PACKAGE void * __fastcall addp(void * p, void * increment);
extern PACKAGE void * __fastcall subp(void * p, int decrement = 0x1);
extern PACKAGE void * __fastcall subp(void * p, void * decrement);
extern PACKAGE int __fastcall PosEx(AnsiString SubStr, AnsiString MainString, int i);

}
using namespace Ddeexlunt;

extern PACKAGE TForm1 *Form1;

//---------------------------------------------------------------------------
#endif

Привет. Спасибо огромное за работающий пример на делфи. у меня вопрос возник: отображение в таблице выводимых данных запаздывает из за постоянного изменения данных? ну на примере стакана? или из за графической прорисовки в мемо и стринггриде?

Автор: DrMcSheen 18.12.2010, 18:03
А что нужно писать в диалоге квика, чтоб подключиться к приложенному примеру на делфи?
http://s1.ipicture.ru/Gallery/Viewfull/2654624.html

Автор: MasterLom 20.12.2010, 13:03
Exel
Книга1
Лист1

Автор: DrMcSheen 21.12.2010, 03:01
 smile 

Автор: DrMcSheen 23.1.2011, 13:22
Кароч, вот что получилось.
Имя сервера My_DDE
Имена таблиц Table_1, Table_2 и т.д.
В квике - на таблице правой кнопкой - вывод через DDE.
Проект на 6-м билдере.
По просьбам трудящихся немножко подредактировал и картинку вставил.

Автор: Miller1981 24.1.2011, 15:41
sergshabal - у тебя в коде почти в каждой строчке ошибка. Ты такими темпами не перепишешь.  Там есть канечно свои заморочки по сообщениям и преобразованиям, но в общем у меня где то 2 дня ушло на переписку, если вышеуказанные вещи знать изначально(про сообщения и преобразования) то часов за 4-5 переписать можно. Кому нада обращайтесь, могу предоставить код на Builder c++: [email protected]  icq:340-553-273

Автор: Miller1981 24.1.2011, 21:13
такой вопрос появился - а можно ли несколько таблиц одновременно считывать. По этому коду - всегда будет читатся только одна.

Автор: AntonBV 28.7.2011, 15:13
При попытке вывода таблицы параметров из квика в пример на билдере вылетает исключение DynArrayOutOfRange. С чем может быть связано? В таблице всего 3 инструмента и несколько столбцов, причем стакан сделок выводится на ура...

user posted image




Заранее спасибо.


Перестало вылетать как только отключил галочку в квике "Передавать с названиями столбцов". Почему, так и не понял. ищу дальше, может кто сталкивался?
Оставил всего 3 столбца, тоже заработало все хорошо...


Miller1981
 для того что-бы передавать несколько таблиц, достаточно настроить для каждой разные темы и по ним сортировать в своей программе данные. 

Автор: AntonBV 28.7.2011, 17:46
Ну так что, товарищи, кто-нибудь может найти в чем ошибка, эксперементальным методом выяснил, что количество строк не играет роли, а количество столбцов максимально 11 не считая столбца названия инструмента.. 

Автор: виктор2009 3.11.2015, 13:59
Цитата(DrMcSheen @ 23.1.2011,  13:22)
Кароч, вот что получилось.
Имя сервера My_DDE
Имена таблиц Table_1, Table_2 и т.д.
В квике - на таблице правой кнопкой - вывод через DDE.
Проект на 6-м билдере.
По просьбам трудящихся немножко подредактировал и картинку вставил.

 smile  smile  smile  smile  smile Чувак, респект))))Бился 2 дня, пока нашел твою прогу)))))Воть сейчас модифицировать буду.Спасибо за труд!!!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)