Reputation: 5148
I want to standardize the behaviour on an Devexpress TcxGrid. So I have a unit ClientData with a event:
procedure TClientData.grdOnEnter(Sender: TObject);
begin
mnuCxGridStandardMenu.Grid := TcxGrid(Sender);
end;
If I try to use that event from a TcxGrid.OnEnter event in another unit it refuse to work. If I paste in ClientData.grdOnEnter then a dialog says it is not an valid identifier.
Is it possible to share an event for several units in Delphi 2007 ?
EDIT: The ClientData is a datamodule that is created at startup and freed at applications exit. The reference is in a global var ClientData. So I think it should work to reference it from another unit.
Upvotes: 0
Views: 877
Reputation: 21640
Yes it should work if you assign the event handler through code.
If your event handler does not use anything from the ClientData instance (recommended), you don't even need to create an instance.
A nil variable of type TClientData is enough.
In the sample app below, the ClientData module is not auto-created by the dpr and remains nil. That does not prevent the event handler to work correctly.
the dpr
program Project2;
uses
Forms,
Unit10 in 'Unit10.pas' {Form10},
Unit11 in 'Unit11.pas' {ClientData: TDataModule};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm10, Form10);
Application.Run;
end.
the Form dfm
object Form10: TForm10
Left = 0
Top = 0
Caption = 'Form10'
ClientHeight = 282
ClientWidth = 418
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 168
Top = 168
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
end
the Form pas
unit Unit10;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Unit11, StdCtrls;
type
TForm10 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form10: TForm10;
implementation
{$R *.dfm}
procedure TForm10.Button1Click(Sender: TObject);
begin
if ClientData = nil then
ShowMessage('ClientData is nil')
else
ShowMessage('ClientData is NOT nil');
end;
procedure TForm10.FormCreate(Sender: TObject);
begin
OnClick := ClientData.WhateverEvent;
end;
end.
the DataModule dfm
object ClientData: TClientData
OldCreateOrder = False
Height = 150
Width = 215
end
the DataModule pas
unit Unit11;
interface
uses
SysUtils, Classes, Windows;
type
TClientData = class(TDataModule)
procedure WhateverEvent(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
ClientData: TClientData;
implementation
{$R *.dfm}
procedure TClientData.WhateverEvent(Sender: TObject);
begin
MessageBox(0, PChar('Sender is ' + Sender.ClassName), 'Test', MB_ICONINFORMATION or MB_OK);
end;
end.
Upvotes: 1
Reputation: 3758
You can do it, so long as your form unit has the ClientData unit in its uses clause and a properly instantiated TClientData object exists and is accessible. (Don't get confused between the class definition and the object of that class type). Then, for example, you could add something like this to the OnCreate handler:
// Optional - ClientData may be a 'global' object so won't need creating.
// FClientData could be a form member ora more globally accessible variable.
//FClientData := TClientData.Create(Self);
// or
//FClientData := TClientData.Create(Application);
cxGrid1.OnEnter := FClientData.grdOnEnter;
If the [F]ClientData object is destroyed before your form then you'll get an access violation when something tries to enter the OnEnter method.
Upvotes: 1