Autor Beitrag
lilalaunebaer
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 08.09.06 20:23 
Hallo!
Ich habe zu meiner Fragestellung schon 6 Beiträge gefunden, aber in keinem ist eine eindeutige Lösung hervorgetreten, und sie sind alle älter als 7 Monate .. daher stelle ich hier "erneut" mein Problem vor:

Ich leite aus einer CustomListBox eine neue Listbox ab, und ich möchte die Einträge selber zeichnen.
Dazu verwende ich (pro Listeneintrag) eine Klasse FraktalGraphic, die ich von TGraphicControl abgeleitet habe und die mir irgend ein Bild berechnet, das ich dann mit in den Listeneintrag zeichnen möchte, nebst anderem Kram.

Wenn ich nun die Komponente installiere (Registermethode habe ich ausgeblendet), und auf meinem Formular
platziere, geschieht noch nichts besonderes. wenn ich dann einfach die Anwendung schliesse (also nie UpdateContent aufgerufen wurde), stürzt das Programm ab mit der Meldung "Element <Name der FLB-Kompo> hat kein übergeordnetes Fenster". Wenn ich nen Breakpoint bei Destroy setze, und mir "Count" anzeigen lassen will, zeigt der Hint mir keine Zahl sondern die Exception "EInvalidOperation" an, und wenn ich weiter will kommt eben obige
Fehlermeldung.
Wie kann man das beseitigen?
Also viele sagen, mann muss der ListBox nen Parent geben, aber die IDE macht das doch automatisch, wenn ich
die Kompo auf nem Formular platziere. Auch die angebliche Lösung mit "CreateWND" habe ich nicht nachvollziehen können; ich will ja nicht einmal in der Create-Methode etwas zeichnen, sondern erst später, wenn zur Laufzeit
per Methode "setPositionSet" auch was zum zeichnen da ist .. aber der absturz ist ja da, obwohl kar keine Items in der Liste sind.
Wenn ich die Box einfach platziere, und per Button1Click irgendwelche Items einfüge, so entstehen diese auch brav in der Box. Doch wenn ich dann das Programm beende gibt'S wieder die gleiche Meldung.

Hier ist der ganze Code:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
unit UFractalListBox;
interface
uses ..;

type TFractalListBox = class(TCustomListBox)
  private
    fColor:TColor;
    fPS:TPositionSet;
    fGraphicBorder:Integer;
    fFile: String;
    procedure setGraphicBorder(const Value: Integer);
    procedure setPositionSet(const Value: TPositionSet);
    procedure UpdateContent;

  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); override;
    procedure MeasureItem(Index: Integer; var Height: Integer); override;
    procedure Clear; override;

    property PositionFile:String read fFile;
    //property Canvas; //braucht man das?

  published
    property PositionSet:TPositionSet read fPS write setPositionSet;
    property GraphicBorder:Integer read fGraphicBorder write setGraphicBorder;
    property ItemHeight;
    property OnClick;
    property OnDblClick;
    property OnDrawItem;
end;


implementation

{ TFraktalListBox }

procedure TFractalListBox.Clear;
var x:Integer;
begin
  for x := 0 to Count-1 do begin
     Items.Objects[x].Free;
  end;
  inherited;
end;

constructor TFractalListBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Style := lbOwnerDrawVariable;
  MultiSelect := false;
  fGraphicBorder := 1;
  fPS := TPositionSet.Create;
  fFile := '';
end;

destructor TFractalListBox.Destroy;
var x:Integer;
begin
  for x := 0 to Count-1 do begin
     Items.Objects[x].Free;
  end;
  fPS.Free;
  inherited;
end;

procedure TFractalListBox.DrawItem(Index: Integer; Rect: TRect;
  State: TOwnerDrawState);
begin
  inherited;
  Canvas.FillRect(Rect);
  //if Items.Objects[Index] <> nil then
  //  ShowMessage('DrawItem:'+IntToStr(Index)) else ShowMessage('Object '+IntToStr(Index)+' ist nil.');
  Canvas.Draw(Rect.Left+fGraphicBorder,Rect.Top+fGraphicBorder,TFractalGraphic(Items.Objects[Index]).AsBitmap);
  Canvas.TextOut(ItemHeight+2*fGraphicBorder,Round(0.5*ItemHeight),Items[Index]);
end;

procedure TFractalListBox.MeasureItem(Index: Integer; var Height: Integer);
begin
  inherited;
  if Assigned(Items.Objects[Index]) then begin
    TFractalGraphic(Items.Objects[Index]).SetSize(Height,Height);
    TFractalGraphic(Items.Objects[Index]).Render;
  end;  
end;

procedure TFractalListBox.setGraphicBorder(const Value: Integer);
begin
  if Value <= ItemHeight then begin
    fGraphicBorder := Value;
    Refresh;
  end;
end;

procedure TFractalListBox.setPositionSet(const Value: TPositionSet);
begin
  fPS := Value;
  UpdateContent;
end;

procedure TFractalListBox.UpdateContent;
var x:Integer; fg:TFractalGraphic;
begin
  Clear;
  for x := 0 to fPS.Count do begin
    fg := TFractalGraphic.Create(Parent);
    fg.SetSize(ItemHeight-2*fGraphicBorder,ItemHeight-2*fGraphicBorder);
    fg.Parent := Parent;
    fg.Position := fPS.Positions[x];
    fg.Render;
    Items.AddObject(ComplexToStr(fPS.Positions[x].Von),fg);
  end;
end;

end.


Ich bin dankbar für jeden guten Hinweis / Lösungsvorschlag!
lilalaunebaer
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 08.09.06 20:44 
Titel: Mögliche Antwort:
In meinem Fall habe ich eine Lösung gefunden, die mir jetzt auch einleuchtet:
In der Methode "Destroy" habe ich versucht, manuell die "Items" wegzuwerfen; dies scheint aber
schon vorher zu geschehen..wenn ich die entsprechenden Zeilen einfach streiche, kommt kein fehler mehr ..
aber trotzdem interessiert es mich noch, was man machen könnte, wenn man bereits beim erzeugen listeneinträge abbilden möchte.