Topic: Enabling / disabling objects depending on the use

Hi there,

I am calling on the developer champions here as I am still a newbie in Delphi.

I am looking for a way to enable or disable different objects in a form according to the use I need.

My project being quite complex, I will narrow my issue to the simplest:


Form1

Button1 = add specific record using Form2
Button2 = add specific record using Form2

Button_ADD = add new record using Form2

Button_Edit = show Form2

Form2

Textbox1 , Button_save1

Combobox1, Button_save2

Grid1, Button_edit

Now the constraints:

When click on Form1.Button1 = show Form2 to add a new record with only Form2.Texbox and Form2.Button_save1 enabled

When click on Form1.Button2 = show Form2 to add a new record with only Form2.Combobox and Form2.Button_save2 enabled

When click on Form1.Button_ADD = show Form2 to add a new record with all object enabled except Form2.Grid1 and Button_edit

When click on Form1.Button_Edit = shown Form2 and activate all objects in Form2


We have tried with Dmitry to use Tag in scripts but it does not work the way I want, it always ends up in a messy state where latest tag is stuck in memory somehow.

2 (edited by mathmathou 2015-12-11 11:12:34)

Re: Enabling / disabling objects depending on the use

Hello tcoton,


Have you tried :


  • Link all your buttons, edit etc... as normal with their actions

  • Set all visible properties to FALSE for all elements on Form2

  • Add visible property to TRUE for wanted elements with OnClik ?


procedure Form1_Button1_OnClick (Sender: string; var Cancel: boolean);
begin
    Form2.Edit1.Visible := True;
    Form2.Button_save1.Visible := True;
end;

procedure Form1_Button2_OnClick (Sender: string; var Cancel: boolean);
begin
    Form2.ComboBox1.Visible := true;
    Form2.Button_save2.Visible := True;
end;

procedure Form1_Button_ADD_OnClick (Sender: string; var Cancel: boolean);
begin
    Form2.Button_save1.Visible := True;
    Form2.Button_save2.Visible := True;
    Form2.ComboBox1.Visible := True;
    Form2.Edit1.Visible := True;
end;

procedure Form1_Button_EDIT_OnClick (Sender: string; var Cancel: boolean);
begin
    Form2.Button_save1.Visible := True;
    Form2.Button_save2.Visible := True;
    Form2.ComboBox1.Visible := True;
    Form2.Edit1.Visible := True;
    Form2.TableGrid1.Visible := True;
    Form2.Button_Edit.Visible := True;
end;

And then reset all elements visibility to FALSE on OnClose event of Form2 with :


procedure Form2_OnClose (Sender: string; Action: string);
begin
    Form2.Button_Edit.Visible := False;
    Form2.Button_save1.Visible := False;
    Form2.Button_save2.Visible := False;
    Form2.TableGrid1.Visible := False;
    Form2.ComboBox1.Visible := False;
    Form2.Edit1.Visible := False;
end;
Post's attachments

Attachment icon ConditionalElements.zip 334.46 kb, 521 downloads since 2015-12-11 

I'm a very good housekeeper !
Each time I get a divorce, I keep the house

Zaza Gabor

Re: Enabling / disabling objects depending on the use

Good Morning TCoton, Mathias,

If I understand your problem correctly, yes, I would do it exactly the same way as Mathias suggests.

Derek.

Re: Enabling / disabling objects depending on the use

Hi there,

hiding the objects is a fairly good idea, however, a large form would look pretty ugly, wouldn't it?

I will give it a try, thanks Mathmathou

5 (edited by mathmathou 2015-12-11 13:57:27)

Re: Enabling / disabling objects depending on the use

You could resize Form2 "on the fly" like :


procedure Form1_Button1_OnClick (Sender: string; var Cancel: boolean);
begin
    Form2.Height := 450;
    Form2.Width := 600;
    Form2.Edit1.Visible := True;
    Form2.Button_save1.Visible := True;
end;

procedure Form1_Button2_OnClick (Sender: string; var Cancel: boolean);
begin
    Form2.Height := 250;
    Form2.Width := 420;
    Form2.ComboBox1.Visible := true;
    Form2.Button_save2.Visible := True;
end;

and so on for each button, and then reset the size of Form2 to it's original design on the OnClose event.


I know that's a lot of events and conditions but...


By the way, I think you could even set X and Y positions for each element with the OnClick button.

I'm a very good housekeeper !
Each time I get a divorce, I keep the house

Zaza Gabor

Re: Enabling / disabling objects depending on the use

