Delphi 如何使我的文件DropSouce被所有使用文件的目标接受?
我制作了一个表示文件列表的控件,我希望能够将文件从控件拖动到其他使用文件的应用程序。我实现了IDragSource界面(如下所示),但当我拖动时,文件仅被windows资源管理器、其他应用程序(如Firefox、Yahoo Messenger、Photoshop等)接受。。。不要接受我的文件。我做错了什么?我有一种感觉,IDataObject设置不正确,恐怕我必须自己实现它。。。这对我来说是一项非常复杂的工作,因为我刚刚开始使用接口 下面是重现问题的代码:Delphi 如何使我的文件DropSouce被所有使用文件的目标接受?,delphi,interface,drag-and-drop,delphi-2009,Delphi,Interface,Drag And Drop,Delphi 2009,我制作了一个表示文件列表的控件,我希望能够将文件从控件拖动到其他使用文件的应用程序。我实现了IDragSource界面(如下所示),但当我拖动时,文件仅被windows资源管理器、其他应用程序(如Firefox、Yahoo Messenger、Photoshop等)接受。。。不要接受我的文件。我做错了什么?我有一种感觉,IDataObject设置不正确,恐怕我必须自己实现它。。。这对我来说是一项非常复杂的工作,因为我刚刚开始使用接口 下面是重现问题的代码: unit Unit1; interf
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ActiveX, ShlObj;
type
TMyControl = class(TMemo, IDropSource)
private
function QueryContinueDrag(fEscapePressed:BOOL; grfKeyState:Longint):HResult; stdcall;
function GiveFeedback(dwEffect:Longint):HResult; stdcall;
procedure DoDragAndDrop;
function GetFileListDataObject:IDataObject;
protected
procedure MouseMove(Shift:TShiftState; X,Y:Integer); override;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
public
MyMemo:TMyControl;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{TMyControl}
function TMyControl.QueryContinueDrag(fEscapePressed:BOOL; grfKeyState:Longint):HResult;
begin
if fEscapePressed then Result:=DRAGDROP_S_CANCEL
else if (grfKeyState and (MK_LBUTTON or MK_RBUTTON) = 0) then Result:=DRAGDROP_S_DROP
else Result:=S_OK;
end;
function TMyControl.GiveFeedback(dwEffect:Longint):HResult;
begin
Result:=DRAGDROP_S_USEDEFAULTCURSORS;
end;
procedure TMyControl.DoDragAndDrop;
var AllowedEffects,DropEffect:Longint;
DataObj:IDataObject;
begin
AllowedEffects:=DROPEFFECT_COPY;
DataObj:=GetFileListDataObject;
if DataObj <> nil then
DoDragDrop(DataObj, self, AllowedEffects, DropEffect);
end;
function TMyControl.GetFileListDataObject:IDataObject;
var Desktop:IShellFolder;
Attr,Eaten:ULONG;
Count,x:Integer;
Pidls:array of PItemIDList;
begin
Result:=nil;
Count:=Lines.Count;
if Count<1 then Exit;
if Failed(SHGetDesktopFolder(Desktop)) then Exit;
SetLength(Pidls,Count);
for x:=0 to Count-1 do Pidls[x]:=nil;
try
for x:=0 to Count-1 do
if Failed(Desktop.ParseDisplayName(0, nil, PWideChar(Lines[x]), Eaten, Pidls[x], Attr)) then Exit;
Desktop.GetUIObjectOf(0, Count, Pidls[0], IDataObject, nil, Result);
finally
for x:=0 to Count-1 do
if Pidls[x]<>nil then CoTaskMemFree(Pidls[x]);
end;
end;
procedure TMyControl.MouseMove(Shift:TShiftState; X,Y:Integer);
begin
if ssLeft in Shift then DoDragAndDrop;
inherited;
end;
//---------------------------------
procedure TForm1.FormCreate(Sender: TObject);
begin
MyMemo:=TMyControl.Create(Form1);
MyMemo.Parent:=Form1;
MyMemo.Align:=alClient;
end;
end.
单元1;
接口
使用
窗口、消息、系统工具、变体、类、图形、控件、窗体、,
对话框、StdCtrls、ActiveX、ShlObj;
类型
TMyControl=class(TMemo,IDropSource)
私有的
函数QueryContinueDrag(fEscapePressed:BOOL;grfKeyState:Longint):HResult;stdcall;
功能反馈(dwEffect:Longint):HResult;stdcall;
程序:多拉甘达洛;
函数GetFileListDataObject:IDataObject;
受保护的
过程MouseMove(Shift:TShiftState;X,Y:Integer);推翻
结束;
TForm1=类(TForm)
过程表单创建(发送方:ToObject);
公众的
我的备忘录:TMyControl;
结束;
变量
表1:TForm1;
实施
{$R*.dfm}
{TMyControl}
函数TMyControl.QueryContinueDrag(fEscapePressed:BOOL;grfKeyState:Longint):HResult;
开始
如果按了fescape,则结果:=DRAGDROP\u S\u取消
否则如果(grfKeyState和(MK_LBUTTON或MK_RBUTTON)=0),则结果:=DRAGDROP_S_DROP
其他结果:=S_OK;
结束;
功能TMyControl.GiveFeedback(dwEffect:Longint):HResult;
开始
结果:=DRAGDROP_S_USEDEFAULTCURSORS;
结束;
程序TMyControl.DoDragAndDrop;
var允许效应,DropEffect:Longint;
数据对象:IDataObject;
开始
AllowedEffects:=DROPEFFECT\u COPY;
DataObj:=GetFileListDataObject;
如果DataObj为nil,则
DoDragDrop(DataObj、self、AllowedEffects、DropEffect);
结束;
函数TMyControl.GetFileListDataObject:IDataObject;
var桌面:IShellFolder;
食用:乌龙;
计数,x:整数;
Pidls:PItemIDList的数组;
开始
结果:=无;
计数:=行。计数;
如果Count问题是您使用了不正确的Desktop.GetUIObjectOf调用。调用SomeFolder时,GetUIObjectOf项必须是SomeFolder的子项。但在你的情况下,这不是真的。试着这样做:
type
PPItemIDList = ^PItemIDList;
function GetFileListDataObject(AParentWnd: HWND; const APath: string; AFileNames: TStrings): IDataObject;
var
Desktop: IShellFolder;
Eaten, Attr: ULONG;
i: Integer;
PathIDList: PItemIDList;
PathShellFolder: IShellFolder;
IDLists: PPItemIDList;
IDListsSize: Integer;
Pos: PPItemIDList;
begin
Result := nil;
if AFileNames.Count < 1 then Exit;
if Failed(SHGetDesktopFolder(Desktop)) then Exit;
try
Attr := 0;
if Failed(Desktop.ParseDisplayName(AParentWnd, nil, PWideChar(APath), Eaten, PathIDList, Attr)) then Exit;
try
if Failed(Desktop.BindToStorage(PathIDList, nil, IShellFolder, PathShellFolder)) then Exit;
try
IDListsSize := SizeOf(PItemIDList) * AFileNames.Count;
GetMem(IDLists, IDListsSize);
try
ZeroMemory(IDLists, IDListsSize);
Pos := IDLists;
for i := 0 to AFileNames.Count - 1 do
begin
Attr := 0;
if Failed(PathShellFolder.ParseDisplayName(0, nil, PWideChar(AFileNames[i]), Eaten, Pos^, Attr)) then Exit;
Inc(Pos);
end;
PathShellFolder.GetUIObjectOf(0, AFileNames.Count, IDLists^, IDataObject, nil, Result);
finally
Pos := IDLists;
for i := 0 to AFileNames.Count - 1 do
begin
if Assigned(Pos^) then
CoTaskMemFree(Pos^);
Inc(Pos);
end;
FreeMem(IDLists);
end;
finally
PathShellFolder := nil;
end;
finally
CoTaskMemFree(PathIDList);
end;
finally
Desktop := nil;
end;
end;
类型
PPItemIDList=^PItemIDList;
函数GetFileListDataObject(AParentWnd:HWND;const-APath:string;AFileNames:TStrings):IDataObject;
变量
桌面:IShell文件夹;
食用,Attr:ULONG;
i:整数;
可怜虫:可怜虫;
PathShellFolder:IShellFolder;
空闲列表:ppitemdlist;
idlistsize:整数;
Pos:ppitemiddlist;
开始
结果:=无;
如果AFileNames.Count小于1,则退出;
如果失败(SHGetDesktopFolder(桌面)),则退出;
尝试
属性:=0;
如果失败(Desktop.ParseDisplayName(AParentWnd、nil、PWideChar(APath)、eat、PathIDList、Attr)),则退出;
尝试
如果失败(Desktop.BindToStorage(PathIDList、nil、IShellFolder、PathShellFolder)),则退出;
尝试
IDListSize:=SizeOf(PItemIDList)*AFileNames.Count;
GetMem(IDLists,idlistsize);
尝试
零内存(IDLists、idlistsize);
Pos:=游手好闲者;
对于i:=0的文件名。计数-1 do
开始
属性:=0;
如果失败(PathShellFolder.ParseDisplayName(0,nil,PWideChar(AFileNames[i]),eat,Pos^,Attr)),则退出;
股份有限公司(Pos);
结束;
PathShellFolder.GetUIObjectOf(0,AFileNames.Count,IDLists^,IDataObject,nil,Result);
最后
Pos:=游手好闲者;
对于i:=0的文件名。计数-1 do
开始
如果分配(位置^),则
CoTaskMemFree(Pos^);
股份有限公司(Pos);
结束;
FreeMem(游手好闲者);
结束;
最后
PathShellFolder:=nil;
结束;
最后
CoTaskMemFree(路径列表);
结束;
最后
桌面:=零;
结束;
结束;
您的文件是来自同一个文件夹还是可以位于不同的文件夹中?我的所有文件都在同一个文件夹中。这里缺少很多文件。我们看不到所有的代码。MCVE意味着我们有信心知道您的代码是什么。一些关于代码如何失败的指示会有所帮助。还有调试的详细信息。假设您已经使用跟踪调试进行了调试?好的,我将尝试制作一个MCVE并更新我的问题,但是您将看到代码的其余部分没有什么重要的内容。它是如何失败的?嗯,当我将文件拖到我知道它可以接受文件的应用程序的目标区域(使用explorer测试)时,鼠标指针会变成禁止标志(中间有一条线的圆圈),如果我拖到那里,什么也不会发生。你为什么不看看Anders Melander的拖放套件呢。看这里: