Recent

Author Topic: A few questions about Interfaces : Part 3  (Read 3312 times)

vfclists

  • Hero Member
  • *****
  • Posts: 825
    • HowTos Considered Harmful?
A few questions about Interfaces : Part 3
« on: March 07, 2016, 08:23:19 am »
I am creating an application that I use all the time whilst modifyng it. I create a copy to run, and I also have the IDE open to make changes for the future runs.

What I need to do is to add a function to all the forms in the application in which when I see a change I want to make I use a menu to bring up a dialog that allows me to note the required changes. This may not be present in all the forms.

However it needs something that is present in every form whether included in the units section, something inside Forms, Classes, SysUtils etc or some modifications of them. One object that seems to be present is the Application object, so I want to extend the Application object or any other close object with an Interface that can be tested for, and will run the required form. Is it possible to extend the Application object with an interface?

The other option I can think is to create a project template with a .dpr file that somehow contains ready made code for the interface, and a form template that tests for the interface (used with the new form option).

The Application object or some other global object present in all forms is the most appealing. Is it possible and pragmatic?
Windows - Lazarus 1.0.8/FPC 2.6.0
Linux - Lazarus 1.4.4 /FPC 2.6.4

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7507
Re: A few questions about Interfaces : Part 3
« Reply #1 on: March 07, 2016, 09:14:17 am »
Not without changing LCL source.

The low usage of interfaces in the VCL/LCL is why this feature is so relatively unloved in the Delphi world.

vfclists

  • Hero Member
  • *****
  • Posts: 825
    • HowTos Considered Harmful?
Re: A few questions about Interfaces : Part 3
« Reply #2 on: March 07, 2016, 09:41:17 am »
Not without changing LCL source.

The low usage of interfaces in the VCL/LCL is why this feature is so relatively unloved in the Delphi world.

Is it feasible to create project and form templates which subclass or extend the Application object so that the code for creating a form in the .dpr would be something like:
Code: Pascal  [Select]
  1. MyApplication.CreateForm(TdmCentral, dmCentral);
.

MyApplication would have an interface and the forms would also be created from templates that included the interface definitions.
Windows - Lazarus 1.0.8/FPC 2.6.0
Linux - Lazarus 1.4.4 /FPC 2.6.4

taazz

  • Hero Member
  • *****
  • Posts: 5363
Re: A few questions about Interfaces : Part 3
« Reply #3 on: March 07, 2016, 11:02:28 am »
that's relatively easy to do with out much coding. Create a new unit and save it to a file write the code you want to execute test it debug it etc. Keep in mind that this is a simple pascal unit not a form so no LFM file must be create used etc.
Code: Delphi  [Select]
  1. unit uMyCustomForm;
  2. interface
  3.   uses ...., forms;
  4.  
  5.   TForm = class(Forms.TForm)
  6.   public
  7.     procedure DoMyThing;
  8.   end;
  9. implementation
  10.  
  11. procedure TForm.DoMyThing;
  12. begin
  13. end;
  14.  
  15.  

Now for each form you want to have this ability make sure you add uMyCustomForm as the last unit in the uses clause or at least after the forms unit and you are ready to go.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

vfclists

  • Hero Member
  • *****
  • Posts: 825
    • HowTos Considered Harmful?
Re: A few questions about Interfaces : Part 3
« Reply #4 on: March 08, 2016, 11:54:39 pm »
When I look at this code I see that you somehow overriding the definition of TForm, with a new kind of form. Doesn't it affect the existing TForm definition in some way?

I think I prefer to go with the Application extension route. I am not quite sure what I require exactly, but if I think I can subclass TApplication and implement the interface in it without changing any of the LCL code .dpr files are mainly source code so if I extend the Application with an interface, the forms just have to check if the Application implements the interface.

Will it be a matter simply using
Code: Pascal  [Select]
  1.  if (Application is XXInterface) then
  2.    CallNecessaryRoutines
  3.  

that's relatively easy to do with out much coding. Create a new unit and save it to a file write the code you want to execute test it debug it etc. Keep in mind that this is a simple pascal unit not a form so no LFM file must be create used etc.
Code: Delphi  [Select]
  1. unit uMyCustomForm;
  2. interface
  3.   uses ...., forms;
  4.  
  5.   TForm = class(Forms.TForm)
  6.   public
  7.     procedure DoMyThing;
  8.   end;
  9. implementation
  10.  
  11. procedure TForm.DoMyThing;
  12. begin
  13. end;
  14.  
  15.  

Now for each form you want to have this ability make sure you add uMyCustomForm as the last unit in the uses clause or at least after the forms unit and you are ready to go.

What is the difference between

Code: Pascal  [Select]
  1.   TSomeOtherForm = class(TForm)
  2.   public
  3.     procedure DoMyThing;
  4.   end;
  5.  

and
Code: Pascal  [Select]
  1.   TForm = class(Forms.TForm)
  2.   public
  3.     procedure DoMyThing;
  4.   end;
  5.  

using besides redefining TForm? What benefit does it offer?

Windows - Lazarus 1.0.8/FPC 2.6.0
Linux - Lazarus 1.4.4 /FPC 2.6.4

taazz

  • Hero Member
  • *****
  • Posts: 5363
Re: A few questions about Interfaces : Part 3
« Reply #5 on: March 10, 2016, 11:21:43 am »
When I look at this code I see that you somehow overriding the definition of TForm, with a new kind of form. Doesn't it affect the existing TForm definition in some way?

I think I prefer to go with the Application extension route. I am not quite sure what I require exactly, but if I think I can subclass TApplication and implement the interface in it without changing any of the LCL code .dpr files are mainly source code so if I extend the Application with an interface, the forms just have to check if the Application implements the interface.

Will it be a matter simply using
Code: Pascal  [Select]
  1.  if (Application is XXInterface) then
  2.    CallNecessaryRoutines
  3.  
sure what ever floats your boat, keep in mind that the application was not mend to be inherited nor replaced, it is created before even the first line of code in the project is executed and if you destroy it in order to replace it it will uninitialize everything. You will be better of creating your own global variable that does not use the forms unit at all, which has its own rewards for one you might use it for non desktop applications too.
that's relatively easy to do with out much coding. Create a new unit and save it to a file write the code you want to execute test it debug it etc. Keep in mind that this is a simple pascal unit not a form so no LFM file must be create used etc.
Code: Delphi  [Select]
  1. unit uMyCustomForm;
  2. interface
  3.   uses ...., forms;
  4.  
  5.   TForm = class(Forms.TForm)
  6.   public
  7.     procedure DoMyThing;
  8.   end;
  9. implementation
  10.  
  11. procedure TForm.DoMyThing;
  12. begin
  13. end;
  14.  
  15.  

Now for each form you want to have this ability make sure you add uMyCustomForm as the last unit in the uses clause or at least after the forms unit and you are ready to go.

What is the difference between

Code: Pascal  [Select]
  1.   TSomeOtherForm = class(TForm)
  2.   public
  3.     procedure DoMyThing;
  4.   end;
  5.  

and
Code: Pascal  [Select]
  1.   TForm = class(Forms.TForm)
  2.   public
  3.     procedure DoMyThing;
  4.   end;
  5.  
Easy of use in the first case you need to simple include the unit after the Forms unit and the persistent mechanism will create your new form on the second case you have to make sure that
1) the form is part of the project inluding that needs to have an lfm file.
2) all the forms that require the feature must inherite from that form which is a bit over complicated in my book.

In case you want to change the inheritance hierarchy for any reason you have to edit two or three different this way you edit nothing more than a uses clause.


using besides redefining TForm? What benefit does it offer?
the benefit are, easy of use and easy to change/discard, no secondary form needs to be part of the project, no inheritance to worry about, no designer support is required. Keep in mind that it does not redefine anything it simple puts a new class higher in the search hierarchy for the Tpersistent mechanism to choose it over the one in the forms unit.

Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

vfclists

  • Hero Member
  • *****
  • Posts: 825
    • HowTos Considered Harmful?
Re: A few questions about Interfaces : Part 3
« Reply #6 on: March 11, 2016, 05:01:23 pm »
Quote from: taazz
What is the difference between

Code: Pascal  [Select]
  1.   TSomeOtherForm = class(TForm)
  2.   public
  3.     procedure DoMyThing;
  4.   end;
  5.  

and
Code: Pascal  [Select]
  1.   TForm = class(Forms.TForm)
  2.   public
  3.     procedure DoMyThing;
  4.   end;
  5.  

using besides redefining TForm? What benefit does it offer?

Sorry, could you explain this better.
The first option looks is what you normally get when you create a new form in the IDE and give it a form name.

From what I see about the second option, the one you add via uMyCustomForm,  you create a normal form and by including  uMyCustomForm before the type definition of your own form, your form inherits from the new TForm declaration, but you can still depend on the IDE to design it.

Am I understanding you correctly?
Windows - Lazarus 1.0.8/FPC 2.6.0
Linux - Lazarus 1.4.4 /FPC 2.6.4

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 635
Re: A few questions about Interfaces : Part 3
« Reply #7 on: March 11, 2016, 05:07:49 pm »
Correct. It changes the definition of a TForm, but the IDE doesn't notices that.

taazz

  • Hero Member
  • *****
  • Posts: 5363
Re: A few questions about Interfaces : Part 3
« Reply #8 on: March 11, 2016, 06:56:01 pm »
Quote from: taazz
What is the difference between

Code: Pascal  [Select]
  1.   TSomeOtherForm = class(TForm)
  2.   public
  3.     procedure DoMyThing;
  4.   end;
  5.  

and
Code: Pascal  [Select]
  1.   TForm = class(Forms.TForm)
  2.   public
  3.     procedure DoMyThing;
  4.   end;
  5.  

using besides redefining TForm? What benefit does it offer?

Sorry, could you explain this better.
The first option looks is what you normally get when you create a new form in the IDE and give it a form name.

From what I see about the second option, the one you add via uMyCustomForm,  you create a normal form and by including  uMyCustomForm before the type definition of your own form,
After the unit forms in the uses clause the definition of my form has nothing to do with the hack.
your form inherits from the new TForm declaration, but you can still depend on the IDE to design it.
Am I understanding you correctly?
The new class is not known to the IDE at all, no package created, no wizard written to support the new class, no re compilation of the IDE took place, its not part of the IDE at all. The new class is only known to your executable which now has two TForm classes defined, placing the unit after the forms unit you trick the persistence mechanism to find the new TForm class instead of the one that the IDE used. It is a hack that depends on the way the Persistent mechanism searches for the proper class, which class finds first and how it handles multiple classes. If for any reason the search algorithm is changed, I seriously doubt that it will ever change, it might stop working.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64