Как уведомить контрол о событии?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Ответить
EatMyShorts
новенький
Сообщения: 30
Зарегистрирован: 06.10.2009 19:48:19

Как уведомить контрол о событии?

Сообщение EatMyShorts »

Доброго времени суток.
Есть 2 формы, на 1ой Grid, а на 2ой edit. Как сообщить edit'у что произошло событие OnCellClick на первой форме?
Приходит на ум сделать так:

Код: Выделить всё

unit unit1;//содержит Form1

uses unit2;//содержит Form2

....................

procedure Form1.GridCellClick(cell: TCell);// знаю что не так, прсто для примера  :)
begin
  Form2.edit.Text := Grid.Cell.Text;
end;



Или можно как-то по красивее?
Аватара пользователя
VirtUX
энтузиаст
Сообщения: 880
Зарегистрирован: 05.02.2008 09:52:19
Откуда: Крым, Алушта

Сообщение VirtUX »

А что конкретно нужно передать в Edit.Text из Grid?
EatMyShorts
новенький
Сообщения: 30
Зарегистрирован: 06.10.2009 19:48:19

Сообщение EatMyShorts »

А что конкретно нужно передать в Edit.Text из Grid?

Да
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

EatMyShorts писал(а):Или можно как-то по красивее?

"Покрасивей" - это как? :)
Что-нибудь типа:
Я целлку щёлкнул у Grid'ы,
Мой Drag'n'Drop туды-сюды,
Со вздохом ей присовкупил,
Edit'ы текст. Потом свалил...

;)
EatMyShorts
новенький
Сообщения: 30
Зарегистрирован: 06.10.2009 19:48:19

Сообщение EatMyShorts »

"Покрасивей" - это как? :)
Что-нибудь типа:

Я целлку щёлкнул у Grid'ы,
Мой Drag'n'Drop туды-сюды,
Со вздохом ей присовкупил,
Edit'ы текст. Потом свалил...

Ну покрасивей это в unit2 где находится edit отреагировать на событие которое произошло на первой форме.
v-t-l
энтузиаст
Сообщения: 744
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Сообщение v-t-l »

Это как? Создать процедуру обработки в модуле unit2, потом присвоить ее событию компонента в модуле unit1? :shock:
Врядли это будет покрасивее :D
yuray
новенький
Сообщения: 95
Зарегистрирован: 22.05.2008 14:19:19
Откуда: Ровно, Украина

Сообщение yuray »

Вопрос очень интересный и актуальный. Однозначно писать вот такой код нельзя - нарушается инкапсуляция.

Код: Выделить всё

procedure Form1.GridCellClick(cell: TCell);// знаю что не так, прсто для примера  :) 
begin
  Form2.edit.Text := Grid.Cell.Text;
end;

Способов, как минимум, есть 2.
Первый, который напрашивается, это послать контролу соответствующее сообщение. Пример можно посмотреть в папке %LAZARUS%\examples\messages\.
Наведу пример касательно вопроса.
На форму Form1кладем StringGrid1 и кнопку BitBtn1. По кнопке будем вызывать Form2, на которой расположен Edit1.
При клике по гриде в Form2.Edit1.text будем отображать количество кликов.

Собственно код

Form1

Код: Выделить всё

unit Unit1; 

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  Grids, Buttons, StdCtrls, LCLIntf;

type

  { TForm1 }

  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    StringGrid1: TStringGrid;
    procedure BitBtn1Click(Sender: TObject);
    procedure StringGrid1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  Unit2;

{ TForm1 }

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  Form2.Show;
end;

procedure TForm1.StringGrid1Click(Sender: TObject);
begin
  PostMessage(Form2.Handle, WM_GRIDCLICK, 1, 0);
end;

initialization
  {$I unit1.lrs}

end.


Form2

unit Unit2;

Код: Выделить всё

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  StdCtrls, windows;

const
  WM_GRIDCLICK = WM_USER + 244;

type

  { TForm2 }

  TForm2 = class(TForm)
    Edit1: TEdit;
  private
    { private declarations }
    procedure WMGridClick(var Message:TMessage); message WM_GRIDCLICK;

  public
    { public declarations }
  end;

var
  Form2: TForm2;

implementation

{ TForm2 }

procedure TForm2.WMGridClick(var Message: TMessage);
begin
  Edit1.Text := inttostr(StrToIntDef(Edit1.Text, 0)+Message.WParam);
end;

initialization
  {$I unit2.lrs}

end.


Эстетам объектно-ориентированного программирования этот способ кажется некрасивым. Поэтому, можно обойтись и без сообщений. Тогда нужно использовать свойство процедурного типа. Если кому интересно, могу навести пример и этого способа.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

yuray
yuray писал(а):...нарушается инкапсуляция.

А Ваш код нарушает кроссплатформенность. ;)
yuray
новенький
Сообщения: 95
Зарегистрирован: 22.05.2008 14:19:19
Откуда: Ровно, Украина

Сообщение yuray »

Vadim писал(а):А Ваш код нарушает кроссплатформенность. ;)

Опс... Извините, исправляюсь

Form1

Код: Выделить всё

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  Grids, Buttons, StdCtrls, LCLIntf;

type

  { TForm1 }

  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    StringGrid1: TStringGrid;
    procedure BitBtn1Click(Sender: TObject);
    procedure StringGrid1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  Unit2;

{ TForm1 }

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  Form2.Show;
end;

procedure TForm1.StringGrid1Click(Sender: TObject);
begin
  PostMessage(Form2.Handle, WM_GRIDCLICK, 1, 0);
end;

initialization
  {$I unit1.lrs}

end.


Form2

Код: Выделить всё

unit Unit2; 

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  StdCtrls, LMessages;

const
  WM_GRIDCLICK = LM_USER + 244;

type

  { TForm2 }

  TForm2 = class(TForm)
    Edit1: TEdit;
  private
    { private declarations }
    procedure WMGridClick(var Message:TLMessage); message WM_GRIDCLICK;
  public
    { public declarations }
  end;

var
  Form2: TForm2;

implementation

{ TForm2 }

procedure TForm2.WMGridClick(var Message: TLMessage);
begin
  Edit1.Text := IntToStr(StrToIntDef(Edit1.Text, 0)+Message.WParam);
end;

initialization
  {$I unit2.lrs}

end.
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

EatMyShorts писал(а):Доброго времени суток.
Есть 2 формы, на 1ой Grid, а на 2ой edit. Как сообщить edit'у что произошло событие OnCellClick на первой форме?
Приходит на ум сделать так:
Или можно как-то по красивее?


достаточно красиво? =)

Код: Выделить всё

unit unit1;

uses
  ... unit2;

procedure TForm1.OnCellClick(Sender: TObject;ACol, ARow: integer);
begin
  form2.CellClicked( Sender as TStringGrid, ACol, Arow );
end;

----
unit unit1;

type
  TForm2 = class(TForm)
    edit1 : TEdit;
  pulbic
    procedure CellClicked(AGrid: TStringGrid; ACol, ARow: Integer);
  end;

procedure TForm2.CellClicked(AGrid: TStringGrid; ACol, ARow: Integer);
begin
  edit1.Text :=  AGrid.Cells[ACol, ARow];
end;


можно сделать наоборот, что у form1 дополнительное событие, который вызывается при нажатии на ячейку.
Но так или иначе, хотя бы один из модулей должен знать о другом. Взаимознание совсем не обязательно.
Ответить