[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 325
  • Last Modified:

display output on a dynamicly created component

Hello everybody,

I want to learn to make a console-emulation component. Now
I use this code to test my component dynamicly:

procedure TForm1.FormCreate(Sender: TObject);
begin
  with DSP3270.Create(self) do
  begin
    Parent := self;
    Align := alClient;
    Caption := '...';
    Left := 0;
    Top := 0;
    {...}
  end;
end;

I have even a server and a connection to that server, but I use
temporarly a TMemo to display the output, but I want the
output on the canvas of my dynamicly created component!
Is that possible? I think it has to do something with a TNotify-
Event! But I don’t know how to implement it. This question
is very important for me and I can learn it myself without ask-
ing questions everytime and I think it's not an easy one so I
give 500 point for it.

This is the code that displays the output on the TMEMO:

procedure TForm1.Display;
var
    I : Integer;
begin
    DisplayMemo.Lines.BeginUpdate;
    try
        if DisplayMemo.Lines.Count > 200 then begin
            for I := 1 to 50 do
                DisplayMemo.Lines.Delete(0);
        end;
        DisplayMemo.Lines.Add(Msg);
    finally
        DisplayMemo.Lines.EndUpdate;

        SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0);
        Timer1.Enabled := False;
    end;
 end;

Greetings,

Peter Kiers
0
peterkiers
Asked:
peterkiers
  • 6
  • 4
  • 2
2 Solutions
 
JaccoCommented:
Yes that should be possible although you need to change the way you create to component a bit.

type
  TForm1 = class(TForm)
  private
    fConsole: DSP3270;
  public
    ...
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  fConsole := DSP3270.Create(self);
  with fConsole do
  begin
    Parent := self;
    Align := alClient;
    Caption := '...';
    Left := 0;
    Top := 0;
    {...}
  end;
end;

That way you store the dynamically create component in a field of the form so you can refer to it later in the Display procedure:

procedure TForm1.Display;
begin
  fConsole.OutputStuff(...);
end;

Regards Jacco

0
 
2266180Commented:
well .. it's actually pretty simple :) and no, it has nothing to do with events for the simple reason that the event is not generated by your component. you display a message in your component when sombody else does something ;)

from the top of my head, written directly here (too lazy to start up the ide), but this is the general idea. type
type DSP3270=class
       private
       public
         procedure display(msg:string);
       end;

procedure DSP3270.display(msg:string);
begin
  with yourcanvas do
  begin
    make some calculations for the text's x,y, do some scrolling when needed then output the message:
    TextOut(x,y,msg);
  end;
end;

and instead of calling tform1.display, you call DSP3270.display(msg:string); (after you have created it)

if your app or component is multithreaded and you don't want otehr threads to write on the canvas you can call lock and unlock. also, to prevent flickering, you can use another (hidden) canvas on which you do the drawing and then just copy the canvas to the visible one; or any otehr tehnique you prefer :)
0
 
peterkiersAuthor Commented:
Thanks for the respons, but i need a little more time to try out the examples.

Peter
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
peterkiersAuthor Commented:
Hi,

I have tried the examples, and the example of Ciuly is what I want.

Only I get:
 
Main.pas(198): Undeclared identifier: 'display'

And I can't figure out why I can't call the procedure DSP3270.display(msg); !!!

I did everything you describe:

unit Main;

uses
     DSP3270;

  private
    { Private declarations }
    procedure Display(Msg : String);

procedure TForm1.Display(Msg: String);
var
    I : Integer;
begin
    DisplayMemo.Lines.BeginUpdate;
    try
        if DisplayMemo.Lines.Count > 200 then begin
            for I := 1 to 50 do
                DisplayMemo.Lines.Delete(0);
        end;
        DisplayMemo.Lines.Add(Msg);
        DSP3270.display(msg);                        //here is where it gets wrong.
    finally
        DisplayMemo.Lines.EndUpdate;
        SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0);
    end;
end;


Peter.
 
0
 
JaccoCommented:
It is probably because your unit name is the same as the classname? They should be different. You name the unit name in the uses claus and the classname in the rest of the code.

