Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to improve the use of Delphi Frames

I've used frames in Delphi for years, and they are one of the most powerful features of the VCL, but standard use of them seems to have some risk such as:

  1. It's easy to accidentally move or edit the frame sub-components on a frame's host form without realising that you are 'tweaking' with the frame - I know this does not affect the original frame code, but it's generally not what you would want.

  2. When working with the frame you are still exposed to its sub-components for visual editing, even when that frame is years old and should not be touched.

So I got to thinking....

  1. Is there a way of 'grouping' components such that their positions are 'locked'? This would be useful for finished forms as well as frames. Often other developers return code to me where only the form bounds have changed and even they did not intend any change.

  2. Is there any way of turning a frame and its components into a single Delphi component? If so, the frame internals would be completely hidden and its useability would increase further.

I'm interested in any thoughts...

Brian.

like image 708
Brian Frost Avatar asked Apr 29 '10 07:04

Brian Frost


3 Answers

Registering your frames as a component solves both 1. and 2.:

  1. the components on the frame are locked when you put that frame control on a form or other frame
  2. you will get a component (actually: control) that you can design visually

But: there are a few catches (which can be solved, see article link), of which the most important is this one:

When you put components on your frame, and later drop that frame as a component on a Delphi form or frame, the components are visible in the Structure Pane.

The problem is that because they are visible in the structure pane, you can delete them, causing access violations.

The trick to solve this to not forget the 'sprig'.
I learned that valuable lesson from Ray Konopka during DelphiLive 2009.

Since the lesson is so valuable, I wrote a blog post on it that describes it in detail.

The essential portion is this little piece of code (more details in the blog post):

procedure RegisterFramesAsComponents(const Page: string; const FrameClasses: array of TFrameClass);
var
  FrameClass: TFrameClass;
begin
  for FrameClass in FrameClasses do
  begin
    RegisterComponents(Page, [FrameClass]);
    RegisterSprigType(FrameClass, TComponentSprig);
  end;
end;

Hope this helps.

--jeroen

like image 96
Jeroen Wiert Pluimers Avatar answered Oct 21 '22 04:10

Jeroen Wiert Pluimers


Yes, just register them as components. :-)

Design your frame normally and after this register it. Also be sure to not have unwanted dependencies on different units since these are linked when your 'component' is used. Also you can add published properties in order to use them in the Object Inspector later. See for example the following code generated by the IDE (see also my comments):

unit myUnit;

uses
 ...

type
  TmyComp = class(TFrame) //set your frame name to be the name your component 
    ToolBar1: TToolBar; //different components added in the form designer
    aliMain: TActionList;
    ...
  published //this section is added by hand
    property DataSource: TDataSource read FDataSource write SetDataSource; //some published properties added just for exemplification
    property DefFields: string read FDefFields write SetDefFields;
    ...
  end;


procedure Register; //added by hand

implementation

{$R *.DFM}

procedure Register;
begin
  RegisterComponents('MyFrames', [TmyComp]); //register the frame in the desired component category
end;

Compile the above in a package of your choice, install it and check you component palette. :-)

HTH

like image 42
John Thomas Avatar answered Oct 21 '22 04:10

John Thomas


I'm almost always creating frame instances in code. This is easy and worked well for me so far.

like image 8
Uli Gerhardt Avatar answered Oct 21 '22 04:10

Uli Gerhardt