Solved

Immediate received data from Server in DDE Using Delphi 3

Posted on 1998-12-07
23
752 Views
Last Modified: 2008-02-20
I am buidling an application that is quite calculation intensive. There are 2 programs in the application. A server and a client. Currently, I have been successful in get information from client to server using the pokedata method of the client. on respond to the pokedata, the server onpokedata get activated immediately. That's fine.

My problem is when the server at any time has data to send to the client, the client does not seem to respons.

my server send data by:
    ddeserveritem.text:= 'abc';

according to the book, a change in the serveritem should activate the client too. But it is not happening.
my code to link the client to server is:
  ddeclientitem:= 'ddeserveritem';

i am currently running under win98. Pls show me how i can get immediate respond from client.
0
Comment
Question by:sellandbuy
  • 11
  • 8
  • 4
23 Comments
 
LVL 4

Expert Comment

by:dwwang
ID: 1349633
When data is transfered from server, the DDEClientItem's OnChange Event is triggered, and the Lines property contains the coming data. You must set the DDEClientItem link to a DdeClientConv, and the DdeClientConv's DDEService|DDEtopic name to the DDE Server's EXE Name and the DDEServerConv component name.

For more information, please feel free to ask me :)
0
 
LVL 3

Expert Comment

by:williams2
ID: 1349634
Hmmm..
DDE communication causes a lot of trouble. I did this some time ago, but dwwang might have the answer to this.

having: Examples (..and humor)
wanted: points   (..and humor?)

:-)

Regards
Williams
0
 
LVL 4

Expert Comment

by:dwwang
ID: 1349635
Well, I don't think DDE will cause much trouble, I also have fully working Demo programms for that.
0
 

Author Comment

by:sellandbuy
ID: 1349636
dwwang Can u send me your working demo code ???
0
 

Author Comment

by:sellandbuy
ID: 1349637
dwwang Can u send me your working demo code ???
0
 
LVL 3

Expert Comment

by:williams2
ID: 1349638
No offense dwwang, but why are you not posing it then? It's sure a more leading help to the user, who probably got a Delphi Help explaining what you did in the first place.
It might get you more points too!

but I hope you got a sense of humor anyway!

See ya,
Williams
0
 
LVL 4

Expert Comment

by:dwwang
ID: 1349639
Hi, williams2
Actually I do think I got sense of humor any way. ^_^
I just feel strange what's the big trouble you mean, actually I also want to know if there are any special issues when one programming DDE. Would you talk about it?
Surely you will get points awards. ^_^

sellandbuy:
I'll try to arrange them and send it to you.
0
 
LVL 3

Expert Comment

by:williams2
ID: 1349640
yes dwwang, there are actually small bugs in Delphi that can make the DDE components very hard to get stabil. If you do not take care of this, the DDE-components shuts like an oyster. Another thing is, that writing and reading to the communication is not guaranteed to work perfectly´, since the buffer is shared.
besides that, I cannot create some of the components realtime, why? I don't know. This should be necessary when dealing with a multithread server. If you connect to the same Server component, you are sharing the same buffer as the other client components.

Have you experienced any of this?

Regards,
Williams
0
 
LVL 4

Expert Comment

by:dwwang
ID: 1349641
Thank you williams, as you said, DDE in Delphi is not stable enough, and now I found my programms have problems also.

So sellandbuy, simply reject my answer and let williams send you the sample code.

Williams, also please send one copy to me: dw-wang@263.net, thanks.

Wang
0
 
LVL 3

Expert Comment

by:williams2
ID: 1349642
I will do that, I took me a hardworking month to complete this thing. Either Borland has really ****ed up this feature, or MicroSoft are as usual totally screwed hehe.

But one thing I DIDN'T find out: I had problems executing the DDEServer with the DDClient in Windows NT. It sure works when you are working with the DDEClient directly. But if you f.ex. have to develope CGI's, it doesn't. There are two things that I can do instead:

1: Use ShellExecute to start up the thing, if I cannot find it with a FindWindow API command.
2: Use messaging to see if the server is up, maybe use a callback procedure to find and identify the path of the DDEServer.

Anybody got any ideas?

