views:

91

answers:

2

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.

+1  A: 

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.

shunty
Se my edit addon. ClientData is a global reference to a singleton class. It should work but still refuse to
Roland Bengtsson
Ok. Have you tried assigning the event handler at runtime rather than design time? eg in the OnCreate of the form.I'm wondering if the design time issue is due to the somewhat 'unusual' design of the cxGrid. It's all a combination of a TcxGridSite and grid views etc etc so maybe the OnEnter method doesn't get seen as expected by the form. Could be wrong though...
shunty
Seems it probably isn't to do with the oddities of the cxGrid after all. In D2010 you can assign component references from other modules using the object inspector but you can't assign their methods/event handlers at design time - only run time. As far as I can tell.
shunty
+1  A: 

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.
François