Delphi 如何在Explorer和TcxShellListView之间实现无缝剪贴板?

Delphi 如何在Explorer和TcxShellListView之间实现无缝剪贴板?,delphi,devexpress,delphi-xe2,clipboard,explorer,Delphi,Devexpress,Delphi Xe2,Clipboard,Explorer,我有一个模仿Windows资源管理器的应用程序,它在其他shell控件中使用了TcxShellListView 一个非常好的功能是能够在真正的Windows资源管理器和我的应用程序之间复制和粘贴和剪切和粘贴文件 拖放已经可以开箱即用,但DevExpress似乎还没有实现剪贴板端 有什么想法吗?如果您想自己实现复制/粘贴,其机制几乎与拖放相同。您拥有的拖放代码将创建一个IDataObject。要复制,只需调用OleSetClipboard传递IDataObject即可,而不是调用DoDragDro

我有一个模仿Windows资源管理器的应用程序,它在其他shell控件中使用了
TcxShellListView

一个非常好的功能是能够在真正的Windows资源管理器和我的应用程序之间
复制和粘贴
剪切和粘贴
文件

拖放
已经可以开箱即用,但DevExpress似乎还没有实现剪贴板端


有什么想法吗?

如果您想自己实现复制/粘贴,其机制几乎与拖放相同。您拥有的拖放代码将创建一个
IDataObject
。要复制,只需调用
OleSetClipboard
传递
IDataObject
即可,而不是调用
DoDragDrop
启动拖动。对于粘贴,您可以调用
OleGetClipboard
从剪贴板获取
IDataObject
。然后您只需使用与drop操作完全相同的代码来解码
IDataObject
。就这些

还有另一种方法,在我看来可能是更好的方法。这就是使用
IContextMenu
来完成工作。这方面的例子可以在TurboPower tpShellShock项目中找到。在
StShlCtl
单元中查找
ShellMenuExecute
。只要DevExpress组件使用shell接口,即
IShellFolder
,您就可以使用相同的方法。这种基于shell的方法的优点是,您可以让shell完成工作。如果需要显示一个复制对话框,那么shell将这样做。这将为您提供最完整的用户体验

此代码如下所示:

procedure ShellMenuExecute(
  const Sender : TObject; const Folder : IShellFolder;
  var Pidl : PItemIDList; const Count : Integer;
  const AHandle : THandle; ClipboardAction : TStMenuAction);
var
  CM : IContextMenu;
  CI : TCmInvokeCommandInfo;
begin
  if Folder <> nil then begin
    if (Folder.GetUIObjectOf(AHandle, Count, Pidl,
      IID_IContextMenu, nil, Pointer(CM)) = NOERROR)
    then begin
      ZeroMemory(@CI, SizeOf(CI));
      CI.cbSize := SizeOf(TCmInvokeCommandInfo);
      CI.hwnd := AHandle;
      case ClipboardAction of
        caCut   : CI.lpVerb := 'cut';
        caCopy  : CI.lpVerb := 'copy';
        caPaste : CI.lpVerb := 'paste';
        caProperties : CI.lpVerb := 'properties';
      end;
      CM.InvokeCommand(CI);
      CM := nil;
    end;
  end;
end;
过程ShellMenuExecute(
常量发送方:ToObject;常量文件夹:IShellFolder;
变量Pidl:PItemIDList;常量计数:整数;
常量AHandle:THandle;剪贴板操作:TStMenuAction);
变量
CM:IContextMenu;
CI:TCmInvokeCommandInfo;
开始
如果文件夹为零,则开始
if(Folder.GetUIObjectOf)(AHandle、Count、Pidl、,
IID_IContextMenu,无,指针(CM))=无错误)
然后开始
零内存(@CI,SizeOf(CI));
CI.cbSize:=SizeOf(TCmInvokeCommandInfo);
CI.hwnd:=AHandle;
案例剪贴簿
caCut:CI.lpVerb:='cut';
caCopy:CI.lpVerb:=“复制”;
capast:CI.lpVerb:=“粘贴”;
caproperty:CI.lpVerb:=“属性”;
结束;
CM.调用命令(CI);
厘米:=零;
结束;
结束;
结束;
我认为你应该能够很好地使用这段代码。我要指出的是,handle参数的声明不正确。它应该是
HWND
。它被用作调用
InvokeCommand
期间显示的任何对话框的所有者窗口