Cheers,
Williams
0
 
LVL 3

Expert Comment

by:williams2
ID: 1349643
Hmmm.. Sorry! #2 doesn't work, if the Server is down :-)))) (where have I left my brain todday???)

I'll send the stuff! (I'll see if it's possible to make a posting instead).

Cheers,
Williams
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:sellandbuy
ID: 1349644
So William what did u do to get a onchange method to work when the server change the data ? My client does not execute the onchangeitem event even though the server change it.
0
 

Author Comment

by:sellandbuy
ID: 1349645
Send me the code at sellandbuy@hotmail.com
0
 
LVL 3

Expert Comment

by:williams2
ID: 1349646
Sorry it took some time, it's quite big, so I'm going to make a more simplified version of it. Please hold on, I'll post the answer in a couple of hours.

The current system works as a CGI-DDE client/server system, so I'll have to make some changes to it.

Regards,
Williams
0
 
LVL 3

Accepted Solution

by:
williams2 earned 150 total points
ID: 1349647
Ok guys, this works, and I'll explain how this will going to work:

1. The DDEClient will not startup the server as long as Delphi has the Server project opened.
2. If the Server project is compiled, the client will be able to open the server automatically (though minimized).
3. I experienced, that a CGI-client, will not startup the server automatically in Windows NT, but it will in Win 95/98.

To make the examples below work you do need to do the following things.

Server:
1. Open a new project and activate the Form1's OnCreate and OnDestroy event procedures.
2. Paste the the Server part to unit1.
3. Save the project as 'Ddesrvr.dpr' and compile
4. Run the project or close the project.

Client:
1. Open a new project and activate the Form1's OnCreate and OnShow event procedures.
2. Paste the the Client part to unit1.
3. Run the project.


I excuse that some things might seem a little piculiar, but it is a modified version of my CGI client/server system, though this example does not need any CGI handling.

Server part:
unit Unit1;

interface

uses WinTypes, WinProcs, Classes, Graphics, Forms, Controls, StdCtrls, DdeMan,
  Menus, ExtCtrls, SysUtils, DB, DBTables;

const
  DefaultItem = 'DDETestItem';
  stpBgn = 24;
  stpHgt = 16;

type
  TState = (inactive,Entry,busy,LookUp,Ready);

  TForm1 = class(TForm)
    DdeTestTopic: TDdeServerConv;
    DdeTestItem: TDdeServerItem;
    procedure doOnPoke(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure InputBtnClick(Sender: TObject);
    procedure OutputBtnClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);

  private
    Input,Output: Array[1..10] of TStringList;
    ActLabels: Array[1..10] of TLabel;
    ContentLabel: TLabel;
    Timer: TTimer;
    Memo1: TMemo;
    Memo2: TMemo;
    Procedure GenerelSetup;
    procedure GetResult(i: Integer);
    Procedure GetIncoming;

    procedure OnTimer(Sender: TObject);
  public
    { Public declarations }
    procedure AddClient(nam: String; var MSG: TStringList);
    procedure SendToClient(index: Integer);
    procedure TestStates;
    Procedure SetState(index: Integer; State: TState);
  end;

  TClient = record
    Name: String;
    Lines: TStringList;
    State: TState;
  end;

var
  Form1: TForm1;
  Client: Array[1..10] of TClient;

implementation

uses Dialogs;

