0

I'm a bit new with objects and I have really have been stuck on this, I hope you guys can help me.

I create a simple application to exemplify the problem I am having with Delphi.

I have an object that inherited from TButton, but in creation time I can assign a "Group" to this button, and after I want to be able to change the caption of all button created and to enable and disable it depending on the group that it belongs.

There are 5 button in the form:

  1. Left G1 - Create a button to group one in the left side the form
  2. Right G2 - Create a button to group two in the right side the form
  3. Add caption - Add caption to all button created independent of the group (same caption to all)
  4. Enable G1 - Enable all button that belongs to group one
  5. Disable G1 - Disable all button that belongs to group one

What I want to do is to be able to create as many buttons I want for each different group and then change all the captions at once and enable and disable separate groups at once, this is a sample project from a much bigger application that have lots of objects created so go trough all the objects in the form would be very consuming it would be nice if the change could be made by the object not by the main form.

Please guys I don't want to anyone to make the work for me, I want someone to point me in the right direction, should I use a class even knowing that I can't change the individual properties of the objects is there a way around? Can I somehow implement it on the object or do I need to implement it on the unit calling those objects. Any pointer?

Many thanks in advance.

unit Unit2;

interface

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

type
  TForm2 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  TSample = class(TButton)
  private
    class var count: integer;
  protected
  public
    procedure increseCount;
    constructor Create(AOwner: TComponent; Ypos, Group:Integer); overload;
    class procedure rename(name: string);
    class procedure enableGroup(Group: Integer; value: Boolean);
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

constructor TSample.Create(AOwner: TComponent; Ypos, Group:Integer);
begin
   self.Create(AOwner);
   self.Top := count *50;
   self.Left := Ypos;
   self.Tag := Group;
   increseCount;
   self.Parent := AOwner as TWinControl;
end;

procedure TSample.increseCount;
begin
  count := count + 1;
end;

class procedure TSample.enableGroup(Group: Integer; value: Boolean);
begin
  //???
end;
class procedure TSample.rename(name: string);
begin
  //self.Caption := name; ???
end;

procedure TForm2.Button1Click(Sender: TObject);
var
  left: TSample;
begin
  left := TSample.Create(self, 24, 1);
end;

procedure TForm2.Button2Click(Sender: TObject);
var
  right: TSample;
begin
  right := TSample.Create(self, 200, 2);
end;

procedure TForm2.Button3Click(Sender: TObject);
begin
  TSample.rename('Oi!');
end;

procedure TForm2.Button4Click(Sender: TObject);
begin
  TSample.enableGroup(1, True);
end;

procedure TForm2.Button5Click(Sender: TObject);
begin
  TSample.enableGroup(1, False);
end;

end.
Icaro
  • 14,585
  • 6
  • 60
  • 75
  • What is your question? – David Heffernan Jan 29 '14 at 20:52
  • How to change the caption and how to enable and disable the button that belong to a group in the example I posted. – Icaro Jan 29 '14 at 21:38
  • You want us to write the code for you? You have not made any real effort. How is the code going to find all the controls in the same group? – David Heffernan Jan 29 '14 at 21:39
  • No I don't want the code, I post a code I want to know what and how I should use as the class method is not the way to go as it can't change this properties, if someone give me a hint I can add to the example I already did and re post here with the results adding a new reference for others. – Icaro Jan 29 '14 at 22:12
  • How do you want to find the other controls? Why do you want to use class methods? – David Heffernan Jan 29 '14 at 22:30
  • I'm using class method because as you can see in the code I posted I create some objects on the button1 click event, some in the button2 click event, now I want to call all the button created in the different procedures and update it all. As far as I understood for my research if I want to change a value that belong to all objects I should use a class function. But if i try I get a message [DCC Error] Unit2.pas(67): E2233 Property 'Caption' inaccessible here – Icaro Jan 29 '14 at 22:56
  • Class functions are not what you think they are. How are you going to get hold of all the instances of the buttons? You are going to need to have an instance of the form and walk over its children, recursively. Or maintain your own list. Frankly I think you need to attempt some simpler tasks to build up your knowledge. – David Heffernan Jan 29 '14 at 23:00
  • I'm fixing a application that uses this kind of designer, so I have no other option other then learn how it work, I program in Delphi since version 1 and before that in Pascal, my problem is not with the coding but the designer as I'm old school and use to modify and maintain old codes I am not use to oop. I guess it is time to learn. Thanks I will have a look in how the object can maintain a list of its instances and work out what need to be done. – Icaro Jan 29 '14 at 23:18

