-2

I've searched this and that and didn't find my situation. I have some variable of a type TCustomControl:

var fcontrol:TCustomControl;

Then I use some RTTI magic to create instance of different classes-descendants of TCustomControl:

constructor TFGControl.Create(TheOwner: TComponent; control: string);    
    var classofcontrol:string; class_ref: TPersistentClass;
begin
  case control of 'formspec': classofcontrol:='TPanel';
                     'label': classofcontrol:='TLabel';
                    'button': classofcontrol:='TSpeedButton';
  end;

  class_ref:=GetClass(classofcontrol);

  fcontrol:=TCustomControl(class_ref.Create); 

So, after this I have fcontrol point to instance of desired class. And can assign some methods of it (given that those was described as needed) like this:

  with fcontrol as class_ref do
       begin
            Parent:=Parent;
            if control='formspec' then
               begin
                    Width:=400;
                    Height:=300;
                    Color:=clGray;
               end
            else
                begin
                     top:=20;
                     left:=20;
                     Width:=50;
                     Height:=20;
                     Caption:=control+' - '+inttostr(Parent.ControlCount);
                     Font.Color:=clwhite;
                     Color:=clRed;
                end;

            OnMouseDown:=@MouseDown;
            OnMouseUp:=@MouseUp;
            OnMouseMove:=@MouseMove;
            OnClick:=@Click;   

And it works just great.

But then I want those dynamically created controls to use different Paint methods. I want my newly created instances to use the Paint method of it's ancestors, e.g if class_ref.ClassName is "TPanel" then I want fcontrol to look like TPanel; and if class_ref.ClassName is "TLabel" then I want fcontrol to be drawn like a common label.

The problem is fcontrol is declared as TCustomControl and if I write like this:

            OnPaint:=@Paint;

I can see that it (substitution) works. But what I'm supposed to put inside my new Paint method to invoke Tpanel.Paint if fcontrol is really a TPanel; and TLabel.Paint if fcontrol is really a TLabel?

Regards!

  • I'll gladly provide more info - just don't know what info is needed. So ask whatever seems to be relevant. – konsorumniakku Jun 02 '14 at 17:52
  • 1
    This does not appear to be the solution to any problem. You can't just splice a method from one class onto an unrelated class. I fear that you are so far down this ill advised path that you will not want to hear what I am saying. – David Heffernan Jun 02 '14 at 18:00
  • 1
    It would be better, as always, if you don't post fake code. The case statement does not compile. – David Heffernan Jun 02 '14 at 18:01
  • 2
    Controls *already* call their ancestor methods. Unless *you* did something to make a `TPanel` *not* paint itself like a panel, it will continue to do that all by itself. So what did you do to mess it up? What is that `with` statement really doing? The `Parent:=Parent` assignment is just nonsense, and the event-handler assignments don't make much sense, either, given that `fcontrol.MouseDown` is *not* a valid handler for the `OnMouseDown` event, so the code shouldn't even compile in the first place. Get rid of the `@` operator; it hides errors. – Rob Kennedy Jun 02 '14 at 18:09
  • The code is **not** a fake. I have no delphi around so, continued within Lazarus with -MDelphi switch. Even w/o OnPaint:=@Paint; all I get is a rectaangle of clGrey color; – konsorumniakku Jun 02 '14 at 19:10
  • @DavidHeffernan, I've seen your answers on topics like this, but is there a way to have 1 control (like Tshape but far more complex) which would be drawn like 2-3 different controls (already existing) depending on some property of it? I'd gladly accept your solution if it doesn't consist of only "you're wrong" ;) – konsorumniakku Jun 02 '14 at 19:15
  • The question is tagged delphi not lazarus. The code will not compile in delphi. I can't really help with the problem because you've not stated the problem you are trying to solve. But this isn't the right solution. – David Heffernan Jun 02 '14 at 19:17

1 Answers1

0

with fcontrol as class_ref do

This is not a valid type-cast, nor is it even needed. If you want to set a property dynamically, you can use RTTI instead.

OnPaint:=@Paint;

That will only work for actual TCustomControl-derived objects, so use the is operator to check that:

if fControl is TCustomControl then
  TCustomControl(fControl).OnPaint:=@Paint;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • fcontrol.ClassName is 'TFGControl' while class_ref is 'TPanel' or 'TLabel'. Since class_ref is TPersistentClass I assumed that it's a valid typecast. Lazarus didn't complain at all. The problem with OnPaint:=@Paint is not that it doesn't work or compile. The problem is that I can't make fcontrol to be drawn like TPanel or TLabel... Could you explain in greater details? – konsorumniakku Jun 02 '14 at 19:32
  • I've added a github repo so the code can be reviewed. Note that I've tried some more things after posting the question here. https://github.com/4aiman/formspec Oh, the code is in the editor.pas – konsorumniakku Jun 02 '14 at 19:41