1

我正在构建一个 Delphi XE3 应用程序,它需要能够将文件拖放到它上面。我有资源管理器>应用程序方面的工作,但对于我的生活,我无法弄清楚从应用程序>应用程序时获取文件名。

假设从 Outlook(或任何其他应用程序)中删除了一个文件,只要我filename事先手动分配,我就有这个文件。

SetFormatEtc( FormatEtc , CF_FILECONTENTS );
OleCheck( dataObj.GetData( FormatEtc , Medium ) );
OleStream := TOleStream.Create( IUnknown( Medium.stm ) as IStream );
MemStream := TMemoryStream.Create;
OleStream.Position := 0;
MemStream.CopyFrom( OleStream , OleStream.Size );

TMemoryStream( MemStream ).SaveToFile( 'C:\' + filename );

MemStream.Free;
OleStream.Free;
ReleaseStgMedium( Medium );
4

1 回答 1

6

CF_FILECONTENTS 格式可以包含多个流。您必须检查 CF_FILEDESCRIPTORW 和 CF_FILEDESCRIPTORA 格式以检测流计数和流名称。一些资料来源:

function ContainFormat(ADataObject: IDataObject; AFormat: TClipFormat;
  ATymed: Longint; AAspect: LongInt = DVASPECT_CONTENT; AIndex: LongInt = -1): Boolean;
var Format: TFormatEtc;
begin
  ZeroMemory(@Format, SizeOf(Format));
  Format.cfFormat := AFormat;
  Format.dwAspect := AAspect;
  Format.lindex := AIndex;
  Format.tymed := ATymed;
  Result := ADataObject.QueryGetData(Format) = S_OK;
end;

procedure InvalidMedium;
begin
  raise Exception.Create('Invalid medium');
end;

function ExtractStream(ADataObject: IDataObject; AIndex: Integer): IStream;
var Format: TFormatEtc;
    Medium: TStgMedium;
begin
  ZeroMemory(@Format, SizeOf(Format));
  Format.cfFormat := CF_FILECONTENTS;
  Format.dwAspect := DVASPECT_CONTENT;
  Format.lindex := AIndex;
  Format.tymed := TYMED_ISTREAM;
  ZeroMemory(@Medium, SizeOf(Medium));
  OleCheck(ADataObject.GetData(Format, Medium));
  try
    if (Medium.tymed and TYMED_ISTREAM = 0) or not Assigned(Medium.stm) then
      InvalidMedium;
    Result := IStream(Medium.stm);
  finally
    ReleaseStgMedium(Medium);
  end
end;

procedure WorkWithDropObject(const AFileName: UnicodeString; AStream: IStream);
begin

end;

procedure ProcessDataObject(ADataObject: IDataObject);
var Format: TFormatEtc;
    Medium: TStgMedium;
    FGDA: PFileGroupDescriptorA;
    FGDW: PFileGroupDescriptorW;
    i: Integer;
    Stream: IStream;
begin
  if ContainFormat(ADataObject, CF_FILECONTENTS, TYMED_ISTREAM) then
    begin
      if ContainFormat(ADataObject, CF_FILEDESCRIPTORW, TYMED_HGLOBAL) then
        begin
          Format.cfFormat := CF_FILEDESCRIPTORW;
          Format.dwAspect := DVASPECT_CONTENT;
          Format.lindex := -1;
          Format.tymed := TYMED_HGLOBAL;
          ZeroMemory(@Medium, SizeOf(Medium));
          OleCheck(ADataObject.GetData(Format, Medium));
          try
            if (Medium.tymed and TYMED_HGLOBAL = 0) or (Medium.hGlobal = 0) then
              InvalidMedium;
            FGDW := GlobalLock(Medium.hGlobal);
            if not Assigned(FGDW) then
              RaiseLastOSError;
            try
              for i := 0 to FGDW.cItems - 1 do
                begin
                  Stream := ExtractStream(ADataObject, i);
                  try
                    WorkWithDropObject(FGDW.fgd[i].cFileName, Stream);
                  finally
                    Stream := nil;
                  end;
                end;
            finally
              GlobalUnlock(Medium.hGlobal);
            end;
          finally
            ReleaseStgMedium(Medium);
          end
        end
      else
        if ContainFormat(ADataObject, CF_FILEDESCRIPTORA, TYMED_HGLOBAL) then
          begin
            Format.cfFormat := CF_FILEDESCRIPTORA;
            Format.dwAspect := DVASPECT_CONTENT;
            Format.lindex := -1;
            Format.tymed := TYMED_HGLOBAL;
            ZeroMemory(@Medium, SizeOf(Medium));
            OleCheck(ADataObject.GetData(Format, Medium));
            try
              if (Medium.tymed and TYMED_HGLOBAL = 0) or (Medium.hGlobal = 0) then
                InvalidMedium;
              FGDA := GlobalLock(Medium.hGlobal);
              if not Assigned(FGDA) then
                RaiseLastOSError;
              try
                for i := 0 to FGDA.cItems - 1 do
                  begin
                    Stream := ExtractStream(ADataObject, i);
                    try
                      WorkWithDropObject(FGDA.fgd[i].cFileName, Stream);
                    finally
                      Stream := nil;
                    end;
                  end;
              finally
                GlobalUnlock(Medium.hGlobal);
              end;
            finally
              ReleaseStgMedium(Medium);
            end
          end;
    end;
end;

另外,如果您想创建通用软件,您应该处理以下格式:

  • CF_FILENAMEW/CF_FILENAMEA
  • CF_HDROP
  • CF_IDLIST
  • CF_FILEDESCRIPTORW/CF_FILEDESCRIPTORA/CF_FILECONTENTS
于 2014-01-20T23:57:34.277 回答