Einträge kopieren und verschieben


Zum Kopieren von Einträgen können wir auf Bewährtes zurückgreifen. Wir haben bereits hier besprochen, wie man den Text des markierten Items herausfinden kann.
Das Handle des gezogenen Items haben wir bereits gesichert, also weisen wir es wieder einer TTVItem-Variablen zu:

tv.hItem      := itemFrom;

Diesmal interessiert uns aber mehr als nur der Text des Items, also sieht unsere Flag-Kombination entsprechend aus:

tv.mask       := TVIF_HANDLE or TVIF_TEXT or TVIF_CHILDREN or
  TVIF_IMAGE or TVIF_SELECTEDIMAGE or TVIF_PARAM;

Hier interessieren uns neben Text auch die Images, die der Eintrag benutzt, sowie ein lParam (falls verwendet). Und entscheidend für das Kopieren des Items ist auch die Frage, ob dieser untergeordnete Einträge hat oder nicht.

Das Auslesen des Items funktioniert dann so, wie es bereits beschrieben wurde. Für den Text benötigen wir einen Puffer und dessen Größe. Dann holen wir die Informationen des Items mit Hilfe von "TreeView_GetItem".
Wenn wir den Eintrag haben, können wir ihn an die neue Position kopieren. Die neue Position ist dabei natürlich der Eintrag, der sich beim Abschluss der Drag-Operation unter dem Mauszeiger befunden hat.
Zum Kopieren (oder besser: Einfügen) benötigen wir wieder das schon bekannte Record vom Typ TTVInsertStruct, das wie folgt gefüllt wird:

tvi.hParent      := itemTo;
tvi.hInsertAfter := TVI_SORT;
tvi.item         := tv;

Dann rufen wir "TreeView_InsertItem" auf, übergeben dieses Record und erhalten als Ergebnis das Handle des neu eingefügten Items:

parent           := TreeView_InsertItem(hTV,tvi);

Jetzt ist die Frage: gibt es weitere, untergeordnete Items? Die Antwort gibt uns die Membervariable cChildren des TVItem-Records. Leider liefert uns diese Variable lediglich die Werte Null (es gibt keine untergeordneten Einträge), Eins (es gibt einen oder mehrere untergeordnete Einträge) und I_CHILDRENCALLBACK als Ergebnis zurück. Die Konstante und den Wert Null können wir in unserem Beispiel getrost ignorieren. Uns interessiert nur der Wert Eins.

Also holen wir uns den ersten untergeordneten Eintrag mit Hilfe von "TreeView_GetChild":

child := TreeView_GetChild(hTV,itemFrom);

Weil unser Beispielprogramm eine eigene Prozedur zum Kopieren der Einträge benutzt, brauchen wir diese nur aufzurufen, wobei wir die neu ermittelten Werte für das zu kopierende und das zu empfangende Item angeben:

CopyItems(hTV,child,parent);

Da es aber mehrere Einträge geben kann, benutzen wir nun "TreeView_GetNextSibling". Diese Funktion liefert das jeweils nächsten Item, das sich auf der selben Ebene befindet. Weil wir uns nun aber auf der Ebene des ersten Child-Items befinden, bekommen wir auf die Weise alle untergeordneten Einträge:

child := TreeView_GetNextSibling(hTV,child);

Das Beispielprogramm verwendet auch hier wieder eine while-Schleife, die solange durchlaufen wird bis "child" nil ist. Und weil sich die Prozedur "CopyItems" auf diese Weise immer wieder selbst aufruft, werden alle untergeordneten und unter-unter-unter-...-geordneten Einträge kopiert.

Unsere letzte Aufgabe ist es daher nur noch, den Originaleintrag zu entfernen. Sofern wir das wollen. Im Beispielprogramm geschieht dies, wenn Sie einen Eintrag mit der linken Maustaste verschieben, bzw. wenn Sie die rechte Maustaste benutzen und aus dem Popupmenü dann natürlich "Eintrag verschieben" auswählen. Die Funktionsweise ist dabei recht einfach: Sie rufen "TreeView_DeleteItem" auf und übergeben das Handle des, vor der Drag-Operation gesicherten Items:

TreeView_DeleteItem(hTreeview,hOldItem);