从Delphi中的IDataObject检索文件名

时间:2014-01-20 22:59:10

标签: delphi idataobject

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

假设从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 );

1 个答案:

答案 0 :(得分:5)

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