Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Adding a property in TControl 1

Status
Not open for further replies.

RyanEK

Programmer
Apr 30, 2001
323
AU
Hi,

I want to add an integer property in TControl. It's probably not wise to do so, but i need to add it so that all my vcl controls can be assigned a value (much like the Tag property)

My question is, is it a matter of just adding the property and recompiling vcl50.bpl? Delphi prompts that it is necessary to rename the package. I'm not sure what to do from here.

thanks and rgds,
Ryan
 
I'm not trying to discourage you but why do you actually need to create an extra property? Why not just use the Tag property as you yourself suggested? Clive [infinity]
 
Ahhh because I am already using the tag property to hold another value.

thanks
Ryan
 
I hope you can find an easier way to do what you need to do, but if you really need to "add a property" you can create your own object and use the tag to point to it. Your object can contain the original tag value plus whatever else you need to do. Here is code to handle the request as stated, i.e. add one additional integer property. In the example, Button 3 is used to simulate form creation and Button 4 illustrates that the original tag and the extra value are available as long as the form exists. (This was done in Delphi 4, so TList was used. Freeing up all of the objects in the list would be the programmer's responsibility. If you use Delphi 5, you should be able to use a TObjectList to make the job easier.)

Code:
type
  TSuperTag = class(TObject)
    Tag: integer;
    Extra: integer;

  TForm1 = class(TForm)
    Button3: TButton;
    Button4: TButton;
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private declarations }
    SuperTags:TList;
  public
    { Public declarations }
  end;

implementation

{$R *.DFM}

{Simulate form create and set up super tag on Button3.}
procedure TForm1.Button3Click(Sender: TObject);
var
  Button3SuperTag:TSuperTag;
begin
  if not Assigned(SuperTags) then
    begin
      SuperTags := TList.Create;
      Button3.Tag := 42;
      Button3SuperTag := TSuperTag.Create;
      SuperTags.Add(Button3SuperTag);
      Button3SuperTag.Tag := Button3.Tag;
      Button3.Tag := Integer(Pointer(Button3SuperTag));
      TSuperTag(Button3.Tag).Extra := 4200;
    end;
end;

{Read Tag and Extra properties of Button3}
procedure TForm1.Button4Click(Sender: TObject);
begin
  ShowMessage('Tag=' + IntToStr(TSuperTag(Button3.Tag).Tag)
         + ' Extra=' + IntToStr(TSuperTag(Button3.Tag).Extra));

end;

end.

 
Hi Zathras,

Thats an awesome answer mate and I appreciate it.
Unfortunatly, I forgot to mention that I actually want to be able to assign the Integer value at Design time.
Is this even possible?

thanks
Ryan
 
I don't think so. You are on the verge of writing custom components.

How about this? If you only want to set it at design time and never change it, you could adopt a naming convention that has the desired number attached. I.e., pbOk could have the name pbOk_00001 and pbCancel could have the name pbCancel_00002, etc.

I was assuming that the value needed to be set dynamically. I guess I don't really understand the point.

I might be able to be more helpful if I knew what you really want. Perhaps there is another approach to solving the real problem. There may be a creative way of using TStringList or TObjectList to accomplish the real objective.
 
I found this post which might be helpful:

You can create a descendant of any class with an extra integer field:
Code:
type TMyControl = class(TControl) 
public 
  ExtraTag:integerl; 
end;

The problem comes if you want this extra property to apply to a control used at design time: you will have to register it as an installed component in your IDE, and you would have to do this for every control you want.

It might be simpler to pack more information into the Tag property, either using it as two 16-bit integers if you don't need the full 32-bit integer range, or using it as a pointer to a record (or class) type you create and free yourself. This could then contain any amount of extra data.

Clive [infinity]
 
Clive: Thanks for post. I came across that as well and was hoping there was another way round it!

Zathras: I have to implement an Access Control system on my application. This means that a user can hide/enable forms, tabs and even to the field level. To achieve this, I want to be able to group controls. I want to be able to assign several controls on the form some sort of grouping ID.
The tag property would be perfect for this but it is already in use.

Your naming convention would work, but would be a little time consuming. The ability to assign the grouping id's at design time would save me a heap of work.

thanks!
Ryan


 
If the current use of the tag doesn't require the full range of values, then perhaps Clive's second suggestion is a workable solution.

E.g. If tags range from 1 to 999 now, and you need to "piggy-back" additional numbers from 1 to 999 (although trying to manage more than a few configurations is bound to be rather difficult), then you could use tags like 1001, 1002, 1003, 2001, 2002, 2003, etc.

Otherwise I don't know of any other way than to create custom components. I'm told that it's not too difficult, although I have never done it myself.

Good luck.

By the way, how are you planning to use an integer for access control. Say, for example, you have 6 fields and 6 classes of users where each class of user sees a different set of four of the fields. I can visualize assigning codes of 1, 2, 4, 8, 16, and 32 to each of the user classes and then assigning values of 15, 30, 27, etc. to the number. This seems rather cumbersome and error-prone. I'm not sure, but I think if I were doing something like that (6 fields 6 type of users), I would probably have some code that puts the names of the four specific fields per user type (concatenated with an access ID number) into an TStringList at design time. Then during execution I would loop thru the components on the form, looking up in the TStringList to see whether to hide (not found) or show (found) the fields one by one. I think this "scales up" (handles growth when additional items need to be handled for security sake) better than using an integer as well.

Here is some sample code that may give you some ideas:

Code:
var
  SecurityAssignments:TStringList;

procedure TForm1.Button1Click(Sender: TObject);
var
  SecurityID:string;
begin;
 if not Assigned(SecurityAssignments) then
    SecurityAssignments := TStringList.Create;
 SecurityAssignments.Clear;
 SecurityId := '1';
 SecurityAssignments.Add(SecurityId + 'dfFieldA');
 SecurityAssignments.Add(SecurityId + 'dfFieldB');
 SecurityAssignments.Add(SecurityId + 'dfFieldC');
 SecurityAssignments.Add(SecurityId + 'dfFieldD');
 SecurityID := '2';
 SecurityAssignments.Add(SecurityId + 'dfFieldB');
 SecurityAssignments.Add(SecurityId + 'dfFieldD');
 SecurityAssignments.Add(SecurityId + 'dfFieldE');
 SecurityAssignments.Add(SecurityId + 'dfFieldF');

 if SecurityAssignments.IndexOf('2dfFieldD') >= 0 then
 ShowMessage('dfFieldD ok for security ID 2');
end;
 
Thanks again Zathras. I'll look into the piggy back suggestion.

As for the Access Control across the controls, I have already implented it and it is working pretty well.

Your pretty much on the mark as to how I did it. I wrote a base form that is inherited by all my forms that loops through all the controls, and checks it against my permissions list. The permission list is a list of control identifiers and its status.

eg. frmMain.edtCode,'H' will hide the Code editbox on the main form.

What i was trying to do here is say for example this editbox has a label, instead of having to create another permission list record for the label, i would just assign it a group ID.

Anyways, thanks for all your help, I'll see what i can do from here :)
Ryan
 
...for example this editbox has a label...

If you are putting a TLabel in front of a TEdit, then you should already be specifying the accelerator key with an ampersand in the Caption such as &Office: in the TLabel Caption property and linking it to the TEdit by using the FocusControl property. This is what allows a user to type Alt-O (in this example) to jump to the designated TEdit control.

In that case, when the object is TLabel simply check the FocusControl property instead of the Name property. (A simple If..Else construct.)

If you do that, do you still need a group ID?



 
Zathras... brilliant suggestion! That works well!

thanks
Ryan
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top