Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];

Вниз

Drag&drop из программы в проводник   Найти похожие ветки 

 
kami ©   (2005-05-29 01:54) [0]

Есть программа с набором данных, каждая группа данных представлена в виде элемента ListView. Если это имеет значение, данные запакованы в TStream. Как можно перетащив ListItem на проводник, сохранить эти данные в файл?
Прошу сильно не пинать, с Drag&Drop столкнулся впервые и имею об этом весьма смутное представление. Порывшись несколько часов в хелпе и MSDN понял, что ничего не понял :(, кроме того, что используются TDragObject и/или IDataObject, но вот как - ???? Подобные ветки уже были, но давно, их следов я не обнаружил.
Подскажите, пожалуйста, последовательность действий для перетаскивания данных из программы в проводник, чтобы тот сохранил их в файл.


 
Cobalt ©   (2005-05-29 02:03) [1]

Если уж ты сам наткнулся в MSDN на IDataObject - то тебе надо сделать ещё одну вещь - прочитать полностью Overview этой темы.


 
kami ©   (2005-05-29 03:42) [2]

Мдааа. Наверное, надо было заводить ветку в API :(
2 [1] Cobalt ©   & all
Подправьте, пожалуйста, если неправильно понял...
Когда определили, что пользователь начал перетаскивать ListItem ( то есть в OnStartDrag?), нужно инициализировать IDataSource, IDropSource и вызвать DoDragDrop, и на этом вроде всё?
Если так, то сразу вопрос : в IDataSource.SetData в FORMATETC что нужно ставить в полях cfFormat, dwAspect ( tymed, как я понял, должен быть TYMED_ISTREAM, т.к. данные у меня хранятся в потоке). С структурой STGMEDIUM вроде понятно, но вот только как проводник узнает, что нужно сохранить данные в файл, если в ней поставить так же tymed:=TYMED_ISTREAM ?
И еще - методы IDropSource::GiveFeedback и QueryContinueDrag нужно определять в своей программе, как, например, обработчики событий компонентов?


 
kami ©   (2005-05-29 03:46) [3]

Упс... Вопрос про методы IDropSource снимается, посмотрел в OLE2.pas - они объявлены как абстрактные, соответственно - нуна их перекрыть :)


 
kami ©   (2005-05-29 03:57) [4]

[2] kami
IDataSource=>IDataObject


 
Cobalt ©   (2005-05-29 13:17) [5]

2 kami ©
Попробуй поискать в MSDN примерчик - по ключевым словам - там иногда бывает. Правда, на С, но настоящего программиста это не остановит ;)

не приглядывался, но вот наткнулся в MS SDK на
Scrap Files
Windows allows the user to transfer objects within a data file to the desktop or a folder. The result of the transfer operation is a file icon called a scrap. An OLE application automatically supports the creation of scrap files if its IDataObject interface supports enough data formats so that the drop target can create either an embedding or a shortcut object. You do not need to add any other functionality to your application to allow the user to create a scrap file. However, there are two optional features you may wish to add to your application: round-trip support and caching additional data formats in a scrap file. Round-trip support means that an object can be dragged out of a document and into a new container and then dragged from the new container back into the original document.

Round-Trip Support
When the user transfers a scrap into your application, it should integrate the scrap as if it were being transferred from its original source. For example, if a selected range of cells from a spreadsheet is transferred to the desktop, they become a scrap. If the user transfers the resulting scrap into a word processing document, the cells should be incorporated as if they were transferred directly from the spreadsheet. Similarly, if the user transfers the scrap back into the spreadsheet, the cells should be integrated as if they were originally transferred within that spreadsheet.

Your application must include code that integrates a scrap into a document; otherwise, the embedding object of the scrap is copied into the document rather than the data associated with the scrap. To retrieve the data for the scrap, your application must examine the class identifier, CLSID, of the scrap object by retrieving the CF_OBJECTEDESCRIPTOR file format data. If the application recognizes the CLSID, the application should transfer the native data into the document rather than calling the OleCreateFromData function.


P.S. если реализуешь - было бы любопытно глянуть на реализацию :)


 
kami ©   (2005-06-03 02:05) [6]

Ура !!!!
После долгих мучений и невозможности дорваться до компьютера (работы навалили выше ушей), все-таки сделал это!!!

Итак, реализация Drag & Drop из MemoryStream в проводник с преобразованием в файл без временного сохранения в TempDirectory. Промежуточные реализации IDataObject и IDropSource писать было лень, поэтому за основу был взят Drag and Drop Component Suite v.3.7 (бесплатный, с открытыми исходниками). Взять можно http://www.torry.ru/vcl/system/draganddrop/dragdrop.exe, а откуда сам скачивал - не помню :))


TFileContent=record
    FileName:string;
    FileSize:Longint;
    FileIStream:IStream;
 end;
TDropContentFileSource=class (TDropSource)
 protected
       function DoGetData(const FormatEtcIn: TFormatEtc;
                out Medium: TStgMedium):HRESULT; override;
      { вызывается в IDataObject.GetData}
 private
       FFileContentsCount:integer;
       procedure FillFileDescriptor(FileIndex: integer;var FD:TFileDescriptor);
 public
       FileContents:array[0..maxFormats-1] of TFileContent;
       constructor Create(aOwner: TComponent); override;
       procedure AddFileContent(FileName:string; var Stream:TMemoryStream; FreeAfterAdd:Boolean);
       procedure DeleteFileContent(FileName:string);overload;
       procedure DeleteFileContent(index:integer);overload;
 published
       property FileContentsCount:integer read FFileContentsCount;
 end;