{$R *.DFM}

  Procedure TForm1.GenerelSetup;
    function createLabel(ALeft,ATop: Integer; Cap: String): TLabel;
    Begin
      Result:= TLabel.Create(Self);
      With result do
      begin
        Caption:= Cap;
        AutoSize:= True;
        left:= ALeft;
        Top:= ATop;
        Parent:= Self;
      End;
    End;
  var
    i,t: Integer;
    button: TButton;
  Begin
    SetBounds(Left,Top,348,315);
    Caption:= 'DDE Server';

    memo1:= TMemo.Create(self);
    memo1.SetBounds(0,211,337,76);
    memo1.Parent:= Self;
    memo2:= TMemo.Create(self);
    memo2.setBounds(0,0,0,0);
    memo2.Parent:= Self; //Dummy!!
    Timer:= TTimer.Create(Self);
    Timer.Interval:= 1000;
    Timer.OnTimer:= OnTimer;
    Timer.Enabled:= True;

    createLabel(72,0,'Status:');
    createLabel(184,0,'Last known Input / Output:');
    createLabel(6,192,'Contents:');
    ContentLabel:= createLabel(61,192,'');
    ContentLabel.Font.Color:= clBlue;
    ContentLabel.Font.Name:= 'MS Sans Serif';
    ContentLabel.Font.Style:= [fsBold];
    t:= stpBgn;
    For i:= 1 to 10 do
    Begin
      createLabel(6,t,'Client'+IntToStr(i)+':');
      ActLabels[i]:= createLabel(72,t,'');

      Button:= TButton.Create(Self);
      Button.SetBounds(184,t,75,stpHgt+1);
      Button.Tag:= i;
      Button.Caption:= 'Input';
      Button.Parent:= Self;
      Button.OnClick:= InputBtnClick;
      Input[i]:= TStringList.create;

      Button:= TButton.Create(Self);
      Button.SetBounds(264,t,75,stpHgt+1);
      Button.Tag:= i;
      Button.Caption:= 'Ouput';
      Button.Parent:= Self;
      Button.OnClick:= OutputBtnClick;
      Output[i]:= TStringList.create;

      SetState(i,inactive);
      Inc(t,stpHgt);
    End;
  End;


//*******************************CLI / SERV********************************
//***************Client Message Interface functions************************

procedure TForm1.SendToClient(index: Integer);
var
  nam: String;
begin // Send back to client og reset 'Client'
  // On weird circumstances, it's necessary to use a visual component
  // (memo2) as a temporary storage device. Or the transmission will not
  // go through!!!
  Nam:=Client[index].name;
  memo2.Lines.SetText(Client[index].Lines.getText);
  memo2.Lines.Insert(0,'[2'+copy(nam,2,length(nam)) );
//  ShowMessage('Sending to the client');
  DdeTestItem.Lines:=memo2.Lines;
//  ShowMessage('Sent!');
  Output[index].clear;
  Output[index].setText(Memo2.Lines.getText);
  Client[index].Lines.free;
  SetState(index,Inactive);
end;

procedure TForm1.AddClient(nam: String; var MSG: TStringList);
var i: Integer;
begin // Add new client task
  i:=1;
  While (i<10) and (Client[i].State<>inactive) do inc(i);
  with Client[i] do
  Begin
    name:=nam;
    Input[i].clear;
    Input[i].AddStrings(DdeTestItem.Lines);
    Lines:= TStringlist.create;
    Lines.SetText(MSG.getText); // SQL
    SetState(i,Busy);
  end;
end;

//***************************************

Procedure TForm1.SetState(index: Integer; State: TState);
Begin
  case State of
    inactive : ActLabels[index].Caption:='Inactive';
    Entry    : ActLabels[index].Caption:='Entering';
    busy     : ActLabels[index].Caption:='Waiting';
    LookUp   : ActLabels[index].Caption:='SQL lookup';
    Ready    : ActLabels[index].Caption:='Ready';
  end;
  Client[index].State:=State;
end;

procedure TForm1.TestStates;
var // Test process-state
  found: Boolean;
  i: Integer;
Begin
  i:=1; found:=False;
  while (i<10) and not(found) do
  begin
    Case Client[i].State of
      busy  : GetResult(i);// Do something
      ready : SendToClient(i);
    end;
    if Client[i].State<>inactive then found:=True else inc(i);
  end;
end;

procedure TForm1.GetResult(i: Integer);
Begin
  with Client[i] do
  begin
    SetState(i,Lookup);
    Lines.Clear;
    Lines.Add('Hi client '+name);
    SetState(i,ready);
  end;
End;

Procedure TForm1.GetIncoming;
var
  Name: String; // OnPoke Event invoked by client
  List: TStringList;
begin
  Name:=DdeTestItem.text;
  if copy(Name,1,2)='[C' then
  Begin
    List:= TStringList.create;
    List.AddStrings(DdeTestItem.Lines);
    List.Delete(0);
    AddClient(Name,List);
    DdeTestItem.Lines.clear;
    List.free;
  End;
