Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Работа с компонентами [D5, WinME]


Gari ©   (2002-09-16 09:08:00) 

Доброе утро уважаемые господа. У меня вопрос такого порядка: помещаю компонент на форму (собственно созданный, компонент "А"), у которого одно из свойств имеет тип компонента "В". Помещаю на форму компонент "В", устаноавливаю в "А" свойство, ссылающееся на компонент "В". А вот далее вопрос, почему, и как устранить ошибку возникающую при удалении компонента "В" с формы(Ошибка доступ к переменной). Помогите если можете.


Andrey Shakula   (2002-09-16 13:51:00) [1]

Да незачто. А, я уже тебе примерчик накидал. Просто и красиво.


unit NewComponent;

interface

uses
Classes;

type
TNewComponent = class(TComponent)
private
{ Private declaration }
FComponent: TComponent;
procedure SetComponent(Value: TComponent);
protected
{ Protected declaration }
procedure Notification(AComponent: TComponent; Operation: TOperation);
override;
public
{ Public declaration }
published
{ Published declaration }
property Components: TComponent read FComponent write SetComponent;
end;

procedure Register;

implementation

procedure TNewComponent.SetComponent(Value: TComponent);
begin
if FComponent <> Value then
begin
if Assigned(FComponent) then
Self.RemoveFreeNotification(FComponent);
if Assigned(Value) then
Self.FreeNotification(Value);
FComponent := Value;
end;
end;

procedure TNewComponent.Notification(AComponent: TComponent; Operation: TOperation);
begin
if (Operation = opRemove) and (FComponent = AComponent) then
FComponent := nil;
inherited Notification(AComponent, Operation);
end;

procedure Register;
begin
RegisterComponents("Samples", [TNewComponent]);
end;

end.


Gari   (2002-09-16 13:17:00) [2]

все работает просто, класс. Это я сам немного ступил. Не там описал процедуру Notification. Огромное спасибо Andrey Shakula. Он мне очень помог. Видно мир не без добрых людей.


Gari   (2002-09-16 13:13:00) [3]

Исправил. Теперь свойство записать можно, но при удалении возникает таже ошибка. Андрей я перекрыл метод как ты написал (16.09.02 10:40). Подскажи если можешь. За ранее огромное спасибо.


Andrey Shakula   (2002-09-16 12:37:00) [4]

Sorry. Писал на скорую руку,

Procedure TТвойКомпонентА.SetB(Value: TComponent);
begin
if FB<> Value then
begin
if Assigned(FB) then
Self.RemoveFreeNotification(FB);
if Assigned(Value) then
Self.FreeNotification( Value);
FB := Value;
end;
end;

Но, если на одной форме оба компонента, то должно работать без всяких
if Assigned(FB) then
Self.RemoveFreeNotification(FB);
if Assigned(Value) then
Self.FreeNotification( Value);
нужно только Notification перекрыть.
Если не знаешь, как перекрывать, то пиши ответим.


Gari   (2002-09-16 11:19:00) [5]

Уважаемый Andrey Shakula, попробовал как вы написали, но увы теперья даже не могу записать свойство. Выдает туже ошибку, что и раньше при удалении (Access violetion at adress ....). Если есть еще мысле поделитесь пожалуйста, работа висит.


Gari   (2002-09-16 10:48:00) [6]

Огромно спасибо, учту и допишу.


Andrey Shakula   (2002-09-16 10:46:00) [7]

В догонку:
Писал, писал а главного и не написал.

Procedure TТвойКомпонентА.SetB(Value: TComponent);
begin
if FB<> Value then
begin
if Assigned(FB) then
Self.RemoveFreeNotification(FB);
if Assigned(Value) then
Self.FreeNotification(FB);
FB := Value;
end;
end;


Gari   (2002-09-16 10:44:00) [8]

За ранее огромное спасибо, попробую так как вы посоветовали.


Andrey Shakula   (2002-09-16 10:40:00) [9]

Думаю что проблема в этом.

Перекрой Notification.

