Some way to reorder component positions, sizes, property (properties in general) at runtime according to a design-time rule

We have an application with many components in forms (panels, tabs, edits, drop-down lists, etc.). But depending on the user profile, most of them may be automatically filled and / or not visible. This way, users could do their job faster.

Question: is there an easier way to create, post, change ownership, etc. at runtime? I would like to create 2 .dfm files for this device and then tell something to use .dfm. For example: "Hi, the user is advanced, use Unit1Advanced.dfm!" A working example will be nice. I would also like to use this in Delphi 7, but it should work at least in Delphi XE.

What I know still exists:

  • ComponentsToCode function from GExperts can create code from this component as gabr, specified in this answer .
  • I could create 2 forms and create the desired one at runtime. But this means that there is one additional .pas file for each additional .dfm file. It will be harder to maintain.
  • This answer seems like a clue. But I'm not used to the TReader and TWriter classes ...
+1
source share
4 answers

Warning: This answer is for completeness and for experimental purposes only. It should never be used in real world scenarios.

You want two separate form definition files for just one source code file.

The key is to use the CreateNew constructor. To quote the documentation for it:

Use CreateNew instead of Create to create the form without using the associated .DFM file to initialize it.

  • First write an extended form:

     unit Advanced; interface uses Classes, Controls, Forms, StdCtrls; type TAdvancedForm = class(TForm) StandardGroupBox: TGroupBox; StandardButton: TButton; AdvancedGroupBox: TGroupBox; AdvancedButton: TButton; procedure StandardButtonClick(Sender: TObject); procedure AdvancedButtonClick(Sender: TObject); end; implementation {$R *.dfm} procedure TAdvancedForm.StandardButtonClick(Sender: TObject); begin Caption := Caption + ' Button1Click'; end; procedure TAdvancedForm.AdvancedButtonClick(Sender: TObject); begin Caption := Caption + ' Button2Click'; end; end. 
  • Build the application and copy Advanced.dfm to Standard.dfm .

  • Open Standard.dfm in a text editor and remove the additional components (in this case, the extended group field containing the button), and rename the form and form type to (T)StandardForm :

     object StandardForm: TStandardForm ... object StandardGroupBox: TGroupBox ... object StandardButton: TButton ... end end end 
  • Add a standard form resource to Advanced.pas :

     {$R *.dfm} {$R Standard.dfm} 
  • And now with the following code, you can open both form definitions for the same source file:

     uses Advanced; procedure TForm1.OpenAdvancedFormClick(Sender: TObject); var Form: TAdvancedForm; begin Form := TAdvancedForm.Create(Application); Form.Show; end; procedure TForm1.OpenStandardFormClick(Sender: TObject); var { Form: TAdvancedForm; // This is tricky! The form we are about to create has // no AdvancedGroupBox nor AdvancedButton, so make sure // you are not calling it with code completion. Form: TStandardForm; // Compiler has no knowledge of TStandardForm! } Form: TForm; // So declare your form as TForm! begin // But create it as TAdvancedForm, otherwise components will not be found! Form := TAdvancedForm.CreateNew(Application); ReadComponentRes('TStandardForm', Form); Form.Show; end; 
+2
source

I can give you a solution based on your point 2. Start with an inexperienced user form, place all the controls as needed, and embed the necessary code in the pas file. Then create a new form, inherited from the first, and customize it to the needs of an experienced user. If necessary, you can also add some implementation.

A more flexible approach might be to inherit both forms from a common character. The actual implementation of this scheme is highly dependent on your situation.

+4
source

Your desire to have only one .pas file for several .dfm files is almost impossible, but also a little incomprehensible: the code will be limited to a less advanced form, it is possible, but not really recommended .

Regarding your separation requirements:

  • Create: create two drawings and do this Visual Form Inheritance (VFI), like Uwe , so you don't have a separate maintenance problem.
  • Position and size: This is a very bad idea. Let the controls stay in one place for each user. Users can get extended privileges and be shocked by an unfamiliar arrangement. The only exception that I would like to make is the minimum size of the form: the extended version may be higher and / or wider.
  • Change ownership: Yes, I understand what you mean, but the controls do not belong to the user, and they should not. Implement some kind of controller that deals with what type of form should be created.

In case VFI is not an option, I suggest that you create only an extended form and control the hiding of advanced controls by setting the Visible property of the associated actions . Do this in or through the installer for the Advanced: Boolean property, which must exist. Or group all advanced controls on one or more containers: group fields, panels, or frames, such as LU RD comments. Then just set the visibility of this container. Existing scrollbars will automatically adjust or disappear. Please note that you can still access these controls, even if you do not want to.

+3
source

DevExpress ExpressLayout components may be useful - see http://devexpress.com/Products/VCL/ExLayoutControl/

They provide customization of the runtime runtime form - runtime customization - screen resolution independence and much more

0
source

All Articles