Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Компоненты";
Текущий архив: 2005.09.04;
Скачать: [xml.tar.bz2];

Вниз

Коллекции   Найти похожие ветки 

 
Navi   (2004-10-09 17:05) [0]

Здравствуйте!
Делаю компонент:

 Tbox = class(TGraphicControl)
 private
   FOnPaint: TNotifyEvent;
   FLayers: TLayersCollection;
   FCurLayer: TLayer;
   procedure SetLayers(const Value: TLayersCollection);
 protected
   procedure Paint; override;
 public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
   property CurLayer: TLayer read FCurLayer write FCurLayer;
 published
   property Layers: TLayersCollection read FLayers write SetLayers;
 end;

Где:
 TLayersCollection = class(TCollection);
 TLayer = class(TCollectionItem);

FCurLayer при создании должен указывать на самый первый элемент FLayers. Конструктор
делаю так:

constructor Tbox.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 ControlStyle:= ControlStyle + [csReplicatable];
 Width:= 105;
 Height:= 105;
 FLayers:= TLayersCollection.Create(Self);
 FCurLayer:= FLayers.Add;
end;

Но при использовании этого компонента обращение к св-ву CurLayer вызывает
Access Violation in user32.dll. Эффект не постоянный, отчего зависит не понял. Я
привел кусок не готового компонента. В готовом - 2 коллекции, реализация и
объявления абсолютно аналогичные. Access Violation всегда только при обращении
к CurLayer. Хелп читал (может криво), решения не нашел.

Помогите лечить.
Спасибо.


 
Гаврила ©   (2004-10-09 17:34) [1]

приведенной информации недостаточно для ответа.
Что из себя представляет  TLayer ?


 
Navi   (2004-10-09 17:36) [2]

TLayer = class(TCollectionItem)
 private
   FName: String;
   FVisible: Boolean;
   procedure SetName(const Value: String);
   procedure SetVisible(const Value: Boolean);
 public
   constructor Create(Collection: TCollection); override;
 published
   property Name: String read FName write SetName;
   property Visible: Boolean read FVisible write SetVisible default True;
 end;

{ TLayer }

constructor TLayer.Create(Collection: TCollection);
begin
 inherited;
 FName:= "0";
 FVisible:= True;
end;

procedure TLayer.SetName(const Value: String);
begin
 if FName <> Value then
 begin
   FName:= Value;
   Changed(False);
 end;
end;

procedure TLayer.SetVisible(const Value: Boolean);
begin
 if FVisible <> Value then
 begin
   FVisible:= Value;
   Changed(False);
 end;
end;


 
Семен Сорокин ©   (2004-10-09 17:46) [3]

нехватает еще описания TLayersCollection.

ЗЫ. что происходит в процедуре
procedure SetLayers(const Value: TLayersCollection);

-уничтожается ли старый TLayersCollection
-переопределяется ли FCurLayer на новый элемент
-существует ли элемент TLayer у Value


 
Гарвила   (2004-10-09 17:48) [4]

Нет тут никакого криминала, по карйней мере не вижу
значит ошибка в другом месте


 
Navi   (2004-10-09 18:23) [5]

TLayersCollection = class(TCollection)
 private
   FPage: Tbox;
   FOnItemChange: TItemChangeEvent;
 protected
   function GetItem(Index: Integer): TLayer;
   procedure SetItem(Index: Integer; const Value: TLayer);
   function GetOwner: TPersistent; override;
   procedure Update(Item: TCollectionItem); override;
   procedure DoItemChange(Item: TCollectionItem); dynamic;
 public
   constructor Create(APage: Tbox);
   function Add: TLayer;
   property Items[Index: Integer]: TLayer read GetItem write SetItem; default;
 published
   property OnItemChange: TItemChangeEvent read FOnItemChange write FOnItemChange;
 end;

{ TLayerCollection }

function TLayersCollection.Add: TLayer;
begin
 Result:= TLayer(inherited Add);
end;