end;

//******************************* CLI / SERV ********************************


// ********** Event Based Procedure calls **************
procedure TForm1.doOnPoke(Sender: TObject);
Begin GetIncoming End;

procedure TForm1.OnTimer(Sender: TObject);
begin TestStates end;

procedure TForm1.InputBtnClick(Sender: TObject);
var
  Knr: Integer;
begin
  Knr:= (Sender as TButton).tag;
  if Input[Knr]<>nil then
  begin
    ContentLabel.Caption:='Input from client'+IntToStr(Knr);
    Memo1.Lines.SetText(Input[Knr].getText);
  end;
end;

procedure TForm1.OutputBtnClick(Sender: TObject);
var
  Knr: Integer;
begin
  Knr:= (Sender as TButton).tag;
  if Output[Knr]<>nil then
  begin
    ContentLabel.Caption:='Output to client'+IntToStr(Knr);
    Memo1.Lines.SetText(Output[Knr].getText);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  GenerelSetup;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var i: Integer;
begin
  For i:=1 to 10 do
  begin Input[i].free; Output[i].free end;
end;

end.




Client part:
unit unit2;

interface

uses WinTypes, WinProcs, Classes, Graphics, Forms, Controls, StdCtrls, Menus,
     DdeMan, IniFiles;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
    Memo1: TMemo;
    Edit1: TEdit;
    Button: TButton;
    DdeClient: TDdeClientConv;
    DdeClientItem: TDdeClientItem;
    ClientLabel: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure DdeClientItemChange(Sender: TObject);
    procedure NewLink;
    procedure DoOnReceive;
    Function TestCmd(var Cmd: String; Line: String): Boolean;
  public
    { Public declarations }
  end;

const
  ServerName = 'DdeSrvr';
  ItemName = 'DdeTestItem';
  TopicName = 'DdeTestTopic';

var
  Form1: TForm1;
  ClientName: String;
  OutputFile: textFile;
  Expr: TStringList;

implementation

uses Dialogs, SysUtils;

{$R *.DFM}

// ************************** CLI / SER **************************

procedure TForm1.NewLink;
begin
  DdeClient.SetLink (ServerName, TopicName);
  DdeClientItem.DdeConv := DdeClient;
  DdeClientItem.DdeItem := ItemName;
end;

Function TForm1.TestCmd(var Cmd: String; Line: String): Boolean;
Begin // Tests the address on known messages from server
      // can be used for other suitable commands.
  Cmd:= copy(Line,2,length(Line)-2); // Cutting '[...]'
  IF (Cmd='2C'+ClientName) OR (Cmd='Exit') then
  Begin
    Cmd:= copy(Line,2,length(Line)-2);
    Result:= True;
  end else
  begin
    Cmd:= '';
    Result:= False;
  End;
End;

procedure TForm1.DoOnReceive;
var // Treatment of received material from server
    // as eventual finish of Script and program.
  Cmd: String;
  List: TStringList; //Buffer
begin
  IF TestCmd(Cmd,DdeClientItem.Text) then
  begin
    If Cmd='2C'+ClientName then
    begin
      List := TStringList.create;
      List.setText(DdeClientItem.Lines.GetText);
      List.Delete(0); //Delete commandline
      Expr.clear;
      Expr.AddStrings(List);
      DdeClientItem.Lines.Clear;
      memo1.Clear;
      Memo1.Lines.AddStrings(Expr);
//      Close;
      List.free;
    end else
    If Cmd='Exit' then Close;
  End;
end;
// ************************** CLI / SER **************************


