Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Problem mit Treeview, CustomDrawItem


Gausi - Mo 10.05.04 13:03
Titel: Problem mit Treeview, CustomDrawItem
Ich habe eine Treeview mit Knoten auf verschiedenen Leveln. Level 0 sind Termine, Level1 sind Personen, die diesen Terminen zugeordnet sind.
Die Termin-Objekte verwalte ich in einer TObjectlist. Es ist immer sichergestellt, dass der i-te Level-0-Knoten dem i-ten Termin in der Objectlist entspricht. Die Liste ist nach Datum sortiert, und wenn ich ein Datum eines Termins ändere, verschiebe ich auch den Knoten in der Treeview entsprechend:


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:
Procedure TTermin.Datumchange;
[...]
    tmptermin:=terminliste[Form1.Treeview1.Selected.Index] as Ttermin;//dieses Objekt wird bearbeitet
    markierterKnoten:=Form1.TreeView1.Selected;

    [...] // diverse Zuweisungen an die Eigenschaften von tmptermin

    Terminlistesort; //Terminliste nach Datum sortieren

    //alten und neuen Index bestimmen...
    Alterindex:=markierterKnoten.Index;
    Neuerindex:=Terminliste.IndexOf(tmptermin);    
    tmpknoten:=markierterKnoten;
    if neuerindex<alterindex then
    begin
        //...den Knoten bestimmen, zu dem der markierte Knoten veschoben werden soll...
        for i:=neuerindex to alterindex-1 do tmpknoten:=tmpknoten.getPrevSibling;
        //...und dann verschieben
        markierterKnoten.MoveTo(tmpknoten,NaInsert);
    end;
    if alterindex<neuerindex then
    begin
        if neuerindex=gottesdienste.Count-1 then
            markierterKnoten.Moveto(NIL,naaddchild)
        else
        begin
            for i:=alterindex to neuerindex-1 do tmpknoten:=tmpknoten.getNextSibling;
            tmpknoten:=tmpknoten.getNextSibling;
            markierterKnoten.MoveTo(tmpknoten,NaInsert);
        end;
    end;

Bis dahin klappt alles wunderbar.

Ich möchte nun, dass der User einige Termine farblich in der Treeview hervorheben kann. Dazu hat das Objekt "Termin" die Eigenschaft "hervorheben" (True/False). Dazu reagiere ich auf das Event OnCustomDrawItem


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
    with Treeview1.Canvas do
    begin
        if (node.Level=0// Nur die Termine sollen hervorgehoben werden, die zugeteilten POersonen ersma nicht
            and
            (terminliste[node.Index] as Ttermin).hervorheben  //(*)und auch nur, wenn man das möchte!
            then
            begin
                if (cdsSelected in State) then
                begin
                    font.Color:=clHighLightText;
                    brush.Color:=clHighlight;
                end else
                begin
                    font.Color:=clWindowtext;
                    brush.Color:=clskyblue; // Den Termin mit einem schönen Himmelblau unterlegen
                end;
            end;
    end;
end;


Und hier hakt es. Zwar kann ich weitere Termine am Ende des Baumes einfügen, und die weredn auch entsprechend eingefärbt, aber wenn ich den Termin ändere, und der Knoten "gemovt" werden soll, bleibt das Programm hängen und frisst meine ganze CPU-Leistung.

Wenn ich die Zeile (*) auskommentiere, gehts wieder. Es geht auch, wenn ich vor dem Moven ein

Delphi-Quelltext
1:
form1.treeview1.OnCustomDrawItem:=NIL;                    
und danach einform1.treeview1.OnCustomDrawItem:=form1.TreeView1CustomDrawItem;
reinpacke. Aber das is natürlich eine unschöne Lösung.

Ich nehme an, dass ich, während ich einen Knoten Move, nicht wirklich auf den Index zugreifen {kann|sollte}, weil der sich {ständig ändert|nicht definiert ist}. Aber warum kommt dann keine Fehlermeldung, sondern eine (scheinbar)Endlosschleife?


smiegel - Mo 10.05.04 13:13

Hallo,

was passiert, wenn Du vor dem moven Items.BeginUpdate und nach erfolgreicher verschieberei Items.EndUpdate aufrufst?


Gausi - Mo 10.05.04 13:26

naja, was soll ich sagen, dann klappts auch :-)

Aber ob ich jetzt vor jedem Moven meine OndrawItem Prozedur mit der NIL-Zuweisung "verstecke", oder ob ich das in ein Begin- EndUpdate packe, is ja vom Programmieraufwand dasselbe. So muss ich immer noch aufpassen, dass ich nicht einfach nur die Knoten move (passiert gelegentlich auch an anderen Stellen), sondern etwas mehr mache.

Ich würde nur gerne noch verstehen, warum sich das Progg so aufhängt...Danke aber trotzdem, der BeginUpdate Befehl gefällt mir um einiges besser, als das, was ich bisher hatte