constructor TLayersCollection.Create(APage: Tbox);
begin
 inherited Create(TLayer);
 FPage:= APage;
end;

procedure TLayersCollection.DoItemChange(Item: TCollectionItem);
begin
 if Assigned(FOnItemChange) then FOnItemChange(Item);
end;

function TLayersCollection.GetItem(Index: Integer): TLayer;
begin
 Result:= TLayer(inherited GetItem(Index));
end;

function TLayersCollection.GetOwner: TPersistent;
begin
 Result:= FPage;
end;

procedure TLayersCollection.SetItem(Index: Integer; const Value: TLayer);
begin
 inherited SetItem(Index, Value);
end;

procedure TLayersCollection.Update(Item: TCollectionItem);
begin
 inherited Update(Item);
 DoItemChange(Item);
end;

procedure Tbox.SetLayers(const Value: TLayersCollection);
begin
 FLayers.Assign(Value);
end;

procedure Tbox.Paint;
begin
 Canvas.Font:= Font;
 Canvas.Brush.Color:= Color;
 if csDesigning in ComponentState then
   with Canvas do
   begin
     Pen.Style:= psDash;
     Brush.Style:= bsClear;
     Rectangle(0, 0, Width, Height);
   end;
 if Assigned(FOnPaint) then FOnPaint(Self);
end;

destructor Tbox.Destroy;
begin
 FLayers.Free;
 inherited Destroy;
end;


 
Navi   (2004-10-09 18:26) [6]

При создании формы хочу считать CurLayer.Name. Вот здеь и AV. Прохожу по F7 - на CurLayer Inaccessible Value.


 
Семен Сорокин ©   (2004-10-09 18:29) [7]


> procedure Tbox.SetLayers(const Value: TLayersCollection);
> begin
>  FLayers.Assign(Value);
> end;

вот после этого в CurLayer находится битая ссылка


 
Семен Сорокин ©   (2004-10-09 18:32) [8]


> Navi   (09.10.04 18:26) [6]
> При создании формы хочу считать CurLayer.Name. Вот здеь
> и AV. Прохожу по F7 - на CurLayer Inaccessible Value.

правильно а в Design-time был заведен хоть один элемент, если да, то см. [7]


 
Семен Сорокин ©   (2004-10-09 18:35) [9]

procedure TBox.SetLayers(const Value: TLayersCollection);
begin
if FLayers <> Value then begin
 FLayers.Assign(Value);
 if FLayers.Count = 0 then
  FCurLayer := FLayers.Add
 else
  FCurLayer := FLayers[0]
end
end;


ЗЫ. Ахтунг, псевдокод :)


 
Defunct ©   (2004-10-09 18:39) [10]

ошибка в программе.

нельзя же блин быть настолько недальновидным:

> обращение к св-ву CurLayer вызывает Access Violation in user32.dll.
> FCurLayer:= FLayers.Add;

> [3] нехватает еще описания TLayersCollection.

> [5]function TLayersCollection.Add: TLayer;
> begin
>   Result:= TLayer(inherited Add);
> end;

> [6] При создании формы хочу считать CurLayer.Name. Вот здеь и AV.

Теперь нехватает реализации TCollection.Add и реализации обработчика FormCreate.


 
Navi   (2004-10-09 18:50) [11]

procedure TForm1.FillcbLayer;
var
 i: Integer;
begin
 cbLayer.Items.Clear;  // cbLayer: TComboBox;
 for i:= 0 to box.Layers.Count - 1 do // box: Tbox;
 begin
   cbLayer.Items.AddObject(box.Layers.Items[i].Name,
                           TObject(box.Layers.Items[i].ID));
 end;
 i:= cbLayer.Items.IndexOf(box.CurLayer.Name);
 if i >= 0 then cbLayer.ItemIndex:= i else cbLayer.ItemIndex:= 0;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 FillcbLayer;
end;


 
Семен Сорокин ©   (2004-10-09 18:54) [12]