Hi TCoton, Mathias,
Yes, it can make the form look unbalanced.
You could replaced the  xxx.visible := false  with xxx.enabled := false.  That might make it look better.
I've attached an example - it might not have all your conditions, but the principle is the same.
Derek.

Post's attachments

Attachment icon tcotonformbehaviour.zip 337.36 kb, 520 downloads since 2015-12-11 

7 (edited by tcoton 2015-12-12 11:32:42)

Re: Enabling / disabling objects depending on the use

I will try that as well, up to now I have an issue with Mathmathou method as I have to use a tag to set the focus on a field and the object do not react the expected way.


I have this on button 1 click

    Data_edition.Edit_VodafNr.Visible:= True;
    Data_edition.Combo_VodafNrSttus.Visible:= True;
    Data_edition.Button_saveVodafNr.Visible:= True;
    Data_edition.Tag := 1;

this on button 2 click

    Data_edition.Edit_SIMNr.Visible:= True;
    Data_edition.ComboSttus.Visible:= True;
    Data_edition.Button3.Visible:= True;
    Data_edition.Tag := 2;

This on button 3 click

    Data_edition.Edit_IMEI.Visible:= True;
    Data_edition.Button2.Visible:= True;
    Data_edition.Combo_IMEI_Sttus.Visible:= True;
    Data_edition.Tag := 3;

this on Data_edition show

     if Data_edition.Tag = 1 then Data_edition.Edit_VodafNr.SetFocus; // Set Focus on textbox
     if Data_edition.Tag = 2 then Data_edition.Edit_SIMNr.SetFocus;
     if Data_edition.Tag = 3 then Data_edition.Edit_IMEI.SetFocus;

this on Data_edition close

    Data_edition.Edit_VodafNr.Visible:= False;
    Data_edition.Combo_VodafNrSttus.Visible:= False;
    Data_edition.Button_saveVodafNr.Visible:= False;
    Data_edition.Edit_SIMNr.Visible:= False;
    Data_edition.ComboSttus.Visible:= False;
    Data_edition.Button3.Visible:= False;
    Data_edition.Edit_IMEI.Visible:= False;
    Data_edition.Button2.Visible:= False;
    Data_edition.Combo_IMEI_Sttus.Visible:= False;

In the end, the fields are activated in a weird way. First run, all fields visible when click on button 1. Close form. Re-click on button 1, only a few objects are disabled and so on when clicking on the other buttons.

I will double check quietly this weekend.

Re: Enabling / disabling objects depending on the use

Hey tcoton (and all the others following this very interesting thread),


I'm not sure to see where the problem is because in the small project attached :


  • I simply use SetFocus on an object to get the correct focus on Form2

  • Form2 size is different on each click of the 4 buttons

  • some objects even change position on the Onclick event of Button_EDIT and come back to place on OnClose Form2


and it seams to work perfectly... sad



I could be wrong, but :

  • did you set visibility to FALSE for all objects on Form2 in the Object Inspector ?

  • do you reset every visibility to False on OnClose of Form2 ?

  • Why use a tag when SetFocus works for me ?


I was confronted with something similar with conditional show of elements (green or red leds icons) on a function result and I find it faster to set Visible := False on conception (Object Inspector) and call Visible := True on event for only the objects needed, than the contrary.


But every Visible attribut have to be reset at a moment or another, otherwise they mix with next event and the display is messed up.


I choose OnClose as the reset event, but could also be OnShow ,or maybe OnClick on a SAVE button of Form2 I suppose....


Again, I realize this is a lot of code for visual effects", but you're trying to achieve something special right ? smile smile


Anyway, have a look at my code, you'll see focus is correct and resize and move elements as well.


Hope it helps


Cheers


Mathias

Post's attachments

Attachment icon ConditionalElements2.zip 335.49 kb, 547 downloads since 2015-12-12 

I'm a very good housekeeper !
Each time I get a divorce, I keep the house

Zaza Gabor

Re: Enabling / disabling objects depending on the use

Hi Mathmathou,

quick answer as I did not try the 2 last example, thanks guys...busy life.

Yes this is a lot of code for visual effects but I've been working for so long with users mixing up the fields they should use and messing up the data that it might be worth the effort. On the other hand some people may be tempted to create a lot of forms to fit each button call. I would rather have a dynamic form to keep the .exe as lightweight as possible.

I had to set the tag because I get an error that focus cannot be set on an invisible or hidden form... and the focus changes depending on what the user has to input when clicking on the button

10 (edited by tcoton 2015-12-12 18:23:43)