1 Answers1

0

Ok, after the hint from David I find the solution:

First I create an array the same kind of the object Then I create a class function that create this object and save into this array Now every time I need to access any of those objects I can just browse this list and change what need to be change.

Why I did this way? Before I was browsing all objects in my main form what was taking a lot of processing, doing this way I just have to browse objects of the kind I want to change.

Thanks I hope it can help others in the future.

   unit Unit2;

    interface

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

    type
      TForm2 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        Button3: TButton;
        Button4: TButton;
        Button5: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
        procedure Button4Click(Sender: TObject);
        procedure Button5Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;

    type
      TSample = class(TButton)
      private
        class var count: integer;
        class var List: Array of TSample;
      protected
      public
        procedure increseCount;
        constructor Create(AOwner: TComponent; Ypos, Group:Integer); overload;
        class function CreateInstance(AOwner: TComponent; Ypos, Group:Integer): TSample; overload;
        class procedure rename(name: string);
        class procedure enableGroup(Group: Integer; value: Boolean);
      end;

    var
      Form2: TForm2;

    implementation

    {$R *.dfm}

    class function TSample.CreateInstance(AOwner: TComponent; Ypos, Group:Integer): TSample;
    var
     i: Integer;
    begin
      i := Length(List)+1;
      SetLength(List, i);
      List[i-1] := self.Create(AOwner, Ypos, Group);
    end;


    constructor TSample.Create(AOwner: TComponent; Ypos, Group:Integer);
    begin
       self.Create(AOwner);
       self.Top := count *50;
       self.Left := Ypos;
       self.Tag := Group;
       increseCount;
       self.Parent := AOwner as TWinControl;
    end;

    procedure TSample.increseCount;
    begin
      count := count + 1;
    end;

    class procedure TSample.enableGroup(Group: Integer; value: Boolean);
    var
      i: Integer;
    begin
      for i := 0 to Length(List)-1 do
        if List[i].Tag = Group then
          List[i].Enabled := value;
    end;

    class procedure TSample.rename(name: string);
    var
      i: Integer;
    begin
      for i := 0 to Length(List)-1 do
        List[i].Caption := name;
    end;

    procedure TForm2.Button1Click(Sender: TObject);
    var
      left: TSample;
    begin
      left := TSample.CreateInstance(self, 24, 1);
    end;

    procedure TForm2.Button2Click(Sender: TObject);
    var
      right: TSample;
    begin
      right := TSample.CreateInstance(self, 200, 2);
    end;

    procedure TForm2.Button3Click(Sender: TObject);
    begin
      TSample.rename('Oi!');
    end;

    procedure TForm2.Button4Click(Sender: TObject);
    begin
      TSample.enableGroup(1, True);
    end;

    procedure TForm2.Button5Click(Sender: TObject);
    begin
      TSample.enableGroup(1, False);
    end;

    end.
Icaro
  • 14,585
  • 6
  • 60
  • 75
  • 1
    Hate to tell you, but this isn't a great solution - it's a bit of a procedural/OO mess. Class procedures/functions/vars are useful in certain circumstances, but not you've used them to try to make it behave like procedural code. Assuming you only affect buttons on this form, you'd be better off having a TList (or even an array of TList on the form, adding/removing buttons to these lists and having a procedure that takes a List and applies the operation to the entire list. As a preference, I'd also avoid giving an array a var name of 'List' - it's confusing. – Matt Allwood Jan 31 '14 at 11:19
  • Hi Matt, thanks for your inside, I don't have much experience in OO so that is the big reason of the mess. I just have one problem in what you are saying, this is a simplified example, in my actual program I have the same object been use in different forms and units but the object is the same for all (to simplify, lets suppose it is a button on the main form, but all the sub-forms inside can enable or disable depending on what is happening) that why I decide to put the code inside the object. What would you suggest in this case? I am very ken to do my code better. Thanks – Icaro Feb 02 '14 at 19:54