Navi   (09.10.04 18:50) [11]
даже вот так лучше будет:

procedure TBox.SetLayers(const Value: TLayersCollection);
var
 _ind: integer;
begin
 if FLayers <> Value then begin
  _ind := FCurLayer.Index;
  FLayers.Assign(Value);
  if _ind < FLayers.Count then
   FCurLayer := FLayers.Items[_ind]
  else if FLayers.Count = 0 then
   FCurLayer := FLayers.Add
  else
   FCurLayer := FLayers.Items[0]
 end
end;


 
Defunct ©   (2004-10-09 18:57) [13]

Так вот если вылетает в [11] на строчке:

> i:= cbLayer.Items.IndexOf(box.CurLayer.Name);

Это говорит о том, что Box.CurLayer = Nil.

Просмотрите все места, а их должно быть не так уж и много где изменяется CurLayer. Только просмотрите нормально, с учетом всех Inherited вызовов.


 
Defunct ©   (2004-10-09 19:04) [14]

IMHO сделайте лучше нормальный выбор текущего слоя по индексу как во всех списочных компонентах:

Tbox = class(TGraphicControl)
private
  FIndex : Integer; // Индекс текущего слоя
  ...
  Function GetCurrentLayer:TLayer;
 public
  property CurLayer: TLayer read GetCurrentLayer;
  ..
End;

 

Function TBox.GetCurrentLayer;
Begin
 If FIndex< Count Then Result := Collection.Items[FIndex]
                  Else Result := Nil;
End;


 
Navi   (2004-10-09 19:12) [15]

Defunct (09.10.04 18:57) [13]
Да нет совсем не Nil, а именно Inaccessible Value. Пробовал я в конструкторе TBox-а присваивать FCurLayer:= Nil. Тогда в
i:= cbLayer.Items.IndexOf(box.CurLayer.Name); (понятно почему) выскакивает AV, но уже не в user32.
Прошелся я по F7 до FillcbLayer не нашел. А CurLayer изменяется уже после первого вызова FillcbLayer.

Семен Сорокин ©   (09.10.04 18:54) [12] А какая разница в реализации SetLayers, если при FillcbLayer он не исп-ся, он же только на запись. И до первого применения FillcbLayer не вызывается.


 
Семен Сорокин ©   (2004-10-09 19:19) [16]


> Navi   (09.10.04 19:12) [15]
> А какая разница
> в реализации SetLayers, если при FillcbLayer он не исп-ся,
> он же только на запись. И до первого применения FillcbLayer
> не вызывается.

А вот здесь Вы не правы - он вызывается после чтения свойcтв из ресурсов dfm.


 
Navi   (2004-10-10 08:49) [17]

Делать как советует Defunct © (09.10.04 19:04) [14] я изначально не хотел, но если Мастер советует... Вобщем работает отлично. Попутно еще вопрос (может надо новую ветку делать, но вроде тема уже здесь разобрана). Вот в Navi (09.10.04 17:36) [2] конструктор TLayer дает имя слою "0". Так вот былобы идеально еслибы слой с именем 0 нельзя было удалить ни в инспекторе объектов ни програмно. Когда юзер грохает слой, я отслеживаю, чтобы не снес 0, а в инспекторе все удаляется легко. Как это сделать?
Спасибо.



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

Форум: "Компоненты";
Текущий архив: 2005.09.04;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.011 c
1-1123165458
VID
2005-08-04 18:24
2005.09.04
ДЛЯ ПРОФИ. OleContainer и его OleObject. У них недопонимание :)


1-1123944383
tazik
2005-08-13 18:46
2005.09.04
Как выделить слова из KAК-файла


3-1122436030
rentgen
2005-07-27 07:47
2005.09.04
Номер фильтрованное записи


1-1124171980
~ShamaN~
2005-08-16 09:59
2005.09.04
ComboBox


2-1123240002
Гость22
2005-08-05 15:06
2005.09.04
Как изменить имя проекта?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский