比如在一个窗体中有一个ListView,里面填充了硬盘中某个盘符下的文件和文件夹名。如果用户选中其中一项并按"Ctrl + C",然后在Windows其它地方按"Ctrl + V",那么这个程序就会把它复制过去。如果用户在Windows其它地方按"Ctrl + C"复制了一个文件,并在这个窗体上按了"Ctrl + V",那么程序就会在这个ListView中增加一项被复制的文件名。不知大家以前做过类似的工具没有,我想请问大家一下这个问题的实现思路,具体就是如何得知Windows复制过来的文件名?以及向Windows其它地方复制时,如何知道用户按"Ctrl + V"时所在的路径?谢谢!

解决方案 »

  1.   

    支持,试一下剪贴板我想可以的,我也想提个问题,从listview往外拖东西,或者从外往里拖咋办,我知道用ondragover等事件,但我想知道怎么从explorer往listview里面拖
      

  2.   

    关于从explore向listview里面拖,你可以通过DragQueryFile去得知被拖放的文件数和文件名.可以参考一下
    http://cache.baidu.com/c?word=delphi%2Cdragqueryfile&url=http%3A//www%2Eyesky%2Ecom/20000701/89833%2Eshtml&b=0&a=6&user=baidu 里面的例子.我现在觉得困难的是键盘或鼠标来实现复制粘帖,剪贴板可能不行,复制文本有用,复制文件还是个问题.
      

  3.   

    并且ListView中的不是真文件,只是文件名,当用户在ListView中"Ctrl + C"的时候,我并不希望这个时候就把文件传上去(指传到剪贴板或其它临时区域),然后用户在其它地方"Ctrl + V"的时候,我的程序如何得知?如果建键盘钩子,我又如何得知用户希望拷贝的路径?
      

  4.   

    使用钩子,可以做到这个,Hook文件操作就可以...unit CopyMain;interfaceuses Windows, ComObj, ShlObj,controls;type
      TCopyHook = class(TComObject, ICopyHook)
      protected
        function CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; pszSrcFile: PAnsiChar;
          dwSrcAttribs: DWORD; pszDestFile: PAnsiChar; dwDestAttribs: DWORD): UINT; stdcall;
      end;  TCopyHookFactory = class(TComObjectFactory)
      protected
        function GetProgID: string; override;
        procedure ApproveShellExtension(Register: Boolean; const ClsID: string);
          virtual;
      public
        procedure UpdateRegistry(Register: Boolean); override;
      end;implementationuses ComServ, SysUtils, Registry, CopyHookForm;{ TCopyHook }
    function TCopyHook.CopyCallback(Wnd: HWND; wFunc, wFlags: UINT;
      pszSrcFile: PAnsiChar; dwSrcAttribs: DWORD; pszDestFile: PAnsiChar;
      dwDestAttribs: DWORD): UINT;
    const
      FO_COPY = 2;
      FO_DELETE = 3;
      FO_MOVE = 1;
      FO_RENAME = 4;
    var
      CopyDigForm: TCopyDigForm;
    begin
      Result := mrYes;
      CopyDigForm := TCopyDigForm.CreateParented(Wnd);
      try
        CopyDigForm.SourceEdit.Text := pszSrcFile;  //这里就是源文件的路径
        CopyDigForm.DestEdit.Text := pszDestFile; //这里是目标文件的路径
        Case wFunc of
          FO_MOVE:
          begin
            CopyDigForm.OperLable.Caption  := '拖动';
            case CopyDigForm.ShowModal of
              mrYes : Result := mrYes;
              mrNo : Result := mrNo;
              mrCancel: Result := mrCancel;
            end;
          end
          else
            Result := mrYes;
        end;
      finally
        CopyDigForm.Free;
      end;
    end;{ TCopyHookFactory }function TCopyHookFactory.GetProgID: string;
    begin
      Result := '';
    end;procedure TCopyHookFactory.UpdateRegistry(Register: Boolean);
    var
      ClsID: string;
    begin
      ClsID := GUIDToString(ClassID);
      inherited UpdateRegistry(Register);
      ApproveShellExtension(Register, ClsID);
      if Register then
    //    file://将/clsid 加入到注册表的CopyHookHandlers中
        CreateRegKey('directory\shellex\CopyHookHandlers\' + ClassName, '',
          ClsID)
      else
        DeleteRegKey('directory\shellex\CopyHookHandlers\' + ClassName);
    end;procedure TCopyHookFactory.ApproveShellExtension(Register: Boolean;
      const ClsID: string);
    const
      SApproveKey = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved';
    begin
      with TRegistry.Create do
        try
          RootKey := HKEY_LOCAL_MACHINE;
          if not OpenKey(SApproveKey, True) then Exit;
          if Register then WriteString(ClsID, Description)
          else DeleteValue(ClsID);
        finally
          Free;
        end;
    end;const
      CLSID_CopyHook: TGUID = '{4D13DABE-6D71-4FD2-BA19-FFC45823925D}';
      LIBID_CopyHook: TGUID = '{458259DE-3A9E-474F-B64B-1B7628DD9A41}';
    initialization
      TCopyHookFactory.Create(ComServer, TCopyHook, CLSID_CopyHook,
        'CR_CopyHook', 'File_Hook',ciMultiInstance, tmApartment);
    end.
      

  5.   

    谢谢GARNETT2183的回复,我先研究一下:)
      

  6.   

    弄一个shell hookunit CopyHook_Unit;interfaceuses Windows, ComObj, ShlObj, StdVcl,Dialogs;type
      TCopyMain = class(TComObject, ICopyHook)
      protected
        function CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; pszSrcFile: PAnsiChar;
          dwSrcAttribs: DWORD; pszDestFile: PAnsiChar; dwDestAttribs: DWORD): UINT; stdcall;
      end;  TCopyHookFactory = class(TComObjectFactory)
      protected
        function GetProgID: string; override;
        procedure ApproveShellExtension(Register: Boolean; const ClsID: string);
          virtual;
      public
        procedure UpdateRegistry(Register: Boolean); override;
      end;implementationuses ComServ, SysUtils, Registry;function TCopyMain.CopyCallback(Wnd: HWND; wFunc, wFlags: UINT;
      pszSrcFile: PAnsiChar; dwSrcAttribs: DWORD; pszDestFile: PAnsiChar;
      dwDestAttribs: DWORD): UINT;
    const
      FO_COPY = 2;
      FO_DELETE = 3;
      FO_MOVE = 1;
      FO_RENAME = 4;
    var
      sOp:string;
      tm : string;
    begin
      Case wFunc of
        FO_COPY:    sOp:=format('你确定要将 %s 拷贝到 %s 吗?',[pszSrcFile,pszDestFile]);
        FO_DELETE:  sOp:=format('你确定要将 %s 删除吗?',[pszSrcFile]);
        FO_MOVE:    sOp:=format('你确定要将 %s 转移到 %s 吗?',[pszSrcFile,pszDestFile]);
        FO_RENAME:  sOp:=format('你确定要将 %s 重命名为 %s 吗?',[pszSrcFile,pszDestFile]);
      else
        sOp:=format('无法识别的操作代码 %d',[wFlags]);
      end;  Result := MessageBox(Wnd,  PChar(sOp),
        '文件挂钩演示', MB_YESNOCANCEL);    
    end;function TCopyHookFactory.GetProgID: string;
    begin
      Result := '';
    end;procedure TCopyHookFactory.UpdateRegistry(Register: Boolean);
    var
      ClsID: string;
    begin
      ClsID := GUIDToString(ClassID);
      inherited UpdateRegistry(Register);
      ApproveShellExtension(Register, ClsID);
      if Register then
        CreateRegKey('directory\shellex\CopyHookHandlers\' + ClassName, '',
          ClsID)
      else
        DeleteRegKey('directory\shellex\CopyHookHandlers\' + ClassName);
    end;procedure TCopyHookFactory.ApproveShellExtension(Register: Boolean;
      const ClsID: string);
    const
      SApproveKey = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved';
    begin
      with TRegistry.Create do
        try
          RootKey := HKEY_LOCAL_MACHINE;
          if not OpenKey(SApproveKey, True) then Exit;
          if Register then WriteString(ClsID, Description)
          else DeleteValue(ClsID);
        finally
          Free;
        end;
    end;const
      CLSID_CopyHook: TGUID = '{66CD5F60-A044-11D0-A9BF-00A024E3867F}';
      LIBID_CopyHook: TGUID = '{D2F531A0-0861-11D2-AE5C-74640BC10000}';initialization
      TCopyHookFactory.Create(ComServer, TCopyMain, CLSID_CopyHook,
        'CR_CopyHook', '文件操作挂钩演示',ciMultiInstance, tmApartment);
    end.
      

  7.   

    这种方法只能Hook文件夹的操作
      

  8.   

    即使是文件夹,当在自己的窗体中按"Ctrl + V"的时候,也不会响应 FO_COPY:...操作.不知道还有什么办法没?
      

  9.   

    ICopyHook只针对文件夹,不能钩住文件操作,可能需要用API Hook.