Re: Enabling / disabling objects depending on the use

Derek's solution is pretty elegant, what is the function check?
I still, however get THE error: cannot focus a disabled or invisible window when I use SetFocus on different TextBoxes... weird!

Mathmathou's solution works as long as the button has no event. For example on ConditionalElements2 when addind the event: New record on Button_ADD, then disable Form2.Show in the script, you get THE error: cannot focus a disabled or invisible window.

Re: Enabling / disabling objects depending on the use

Hi TCoton, Hi Matthias,
It is also quite nice not just to set various fields to enabled := false but also to change their colour otherwise the user might be tempted to try and click in fields that are still showing 'white' - I tend to use clbtnface to be consistent with other Windows applications where an option isn't available.
I changed the example I did to show this and it is attached.  Of course, it is a few more lines of code but if it stops errors and makes it easier to use, then it is worth it.
I'm sorry but I'm not sure what you mean when you ask "what is the function check?"
Anyway, hope this helps.
Derek.

Post's attachments

Attachment icon tcotonformbehaviour 2.zip 338.27 kb, 561 downloads since 2015-12-12 

Re: Enabling / disabling objects depending on the use

Thanks Derek, nice example.

I am totally puzzled with the enable true or false with my project since it does not behave as expected, I managed somehow to remove the error message but the object activation is random.

I tried to disable everything on form2 and enable only what I need to make sense but I face the following issue when inspired by Derek's method using check = ...

All object are disabled in form2 by default.

On first run, if I click on button1 to trigger chek ='A', the objects I need are ok and the un-needed are disabled. Perfect

Then, I go back to form1 after doing my stuffs and I click on button2 to trigger check = 'B', the objects I need are enabled + the objects previously enabled!! hmm

I do what I need and back to form1, I click on button3 to trigger check = 'C', the objects I need are enabled + the objects previously enabled!! hmm

and so on... To reset, I have to close the app and restart. Any hint to reset the objects being enabled to their normal status "disabled" everytime?

Please do not tell me, I have to explicitly set the objects I do not need to disable in addition to the ones I want to be enabled sad

Focus works well though! smile

Re: Enabling / disabling objects depending on the use

Good Evening Tcoton,
I have always been puzzled that the attributes of the objects on the form do not get reset when it is closed.
So I end up ignoring an object's default status and set it explicitly one way or the other which takes more time and makes the script longer, but it's the only way I know to make sure it works 100%.
Sorry - I know it's not what you wanted to hear - LOL!
Derek.

Re: Enabling / disabling objects depending on the use

Aaaargh, too much script! yikes

Re: Enabling / disabling objects depending on the use

I would like to thank you all for you help, much appreciated.

I still wonder why when an object has a default property set to disabled, I have to disable it when I close the form but...well life is full of mysteries.

To be fairplay, I liked Mathmathou's dynamic form redrawing but it would take too much of my current limited time to calculate the window positions and size depending on the screen in use for this project. I keep it warm though! smile

16 (edited by tcoton 2015-12-15 18:19:19)

Re: Enabling / disabling objects depending on the use

The final solution was to set default properties to disabled

and on check = '<matching letter>', I set the required objects to enabled to minimize scripting

I set the focus at last step once objects are enabled before the end;

on form2_close, I set all properties to disabled for reset smile

example (very short version):

procedure Details_Button_AddContract_OnClick (Sender: string; var Cancel: boolean);
begin
     check := 'E';
end;


procedure Data_Edition_OnShow (Sender: string; Action: string);
begin
     if check = 'E' then
     begin
    Data_edition.Edit_Tariff.Enabled:= True;
    Data_edition.Button1.Enabled:= True;// button save
    Data_edition.Edit_Tariff.SetFocus;
     end;
end;

procedure Data_Edition_OnClose (Sender: string; Action: string);
begin
    // Reset properties

    Data_edition.Edit_Tariff.Enabled:= False;
    Data_edition.Button1.Enabled:= False;// button save
end;

Please note that if a query has to be triggered in Form2, place it within the Button_On_Click procedure as it would not work with Form2_On_Show

Re: Enabling / disabling objects depending on the use

No offence taken Tcoton, you're right, that's a lot of code to resize, move and reset elements "on the fly".


I thank you for that very interesting thread you launched, and keep in safe place your "flag" idea.


Flags are actually something that exists in Delphi, but they are used to jump directly to some piece of code. Not yet implemented in MVD I think.


Mathias

I'm a very good housekeeper !
Each time I get a divorce, I keep the house

Zaza Gabor