Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 如何使我的文件DropSouce被所有使用文件的目标接受?_Delphi_Interface_Drag And Drop_Delphi 2009 - Fatal编程技术网

Delphi 如何使我的文件DropSouce被所有使用文件的目标接受?

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

我制作了一个表示文件列表的控件,我希望能够将文件从控件拖动到其他使用文件的应用程序。我实现了IDragSource界面(如下所示),但当我拖动时,文件仅被windows资源管理器、其他应用程序(如Firefox、Yahoo Messenger、Photoshop等)接受。。。不要接受我的文件。我做错了什么?我有一种感觉,IDataObject设置不正确,恐怕我必须自己实现它。。。这对我来说是一项非常复杂的工作,因为我刚刚开始使用接口

下面是重现问题的代码:

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的拖放套件呢。看这里: