Pisanie komponentu

0

Jak poprawnie napisać komponent który podobnie jak w np. TImage w Object Inspectorze podaje się jakąś bitmape, bo po umieszczeniu w projekcie napisanego przeze mnie komponentu zaraz po wybraniu bitmapy pokazuje się błąd Access Violation .... [???]
Kod komponentu:

unit AnimeButton1;

interface

uses
  SysUtils, Classes, Messages, Controls, Graphics, ExtCtrls;

type
  TAnimeButton1 = class(TImage)
  private
    Timer: TTimer;
    FInterval: integer; //szybkość animacji
    FEnable: Boolean; //komponent aktywny
    {Obrazki do animacji}
    FImage0: TBitmap;
    FImage1: TBitmap;
    FImage2: TBitmap;
    FImage3: TBitmap;
    FImage4: TBitmap;
    FImage5: TBitmap;
    FImage6: TBitmap;

    Click: Boolean; //kierunek animacji
    Postep: Byte; //numer wyswietlanego obrazka

    FOnEnter, FOnLeave : TNotifyEvent;

    procedure SetInterval(AInterval: integer);
    procedure SetEnable(AEnable: Boolean);
    procedure SetImage0(AImage0: TBitmap);
  protected
    procedure OnTimer(Sender : TObject); virtual;
    {zdarzenie obsługujące Timer}
    procedure CMMouseEnter(var Msg: TMessage); message CM_MOUSEENTER;
    {zdarzenie wywoływane po najechaniu kursorem na objekt}
    procedure CMMouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
    {zdarzenie wywoływane po zjechaniu kursora z objektu}
  public
    constructor Create(AOwner : TComponent); override;
    destructor Destroy; override;
    procedure RefreshPaint;
  published
    property Interval : Integer
      read FInterval write SetInterval default 50;
    property Enable : Boolean
      read FEnable write SetEnable default True;
    {Obrazki do animacji}
    property Image0 : TBitmap
      read FImage0 write SetImage0;
    property Image1 : TBitmap
      read FImage1 write FImage1;
    property Image2 : TBitmap
      read FImage2 write FImage2;
    property Image3 : TBitmap
      read FImage3 write FImage3;
    property Image4 : TBitmap
      read FImage4 write FImage4;
    property Image5 : TBitmap
      read FImage5 write FImage5;
    property Image6 : TBitmap
      read FImage6 write FImage6;
    property OnMouseEnter : TNotifyEvent
      read FOnEnter write FOnEnter;
    property OnMouseLeave : TNotifyEvent
      read FOnLeave write FOnLeave;

    property Width default 70;
    property Height default 35;
  end;

procedure Register;

implementation

constructor TAnimeButton1.Create(AOwner : TComponent);
begin
  inherited;
  Image0 := TBitmap.Create;
  Image1 := TBitmap.Create;
  Image2 := TBitmap.Create;
  Image3 := TBitmap.Create;
  Image4 := TBitmap.Create;
  Image5 := TBitmap.Create;
  Image6 := TBitmap.Create;
  FInterval := 50;
  Timer := TTimer.Create(Self);
  Timer.Interval := FInterval;
  Timer.OnTimer := OnTimer;
  Timer.Enabled := False;
  Height := 35;
  Width := 70;
  FImage0 := TBitmap.Create;
  FImage1 := TBitmap.Create;
  FImage2 := TBitmap.Create;
  FImage3 := TBitmap.Create;
  FImage4 := TBitmap.Create;
  FImage5 := TBitmap.Create;
  FImage6 := TBitmap.Create;
  if FImage0 <> nil then Picture.Bitmap := FImage0;
  Click := false;
  Postep := 0;
  FEnable := true;
end;

destructor TAnimeButton1.Destroy;
begin
  inherited;
  FImage0.Free;
  FImage1.Free;
  FImage2.Free;
  FImage3.Free;
  FImage4.Free;
  FImage5.Free;
  FImage6.Free;
end;

procedure TAnimeButton1.RefreshPaint;
begin
  case Postep of
    0:  begin
          Picture.Bitmap:=FImage0;
          Timer.Enabled:=false;
          Click:=False;
          exit;
        end;
    1: Picture.Bitmap:=FImage1;
    2: Picture.Bitmap:=FImage2;
    3: Picture.Bitmap:=FImage3;
    4: Picture.Bitmap:=FImage4;
    5: Picture.Bitmap:=FImage5;
    6:  begin
          Picture.Bitmap:=FImage6;
          Timer.Enabled:=false;
          Click:=True;
          exit;
        end;
  end;
end;

procedure TAnimeButton1.OnTimer(Sender: TObject);
begin
  if Click then inc(postep) else dec(postep);
  case Postep of
    0:  begin
          Picture.Bitmap:=FImage0;
          Timer.Enabled:=false;
          Click:=False;
          exit;
        end;
    1: Picture.Bitmap:=FImage1;
    2: Picture.Bitmap:=FImage2;
    3: Picture.Bitmap:=FImage3;
    4: Picture.Bitmap:=FImage4;
    5: Picture.Bitmap:=FImage5;
    6:  begin
          Picture.Bitmap:=FImage6;
          Timer.Enabled:=false;
          Click:=True;
          exit;
        end;
  end;
end;

procedure TAnimeButton1.CMMouseEnter(var Msg: TMessage);
begin
  if csDesigning in ComponentState then
  begin
    Exit;
  end;
  if FEnable then
  begin
    Click := True;
    Timer.Enabled := True;
  end;
end;

procedure TAnimeButton1.CMMouseLeave(var Msg: TMessage);
begin
   if csDesigning in ComponentState then
  begin
    Exit;
  end;
  if FEnable then
  begin
    Click := False;
    Timer.Enabled := True;
  end;
end;

procedure TAnimeButton1.SetImage0(AImage0: TBitmap);
begin
  FImage0:=AImage0;
  Height:=AImage0.Height;
  Width:=AImage0.Width;
  Picture.Bitmap:=FImage0;
end;

procedure TAnimeButton1.SetEnable(AEnable: Boolean);
begin
  Timer.Enabled:=AEnable;
  FEnable:=AEnable;
  if not AEnable then
    Picture.Bitmap:=FImage0;
end;

procedure TAnimeButton1.SetInterval(AInterval: integer);
begin
  FInterval:=AInterval;
  Timer.Interval:=AInterval;
end;

procedure Register;
begin
  RegisterComponents('FFFelek', [TAnimeButton1]);
end;

end.

Tylko nie komentować tego bo dopiero ucze się pisania komponentów.

