Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.07.08;
Скачать: CL | DM;

Вниз

Форма + интерфейс   Найти похожие ветки 

 
kull ©   (2002-06-26 10:45) [0]

Вот такой интересный вопросик: Как форму наследовать от интерфейса?

Так?

IMyForm = interface
...
end;

TForm1 = class(TForm, IMyForm)
...
end;

var
itf : IMyForm;

begin
itf := TForm1.Create(Application);
itf := nil;
end;

Что то здесь не так, когда делаю itf := nil - форма остается.


 
Polevi ©   (2002-06-26 10:57) [1]

а что с ней должно произойти по твоему
обнулил ты указатель и что ?


 
kull ©   (2002-06-26 11:10) [2]

Так, если бы я сделал так:

type
IMyObject = interface
...
end;

TMyObject = class(TInterfacedObject,IMyObject)
end;

var
itf : IMyObject;

begin
itf := TMyObject.Create;
itf := nil;
end;

экземпляр класса TMyObject бы уничтожился.

Я понимаю что форма это не TInterfacedObject, но как можно это реализовать?


 
Skier ©   (2002-06-26 11:52) [3]

> kull
"Что то здесь не так, когда делаю itf := nil - форма остается"

А с чего ты взял что она остаётся ???


 
kull ©   (2002-06-26 12:14) [4]


> А с чего ты взял что она остаётся ???

Ну я же вижу ее на экране!


 
Игорь Шевченко ©   (2002-06-26 12:20) [5]

kull © (26.06.02 12:14)

А кнопки меню Debug и View CPU из клавиатуры выломаны, что ими нельзя воспользоваться ? :-))

http://www.tuxedo.org/~esr/faqs/smart-questions.html



 
Skier ©   (2002-06-26 12:25) [6]

> kull
Из твоего кода следует, что ты её вообще не показываешь

itf := TForm1.Create(Application);
itf := nil;

Тогда давай уж код целиком.


 
kull ©   (2002-06-26 12:32) [7]


> Из твоего кода следует, что ты её вообще не показываешь


ничего не следует.
Я в Object inspector-e ставлю Visible у формы в True.

А вот весь код:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
IMyForm = interface
end;

