Hallo,
es geht um Drag&Drop innerhalb eines TTreeViews, also um's verschieben oder kopieren (Wenn Strg gedrückt) von Nodes.
Das habe ich soweit hinbekommen, wobei ich beim OnDragDrop des TV über GetKeyState(VK_Control) feststelle, ob in dem Moment die Strg-Taste gedrückt ist.
Jetzt wollte ich auch, das ein anderer Cursor angezeigt wird. Dabei nutze ich die Informationen von
hier. Arbeite also mit einem eigenen DragObject, was auch gut klappt, nutze als alternativen Cursor crMultiDrag, da ich zu faul war mir einen anderen zu malen.
Jetzt wollte ich aber auch mal versuchen (ebenfalls nach obiger Anleitung) den Text des gerade gedraggten Nodes neben dem Cursor anzuzeigen. Auch das klappt, allerdings kommt es beim "überfahren" von TTreenodes zu Artefaktbildung, d.h. der TreeView zeichnet sich nicht richtig (Siehe Bild)?
Woran könnte das legen, bzw. was muss ich machen? Im OnEndDrag rufe ich mittlerweile TV.Repaint auf, sonst würde der auch nach Ende des Drag&Drop-Vorganges so falsch gezeichnet bleiben.
Hier der relevante(?) Code soweit:
Delphi-Quellcode:
type
TNodeDragObject = class(TDragControlObject)
private
fData:String;
FX, FY: Integer;
FDragImages: TDragImageList;
protected
function GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor; override;
function GetDragImages: TDragImageList; override;
public
constructor Create(Control:TControl;Data:String; X, Y: Integer); reintroduce;
destructor Destroy; override;
property Data:String read fData;
end;
constructor TNodeDragObject.Create(Control: TControl; Data: String; X, Y: Integer);
begin
inherited create(Control);
fData:=Data;
FX:=X;
FY:=Y;
end;
destructor TNodeDragObject.Destroy;
begin
FDragImages.Free;
inherited;
end;
function TNodeDragObject.GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor;
var i:integer;
begin
i:=GetKeyState(VK_Control);
if Accepted and ((i=-127)or(i=-128)) then
Result := crMultiDrag
else
Result := inherited GetDragCursor(Accepted, X, Y)
end;
function TNodeDragObject.GetDragImages: TDragImageList;
var Bmp: TBitmap;
BmpIdx: Integer;
begin
if not Assigned(FDragImages) then
FDragImages := TDragImageList.Create(nil);
Result := FDragImages;
Result.Clear;
Bmp := TBitmap.Create;
try
//Make up some string to write on bitmap
Bmp.Canvas.Font.Name := 'Arial';
Bmp.Canvas.Font.Style := Bmp.Canvas.Font.Style + [fsItalic];
Bmp.Height := Bmp.Canvas.TextHeight(Data);
Bmp.Width := Bmp.Canvas.TextWidth(Data);
//Fill background with olive
Bmp.Canvas.Brush.Color := clOlive;
Bmp.Canvas.FloodFill(0, 0, clWhite, fsSurface);
//Write a string on bitmap
Bmp.Canvas.TextOut(0, 0, Data);
Result.Width := Bmp.Width;
Result.Height := Bmp.Height;
//Make olive pixels transparent, whilst adding bmp to list
BmpIdx := Result.AddMasked(Bmp, clOlive);
Result.SetDragImage(BmpIdx, FX, FY);
finally
Bmp.Free;
Application.ProcessMessages;
end
end;
procedure TMain.TVStartDrag(Sender: TObject; var DragObject: TDragObject);
var s:String;
Pt:TPoint;
begin
s:=(Sender as TTreeView).Selected.Text;
FDragObject:=TNodeDragObject.Create(Sender as TTreeView,s,-10,0);
DragObject:=FDragObject;
end;