delphi - 拖动节点时 TTreeView 选择故障

标签 delphi drag-and-drop treeview delphi-7

我正在为 TTreeView 实现拖放功能。在其 OnStartDrag 事件中,我正在创建派生类的 DragOcject:

  TTreeDragControlObject = class(TDragObject)
  private
    FDragImages: TDragImageList;
    FText: String;
  protected
    function GetDragImages: TDragImageList; override;
  end;

procedure TfrmMain.tvTreeStartDrag(Sender: TObject;
  var DragObject: TDragObject);
begin
  DragObject := TTreeDragControlObject.Create;
  TTreeDragControlObject(DragObject).FText := tvTree.Selected.Text;
end;

这是我的 DragObcject 的覆盖 GetDragImages 函数:

function TTreeDragControlObject.GetDragImages: TDragImageList;
var
  Bmp: TBitmap;
begin
  if FDragImages = nil then
  begin
    FDragImages := TDragImageList.Create(nil);
    Bmp := TBitmap.Create;
    try
      Bmp.Width := Bmp.Canvas.TextWidth(FText) + 25;
      Bmp.Height := Bmp.Canvas.TextHeight(FText);

      Bmp.Canvas.TextOut(25, 0, FText);

      FDragImages.Width := Bmp.Width;
      FDragImages.Height := Bmp.Height;
      FDragImages.SetDragImage(FDragImages.Add(Bmp, nil), 0, 0);
    finally
      Bmp.Free;
    end;
  end;

  Result := FDragImages;
end;

一切正常,除了在树节点上拖动时出现绘画故障:

The node glitch

如何避免这种行为?

最佳答案

根据 @Sean 和 @bummi 的回答,我将发布在 D5 中对我有用的完整代码和结论。

在 WinXP 上,XPManifest 不是必须的 - 需要 Hide/ShowDragImage

在 Win7 上需要 XPManifest。 Hide/ShowDragImage不是必须的。

结论 - 同时使用 XPManifest 和 HideDragImageShowDragImage 确保 TV 在 XP/Win7 上都能工作。

<小时/>
type 
  TTreeDragControlObject = class(TDragControlObject)
  private
    FDragImages: TDragImageList;
    FText: String;
  protected
    function GetDragImages: TDragImageList; override;
  public
    destructor Destroy; override;
    procedure HideDragImage; override;
    procedure ShowDragImage; override;
    property DragText: string read FText write FText;
  end;

  TForm1 = class(TForm)
    TreeView1: TTreeView;
    procedure TreeView1StartDrag(Sender: TObject; var DragObject: TDragObject);
    procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
    procedure TreeView1EndDrag(Sender, Target: TObject; X, Y: Integer);
  private
    FDragObject: TTreeDragControlObject;
  public
  end;

...

{ TTreeDragControlObject}
destructor TTreeDragControlObject.Destroy;
begin
  FDragImages.Free;
  inherited;
end;

procedure TTreeDragControlObject.HideDragImage;
begin
  GetDragImages.HideDragImage;
end;

procedure TTreeDragControlObject.ShowDragImage;
begin
  GetDragImages.ShowDragImage;
end;

function TTreeDragControlObject.GetDragImages: TDragImageList;
var
  Bmp: TBitmap;
begin
  if FDragImages = nil then
  begin
    FDragImages := TDragImageList.Create(nil);
    Bmp := TBitmap.Create;
    try
      Bmp.Width := Bmp.Canvas.TextWidth(FText) + 25;
      Bmp.Height := Bmp.Canvas.TextHeight(FText);
      Bmp.Canvas.TextOut(25, 0, FText);
      FDragImages.Width := Bmp.Width;
      FDragImages.Height := Bmp.Height;
      FDragImages.SetDragImage(FDragImages.Add(Bmp, nil), 0, 0);
    finally
      Bmp.Free;
    end;
  end;
  Result := FDragImages;
end;

{ TForm1 }
procedure TForm1.TreeView1StartDrag(Sender: TObject; var DragObject: TDragObject);
begin
  FDragObject := TTreeDragControlObject.Create(TTreeView(Sender));
  FDragObject.DragText := TTreeView(Sender).Selected.Text;
  DragObject := FDragObject;
end;

procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  Accept := Source is TTreeDragControlObject;
end;

procedure TForm1.TreeView1EndDrag(Sender, Target: TObject; X, Y: Integer);
begin
  FDragObject.Free;
end;
<小时/>

请注意,在您的代码中,FDragImagesvar DragObject 都在泄漏内存。我建议使用 TDragControlObject 而不是 TDragObject (你的 tvTreeEndDrag 现在会火吗? - 它没有为我火)

关于delphi - 拖动节点时 TTreeView 选择故障,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13623298/

相关文章:

delphi - 通过集合/列表/其他容器使用 AWE Memory 进行数据存储

delphi - 如何检查数组是否已排序?

qt - 设置 QTreeView 标题的标题文本

xml - IXMLDocument.SaveToFile() 使用制表符而不是空格进行缩进

delphi - Delphi XE2 pro 中的 REST 服务器

javascript - 如何通过 Chrome 扩展模拟文件拖放上传?

C++ - main 的参数

c# - 如何创建 "Shell IDList Array"以支持将虚拟文件从 C# 拖放到 Windows 资源管理器?

java - CheckBoxTreeTableCell 选择父事件下的所有子项

css - 如何在JavaFX中更改TreeItem的下划线颜色?