Does that mean that I can't share a Form between delphi 2007 and 2009?
5 Answers
DoubleBuffered has been in TWinControl for some time now. The difference in Delphi 2009 is that it's published now. If you can live with only ignoring the errors (and not making the properties work instead), here is a possible solution:
unit Delphi2009Form;
interface
uses
Windows, Classes, SysUtils, Controls, Forms;
type
{$IFDEF VER200}
TDelphi2009Form = class(TForm);
{$ELSE}
TDelphi2009Form = class(TForm)
private
procedure ReaderError(Reader: TReader; const Message: string; var Handled: Boolean);
protected
procedure ReadState(Reader: TReader); override;
end;
TReaderErrorProc = procedure(const Message: string);
var
ReaderErrorProc: TReaderErrorProc = nil;
{$ENDIF}
implementation
{$IFNDEF VER200}
type
THackReader = class(TReader);
procedure TDelphi2009Form.ReaderError(Reader: TReader; const Message: string; var Handled: Boolean);
begin
with THackReader(Reader) do
Handled := AnsiSameText(PropName, 'DoubleBuffered') or AnsiSameText(PropName, 'ParentDoubleBuffered');
if Handled and Assigned(ReaderErrorProc) then
ReaderErrorProc(Message);
end;
procedure TDelphi2009Form.ReadState(Reader: TReader);
begin
Reader.OnError := ReaderError;
inherited ReadState(Reader);
end;
{$ENDIF}
end.
Then change the declarations of the forms in your project to inherit from TDelphi2009Form, e.g.:
type
TFormMain = class(TDelphi2009Form)
...
This will work at runtime - the property errors will be ignored. To make it work at design time, too, create a design-only package, add designide.dcp to its requires clause, and add the following unit to it:
unit Delphi2009FormReg;
interface
uses
Delphi2009Form;
procedure Register;
implementation
uses
DesignIntf, DesignEditors, ToolsAPI;
procedure ShowReaderError(const Message: string);
begin
with BorlandIDEServices as IOTAMessageServices do
AddTitleMessage(Message);
end;
procedure Register;
begin
RegisterCustomModule(TDelphi2009Form, TCustomModule);
ReaderErrorProc := ShowReaderError;
end;
initialization
finalization
ReaderErrorProc := nil;
end.
Install the package in Delphi 2007 IDE and property errors for DoubleBuffered and ParentDoubleBuffered properties will be ignored automatically when opening your forms in the IDE. The values of the properties will be lost when you save the form in Delphi 2007 so you should initialize them in code instead.
EDIT: I've added code to output the reader error messages to the IDE Messages window:
Delphi projects have always been extremely easy to port forward to new versions. You have to be more careful, but using current code with older compilers is pretty straight forward, too. I maintained code in Delphi 2005/2006/2007 that other people still needed to use in Delphi 6 and 7.
If you remove the incompatible properties from the DFMs, they should work properly in older versions without messing them up for Delphi 2009. The biggest example is the explicit* properties introduced in Delphi 2006. I have a home brewed "DFM scrubber" that strips these out. Remember, these properties exist for a reason, so you should only scrub ones that you intend to be backward compatible.
You might also consider investing in static code analysis tools like CodeHealer or Pascal Analyzer. On top of pointing out problems (especially CodeHealer) and helping you clean up your code, you can choose which version of Delphi to analyze against, making it easier to find incompatibilities aside from DFM properties. And they can be automated as part of your build process.
Just a note. Share the source code, but keep separate projects for each version. This is especially important between Delphi 2007 and Delphi 2009. The more recent .dproj file uses the same extension, but isn't compatible with Delphi 2007. You could run in to some problame with incompatible resources, too.
Each form has a dfm file which contains the property settings of the form and its components. Some property values have defaults so they are not stored if the default value is kept. Is just did a small test:
- Create a form in 2009
- Add a couple of standard controls
- Save it
- Open it in 2006 (sorry no 2007 on this pc)
And it worked without messages. But maybe you are not so lucky.
With Delphi, it is often a bit troublesome to share data between versions. Upgrading posibilities are great, but downgrading is troublesome. So I advise against sharing form files between different versions.
As far as I know, it is not possible to add conditional defines in the dfm file. But then again, do we really want that... I would prefer a mechanism that ignores unknown properties.
You can safely add the properties in code in your OnCreate method for the form, and wrap an {$IFDEF VER200} // NEW PROPERTIES {$ENDIF} around them. You can leave DoubleBuffered outside the ifdefs, as it was present in Delphi 2007, just not available to the property inspector.
You will ONLY have to worry about the properties which you set different from the default. For doublebuffered, you only need to worry about this if it is set to true.
When loading the Delphi 2009 form in Delphi 2007, you will get a warning that a property is going to get destroyed, just make note of those properties, as those are the ones that you will need to deal with.
I am using just such a method to migrate my code to Delphi 2009 from Delphi 2006. Most of my projects contain several shared units and must compile in Delphi 2006 for the shipping version and Delphi 2009 for the "next" release. I also make lots of use of the {$IFDEF UNICODE} define where I need to insure a string is widestring, or ansistring depending on the routine.