//--------------------------------------------------------
procedure TStreamToIStream(var Stream:TMemoryStream;var stm:IStream;FreeAfterCopy:Boolean);
var
  p:Int64;
begin
    if not assigned(Stream) then
       stm:=nil
    else
        if CreateStreamOnHGlobal(0,False,stm)=S_OK then
           begin
                stm._AddRef;
                stm.SetSize(Stream.size);
                stm.Write(Stream.Memory,Stream.Size,@p);
                stm.Seek(0,STREAM_SEEK_SET,p);
                if FreeAfterCopy then
                   Stream.Free;
           end;
end;

{ TDropContentFileSource }

procedure TDropContentFileSource.AddFileContent(FileName: string;
 var Stream: TMemoryStream; FreeAfterAdd: Boolean);
begin
    FileContents[FFileContentsCount].FileName:=FileName;
    FileContents[FFileContentsCount].FileSize:=Stream.Size;
    TStreamToIStream(Stream,FileContents[FFileContentsCount].FileIStream,FreeAfterAdd);
    inc(FFileContentsCount);
end;

constructor TDropContentFileSource.Create(aOwner: TComponent);
begin
 inherited Create(AOwner);

 FFileContentsCount:=0;
 AddFormatEtc(CF_FileGroupDescriptor,nil,DVASPECT_CONTENT,-1, Tymed_HGLOBAL);
 AddFormatEtc(CF_FileContents,nil,DVAspect_Content,-1,Tymed_IStream);
end;

procedure TDropContentFileSource.FillFileDescriptor(FileIndex:integer;var FD:TFileDescriptor);
begin
    FD.dwFlags:=FD_FILESIZE or FD_ATTRIBUTES or FD_CREATETIME;
    FD.nFileSizeHigh:=0;
    FD.nFileSizeLow:=FileContents[FileIndex].FileSize;
    StrPCopy(@FD.cFileName[0],FileContents[FileIndex].FileName);
    FD.dwFileAttributes:=FILE_ATTRIBUTE_NORMAL;
    FD.ftCreationTime.dwLowDateTime:=LoWord(DateTimeToFileDate(Now));
    FD.ftCreationTime.dwHighDateTime:=HiWord(DateTimeToFileDate(Now));
end;

function TDropContentFileSource.DoGetData(const FormatEtcIn: TFormatEtc;
 out Medium: TStgMedium): HRESULT;
var
  pFileGroup:pFileGroupDescriptor;
begin
    Result:=DV_E_FORMATETC;
    Medium.tymed:=0;
    Medium.unkForRelease:=nil;
    Medium.hglobal:=0;
    if FormatEtcIn.cfFormat=CF_FileGroupDescriptor then
       if (FormatEtcIn.dwAspect=DVAspect_Content) and
          (FormatEtcIn.tymed=Tymed_HGlobal) then
          begin
               Medium.tymed:=Tymed_HGlobal;
               Medium.hGlobal:=GlobalAlloc(GMEM_Share or GHND,SizeOf(TFileGroupDescriptor)+SizeOf(TFileDescriptor)+1);
               if Medium.hGlobal=0 then
                  begin
                       Result:=E_OutOfMemory;
                       exit;
                  end;
               pFileGroup:=GlobalLock(Medium.HGlobal);
               pFileGroup^.cItems:=1;
               FillFileDescriptor(0,pFileGroup^.fgd[0]);
               GlobalUnLock(Medium.HGlobal);
               Result:=S_OK;
          end;
    if FormatEtcIn.cfFormat=CF_FileContents then
       if (FormatEtcIn.tymed and Tymed_IStream)<>0  then
          begin
               Medium.tymed:=Tymed_IStream;
               Medium.unkForRelease:=nil;
               Medium.stm:=Pointer(FileContents[FormatEtcIn.lindex].FileIStream);
               Result:=S_OK;
          end;
end;

В принципе, все :)) Осталось только пара неясных вопросов - как в FileGroupDescriptor можно запихнуть несколько дескрипторов файлов, ну и разобраться, почему при закрытии тестового приложения вылазит AV. Последнее - мелочи :)
Ежели кто может сказать где в этом коде глюкодром - пожалуйста, ткните меня носом.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.041 c
3-1116476386
dreamse
2005-05-19 08:19
2005.06.29
Какой коммандой удалить базу из SQL сервера ?


3-1116589157
ZakJ
2005-05-20 15:39
2005.06.29
Помогите пожалуйста с запросом!


8-1109699665
Руслана
2005-03-01 20:54
2005.06.29
Где можно почитать о создании собственного кодека (аудио)


1-1117624080
Anics
2005-06-01 15:08
2005.06.29
Как отловить событие внутри родительской формы MDI приложен


14-1117970147
Juice
2005-06-05 15:15
2005.06.29
Глючит проводник. Что делать ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский