Jump to content
Girish Patil

Common code base for VCL and FMX control code

Recommended Posts

Hi,

 

I’m checking to see if there are better ways to have a common codebase for both VCL and FMX components.

Here’s some information on the scenario and the current implementation:

  • We are working on having a common code base for the Document Printer component in Document Studio.
  • Only about 10-15 lines of code are platform (OS) and framework (VCL/FMX) specific.
  • The VCL component needs to link to/use VCL units - Printer, Graphics, etc., and likewise the FMX version needs to link to/use FMX units - Printer, Graphics…
  • Since the controls link to different frameworks and their respective units and since they need to be installed on the component palette, the unit that contains the control needs to be different for each framework (VCL, FMX).
  • And It’s organised in the following way currently:

Unit vclgtDocumentPrinter

{$Define gtVCL}

{$Include gtDocumentPrinter.inc} // this file has all the code

 

Unit FMX.gtDocumentPrinter

{$Define gtFMX}

{$Include gtDocumentPrinter.inc} // this file has all the code

 

There’s one apparent issue with this way: code completion doesn’t work in the inc file.

 

Are there better ways of having a common code base for controls in the scenario explained above?

 

Thank you,

--

Girish Patil
Gnostice
www.gnostice.com

Share this post


Link to post

I suggest you to create 2 different packages, with the same units, but need to have 2 different packages, one for FMX and one for VCL. After create packages, add in the project options of each package, in the "Conditional defines" something like USING_VCL for the vcl package and USING_FMX for the fmx package.In code of your .pas just use:

{$IFDEF USING_VCL}
...
{$ENDIF}

or

{$IFDEF USING_FMX}
...
{$ENDIF}

 

Edited by vfbb
  • Like 1

Share this post


Link to post
6 hours ago, Girish Patil said:

I’m checking to see if there are better ways to have a common codebase for both VCL and FMX components.

Is your component visual (derived from TControl)?  Or is it non-visual (derived from TComponent)?  Non-visual components can be used in both VCL and FMX without splitting up the implementation (just IFDEF the pieces you need).  But visual controls take more work to design for separate frameworks.

6 hours ago, Girish Patil said:

Only about 10-15 lines of code are platform (OS) and framework (VCL/FMX) specific.

Then those lines should be in separate units.  The rest of your code should be in a common unit(s) that the framework-specific units can then use.

6 hours ago, Girish Patil said:
  • The VCL component needs to link to/use VCL units - Printer, Graphics, etc., and likewise the FMX version needs to link to/use FMX units - Printer, Graphics…

This is where Unit Scope Names come into play.  Create separate VCL-specific and FMX-specific projects with appropriate Unit Scope Names specified in the Project Options, and then don't use any Unit Scope names in your code.  That way, you have less IFDEF'ing to do.

6 hours ago, Girish Patil said:
  • Since the controls link to different frameworks and their respective units and since they need to be installed on the component palette, the unit that contains the control needs to be different for each framework (VCL, FMX).
  • And It’s organised in the following way currently:

Unit vclgtDocumentPrinter

{$Define gtVCL}

{$Include gtDocumentPrinter.inc} // this file has all the code

 

Unit FMX.gtDocumentPrinter

{$Define gtFMX}

{$Include gtDocumentPrinter.inc} // this file has all the code

Your common gtDocumentPrinter code should be in its own separate unit, not in an include file.

6 hours ago, Girish Patil said:

There’s one apparent issue with this way: code completion doesn’t work in the inc file.

All the more reason not to use an include file.

  • Like 2

Share this post


Link to post

The simplest solution is like ICS team did. Create usual VCL unit with some IFDEFs disabling unit-specific lines when UseFMX is defined and a thin wrapper for FMX that includes VCL unit like an inc

 

Share this post


Link to post

Thanks to all who replied. I was looking into the details, the code base side-by-side with the suggestions.

On 4/4/2020 at 7:15 AM, Remy Lebeau said:

Is your component visual (derived from TControl)?  Or is it non-visual (derived from TComponent)?  Non-visual components can be used in both VCL and FMX without splitting up the implementation (just
IFDEF the pieces you need).

I/we were aware of this and the unit scoping, and have gone this way with some components before, but it had started out being separate units so continued to go that way. And then again, I paused to see if there was a better way to go 🙂

 

We've gone with the separate packages, unit scoping, and same unit approach. Will need to do some package reorganization and some code reorganisation, but it will definitely make things cleaner. So, might as well do it! We will have dialogs for the components and that will be very platform specific and linking to the visual classes/units of the frameworks, but that can be separated out in one of the suggested ways. Thanks.

Edited by Girish Patil

Share this post


Link to post
On 4/4/2020 at 4:10 PM, Fr0sT.Brutal said:

The simplest solution is like ICS team did. Create usual VCL unit with some IFDEFs disabling unit-specific lines when UseFMX is defined and a thin wrapper for FMX that includes VCL unit like an inc

 

This is also useful. Thanks.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×