Указатель на форму
Подскажите пожалуйста, как мне работать с экземпляром конкретной формы в классе, где о ней ничего не известно. Необходимо получить содержимое текстового поля этой формы, например Edit1. Передаю допустим так:
procedure TForm1.MyProc();
begin
NextProc(self);
end;
А в процедуре NextProc()? Как получить? Как обрабатывать?
procedure NextProc(Sender: TObject);
begin
(Sender as TForm).Top := 100;
(Sender as TForm).Caption := 'Эта форма приехала к нам из MyProc()';
end;
Очевидно, NextProc() выглядеть должен так:
procedure NextProc(Sender: TObject);
begin
(Sender as TForm).Top := 100;
(Sender as TForm).Caption := 'Эта форма приехала к нам из MyProc()';
end;
Sender: TObject - не прокатит видимо, потому как sender будет в данном случае иметь только общие свойства и методы класса TForm, а мне надо конкретное поле конкретного экземпляра:( Здесь похоже только с указателями, только вот как?
Sender: TObject - не прокатит видимо, потому как sender будет в данном случае иметь только общие свойства и методы класса TForm, а мне надо конкретное поле конкретного экземпляра:( Здесь похоже только с указателями, только вот как?
Ты бы попробовал для начала...
В данном случае Sender как раз и есть конкретный экземпляр (объект).
Sender: TObject - не прокатит видимо, потому как sender будет в данном случае иметь только общие свойства и методы класса TForm
Для начала нужно знать, видно ли из Nextproc() класс формы. Если видно, то использовать операторы приведения типов: as или TYourForm(Sender). Но прежде чем приводить типы, естественно нужно проверить, принадлежит ли Sender к нужному классу, - оператор is.
Ты бы попробовал для начала...
В данном случае Sender как раз и есть конкретный экземпляр (объект).
Попробовал. Похоже не надо было упрощать ситуацию... Сейчас попробую описать, как у меня все обстоит на самом деле...
Ты прав, конечно, Sender здесь тот самый экземпляр, но мне не нужен Tform. Нужна ссылка на объект класса TForm1. Она передается процедуре NextProc(), которая реально находится в отдельном классе. Таким образом описание класса TForm1 находится в модуле формы Form1 и класс о TForm1 не знает. Значит, я не могу сделать так:
procedure NextProc(Sender: TForm1);
begin
Sender.Edit1 := '1';
end;
Не могу, так как TForm1 здесь, в классе не виден.
Приведенная мною выше упрощенная процедура
procedure TForm1.MyProc(); в моей реальной программе создает экземпляр класса и вызывает его метод NextProc(), передавая ему ссылку на форму. Вот :-)
Если я сделаю вот так:
procedure NextProc(Sender: TForm);
begin
Sender.Edit1 := '1';
end;
то поле Edit1 видно не будет, так как, насколько я понимаю Sender приводится к базовому объекту TForm. Так? Компилятор выдает ошибку:)
А каков выход?
Описывать класс в модуле формы?
Для начала нужно знать, видно ли из Nextproc() класс формы. Если видно, то использовать операторы приведения типов: as или TYourForm(Sender). Но прежде чем приводить типы, естественно нужно проверить, принадлежит ли Sender к нужному классу, - оператор is.
Нет, не видно класс формы. Если я пытаюсь присоединить к классу ссылочку на форму:
uses Form1,
то delphi не дает мне этого сделать, так как в той же форме есть ссылка на данный класс. Выдается сообщение об ошибке:(
Вот форма и класс.
//Моя форма
unit FormEditRecord;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, CApplication, CDataBase, CFormsValidator, CFormEditValidator;
type
TfrmEditRecord = class(TForm)
//Описываем компоненты
//-------------
//То самое текстовое поле:
txtEdit1: TEdit;
procedure mmnuEditRecord_File_SaveClick(Sender: TObject);
private { Private declarations }
public { Public declarations }
end;
var
frmEditRecord: TfrmEditRecord;
ocFormEditValidator :clsFormEditValidator;
implementation
{$R *.dfm}
procedure mmnuEditRecord_File_SaveClick(Sender: TObject)
begin
//Инициализируем класс проверки полей для формы FormEditValidator
ocFormEditValidator := clsFormEditValidator.Create();
{! -- Вот здесь отсылаем ссылку на форму. Sender в данном случае ссылка на экземпляр формы}
ocFormEditValidator.ValidateF(Sender);
ocFormEditValidator.Free();
end;
end.
//Мой класс
unit CFormEditValidator;
interface
uses
Windows, Messages, SysUtils, Dialogs, CFormsValidator;
//Вот здесь не получается добавить ссылку на форму FormEditRecord:
//[Fatal Error] FormEditRecord.pas(9): Circular unit reference to 'FormEditRecord'
type
clsFormEditValidator = class(TObject)
protected {}
public
constructor Create();
procedure ValidateF(mSender :TForm);
end;
implementation
procedure clsFormEditValidator.ValidateF(mSender :TForm);//Тот самый NextProc()
begin
//mSender.txtEdit1.Text - тексовое поле не доступно,
//а (mSender as TfrmEditRecord).txtEdit1.Text не сработает, так как
//описание TfrmEditRecord не доступно здесь.
end;
end.
Вывод: попытаться описать класс в модуле формы FormEditRecord, или можно как-то иначе?
Так тогда тебе надо передавать в NextProc() не форму, а нужный контрол этой формы. Или я опять что-то не понял?
Контролов на форме много. Я хотел получать их содержимое имея указатель на форму.
unit CFormEditValidator;
interface
uses
Windows, Messages, SysUtils, Dialogs;
type
clsFormEditValidator = class(TObject)
protected {}
public
constructor Create();
procedure ValidateF(mSender :TForm);
end;
implementation
[COLOR=red]uses CFormsValidator;[/COLOR] // ;)
procedure clsFormEditValidator.ValidateF(mSender :TForm);//Тот самый NextProc()
begin
//mSender.txtEdit1.Text - тексовое поле не доступно,
//а (mSender as TfrmEditRecord).txtEdit1.Text не сработает, так как
//описание TfrmEditRecord не доступно здесь.
end;
end.
Вывод: попытаться описать класс в модуле формы FormEditRecord, или можно как-то иначе?
Вобщем, стало немного понятнее, что тебе надо. Но что-то ты там понаворотил лишнего...
Вот я попытался даже сохранить твои имена, сделал четыре Edit'а с кнопкой и вот что получилось:
unit FormEditRecord;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, CFormEditValidator;
type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
mmnuEditRecord_File_Save: TButton;
procedure mmnuEditRecord_File_SaveClick(Sender: TObject);
private
ocFormEditValidator: clsFormEditValidator;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.mmnuEditRecord_File_SaveClick(Sender: TObject);
begin
Self.ocFormEditValidator := CFormEditValidator.clsFormEditValidator.Create;
Self.ocFormEditValidator.ValidateF(Self);
end;
end.
unit CFormEditValidator;
interface
uses Windows, Messages, SysUtils, Dialogs, Forms, StdCtrls;
type
clsFormEditValidator = class(TObject)
protected
public
constructor Create();
procedure ValidateF(mSender :TForm);
end;
implementation
{ clsFormEditValidator }
constructor clsFormEditValidator.Create;
begin
inherited;
end;
procedure clsFormEditValidator.ValidateF(mSender: TForm);
var n: Integer;
begin
for n:=0 to mSender.ControlCount-1 do
begin
if mSender.Controls[n].ClassName = 'TEdit' then
begin
showmessage('Контрол: '+ (mSender.Controls[n] as TEdit).Name + #10#13 +
'Типа: '+ (mSender.Controls[n] as TEdit).ClassName + #10#13 +
'Содержимое: "' + (mSender.Controls[n] as TEdit).Text + '"');
end;
end;
end;
end.
Думаю, дальше решишь, что со всем этим добром делать.
unit CFormEditValidator;
interface
uses
Windows, Messages, SysUtils, Dialogs;
type
clsFormEditValidator = class(TObject)
protected {}
public
constructor Create();
procedure ValidateF(mSender :TForm);
end;
implementation
[COLOR=red]uses CFormsValidator;[/COLOR] // ;)
procedure clsFormEditValidator.ValidateF(mSender :TForm);//Тот самый NextProc()
begin
//mSender.txtEdit1.Text - тексовое поле не доступно,
//а (mSender as TfrmEditRecord).txtEdit1.Text не сработает, так как
//описание TfrmEditRecord не доступно здесь.
end;
end.
Хмм, так оно работает:) А в чем разница?
Вобщем, стало немного понятнее, что тебе надо. Но что-то ты там понаворотил лишнего...
Вот я попытался даже сохранить твои имена, сделал четыре Edit'а с кнопкой и вот что получилось.
Просто здорово. Огромное спасибо:). То, что нужно!
Хмм, так оно работает:) А в чем разница?
Дык это ж матчасть :) Два модуля не могут ссылаться друг на друга в интерфейсном разделе (отсюда и ошибка: Circular unit reference to <unit>), а в разделе реализации - пожалуйста.
Способ mfender'а немного смущает наличием цикла по компонентам формы - ИМХО лишний он, хотя выбор остается за тобой.
Дык это ж матчасть :) Два модуля не могут ссылаться друг на друга в интерфейсном разделе (отсюда и ошибка: Circular unit reference to <unit>), а в разделе реализации - пожалуйста.
Способ mfender'а немного смущает наличием цикла по компонентам формы - ИМХО лишний он, хотя выбор остается за тобой.
Спасибо, все понятно:) В ближайшие выходные за доки;)
Способ mfender'а немного смущает наличием цикла по компонентам формы - ИМХО лишний он, хотя выбор остается за тобой.
Это я для наглядности, чтобы показать, что в переданном в метод стороннего объекта объект можно юзать вдоль и поперёк. Конечно, проще искать нужный контрол Find'ом. Но там тот же цикл...