Nikt <ort>niewie </ort>o co chodzi czy nie chce się nikomu czytać tego kodu? :[

0
fffelek napisał(a)

Nikt niewie o co chodzi czy nie chce się nikomu czytać tego kodu? :[

szczerze ? to drugie raczej
// chyba wystarczyło pierwsze zdanie - już nie pamiętam i nie chce mi się szukać jak to mam zrobione ale zdaje się że musi być TPicture a nie TBitmap jeśli chcesz to na Inspectora dać

0

a mi sie wydaje ze zamiast:

Picture.Image := FImageX;

powinno byc cos w stylu

Picture.Image.Bitmap.Assign(FImageX);

ale głowy nie dam bo nie mam delphi przy sobie a az tak berdzo mi sie w kod nie chcialo zaglebiac :F

0

Niestety żadna z tych propozycji nic mi nie pomogła. Dalej komponent działa tak jak powinien przy dynamicznym utworzeniu go, a przy dodaniu go w czasie projektowania wywołuje błąd.

0
fffelek napisał(a)

Niestety żadna z tych propozycji nic mi nie pomogła. Dalej komponent działa tak jak powinien przy dynamicznym utworzeniu go, a przy dodaniu go w czasie projektowania wywołuje błąd.

Debuguj go i wtedy powiedz w którym momencie pojawia się AV.

0

Niemógł by ktoś skopiować tego kodu, zainstalować komponent u siebi, podać w object inspektorze jakiś obrazek i zobaczyć co się dzieje w tym po zrobieniu tego, bo chyba mnie nie rozumiecie zbyt dobrze.

0
fffelek napisał(a)

Niemógł by ktoś skopiować tego kodu, zainstalować komponent u siebi, podać w object inspektorze jakiś obrazek i zobaczyć co się dzieje w tym po zrobieniu tego, bo chyba mnie nie rozumiecie zbyt dobrze.

taaa, jasne, już my znamy te numery - a tam jest ukryte w kodzie format ce ... nie no żartuję ale nie chce mi się odpalać delphi specjalnie żeby zainstalować komponent żeby sprawdzić co jest be - i raczej nikomu się nie chce

tak lookając po raz drugi na kod widzę że przypisujesz bitmapę przez

property write Bitmapa;

nie można tak
więc po pierwsze primo ultimo
TBitmap zamieniasz na TPicture
po drugie primo ultimo
pod write podpinasz procedurę ustawiająca a nie od razu zmienną, czyli write SetBitmap1

procedure TwojaKlasa.SetBitmap1(Val: TPicture);
begin
  pierwszyPikczur.Assign(Val);
end;

nie możesz przypisać od razu Picture do Picture w stylu

pierwszyPikczur := Val; tak jak to robisz bo jako Val jest podawany chwilowo skontruowany objekt, który jest zaraz niszczony
przypisujesz wskaźnik tego elementu do wewnętrznej zmiennej, przez co to co utworzyłeś przez Create idzie w zapomnienie, a twoja zmienna dostaje wskaźnik czegoś co zostało od razu po przypisaniu skasowane, przez co dostajesz Access Violation próbując się do tego odwołać (prawdopodobnie już w Object Inspectorze)

czyli
a.Assign(b); jest dobre - kopiuje zawartość objektu
a := b; jest be - przypisuje tylko wskaźnik objektu, a staje się tylko "skrótem" do b

łapiesz, czaisz, jarzysz, kumasz ? to leć naprawiać komponent

0

Zrobiłem wszystko tak jak Adamo napisał i dalej to samo, od ******* <ort>błendów </ort>AV.

0

A spróbuj tak

FObrazek1, FObrazek2 FObrazek3, ...: TPicture;

property obrazek1: TPicture read FObrazek1 write SetPicture1;
property obrazek2: TPicture read FObrazek2 write SetPicture2;
property obrazek3: TPicture read FObrazek3 write SetPicture3;
...

oraz

constructor TKomponent.Create(...);
begin
  inherited Create(...);
  FObrazek1 := TPicture.Create;
  FObrazek2 := TPicture.Create;
  FObrazek3 := TPicture.Create;
  ...
end;

destructor TKomponent.Destroy;
begin
  FObrazek1.free;
  FObrazek2.free;
  FObrazek3.free;
  inherited Destroy;
end;

procedure TKomponent.SetPicture_i_(Value: TPicture);
begin
  a.Assign(Value);
end;
0

Jest już lepiej, ale pojawia się dalej jeden błąd.

0

jaki mianowicie

0
fffelek napisał(a)

Zrobiłem wszystko tak jak Adamo napisał i dalej to samo, od ******* <ort>błendów </ort>AV.

fffelek napisał(a)

Jest już lepiej, ale pojawia się dalej jeden błąd.

no to chyba jednak nie zrobiłeś tak jak pisałem skoro po zrobieniu tego co mówiłem dostałeś pełno błędów a jak ktoś inny napisał to samo tylko w postaci czystego kodu to nagle tylko jeden błąd :-| po prostu czekasz aż ktoś przepisze idealnie ten komponent od góry do dołu

0

Gość napisał to samo jednak z wyjątkiem jednego wyrzenia

inherited Create(...);

. A błąd to Access Violation at adress ... in module 'rtl70.dpl'. Read of adress ... (używam Delphi 7).

0

Jeśli nikt niewie co powoduje ten błąd, to może wie ktoś gdzie jest kod jekiegoś komponentu który ma własciwość TPicture w published?

0
fffelek napisał(a)

Jeśli nikt niewie co powoduje ten błąd, to może wie ktoś gdzie jest kod jekiegoś komponentu który ma własciwość TPicture w published?

mhm TImage :>

0

Ale mi jest potrzebny kod źródłowy a w mojej wersji Delphi go nie ma.

0
fffelek napisał(a)

Ale mi jest potrzebny kod źródłowy a w mojej wersji Delphi go nie ma.

wystarczy żebyś tylko dokładnie przeczytał wszystko co powyżej napisane, prosty komponent:

<font size="1">unit DwaPicture;

interface

uses Graphics, Classes, SysUtils, Controls, Messages, Windows;

type TDwaPicture = class(TGraphicControl)
Pic1, Pic2: TPicture;
private
procedure SetPic1(const Value: TPicture);
procedure SetPic2(const Value: TPicture);
procedure Paintink(var Msg: TMessage); message WM_PAINT;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Pikczur_pierwszy: TPicture read Pic1 write SetPic1;
property Pikczur_drugi: TPicture read Pic2 write SetPic2;
end;

procedure Register;

implementation

{ TDwaPicture }

constructor TDwaPicture.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Pic1 := TPicture.Create;
Pic2 := TPicture.Create;
end;

destructor TDwaPicture.Destroy;
begin
Pic1.Free;
Pic2.Free;
inherited;
end;

procedure TDwaPicture.Paintink(var Msg: TMessage);
begin
Canvas.Draw(0, 0, Pic1.Graphic);
end;

procedure TDwaPicture.SetPic1(const Value: TPicture);
begin
Pic1.Assign(Value);
end;

procedure TDwaPicture.SetPic2(const Value: TPicture);
begin
Pic2.Assign(Value);
end;

procedure Register;
begin
RegisterComponents('Samples', [TDwaPicture]);
end;

end.</span>

0

Wielkie dzięki [!!!] Zrobiłem ten komponent na podstawie TGraphicControl i wszystko działa.

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