Problem z jednym komponentem (TFont=Access Violation)

0

czesc!
na wstepie przepraszam, jesli to pytanie nadaje sie do newbie, ale ostatecznie chyba nie pytam o jakies totalne podstawy...

mam problem z jednym komponentem: SevenButton (http://www.torry.net/authorsmore.php?id=7384).
to jest button z wygladem z windows7.
ma mozliwosc zmiany czcionki w zaleznosci od jego stanu (hot, down, disabled, focused).
problem polega na tym, ze w momencie gdy zmieniam jedna z tych czcionek w object inspectorze - delphi sie wysypuje z bledem access violation w rtl70.bpl i trzeba ubijac proces delphi bo nastepuje milion bledow av.

co moze byc przyczyna takiego zachowania?
jakies pomysly, co powinienem sprawdzic?

nie jestem najlepszy w pisaniu komponentow ale pamietam ze kiedys mialem podobne problemy podczas pisania pierwszego wlasnego komponentu, niestety nie pamietam juz co bylo przyczyna i jak sie jej pozbylem.

dodam jeszcze ze z ciekawosci zmienilem czniocnki w onCreate formy - wtdy przy zamykaniu programu wywalilo wyjatek w destruktorze komponentu przy zwalnianiu czcionki: FFontHot.Free;

dziki z gory za pomoc

0

Skoro Delphi siada, to przeanalizuj wszystkie właściwości "properties" komponentu.
Myślę, że same procedury i funkcje możesz nie sprawdzać na początek.

1

to nigdy nie miało prawa działać - jakaś ciućma bez podstaw o komponentach to pisała.

wszystkie właściwości, które są typu klasowego musisz przerobić tak

zamiast

property FontFocused: TFont read FFontFocused write FFontFocused;

dajesz

 property FontFocused: TFont read FFontFocused write SetFontFocused;

a metoda SetFontFocused musi wyglądać tak

procedure xxx.SetFontFocused(Value: TFont);
begin
  FFocusedFont.Assign(Value);
end; 

Jest tak ponieważ delphi w momencie edycji właściwości tworzy jej kopię, zmieniasz tą kopię i jeśli zatwierdzisz zmiany to kopia jest podstawiana pod właściwość. Jeśli właściwość jest obiektem to po podstawieniu kopia zostaje zniszczona. Jeśli właściwość wygląda tak jak tu to tak naprawdę tracisz wskaźnik do obiektu stworzonego w konstruktorze, a dostajesz tam wskaźnik na coś, co jest chwilę później niszczone.

Na dobrą sprawę tutaj też powinno być inaczej

property Border: TSevenButtonBorder read FBorder write FBorder;
property Colors: TSevenButtonColors read FColors write FColors;
property Fonts: TSevenButtonFonts read FText write FText;
property Pictures: TSevenButtonPictures read FPictures write FPictures;

i dodatkowo każda z tych klas powinna pokryć metodę AssignTo

0

Dziekuje Misiekd! Jestes wielki! :)
i dziekuje za wyjasnienie reakcji zachodzacych w kodzie.
nie rozumiem tylko "dodatkowo każda z tych klas powinna pokryć metodę AssignTo", o co dokladnie chodzi?

0

FFocusedFont.Assign(Value); wywołuje tak naprawdę metodę AssignTo obiektu Value

procedure TPersistent.Assign(Source: TPersistent);
begin
  if Source <> nil then Source.AssignTo(Self) else AssignError(nil);
end;

Metoda AssignTo ma za zadanie skopiować właściwości Value do FFocusedFont - coś na kształt
Self.Name := Value.Name;
Self.Size := Value.Size;

w uproszczeniu można porównać klasę TPersistent i jej metodę Assign do konstruktora kopiującego z c++.

nie rozumiem tylko "dodatkowo każda z tych klas powinna pokryć metodę AssignTo", o co dokladnie chodzi?

Ponieważ te dodatkowe klasy nie posiadają właściwości o typach prostych i nie mają edytorów właściwości to tak naprawdę w OI nie zmieniasz Border, Colors, Fonts czy Pictures tylko to co one tam mają dalej. Dlatego tutaj nic się nie sypie i nie masz AV. Jeśli jednak chciałbyś napisać edytor właściwości dla np. TSevenButtonFonts, który by Ci pozwolił zmienić wszystkie fonty w jednym okienku to wtedy bez nadpisania AssignTo (ew. Assign) Ci to nie zadziała - zmienisz w edytorze kopię "roboczą" klasy, ale nie będziesz miał kodu, który "przekopiuje" wartości właściwości z obiektu roboczego do docelowego.

0

nastala jasnosc. dziekuje:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1