Newsgroups : Borland : borland.public.delphi.nativeapi.win32 : 2007 Jun : Delphi 7 Component Editor Woes...
| Subject: | Delphi 7 Component Editor Woes... |
| Posted by: | "Welton" (welton at labdaq dot com) |
| Date: | Wed, 20 Jun 2007 16:44:23 |
I'm not sure if this is the right forum for this message, but the
borland.public.delphi.vcl.components.writing forum seems to be gone.
Apologies for the cross posting. I initially posted this in the general
forum, but was instructed that post it here.
I am attempting to write a component (TRuleDomains, a component that has a
list of TRuleDomain components, created using the component editor) and an
associated component editor (TRuleDomainsComponentEditor). I have the
basics for my component in place, and I have created the component editor.
I can drop my component on a form, double click the form and it displays my
editor. I can click the Add button on my component editor form, and the new
TRuleDomain items are created. I can see them listed in the form's class
definition. However, after I use the editor to add items (TRuleDomain) to
my component, something BAD happens to Delphi. If I click the File/Close
All menu, it closes the form designer, but does not close the associated
.pas file or the component editor form. If I try again to close the .pas
file, Delphi gives me --"Field Form1.RuleDomains1 does not have a
corresponding component. Remove the declaration?" errors for each of the
components (TRuleDomains and TRuleDomain) that I have created. After that,
Delphi will abruptly unload itself from memory. Delphi just disappears. I
have included my aapRuleDomains.pas, aapRuleDomainsComponentEditorFrm.pas
and .dfm below. Can anyone please show me where I am going off the rails?
I've been Googling and reviewing examples of component editors, as well as
looking at some comercial property editors in third party code that we have
licensed, and from what I can see I my code matches the stuff I've been
looking. I've been going around in circles for three days now.
After playing around with this a little more, I have a little better
idea of what is happening. I create a new application, drop my TRuleDomains
component onto the form creating RuleDomains1, and then double click my
RuleDomains1 component and the component editor is displayed. When I click
the Add button in the RuleDomains component editor, it creates a new
TRuleDomain component, by calling TRuleDomain.Create(RuleDomains1.Owner),
thereby assigning the owner of RuleDomains1 to the new TRuleDomain instance.
At this point I can see the new TRuleDomain component listed in the form's
component declaration section (above the private declaration section.) If I
view the form's .dfm, I can see the TRuleDomains definition as well as the
TRuleDomain definition, however, when if this form is saved, and I view the
.dfm, the TRuleDomains definition is there, but not the TRuleDomain
definition. In short, it appears that any TRuleDomain component that is
created by the component editor doesn't really get added to the .dfm file.
What can I do to make sure the both the .pas and .dfm files are correctly
updated when I create a new component through a component editor?
Any help would be greatly appreciated.
TIA,
Welton
-------------------------------------------------------------------------
unit aapRuleDomains;
interface
uses
SysUtils, Classes, DesignEditors;
type
TDomainDataFormat = (ddfString, ddfInteger, ddfBoolean, ddfDateTime,
ddfList, ddfNameValue);
TAllowedOperator = (acEqual, acNotEqual, acBetween, acNotBetween, acOneOf,
acNotOneOf);
TAllowedOperators = set of TAllowedOperator;
TRuleDomain = class(TComponent)
private
fFieldName: string;
fDomainDataFormat: TDomainDataFormat;
fAllowedOperators: TAllowedOperators;
fDefinition: string;
procedure SetDomainDataFormat(const Value: TDomainDataFormat);
procedure SetFieldName(const Value: string);
procedure SetAllowedOperators(const Value: TAllowedOperators);
procedure SetDefinition(const Value: string);
public
procedure Assign(aSource: TPersistent); override;
published
property DomainDataFormat: TDomainDataFormat read fDomainDataFormat
write SetDomainDataFormat;
property FieldName: string read fFieldName write SetFieldName;
property Definition: string read fDefinition write SetDefinition;
property AllowedOperator: TAllowedOperators read fAllowedOperators write
SetAllowedOperators;
end;
TRuleDomains = class(TComponent)
private
fItems: TList;
function GetCount: integer;
function GetItems(Index: integer): TRuleDomain;
procedure SetItems(Index: integer; const Value: TRuleDomain);
protected
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
function AddItem: TRuleDomain;
procedure DeleteItem(Index: integer);
property Items[Index: integer]: TRuleDomain read GetItems write
SetItems;
property Count: integer read GetCount;
end;
TRuleDomainsComponentEditor = class(TComponentEditor)
public
procedure ExecuteVerb(Index: integer); override;
function GetVerb(Index: integer): string; override;
function GetVerbCount: integer; override;
end;
procedure Register;
implementation
uses
DesignIntf,
aapRuleDomainsComponentEditorFrm;
procedure Register;
begin
RegisterComponents('Antek', [TRuleDomains]);
RegisterNoIcon([TRuleDomain]);
RegisterComponentEditor(TRuleDomains, TRuleDomainsComponentEditor);
end;
{ TRuleDomains }
function TRuleDomains.AddItem: TRuleDomain;
begin
result := TRuleDomain.Create(Self.Owner);
fItems.Add(result);
end;
constructor TRuleDomains.Create(aOwner: TComponent);
begin
inherited;
fItems := TList.Create;
end;
procedure TRuleDomains.DeleteItem(Index: integer);
begin
fItems.Delete(Index);
end;
destructor TRuleDomains.Destroy;
begin
while Count > 0 do
Items[Count - 1].Free;
FItems.Free;
FItems := nil;
inherited;
end;
function TRuleDomains.GetCount: integer;
begin
result := fItems.Count;
end;
function TRuleDomains.GetItems(Index: integer): TRuleDomain;
begin
result := TRuleDomain(fItems[Index]);
end;
procedure TRuleDomains.SetItems(Index: integer; const Value: TRuleDomain);
begin
fItems[Index] := Value;
end;
{ TRuleDomainsComponentEditor }
procedure TRuleDomainsComponentEditor.ExecuteVerb(Index: integer);
begin
case Index of
0: ShowRuleDomainsComponentEditorForm(Designer,
TRuleDomains(Component));
else
inherited;
end;
end;
function TRuleDomainsComponentEditor.GetVerb(Index: integer): string;
begin
case Index of
0: result := 'Edit...';
1: result := '-';
end;
end;
function TRuleDomainsComponentEditor.GetVerbCount: integer;
begin
result := 1;
end;
{ TRuleDomain }
procedure TRuleDomain.Assign(aSource: TPersistent);
begin
inherited Assign(aSource);
end;
procedure TRuleDomain.SetAllowedOperators(const Value: TAllowedOperators);
begin
fAllowedOperators := Value;
end;
procedure TRuleDomain.SetDefinition(const Value: string);
begin
fDefinition := Value;
end;
procedure TRuleDomain.SetDomainDataFormat(const Value: TDomainDataFormat);
begin
fDomainDataFormat := Value;
end;
procedure TRuleDomain.SetFieldName(const Value: string);
begin
fFieldName := Value;
end;
end.
-------------------------------------------------------------------------
unit aapRuleDomainsComponentEditorFrm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, DesignWindows, DesignIntf,
aapRuleDomains;
type
TfrmRuleDomainsEditor = class(TDesignWindow)
pnlButtons: TPanel;
lbRuleDomains: TListBox;
btnAdd: TButton;
btnDelete: TButton;
btnClose: TButton;
procedure btnCloseClick(Sender: TObject);
procedure btnAddClick(Sender: TObject);
procedure lbRuleDomainsClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
fDesigner: IDesigner;
fRuleDomains: TRuleDomains;
public
end;
procedure ShowRuleDomainsComponentEditorForm(aDesigner: IDesigner;
aRuleDomains: TRuleDomains);
implementation
{$R *.dfm}
procedure ShowRuleDomainsComponentEditorForm(aDesigner: IDesigner;
aRuleDomains: TRuleDomains);
var
i: integer;
vForm: TfrmRuleDomainsEditor;
vItem: TRuleDomain;
begin
vForm := TfrmRuleDomainsEditor.Create(Application);
vForm.fDesigner := aDesigner;
vForm.fRuleDomains := aRuleDomains;
for i := 0 to vForm.fRuleDomains.Count - 1 do
begin
vItem := vForm.fRuleDomains.Items[i];
vForm.lbRuleDomains.Items.AddObject(vItem.Name, vItem);
end;
vForm.Show;
end;
procedure TfrmRuleDomainsEditor.btnCloseClick(Sender: TObject);
begin
Close;
end;
procedure TfrmRuleDomainsEditor.btnAddClick(Sender: TObject);
var
vItem: TRuleDomain;
begin
vItem := fRuleDomains.AddItem;
vItem.Name := fDesigner.UniqueName('RuleDomain');
lbRuleDomains.Items.AddObject(vItem.Name, vItem);
fDesigner.Modified;
end;
procedure TfrmRuleDomainsEditor.lbRuleDomainsClick(Sender: TObject);
var
i: integer;
begin
for i := 0 to lbRuleDomains.Count - 1 do
begin
if lbRuleDomains.Items[i] <>
TRuleDomain(lbRuleDomains.Items.Objects[i]).Name then
lbRuleDomains.Items[i] :=
TRuleDomain(lbRuleDomains.Items.Objects[i]).Name;
if lbRuleDomains.Selected[i] then
fDesigner.SelectComponent(TPersistent(lbRuleDomains.Items.Objects[i]));
end;
end;
procedure TfrmRuleDomainsEditor.FormClose(Sender: TObject; var Action:
TCloseAction);
begin
Action := caFree;
end;
end.
-------------------------------------------------------------------------
object frmRuleDomainsEditor: TfrmRuleDomainsEditor
Left = 349
Top = 144
Width = 272
Height = 369
Caption = 'Rule Domains Editor'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnClose = FormClose
PixelsPerInch = 96
TextHeight = 13
object pnlButtons: TPanel
Left = 176
Top = 0
Width = 88
Height = 335
Align = alRight
TabOrder = 0
DesignSize = (
88
335)
object btnAdd: TButton
Left = 8
Top = 8
Width = 75
Height = 25
Caption = '&Add'
TabOrder = 0
OnClick = btnAddClick
end
object btnDelete: TButton
Left = 8
Top = 40
Width = 75
Height = 25
Caption = '&Delete'
TabOrder = 1
end
object btnClose: TButton
Left = 8
Top = 303
Width = 75
Height = 25
Anchors = [akLeft, akBottom]
Caption = '&Close'
TabOrder = 2
OnClick = btnCloseClick
end
end
object lbRuleDomains: TListBox
Left = 0
Top = 0
Width = 176
Height = 335
Align = alClient
ItemHeight = 13
TabOrder = 1
OnClick = lbRuleDomainsClick
end
end