// ********************* Event based procedures ********************
procedure TForm1.DdeClientItemChange(Sender: TObject);
Begin
  DoOnReceive
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Caption:= 'DDE Client';
  SetBounds(Left,Top,396,343);
  ClientLabel:= TLabel.Create(Self);
  ClientLabel.SetBounds(0,0,0,0);
  ClientLabel.AutoSize:= True;

  Button:= TButton.Create(Self);
  Button.SetBounds(312,104,75,25);
  Button.Caption:= 'Try me!';
  Button.OnClick:= Button1Click;
  Button.Parent:= Self;

  Edit1:= TEdit.Create(Self);
  Edit1.SetBounds(0,136,385,21);
  Edit1.Text:= 'Hello server, what have you got for me today?';
  Edit1.Parent:= Self;

  memo1:= TMemo.Create(Self);
  memo1.SetBounds(0,160,385,153);
  memo1.Parent:= Self;

  DDEClient:= TDDEClientConv.Create(Self);
  DDEClient.ServiceApplication := 'DDESRVR';
  DDEClient.FormatChars := True;
  DdeClientItem:= TDdeClientItem.Create(Self);
  DdeClientItem.DdeConv := DdeClient;
  DdeClientItem.OnChange := DdeClientItemChange;

  Expr:= TStringList.create

end;

procedure TForm1.FormShow(Sender: TObject);
begin
  NewLink;
  Randomize;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Query: TStringList;
  DdeCli : TDdeClientConv;
begin
  Clientname:= 'Test'+IntToStr(Random(10000));
  ClientLabel.Caption:= 'My name is: '+Clientname;
  Query:= TStringList.Create;
  Query.Add(Edit1.Text);
  DdeCli := DdeClientItem.DdeConv;
  Query.insert(0,'[C'+ClientName+']');
  DdeCli.PokeDataLines(DdeClientItem.DdeItem, Query);
  Query.free;
end;

end.


Regards,
Williams
0
 
LVL 3

Expert Comment

by:williams2
ID: 1349648
Sorry, I forgot some things in the Server part, I need to do some major changes, try this one instead:

Server Part:
unit Unit1;

interface

uses WinTypes, WinProcs, Classes, Graphics, Forms, Controls, StdCtrls, DdeMan,
  Menus, ExtCtrls, SysUtils, DB, DBTables;

const
  DefaultItem = 'DDETestItem';
  stpBgn = 24;
  stpHgt = 16;

type
  TState = (inactive,Entry,busy,LookUp,Ready);

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);

  private
    Input,Output: Array[1..10] of TStringList;
    ActLabels: Array[1..10] of TLabel;
    ContentLabel: TLabel;
    Timer: TTimer;
    Memo1: TMemo;
    Memo2: TMemo;
    DdeTestTopic: TDdeServerConv;
    DdeTestItem: TDdeServerItem;
    Procedure GenerelSetup;
    procedure GetResult(i: Integer);
    Procedure GetIncoming;

    procedure doOnPoke(Sender: TObject);
    procedure OnTimer(Sender: TObject);
    procedure InputBtnClick(Sender: TObject);
    procedure OutputBtnClick(Sender: TObject);
  public
    { Public declarations }
    procedure AddClient(nam: String; var MSG: TStringList);
    procedure SendToClient(index: Integer);
    procedure TestStates;
    Procedure SetState(index: Integer; State: TState);
  end;

  TClient = record
    Name: String;
    Lines: TStringList;
    State: TState;
  end;

var
  Form1: TForm1;
  Client: Array[1..10] of TClient;

implementation

uses Dialogs;