Also where do you dynamically create the class now? I think it is missing. Like I said in my first comment: you need a field to store a reference to the created instance and create it in the FormCreate.

Can you post the code of the DSP3270 unit?

Regards Jacco
0
 
2266180Commented:
there is no need for the  DSP3270 unit :)

as jacco suggested (and I forgot to mentin :) ) you need a variable that hold the dinamically created object. that is where jacco's code comes in. (the formcreate part)

after that you call

procedure TForm1.Display(Msg: String);
var
    I : Integer;
begin
    DisplayMemo.Lines.BeginUpdate;
    try
        if DisplayMemo.Lines.Count > 200 then begin
            for I := 1 to 50 do
                DisplayMemo.Lines.Delete(0);
        end;
        DisplayMemo.Lines.Add(Msg);
         fConsole.display(msg);                        //here is where it gets wrong. // per jacco's naming
    finally
        DisplayMemo.Lines.EndUpdate;
        SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0);
    end;
end;

cheers
0
 
peterkiersAuthor Commented:
This is the code as you can see there is not much in it,yet.

unit DSP3270;

interface

uses
  SysUtils, Classes, Controls;

type
  TDSP3270 = class(TCustomControl)
  private
    { Private declarations }
  protected
    { Protected declarations }
    procedure Paint; override;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure display(msg:string);
  published
    { Published declarations }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TDSP3270]);
end;

{ TDSP3270 }

constructor TDSP3270.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
//
end;

destructor TDSP3270.Destroy;
begin
  //
  inherited;
end;

procedure TDSP3270.display(msg: string);
begin
with canvas do
  begin
    TextOut(0,0,msg);
  end;
end;
0
 
JaccoCommented:
This is code that compiles. These are two pascal units. First is DSP3270.pas and the second Unit1.pas

===========================================================
unit DSP3270;

interface

uses
  Graphics;

type
  TDSP3270 = class
  public
    procedure Display(const aCanvas: TCanvas; X, Y: Integer; const aMessage: string);
  end;

implementation

{ TDSP3270 }

procedure TDSP3270.Display(const aCanvas: TCanvas; X, Y: Integer; const aMessage: string);
begin
  aCanvas.TextOut(X, Y, aMessage);
end;

end.
===========================================================
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DSP3270, StdCtrls;

type
  TForm1 = class(TForm)
    DisplayMemo: TMemo;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    fConsole: TDSP3270;
    procedure Display(Msg: String);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  fConsole := TDSP3270.Create;
end;

procedure TForm1.Display(Msg: String);
var
    I : Integer;
begin
    DisplayMemo.Lines.BeginUpdate;
    try
        if DisplayMemo.Lines.Count > 200 then begin
            for I := 1 to 50 do
                DisplayMemo.Lines.Delete(0);
        end;
        DisplayMemo.Lines.Add(Msg);
        fConsole.display(Form1.Canvas, 0, 0, 'Text');
    finally
        DisplayMemo.Lines.EndUpdate;
        SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0);
    end;
end;


end.
===========================================================
0
 
peterkiersAuthor Commented:
I get this error: [Error] Main.pas(50): Not enough actual parameters
in this procedure:

procedure TForm1.FormCreate(Sender: TObject);
begin
  fConsole := TDSP3270.Create;
end;

i think because you put this in your code:

type
  TDSP3270 = class

But i still want to use:
  TDSP3270 = class(TCustomControl)

Peter
0
 
JaccoCommented:
You can use

procedure TForm1.FormCreate(Sender: TObject);
begin
  fConsole := TDSP3270.Create(Self);
end;

Regards Jacco
0
 
peterkiersAuthor Commented:
I need some time to try this out.

Ill be back

Peter
0
 
peterkiersAuthor Commented:
Hi,

It works now, I had to make some adjustments:

procedure TForm1.Display(aMessage: String);
    .....
        fConsole.display( 0, 0, aMessage);
       .....

{DSP3270}

procedure TDSP3270.Display(const  X, Y: Integer;
  const aMessage: string);
begin
  Canvas.TextOut(X, Y, aMessage);
end;

thanks guys for all the help, and I think you deserve both the points.

Greetings,

Peter
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 6
  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now