procedure TТвойКомпонентА.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
case Operation of
opInsert:
begin
end;
opRemove:
begin
if (Self.B = AComponent) then
FB := nil;
end;
end;
end;
При условии что компонент A и B находятся на одной форме или одном дата модуле. Если на разных то установка свойства A.B
должна выглядеть примерно так

Procedure TТвойКомпонентА.SetB(Value: TComponent);
begin
if Assigned(FB) then
Self.RemoveFreeNotification(FB);
if Assigned(Value) then
Self.FreeNotification(FB);
end;


Gari   (2002-09-16 10:36:00) [10]

Уважаемый Anatoly Podgoretsky, а функция Get написаная Lord-ом Warlock-ом правильная или нет? Если нет то как правиль описать эту функцию. За ранее огромное спасибо.


Anatoly Podgoretsky   (2002-09-16 10:30:00) [11]

torba (16.09.02 10:25)
То что он написал, это в приципе ошибка, нельзя назначить nil, то что ты привел выше может быть и ошибой и нет, все будет зависить от компонента, например может происходить утечка памяти, пример

FB = xxx

затем

FB = yyy

xxx утеряно, ошибки такого рода потом будешь долго искать.
В варианте, который я предлагаю это может выглядеть так:

if Value = FB then Exit;
FB.Free;
FB: = value;

утечки нет, лишней инициализации нет, не в этом случае конечно, но никакие действия не производятся, если значение FB уже установлено.
Если же конечно FB ординарный тип, то все это можно опустить, но тогда и SetB не нужна.


Gari   (2002-09-16 10:09:00) [12]

По ходу нашего общения у меня возник еще вопрос. Как написал Lord Warlock, это стандартное определение процедур Get и Set, а вот как написал уважаемый Anatoly Podgoretsky, мне не совсем понятно как это спасет от возникновения ошибки. Если не трудно разясните пожалуйста.


Anatoly Podgoretsky   (2002-09-16 09:58:00) [13]

А вот так писать не надо, не удастся сделать Unassigned, правильнее писать по другому

function SetB(Value: TComp)
begin
if Value = FB theb Exit;
действия по инициализации или по удалению старого мусора
FB: = value;
end;


Lord Warlock   (2002-09-16 09:48:00) [14]

Исключительная ситуация вообще не должна возникать, но если очень хочется, то:

function SetB(Value: TComp)
begin
if Assigned(Value) then
FB:= value;
end;
function GetB
begin
result:= nil;
if Assigned(FB) then
result:=FB;
end;


но по моему этого совсем не нужно, да и не пишет никто так


Gari   (2002-09-16 09:38:00) [15]

После нажатия этих клавишь, сгенерится код (в смысле болванка), а что внутри. Как присваивать значения я знаю,(В функции
function SetB
begin
FB:= value;
end;
function GetB
begin
result:= FB;
end;
кажется так.
А как обработать исключительную ситуацию, или она при таком описании не возникает. Подскажи если знаешь.


Lord Warlock   (2002-09-16 09:29:00) [16]

Gari (16.09.02 09:24)
Используй вариант 1, а еще лучша напиши так:

property B: TComp read GetB write SetB

и жми Ctrl+Shift+C

Содержание этих процедур предельно простое, но позволяет избежать подобных ошибок. У меня есть компонент с таким свойством, все прекрасно удаляется. Если что не так, посмотри исходники любого компонента с подобным свойством


Gari   (2002-09-16 09:24:00) [17]

Извеняюсь, в смысле второй вареант. Не через процедуру вызываемую при изменении свойства.


Lord Warlock   (2002-09-16 09:22:00) [18]

Gari (16.09.02 09:15)

какой конкретно вариант, 1 или 2. Это большая разница


Gari   (2002-09-16 09:15:00) [19]

Описано через read write


Lord Warlock   (2002-09-16 09:14:00) [20]

Добрый день.

Как в компоненте А описано свойство В?

FB: TComp

property B: TComp read FB write SetB
или
property B: TComp read FB write FB
?


Наверх

Титульная страница Поиск, карта сайта Написать письмо