如何将文件从Explorer Shell拖放到Delphi应用程序中的VirtualTreeView控件中? [英] How do you drag and drop a file from Explorer Shell into a VirtualTreeView control in a Delphi application?

查看:178
本文介绍了如何将文件从Explorer Shell拖放到Delphi应用程序中的VirtualTreeView控件中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由Mike Lischke在VirtualTreeView中进行广泛的拖放支持,而且我使用的是TVirtualStringTree,它具有一些拖放事件,但是我无法弄清楚如何让它接受一个shell拖动,将某些文件从windows explorer shell下载到我的应用程序中。我想加载这些文件,当它们被拖到放置控件上时。



我尝试使用Anders Melander的第三方代码集来处理拖放,但是因为VirtualTreeView已经将自身注册为放置目标,所以我无法使用它。



编辑:我找到了一个简单的解决方法:在VT.TreeOptions中关闭toAcceptOLEDrop。杂项选项
如果有人知道使用VirtualTreeView的方式,而不使用第三方OLE-shell-drag-drop库,并使用其广泛的OLE拖放支持来提取从Shell拖入的文件名列表,那将是很酷的。

解决方案

我的实现(与Delphi 2010一起工作。必须添加ActiveX,ShellApi才能使用编译):

  procedure TfMain.vstTreeDragDrop(发件人:TBaseVirtualTree;源:TObject; 
DataObject:IDataObject;格式:TFormatArray; Shift:TShiftState;
Pt:TPoint; var Effect:Integer; Mode:TDropMode);
var
I,j:整数;
MyList:TStringList;
AttachMode:TVTNodeAttachMode;
begin
如果Mode = dmOnNode然后
AttachMode:= amInsertBefore
否如果Mode = dmAbove然后
AttachMode:= amInsertBefore
否如果Mode = dmBelow then
AttachMode:= amInsertAfter
else
AttachMode:= amAddChildLast;

MyList:= TStringList.Create;
尝试
为i:= 0到高(格式) - 1 do
开始
如果(格式[i] = CF_HDROP)然后
开始
GetFileListFromObj(DataObject,MyList);

//这里我们有所有文件名
为j:= 0到MyList.Count - 1 do
begin
Sender.InsertNode(Sender.DropTargetNode,AttachMode) ;
结束
结束
结束
finally
MyList.Free;
结束
结束

程序TfMain.GetFileListFromObj(const DataObj:IDataObject;
FileList:TStringList);
var
FmtEtc:TFormatEtc; //指定所需的数据格式
中:TStgMedium; //包含文件列表的存储介质
DroppedFileCount:Integer; //丢弃的文件数
I:整数; //循环通过丢弃的文件
FileNameLength:Integer; //删除文件名的长度
FileName:string; //删除文件的名称
begin
//从数据对象获取所需的存储介质
FmtEtc.cfFormat:= CF_HDROP;
FmtEtc.ptd:= nil;
FmtEtc.dwAspect:= DVASPECT_CONTENT;
FmtEtc.lindex:= -1;
FmtEtc.tymed:= TYMED_HGLOBAL;
OleCheck(DataObj.GetData(FmtEtc,Medium));
尝试
尝试
//获取丢弃的文件数
DroppedFileCount:= DragQueryFile(
Medium.hGlobal,$ FFFFFFFF,nil,0
);
//获取每个文件的名称并处理它
为I:= 0到Pred(DroppedFileCount)do
begin
//获取文件名的长度,然后命名自身
FileNameLength:= DragQueryFile(Medium.hGlobal,I,nil,0);
SetLength(FileName,FileNameLength);
DragQueryFileW(
Medium.hGlobal,I,PWideChar(FileName),FileNameLength + 1
);
//添加文件名以列出
FileList.Append(FileName);
结束
finally
//整理 - 释放放置句柄
//在此
之后不再使用DropH DragFinish(Medium.hGlobal);
结束
finally
ReleaseStgMedium(Medium);
结束

end;


There is extensive drag and drop support in VirtualTreeView by Mike Lischke, and I am using TVirtualStringTree, which has some on-drag-and-drop events, but I can not figure out how to get it to accept a shell drag-and-drop of some files from the windows explorer shell, into my application. I want to load the files, when they are dragged onto the drop control.

I tried using a third-party set of code from Anders Melander, to handle drag and drop, but because VirtualTreeView already registers itself as a drop target, I can't use that.

edit: I found a simple workaround: Turn off toAcceptOLEDrop in VT.TreeOptions.MiscOptions. It would be cool if anybody knows a way to use VirtualTreeView without using a third party OLE-shell-drag-drop library and using its extensive OLE drag/drop support to extract a list of filenames dragged in from the Shell.

解决方案

My implementation (Works very well with Delphi 2010. Must add ActiveX, ShellApi to uses to compile):

procedure TfMain.vstTreeDragDrop(Sender: TBaseVirtualTree; Source: TObject;
  DataObject: IDataObject; Formats: TFormatArray; Shift: TShiftState;
  Pt: TPoint; var Effect: Integer; Mode: TDropMode);
var
  I, j: Integer;
  MyList: TStringList;
  AttachMode: TVTNodeAttachMode;
begin
  if Mode = dmOnNode then
    AttachMode := amInsertBefore
  else if Mode = dmAbove then
    AttachMode := amInsertBefore
  else if Mode = dmBelow then
    AttachMode := amInsertAfter
  else
    AttachMode := amAddChildLast;

  MyList := TStringList.Create;
  try
    for i := 0 to High(formats) - 1 do
    begin
      if (Formats[i] = CF_HDROP) then
      begin
        GetFileListFromObj(DataObject, MyList);

        //here we have all filenames
        for j:=0 to MyList.Count - 1 do
        begin
          Sender.InsertNode(Sender.DropTargetNode, AttachMode);
        end; 
      end;  
    end;
  finally
    MyList.Free;
  end;
end;

procedure TfMain.GetFileListFromObj(const DataObj: IDataObject;
  FileList: TStringList);
var
  FmtEtc: TFormatEtc;                   // specifies required data format
  Medium: TStgMedium;                   // storage medium containing file list
  DroppedFileCount: Integer;            // number of dropped files
  I: Integer;                           // loops thru dropped files
  FileNameLength: Integer;              // length of a dropped file name
  FileName: string;                 // name of a dropped file
begin
  // Get required storage medium from data object
  FmtEtc.cfFormat := CF_HDROP;
  FmtEtc.ptd := nil;
  FmtEtc.dwAspect := DVASPECT_CONTENT;
  FmtEtc.lindex := -1;
  FmtEtc.tymed := TYMED_HGLOBAL;
  OleCheck(DataObj.GetData(FmtEtc, Medium));
  try
    try
      // Get count of files dropped
      DroppedFileCount := DragQueryFile(
        Medium.hGlobal, $FFFFFFFF, nil, 0
        );
      // Get name of each file dropped and process it
      for I := 0 to Pred(DroppedFileCount) do
        begin
          // get length of file name, then name itself
          FileNameLength := DragQueryFile(Medium.hGlobal, I, nil, 0);
          SetLength(FileName, FileNameLength);
          DragQueryFileW(
            Medium.hGlobal, I, PWideChar(FileName), FileNameLength + 1
            );
          // add file name to list
          FileList.Append(FileName);
        end;
    finally
      // Tidy up - release the drop handle
      // don't use DropH again after this
      DragFinish(Medium.hGlobal);
    end;
  finally
    ReleaseStgMedium(Medium);
  end;

end;

这篇关于如何将文件从Explorer Shell拖放到Delphi应用程序中的VirtualTreeView控件中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