Hier kommt die Maus ...


Angesprochen habe ich es bereits: im Windows Explorer wird während des Ziehens immer automatisch der Ordner markiert, über dem sich der Mauszeiger gerade befindet. Und natürlich wird auch das transparente Bild des gezogenen Ordners entsprechend verschoben.
Um diesen Effekt zu erreichen, bemühen wir die Nachricht "WM_MOUSEMOVE, wobei Sie die auch schon erwähnte bool-Variable heranziehen. Das ist insbesondere dann notwendig, wenn Sie in Ihrem Programm sowieso auf Mausbewegungen reagieren, damit diese nicht als Drag-Operation missinterpretiert werden:

WM_MOUSEMOVE:
  if(DragMode) then
  begin
    { ... }
  end;

Zuerst bewegen wir das transparente Drag-Image mit Hilfe von "ImageList_DragMove" auf die aktuelle Position des Mauszeigers. Weil "WM_MOUSEMOVE" diese Position im lParam mitbringt, nutzen wir sie:

ImageList_DragMove(LOWORD(lp),HIWORD(lp));


Effekt #2: Wir markieren das Item im Tree-View, über dem wir uns gerade befinden. Dazu benötigen wir zuerst eine Variable vom Typ TTVHitTestInfo, der wir die Mausposition übergeben:

tvhit.pt.x := LOWORD(lp);
tvhit.pt.y := HIWORD(lp);

Mit Hilfe eines so genannten "hit test" (mit "Kollisionsabfrage" durchaus treffend übersetzt) können wir dann überprüfen, ob sich an der angegebenen Position ein Item befindet. Dazu bietet sich entweder die Nachricht "TVM_HITTEST" oder wieder ein Makro, "TreeView_HitTest", an. Wenn Sie die Nachricht verwenden wollen, müssen Sie die TTVHitTestInfo als lParam übergeben. Mit dem Makro ist es einfacher:

HitHandle  := TreeView_HitTest(hTreeview,tvhit);

Befindet sich nun ein Item "unter" der aktuellen Mausposition, dann entspricht der Rückgabewert dem Handle des Items. Das Makro liefert das Handle bereits als HTREEITEM zurück; das Ergebnis der Nachricht müssten Sie erst entsprechend casten.
Wenn wir nun also ein Item haben, dann markieren wir es mit der Nachricht "TVM_SELECTDROPTARGET" oder mit dem Makro:

if(HitHandle <> nil) then
  TreeView_SelectDropTarget(hTreeview,HitHandle);

Zur Sicherheit sollten Sie das Drag-Image zuvor verstecken und danach wieder sichtbar machen. Auf die Weise vermeiden Sie unschöne Fragmente im Tree-View



Zum Verstecken und Anzeigen benutzen Sie "ImageList_DragShowNolock". Der bool-Parameter entscheidet dabei, ob das Bild versteckt (false) oder angezeigt (true) wird. Im Beispielprogramm finden Sie die Anwendung dieser Funktion.