{$R *.DFM}

  Procedure TForm1.GenerelSetup;
    function createLabel(ALeft,ATop: Integer; Cap: String): TLabel;
    Begin
      Result:= TLabel.Create(Self);
      With result do
      begin
        Caption:= Cap;
        AutoSize:= True;
        left:= ALeft;
        Top:= ATop;
        Parent:= Self;
      End;
    End;
  var
    i,t: Integer;
    button: TButton;
  Begin
    SetBounds(Left,Top,348,315);
    Caption:= 'DDE Server';

    memo1:= TMemo.Create(self);
    memo1.SetBounds(0,211,337,76);
    memo1.Parent:= Self;
    memo2:= TMemo.Create(self);
    memo2.setBounds(0,0,0,0);
    memo2.Parent:= Self; //Dummy!!
    Timer:= TTimer.Create(Self);
    Timer.Interval:= 1000;
    Timer.OnTimer:= OnTimer;
    Timer.Enabled:= True;

    createLabel(72,0,'Status:');
    createLabel(184,0,'Last known Input / Output:');
    createLabel(6,192,'Contents:');
    ContentLabel:= createLabel(61,192,'');
    ContentLabel.Font.Color:= clBlue;
    ContentLabel.Font.Name:= 'MS Sans Serif';
    ContentLabel.Font.Style:= [fsBold];
    t:= stpBgn;
    For i:= 1 to 10 do
    Begin
      createLabel(6,t,'Client'+IntToStr(i)+':');
      ActLabels[i]:= createLabel(72,t,'');

      Button:= TButton.Create(Self);
      Button.SetBounds(184,t,75,stpHgt+1);
      Button.Tag:= i;
      Button.Caption:= 'Input';
      Button.Parent:= Self;
      Button.OnClick:= InputBtnClick;
      Input[i]:= TStringList.create;

      Button:= TButton.Create(Self);
      Button.SetBounds(264,t,75,stpHgt+1);
      Button.Tag:= i;
      Button.Caption:= 'Ouput';
      Button.Parent:= Self;
      Button.OnClick:= OutputBtnClick;
      Output[i]:= TStringList.create;

      SetState(i,inactive);
      Inc(t,stpHgt);
    End;
  End;


//*******************************CLI / SERV********************************
//***************Client Message Interface functions************************

procedure TForm1.SendToClient(index: Integer);
var
  nam: String;
begin // Send back to client og reset 'Client'
  // On weird circumstances, it's necessary to use a visual component
  // (memo2) as a temporary storage device. Or the transamission will not
  // go through!!!
  Nam:=Client[index].name;
  memo2.Lines.SetText(Client[index].Lines.getText);
  memo2.Lines.Insert(0,'[2'+copy(nam,2,length(nam)) );
//  ShowMessage('Senfing to the client');
  DdeTestItem.Lines:=memo2.Lines;
//  ShowMessage('Sent!');
  Output[index].clear;
  Output[index].setText(Memo2.Lines.getText);
  Client[index].Lines.free;
  SetState(index,Inactive);
end;

procedure TForm1.AddClient(nam: String; var MSG: TStringList);
var i: Integer;
begin // Add new client task
  i:=1;
  While (i<10) and (Client[i].State<>inactive) do inc(i);
  with Client[i] do
  Begin
    name:=nam;
    Input[i].clear;
    Input[i].AddStrings(DdeTestItem.Lines);
    Lines:= TStringlist.create;
    Lines.SetText(MSG.getText); // SQL
    SetState(i,Busy);
  end;
end;

//***************************************

Procedure TForm1.SetState(index: Integer; State: TState);
Begin
  case State of
    inactive : ActLabels[index].Caption:='Inactive';
    Entry    : ActLabels[index].Caption:='Entering';
    busy     : ActLabels[index].Caption:='Waiting';
    LookUp   : ActLabels[index].Caption:='SQL lookup';
    Ready    : ActLabels[index].Caption:='Ready';
  end;
  Client[index].State:=State;
end;

procedure TForm1.TestStates;
var // Test process-state
  found: Boolean;
  i: Integer;
Begin
  i:=1; found:=False;
  while (i<10) and not(found) do
  begin
    Case Client[i].State of
      busy  : GetResult(i);// Do something
      ready : SendToClient(i);
    end;
    if Client[i].State<>inactive then found:=True else inc(i);
  end;
end;

procedure TForm1.GetResult(i: Integer);
Begin
  with Client[i] do
  begin
    SetState(i,Lookup);
    Lines.Clear;
    Lines.Add('Hi client '+name);
    SetState(i,ready);
  end;
End;

Procedure TForm1.GetIncoming;
var
  Name: String; // OnPoke Event invoked by client
  List: TStringList;
begin
  Name:=DdeTestItem.text;
  if copy(Name,1,2)='[C' then
  Begin
    List:= TStringList.create;
    List.AddStrings(DdeTestItem.Lines);
    List.Delete(0);
    AddClient(Name,List);
    DdeTestItem.Lines.clear;
    List.free;
  End;
end;

//******************************* CLI / SERV ********************************


// ********** Event Based Procedure calls **************
procedure TForm1.doOnPoke(Sender: TObject);
Begin GetIncoming End;

