Новичок
Профиль
Группа: Участник
Сообщений: 2
Регистрация: 21.9.2010
Репутация: нет Всего: нет
|
Цитата(sergshabal @ 14.3.2009, 21:24) | Вот пытался реализовать дде сервер который бы принимал данные в формате xlTable и выводил их в StringGrid... но увы мои познания в программировании огорчили мня. есть также живой, работающий пример на делфи. Если у когото есть предложения как это все можно собрать на с++ builder буду рад выслушать
Код | 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
|
|
Привет. Спасибо огромное за работающий пример на делфи. у меня вопрос возник: отображение в таблице выводимых данных запаздывает из за постоянного изменения данных? ну на примере стакана? или из за графической прорисовки в мемо и стринггриде?
|