Solved

Immediate received data from Server in DDE Using Delphi 3

Posted on 1998-12-07
23
772 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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
 

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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
creating threads in delphi 1 161
Delphi Yen format 3 59
how can i search if string exist in array ? 3 69
Breakpoint doesn't stop in my variable 3 36
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

756 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