2014-01-20 3 views
1

Я создаю приложение Delphi XE3, которое должно иметь возможность сбросить на него файлы. У меня есть Explorer> Application сторона работы, но для жизни я не могу понять, как получить имя файла при переходе из приложения> Application.Получение имени файла из IDataObject в Delphi

Предполагая, что один файл отбрасывается из версии 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

Формат 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
+0

Af я обнял то, что я делал неправильно, это имеет смысл. благодаря – Ranky

Смежные вопросы