procedure TForm1.OnTimer(Sender: TObject);
begin TestStates end;

procedure TForm1.InputBtnClick(Sender: TObject);
var
  Knr: Integer;
begin
  Knr:= (Sender as TButton).tag;
  if Input[Knr]<>nil then
  begin
    ContentLabel.Caption:='Input from client'+IntToStr(Knr);
    Memo1.Lines.SetText(Input[Knr].getText);
  end;
end;

procedure TForm1.OutputBtnClick(Sender: TObject);
var
  Knr: Integer;
begin
  Knr:= (Sender as TButton).tag;
  if Output[Knr]<>nil then
  begin
    ContentLabel.Caption:='Output to client'+IntToStr(Knr);
    Memo1.Lines.SetText(Output[Knr].getText);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DdetestTopic:= TDdeServerConv.Create(Self);
  DDETestItem:= TDdeServerItem.Create(Self);
  DdetestTopic.Name:= 'DdeTestTopic';
  DDETestItem.Name:= 'DdeTestItem';
  DDETestItem.ServerConv:= DdeTestTopic;
  DDETestItem.OnPokeData:= doOnPoke;

  GenerelSetup;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var i: Integer;
begin
  For i:=1 to 10 do
  begin Input[i].free; Output[i].free end;
end;

end.


and sorry for the inconvenience.

Regards,
Williams
0
 

Author Comment

by:sellandbuy
ID: 1349649
Actually what I have asked for is how to get data from client to server w/o using any timer, but I guess that is Delphi problem, isn't it Williams ? Else I could also set a timer to make the client poll the server for any info.
0
 

Author Comment

by:sellandbuy
ID: 1349650
Is there any way to check the link is there at the server side ??
I tried to set the link again in the onclose message of the client side, but does not work. Or anyone know how to set up for a application being both a client and server ? I read from book but the programs also does not turn out to be able to establish the connection.
0
 
LVL 3

Expert Comment

by:williams2
ID: 1349651
yes, it can be done easily.
You can just send a command, that the server recognizes, so the server will answer the message. But I'm afraid that this is not doing withiut using a Timer or a thread in any of the cases.
You would ofcourse need a timer in order to set a timeout value. But why can't you create a timer?

Regards,
Williams
0
 

Author Comment

by:sellandbuy
ID: 1349652
Ok, if there is a timer where I need to do some processing in the timer procedure, I need to take care and make sure that the processing (on slow or having multiple application running as background) to be completed before the next round of timer calling the same procedure. Else the system will hang if u left the system for a short while alone.
0
 
LVL 3

Expert Comment

by:williams2
ID: 1349653
What do you mean? The server application is actually build upon the fact, that severel clients (i have tested this!) accesses the server doing slow database queries simlutanously.
This is solved by using states.

Regards,
Williams
0
 

Author Comment

by:sellandbuy
ID: 1349654
When u switch to Dos shell application problem starts coming in, probably  due to Windows control over Dos is not too gd. Another problem is that when the client poke on to the server when the server is not ready the system will hang.
0
 
LVL 3

Expert Comment

by:williams2
ID: 1349655
I do not recall any DOS shell applications in this thread? ..When I call a CGI client, I actually use a windows application with a hidden form. The client will maybe appear in the startmenu abr, but it's easy to hide.
This system was not ment for DOS applications, it's a pure windows feature. But if you want the client to shut down automatically, you can always use a command to close down the client, and if that command does not appear, or an error might have happened, you can always use a timeout timer to close it (always use application.terminate to be sure).

The CGI DDE server I made prior to this example, did this and was executed from a DOS prompt within the WEB Server. You should always do error checking with retries and timeouts when doing errortransparent C/S applications.
I have not included that in this sample, that's up to you.

To your question that the system hangs if the server is not started:

I have had some problems with WindowsNT, doing that the server won't startup automatically. I'm not sure why this happens, but you can implement a messages to see if the server is running, and if not then execute it. Else you can also use the single-instance feature at www.torry.ru to make sure that only one server is running.

Regards,
Williams
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
This video discusses moving either the default database or any database to a new volume.
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now