TForm1 = class(TForm,IMyForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
itf: IMyForm;
begin
itf := TForm1.Create(Application);
itf := nil;
end;





> Игорь Шевченко © (26.06.02 12:20)


Мне кажется Debuger здесь ни причем.
Вопрос в консепте...


 
Бурундук   (2002-06-26 12:33) [8]

2kull
зануление ссылки приводит к уничтожению объекта, если такое поведение определено в _Release. Для TInterfacedObject это так.
А для формы - нет.

function TComponent._Release: Integer;
begin
if FVCLComObject = nil then
Result := -1 // -1 indicates no reference counting is taking place
else
Result := IVCLComObject(FVCLComObject)._Release;
end;


 
Fiend ©   (2002-06-26 12:35) [9]

люди гляньте внимательнее!!!
он же просто обнуляет указатель а не вызывает деструктор объекта!
В твоём случае ничего не уничтожается!!!
А объект как бы уничтожился, потому что ты потерял указатель на него, поэтому больше обратиться к нему не можешь,но есть в памяти твоего процесса.
Потому то и форма видна, что она не уничтожена, а просто на нее потерян указатель


 
Skier ©   (2002-06-26 12:35) [10]

> kull

Мда. Учится и ещё раз учиться...



 
Бурундук   (2002-06-26 12:41) [11]

Fiend ©
Врачу, исцелися сам (в смысле гляди внимательней)

У него всё-так не указатель, а интерфейсная ссылка, и обычно её зануления достаточно для уничтожения объекта.


 
Игорь Шевченко ©   (2002-06-26 12:44) [12]

Fiend © (26.06.02 12:35)

C интерфейсами все не так


 
kull ©   (2002-06-26 12:49) [13]

2Бурундук

А как можно сделать такую штуку, то есть правильно переписать _Release?

И шо це таке - IVCLComObject?


 
Skier ©   (2002-06-26 13:00) [14]

> kull

Лови :
Только поправь GUID


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
IMyForm = interface
["{A24918B1-88D7-11D6-B3DB-000102AD844C}"]
procedure Show;
end;

TForm1 = class(TForm,IMyForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
protected
FRefCount: Integer;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
itf: IMyForm;
begin
itf := TForm1.Create(Application);
itf.Show;
itf := nil;
end;


function TForm1._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount);
end;

function TForm1._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result = 0 then Destroy;
end;


end.


 
kull ©   (2002-06-26 13:06) [15]


> Skier © (26.06.02 13:00)

Спасибо это я уже попробовал.
Но если itf сделать членом класса TForm1 и убрать
itf := nil , после закрытия приложения Access Violation.

Здесь мне кажется есть тонкости, ведь форму можно и ручками закрыть, а ссылочка на интерфейс то останется.


 
Skier ©   (2002-06-26 13:10) [16]

> kull
Давай-ка конкретней расскажи чего ты хотишь сделать ?
А то трудно советовать.

Или приведи код где происходит AV и чего ты хочешь
от этого кода добиться.


 
Бурундук   (2002-06-26 13:13) [17]

2 kull ©
Дело в том, что при закрытии приложения itf выходит из зоны видимости и освобождается. А форма к тому времени уже уничтожена, и вызывается _Release уничтоженной формы. Отсюда AV.

Поэтому не рекомендуется смешивать обычные ссылки на объекты и интерфейсные ссыли. А избавиться от обычной ссылки на форму вряд ли удастся, по крайней мере в Screen она пропишется.





 
kull ©   (2002-06-26 13:17) [18]

AV я так думаю происходит из-за того, что при закрытии главной формы все остальные уже закрыты.
А при уничтожении ссылки на интерфейс происходит попытка еще раз закрыть форму отсюда и AV.
На конкретную строчку AV не показывает.




 
Skier ©   (2002-06-26 13:25) [19]

> kull
А как ты форму закрываешь ?
caFree что ли ставишь в обработчике OnClose ??


 
kull ©   (2002-06-26 13:37) [20]

Нет ничего не ставлю:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
IMyForm = interface
end;

TForm1 = class(TForm,IMyForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
FRefCount: Integer;
itf: IMyForm;
protected
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
itf := TForm1.Create(Application);
end;

function TForm1._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount);
end;

function TForm1._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result = 0 then Destroy;
end;

end.


 
vuk ©   (2002-06-27 01:11) [21]

Когда Вы работаете с объектами, реализующими интерфейсы и в то же время являющимися компонентами VCL, Вы должны определиться с тем, кто и как будет управлять временем жизни объекта.
В VCL, как известно временем жизни объекта управляет его владелец, а в интерфейсной модели - сам объект посредством счетчика ссылок (если этот подсчет реализован). Если попытаться смешать эти два подхода, то как раз и возникают различные конфликты. Поэтому, как уже зметили выше эти модели лучше не смешивать.
Тем не менее необходимость такая зачастую возникает и делать это можно, но нужно это делать осторожно(есть ряд тонкостей). В таком случае лучше будет полагаться не на интерфейсные ссылки, а на стандартную работу с объектами в VCL. Собственно говоря по-умолчанию все так и происходит. Поэтому и не реализован подсчет ссылок в TComponent и его наследниках.




Страницы: 1 вся ветка

Текущий архив: 2002.07.08;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.014 c
3-23442
фл
2002-06-14 11:28
2002.07.08
local SQL запрос: выбрать 5 максимальных


3-23489
Oleon
2002-06-17 10:39
2002.07.08
Interbase 5.0.


14-23766
Val
2002-06-07 13:25
2002.07.08
ваши мысли по поводу?


8-23690
Spirit
2002-02-28 09:14
2002.07.08
Как сделать пазл из картинки?


1-23552
.: Joiro :.
2002-06-24 22:51
2002.07.08
Точный таймер.