msd 5 Posted January 11 Hello Developers, Is it possible to extend the standard VCL component with some features (properties) without creating a new component? For example, I need to add two string properties to the CheckBox component (for auto-saving in an inifile, I need two value properties and a group name), and I think about a new VCL. Does someone have a better idea? Thanks in advance... Share this post Link to post
Die Holländer 49 Posted January 11 >>without creating a new component? >>and I think about a new VCL. Sounds a bit strange.. Don't modify the original VCL component (if you have the Delphi sourcecode..) Modifying_Existing_Controls 1 Share this post Link to post
Lajos Juhász 295 Posted January 11 You cannot add a property without a new class. If you don't want to extend the component you can store the additional information in a dictionary or in other data structure. 1 Share this post Link to post
msd 5 Posted January 11 Hello, Thanks for the reply. Here is a closer explanation of one of my ideas. I have a config form with a lot of checkboxes, which holds data in an ini file. The ini file has sections and values. So, I have a standard checkbox with two additional properties: one is IniSection, and the other is IniProperty OK. I would like to solve this without new components, but I need to keep this scenario: when I call save or load config dara method and I search iniFile by those 2 new properties from the checkbox,. I think that now it is a little bit clearer what I want to do with my additional properties. Thanks again for all the ideas... Share this post Link to post
Kas Ob. 121 Posted January 11 Hi, 7 minutes ago, msd said: I have a config form with a lot of checkboxes, which holds data in an ini file. The ini file has sections and values. So, I have a standard checkbox with two additional properties: one is IniSection, and the other is IniProperty OK. I would like to solve this without new components, but I need to keep this scenario: when I call save or load config dara method and I search iniFile by those 2 new properties from the checkbox,. Do it stupid simple, do you need it to be used or modified by users manually ?!! most likely no.. So, even for both cases (Yes/No) : Name these CheckBoxes with useful and clear names, then use the their names as Ini file Value while use for the Ini file Sections the Form/Frame name ... Don't forget to handle missed value with notification or errors or skip silently.... , For saving (or loading): enumerate all the controls in the form/frame and utilize the tag property to indicate the need to be saved/stored in Ini file or not. Just an idea ! 1 Share this post Link to post
Kas Ob. 121 Posted January 11 Or if you want to go fancy, then build a class/component (a manager) that do that automatically, i mean enumerate all the controls and create an ini file with them, while it such in design time will enumerate all the controls and have a list at design time that can be checked to include/exclude from saving. Building such component will give you huge experience while being fun. 2 Share this post Link to post
dummzeuch 1515 Posted January 11 (edited) Hm, I remember writing something like this (many) years ago, but never actually used it. The code should be on sourceforge, I'll have to look it up. Found it: https://sourceforge.net/projects/dzconfig/ As I said: That was years ago, but maybe you will find it useful. Edited January 11 by dummzeuch 1 Share this post Link to post
msd 5 Posted January 11 52 minutes ago, Kas Ob. said: Hi, Do it stupid simple, do you need it to be used or modified by users manually ?!! most likely no.. So, even for both cases (Yes/No) : Name these CheckBoxes with useful and clear names, then use the their names as Ini file Value while use for the Ini file Sections the Form/Frame name ... Don't forget to handle missed value with notification or errors or skip silently.... , For saving (or loading): enumerate all the controls in the form/frame and utilize the tag property to indicate the need to be saved/stored in Ini file or not. Just an idea ! Hello, It is just like when I develop my config form, the CheckBox Hint is used for ItemName (because of the multiple same names in the config form), and the parent component name represents the ItemScetion, so this is my scenario now. But it is not only check boxes; there are also edit components (text, number, color, date, time, folder name, etc.). This is the main reason why I need some modifications to the base class to make some maintainable code.🙂 I have a lot of cases in my apps with this, but for some cases, like DataSet, I need to create my class or component because I need at least 10 properties to add to make my development process simpler. Thanks anyway; any comment is useful in some way. Share this post Link to post
Kas Ob. 121 Posted January 11 12 minutes ago, msd said: (text, number, color, date, time, folder name, etc.). I have a lot of cases in my apps with this, but for some cases, like DataSet, I need to create my class or component because I need at least 10 properties to add to make my development process simpler. So for such cases these is "case" in Pascal/Delphi Case the control is CheckBox then the value is Boolean type Case of TMemo then the value is Base64 Encoded text. Case of something need more than one property then (like DataSet) MyDataSet.XX or MyDataSet_XX is TXX type ..... 1 Share this post Link to post
Pat Foley 51 Posted January 11 How about a collection of check boxes TCheckListBox The sample simply clears the checkboxes that were in the IDE and adds the ones that are in Array<string> To extend you would change the Panel and Tstrings that the UI uses update the backend. Here the back end simply updates the UI when programs are used. It uses a Ddd pattern Data driven pattern. " Update the data early and often" class function TptrApps.HookInUI(inSG: TStringGrid; inLog: TStrings; inChBxs: TcheckListBox; inBanner: TPanel): TptrApps; begin Result := nil; focusedApp := @cacheApp; var R := TptrApps.Create; R.ChBxs := inChBxs; R.ChBxs.OnClick := R.changeExesList; R.ChBxs.Items.Clear; for var I := Low(goodApps) to High(goodApps) do begin R.ChBxs.Items.add(goodApps[I]); R.ChBxs.Checked[I] := True; ... const selfClass = 'FrmPat'; GoodApps: Tarray<string> = [cEveryThing,'Shell_TrayWnd','Notepad', 'TAppBuilder', 'Window', 'Chrome_WidgetWin_1', 'Notepad++', selfClass, 'TfmPeInformation' ]; 1 Share this post Link to post
Stano 143 Posted January 11 Programmers have a strange way of thinking that I don't understand. Because I'm not a pro-programmer. That's the case here. I'm dealing with something similar. It is about setting values and appearance of individual components on a form. I'm using JSON to do this. That's a significant difference, because you're using IniFile. The principle is simple. The title consists of the names: Owner (form) + Parent + Component The result is e.g.: "frmsubMatchesByRoundfdnvDraw": { "jstpnlTeamVst": { "jstvstTeam": { "VTSearchDirection": 0, "Width": [ 120,165,100,84,167], "Position": [ 0,1,2,3,4], "SortColumn": -1, "VTSearchStart": 2, "ShowSortGlyphs": false, "FirstSetFocus": false, "VTSortDirection": 0 } }, ... }, To do this, functions of the type Read..., Write... function TAppearance.DoCareNoEdit(const ACont: TControl): Boolean; begin Result := True; if (ACont is TAdvOfficeRadioButton) then CareAdvOfficeRadioButton(TAdvOfficeRadioButton(ACont)) else if (ACont is TjstVirtualStringTree) then CarejstVirtualStringTree(TjstVirtualStringTree(ACont)) ... procedure TAppearance.CarejstVirtualStringTree(const AComp: TjstVirtualStringTree); begin AComp.ParentDoubleBuffered := True; FjstVst := AComp; FJsonItemName := oGlobVar.ActualForm.Name +'.'+ FjstVst.Parent.Name +'.'+ FjstVst.Name +'.'; CreateVstPopupMenu; SetVstProperties; end; Hopefully this will help in some way. If I haven't hit the topic at all, then ignore it 1 Share this post Link to post
Anders Melander 1811 Posted January 11 An easy way to introduce new methods and properties to components on a form is to use interposers: type TCheckBox = class(StdCtrls.TCheckBox) private FGroup: string; FValue1: string; FValue2: string; public property Group: string read FGroup write FGroup; property Value1: string read FValue1 write FValue1; property Value2: string read FValue2 write FValue2; end; Insert this in the interface section of your form unit. It must be before the declaration of the form. You can also put it in a separate unit but then you need to ensure that that unit is referenced after StdCtrls. Basically, this trick fools the Delphi DFM loader into creating an instance of your TCheckBox class instead of the standard one in StdCtrls. Note that interposers only enables you to extend a component at run-time. The design-time environment (i.e. the Delphi IDE) knows nothing about this trickery so the new properties will not appear in the property inspector (which is also why I didn't bother declaring them as published). If you want design-time support you will have to create and register a custom component the normal way. 1 1 Share this post Link to post
Remy Lebeau 1421 Posted January 11 (edited) 6 hours ago, msd said: Is it possible to extend the standard VCL component with some features (properties) without creating a new component? In a word, no. However, if you intend to use the extended component in just one form/project, and don't mind setting the new properties in code at runtime rather than with the Object Inspector at design-time, then you could use an interposer class to add the properties, and that way you don't have to make the extra effort of putting the new component in a new package and installing it into the IDE. 6 hours ago, msd said: For example, I need to add two string properties to the CheckBox component (for auto-saving in an inifile For example: unit MyUnit; interface uses ..., Vcl.Forms, Vcl.StdCtrls, System.IniFiles, ...; type TCheckBox = class(Vcl.StdCtrls.TCheckBox) public IniSection: string; IniProperty: string; procedure LoadFromIni(Ini: TCustomIniFile); procedure SaveToIni(Ini: TCustomIniFile); end; TMyForm = class(TForm) SomeCheckBox: TCheckBox; procedure FormCreate(Sender: TObject); ... private procedure LoadConfig; procedure SaveConfig; end; ... implementation ... procedure TCheckBox.LoadFromIni(Ini: TCustomIniFile); begin Checked := Ini.ReadBool(IniSection, IniProperty, False); end; procedure TCheckBox.SaveToIni(Ini: TCustomIniFile); begin Ini.WriteBool(IniSection, IniProperty, Checked); end; procedure TMyForm.FormCreate(Sender: TObject); begin SomeCheckBox.IniSection := ...; SomeCheckBox.IniProperty := ...; end; procedure TMyForm.LoadConfig; var Ini: TIniFile; begin ... SomeCheckBox.LoadFromIni(Ini); ... end; procedure TMyForm.SaveConfig; var Ini: TIniFile; begin ... SomeCheckBox.SaveToIni(Ini); ... end; Edited January 11 by Remy Lebeau 1 1 Share this post Link to post