Link to home
Start Free TrialLog in
Avatar of Delphi_developer
Delphi_developer

asked on

Issue with custom class

Hi

I have a custom class defined:

tTelemetryPanel = class(Panel)
public
  Parent:TWinControl
  Constructor Create(AOwner: TComponent); Override;
private
  property  fParent: TWinControl read Parent write Parent;
Published
    Procedure CreateTelemetryPanel;
end;


...

and

Procedure tTelemetryPanel.CreateTelemetryPanel;
Begin

  TTelemetryPanel(Self).OnResize := myPanelResize;
  TTelemetryPanel(Self).BorderStyle := bsNone;


  vImage := Timage.Create(Nil);

  vImage.Parent := Self;
  vImage.Align := alLeft;

end;

this is defined in new unit.

In Form1 on button click I have this:

procedure TForm1.Button1Click(Sender: TObject);
var vA,vB:TTelemetryPanel;
begin
  vA:=TTelemetryPanel.Create(Self);
  vA.Parent:=Form1.SCPanel147;
  vA.CreateTelemetryPanel;

  vB:=TTelemetryPanel.Create(nil);
  vA.Parent:=Form1.SCPanel144;
  vB.CreateTelemetryPanel;
end;


So, I would like to have two TelemetryPanels on SCPanel147 and 144.

I have a couple of questions:

1. I had to set public 'Parent' otherwise this code failed:

vA.Parent:=Form1.SCPanel147;

Why does it work like that? Shouldn't Parent property work as a basic property?

2. Now it fails on  

vImage.Parent := Self;

when I try to create vImage on this TelemetryPanel. Why it doesn't work? I also tried

 vImage.Parent := TTelemetryPanel(Self);

also didn't work.


3) I would like to have new telemetry panels's width and height as it's parent! How can I do this, can I do this in Create constructor or do I need to have separate code to assign these values?



Thank you
Avatar of thiagoblimeira
thiagoblimeira
Flag of Brazil image

Try setting the Timage as a subcomponent

Here you have the help entry for it:

Call SetSubComponent to indicate that this component is or is not a subcomponent. A subcomponent is a component whose Owner is a component other than the form or data module in which it resides. Unless such a component calls SetSubComponent with IsSubComponent set to true, its published properties will not be saved to the form file.
 
IsSubComponent indicates whether the component is a subcomponent (true) or not (false).
 
SetSubComponent is called at design time either
 
From the constructor of a component that always acts as a subcomponent. In this case, the component calls its own SetSubComponent method from the constructor with IsSubComponent set to true.
 
Immediately after constructing an instance of the subcomponent. In this case, the Owner calls the SetSubComponent method of a component it has just instantiated, with IsSubComponent set to true.
ASKER CERTIFIED SOLUTION
Avatar of Geert G
Geert G
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
1. I had to set public 'Parent' otherwise this code failed:
>>You descended from Panel, not TPanel
didn't this give a compiler error ?

2. Now it fails on
>>Probably because it doesn't know which parent as it is declared in TPanel allready  

3) I would like to have new telemetry panels's width and height as it's parent! How can I do this, can I do this in Create constructor or do I need to have separate code to assign these values?
>>set Align to alClient

it would be better to describe what you want with an image ...
if this is for your telemetry component
i'll give you a rough estimate so you know what the workload will be (this is not to put you off)

for me (it would take me roughly 3 months to get this working)
this is for just the basic things (drawing the graphs and interaction)
the real testing in a production environment would probably add a month for testing and tweaking
this is normal workdays
i would need to up my skills for painting of graphs
and probably some math would be involved too

this is so you know what you are getting into

you'll need to read some books to get this component working
Sam's teach yourself Delphi is the start
Mastering Delphi (very good for component creation)
Tomes of Delphi good too

if your a beginner at delphi, it will probably take 6 to 12 months
Avatar of Delphi_developer
Delphi_developer

ASKER

Geert, thank you, but here is the situation:

I already have the telemetry panel done. It is a very simple panel, which consist of scrollbox and 2 images - create a graph. The 'interactive mode' - to mark points on the graph (image) on MouseOver and some other very simple, but useful actions. So, it works very well, for a prototype... I still need to polish small issues, like antialiasing lines and some discrepancies in scaling.

Now it works as a simple program where all objects are created in code and it all works well... but I need 2 or more of them, so I just wanted to have one class, called twice and create all objects on two separate normal panels. (I was sure component is called when you install new VCL object - component; I didn't know a new class type is already regarded as a component... ).

I got this very basic, but almost suitable/usable, in a few days. I'm a total beginner in components, classes, but not really in Delphi.

The other way to make this work, is to have one unit for each telemetry panel, this would work, but clearly is not a good solution.

I will try you suggestions now. I'll let you know how it goes.
a component is something that functions on it's own (or allmost)

maybe you need to go in the direction of Frames ?
you can create frames like forms, then right click on it to add to Component palette
and then drop them on a form (multiple times too) from the component palette
I would like to make this work, if possible...

It seems I'm getting somewhere. Now I have a procedure 'DrawGraphTemplate', which draws graph's grid, but it fails on this code:


from Form1.Button1clisk I call 'DrawTelemetry' which calls 'DrawGVraphTemplate', which has:

ImageGraph.Picture.Bitmap.Height := ImageGraph.Height;
ImageGraph.Picture.Bitmap.Width := ImageGraph.Width; // FAILS HERE: The parameter is incorrect
ImageGraph.Canvas.Brush.Color := clWhite;

Any suggestions?

I have:
private
    fImageLeft: TImage;
    fImageGraph: TImage;
    fSB: TScrollBox;
    procedure SetImageLeft(const Value: TImage);
    procedure SetImageGraph(const Value: TImage);
    procedure SetSB(const Value: TScrollBox);

Published
     property ImageLeft: TImage read fImageLeft write SetImageLeft;
     property ImageGraph: TImage read fImageGraph write SetImageGraph;
     property SB: TScrollBox read fSB write SetSB;


And also a follow up question... what is the difference if I use 'fImageLeft' or 'ImageLeft', in the code of tTelemetryPanel own's procedures?

Thanx
good for you to have this working allready

ImageLeft is a property
fImageLeft is a private variable (in this case)

a property is like using a in between person to do things (like a waiter)
you tell the waiter (property) to set a certain value
you ask the waiter (property) to get something (a value)

where this waiter gets or sets the value is component specific

the component itself doesn't need to use the waiter, it can go directly in private methods (procedures and functions)
as from protected methods it is supposed to use the property

Have you checked if Picture and Picture.Bitmap <> nil ?
if not Assigned(ImageGraph.Picture.Graphic) or ImageGrap.Picture.Graphic.Empty then
  ImageGraph.Picture.Graphic := TBitmap.Create;

ImageGraph.Picture.Bitmap.Height := ImageGraph.Height;
ImageGraph.Picture.Bitmap.Width := ImageGraph.Width; // FAILS HERE: The parameter is incorrect
ImageGraph.Canvas.Brush.Color := clWhite;

Same for ImageLeft

if these lines are in a private method then use fImageGraph

how did you define "DrawTelemetry"

type
  TTelemetryPanel = class(TPanel)
  private
  protected
  public
    procedure DrawTelemetry; virtual;
  end;

can you call DrawTelemetry directly ?
or is DrawTelemetry called from the method Paint ?