-
Привет всем. Хотел написать небольшой компонент, основанный на объектах (надо для практики), но есть трабла. Помогите пожалуйста. Если я чего не понял, прошу не ругать :) Я начинающий. В целом компонент такого вида:
PMyObj = ^TPMyObj; TOnMyObjEvent = procedure(Sender: PMyObj) of object; TMyObj = object( TObj ) ... (тут всякие свойства...) destructor Destroy; virtual; end;
PMainComp = ^TMainComp; TMainComp = object(TObj) private FOnUpdate: TOnMyObjEvent; ... public property OnUpdate: TOnMyObjEvent read FOnUpdate write FOnUpdate; end; Есть некоторая процедура внутри TMainComp, которая создаёт и формирует экземпляр TMyObj (при помощи New(MyObj, Create), MyObj - PMyObj), а затем вызывает метод OnUpdate(MyObj), внутри которого идёт обращение к свойствам объекта. Как вы уже, наверное, догадались, я успешно получаю обухом по голове :) а почему, понять не в состоянии. Может, от того, что целый день парюсь, но дела не меняются - внутри метода стоит только обратиться к любому свойству MyObj, как прога вылетает. Почему?
-
Код присваивания обработчика событию, и код вызова - не приведены. (Наверняка опять различие ординарной процедуры и метода объекта, но не на 100% - здесь-то оно зачем. А может вы просто Sender и Self перепутали. Без кода непонятно).
-
Ну вот как-то так: type
PMyObj = ^TMyObj;
TOnMyEvent = procedure(Sender: PMyObj) of object;
TMyObj = object( TObj )
Name: string;
private
FOnUpdate: TOnMyEvent;
procedure SetOnUpdate(const Value: TOnMyEvent);
public
destructor Destroy; virtual;
property OnUpdate: TOnMyEvent read FOnUpdate write SetOnUpdate;
end;
PMyComp = ^TMyComp;
TMyComp = object(TObj)
protected
private
FOnUpdate: TOnMyEvent;
procedure SetOnUpdate(const Value: TOnMyEvent);
public
FMyObj: PMyObj;
destructor Destroy; virtual;
property OnUpdate: TOnMyEvent read FOnUpdate write SetOnUpdate;
procedure Go;
end;
function NewMyComp: PMyComp;
implementation
function NewMyComp: PMyComp;
begin
New(Result, Create);
New(Result.FMyObj, Create);
Result.FMyObj.Name := 'MyComp Name';
end;
procedure TMyObj.SetOnUpdate(const Value: TOnMyEvent);
begin
FOnUpdate := Value;
end;
procedure TMyComp.Go;
begin
Self.FMyObj.OnUpdate := Self.FOnUpdate;
if Assigned(Self.FMyObj.OnUpdate) then
Self.FMyObj.OnUpdate(@Self.FMyObj);
end;
procedure TMyComp.SetOnUpdate(const Value: TOnMyEvent);
begin
FOnUpdate := Value;
end;
end. Далее в программе: procedure OnUpdate(Sender: PMyObj);
begin
ShowMessage(Sender.Name);
end;
procedure TForm1.Button1Click(Sender: PObj);
var
MyComp: PMyComp;
begin
MyComp := NewMyComp;
MyComp.OnUpdate := TOnMyEvent(MakeMethod(nil, @OnUpdate) );
MyComp.Go;
MyComp.Free;
end;
-
Это только пример, я специально наваял, но принцип того, что хочу сделать, видно.
-
У меня вот так заработало. А почему, сами разбирайтесь, либо пусть кто другой объяснит. Я в теории - не очень. program project1;
uses KOL;
type
PMyObj = ^TMyObj;
TOnMyEvent = procedure(Sender: PMyObj) of object;
TMyObj = object( TObj )
Name: string;
private
FOnUpdate: TOnMyEvent;
procedure SetOnUpdate(const Value: TOnMyEvent);
public
property OnUpdate: TOnMyEvent read FOnUpdate write SetOnUpdate;
end;
PMyComp = ^TMyComp;
TMyComp = object(TObj)
protected
private
FOnUpdate: TOnMyEvent;
procedure SetOnUpdate(const Value: TOnMyEvent);
public
FMyObj: PMyObj;
property OnUpdate: TOnMyEvent read FOnUpdate write SetOnUpdate;
procedure Go;
end;
function NewMyComp: PMyComp;
begin
New(Result, Create);
New(Result.FMyObj, Create);
Result.Add2AutoFree(Result.FMyObj);
Result.FMyObj.Name := 'MyComp Name';
end;
procedure TMyObj.SetOnUpdate(const Value: TOnMyEvent);
begin
FOnUpdate := Value;
end;
procedure TMyComp.Go;
begin
Self.FMyObj.OnUpdate := Self.FOnUpdate;
if Assigned(Self.FMyObj.OnUpdate) then
Self.FMyObj.OnUpdate(Self.FMyObj);
end;
procedure TMyComp.SetOnUpdate(const Value: TOnMyEvent);
begin
FOnUpdate := Value;
end;
procedure OnUpdate(Dummy, Sender: PMyObj);
begin
ShowMessage(Sender.Name);
end;
procedure Button1Click(Dummy, Sender: PObj);
var
MyComp: PMyComp;
begin
MyComp := NewMyComp;
MyComp.OnUpdate := TOnMyEvent(MakeMethod(nil, @OnUpdate) );
MyComp.Go;
MyComp.Free;
end;
var form, btn: PControl;
begin
form := newform(nil, 'test');
btn := newbutton(form,'click').ResizeParent;
btn.OnClick := TOnEvent(MakeMethod(nil, @Button1Click));
run(Form);
end.
-
Это именно то, что я и подозревал как №1. procedure OnUpdate(Dummy, Sender: PMyObj);
Как я в описании Соль заметил, выросло поколение (хороших, но неграмотных) программеров, которых инфиксная запись и отсутствия явной передачи параметра-объекта сбивает с толку. Не пишут параметр, значит его как бы и нет.
-
Спасибо всем, я понял в чём дело :)
|