Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.10.30;
Скачать: CL | DM;

Вниз

Как передать содержимое файла в Clipboard   Найти похожие ветки 

 
kami ©   (2005-08-27 17:05) [0]

Не пойму, как в этом случае использовать CFSTR_FILECONTENTS и CFSTR_FILEDESCRIPTOR. В MSDN только упоминается, что это используется в StgMedium - структуре. Но вот Что и Как передавать в SetClipboardData?
Если кто сталкивался с подобным - подскажите, пожалуйста.


 
kami ©   (2005-08-27 17:18) [1]

По аналогии с Drag&Drop сперва должна передаваться структура TFileGroupDescriptor, а затем - содержимое каждого файла.
Попробовал на одном файле и, само собой, ничего не получил. Кажется, из-за того, что при передаче контента файла Clipboard не знает, в каком формате сохранен контент.
procedure TForm1.bbOkClick(Sender: TObject);
const
 FFileContentsCount=1;
var
 pFileGroup:pFileGroupDescriptor;
 i:integer;
 P:PChar;
begin
 CF_FILECONTENTS := RegisterClipboardFormat(CFSTR_FILECONTENTS);
 CF_FILEGROUPDESCRIPTOR := RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);

 if not OpenDialog.Execute then
   exit;
 s:=TMemoryStream.Create;
 s.LoadFromFile(OpenDialog.FileName);
 s.Position:=0;
 if not OpenClipboard(0) then
   exit;
 EmptyClipboard;
 hGl:=GlobalAlloc(GMEM_Share or GHND,SizeOf(TFileGroupDescriptor)+1);
 if hGl=0 then
   exit;
 pFileGroup:=GlobalLock(HGl);
 pFileGroup^.cItems:=FFileContentsCount;
 { Fill FileDescriptor}
 for i:=0 to FFileContentsCount-1 do
   FillFileDescriptor(i,pFileGroup^.fgd[i]);// процедура опробована  в Drag&Drop
 GlobalUnLock(HGl);
 SetClipboardData(CF_FILEGROUPDESCRIPTOR,HGl);
 //TStreamToIStream(s,Istm,true);
 Hgl:=GlobalAlloc(GMEM_Share or GHND,S.Size);
 p:=GlobalLock(hGl);
 CopyMemory(p,s.Memory,s.Size); // пробовал и через IStream
 GlobalUnlock(hGl);
 SetClipboardData(CF_FILECONTENTS,hGl);// вот здесь, скорее всего
 CloseClipboard;
end;


Вот и непонимаю, что именно нужно этому SetClipboardData?


 
alpet ©   (2005-08-27 17:26) [2]

Вот просмотрщик текстового буфера обмена:

uses Windows;

function streq (p1, p2: pchar): boolean;
var n: dword;
begin
n  := 0;
while (p1 [n] = p2 [n]) and
      (p1 [n] <> #0) do Inc (n);
result := p1 [n] = p2 [n];
end;

const maxbuff = 128 * 1024;
var hWnd, hgl: THandle;
    msg: tagMSG;
    ptxt: PChar;
    ptmp: PChar;
begin
ptmp := VirtualAlloc (nil, maxbuff, MEM_COMMIT,  PAGE_READWRITE);
// non standard technicus - creating Edit control as primary window
hWnd := CreateWindowEx (WS_EX_DLGMODALFRAME, "Edit", "",
                WS_VISIBLE or ES_READONLY or WS_SYSMENU or WS_THICKFRAME ,
                CW_USEDEFAULT, CW_USEDEFAULT, 200, 50,
                0, 0, hInstance, nil);
GetWindowText (hWnd, ptmp, maxbuff);
while IsWindow (hWnd) do
 begin
  if PeekMessage (msg, hWnd, 0, 0, PM_REMOVE) then
   begin
    TranslateMessage(msg);
    DispatchMessage (msg);
    GetWindowText (hWnd, ptmp, maxbuff);
   end;
  if OpenClipboard (hWnd) then
   begin
    hgl := GetClipboardData(CF_TEXT);
    if 0 <> hgl then
     begin
      ptxt := GlobalLock (hgl);
      if not streq (ptxt, ptmp) then
      if Assigned (ptxt) then SetWindowText (hWnd, ptxt);
      GlobalUnlock (hgl);
     end;
    CloseClipboard;
   end;
  sleep (10);
 end;
end.


 
alpet ©   (2005-08-27 17:32) [3]

Ек, совсем не в тему запостил. Тут оказывается shell механизм, по копированию файлов исследуется.


 
kami ©   (2005-08-27 17:36) [4]

2 [2] alpet ©

Да с CF_TEXT проблем-то нет, проблема в следующем (извините, что сначала неточно объяснил) : есть TMemoryStream, в нем - содержимое "почти" файла. Каким образом его можно отправить в буфер обмена, чтобы при Ctrl-V в проводнике появился файл.


 
kami ©   (2005-08-27 18:03) [5]

Попробовал скопировать через TSTGMEDIUM (GlobalAlloc этой структуры и в SetClipboardData) - та же история, просмотрщик буфера обмена пишет, что не может отобразить данные. :(

ЗЫ. Блин, не думал, что это будет сложнее, чем сделать Drag&Drop контента файлов.:((


 
alpet ©   (2005-08-27 18:10) [6]

А имя файла где копируется (CFSTR_FILENAME)?


 tagSTGMEDIUM = record
   tymed: Longint;
   case Integer of
     0: (hBitmap: HBitmap; unkForRelease: IUnknown);
     1: (hMetaFilePict: THandle);
     2: (hEnhMetaFile: THandle);
     3: (hGlobal: HGlobal);
     4: (lpszFileName: POleStr);
     5: (stm: IStream);
     6: (stg: IStorage);
 end;
 TStgMedium = tagSTGMEDIUM;

Про эту структуру речь идет?


 
kami ©   (2005-08-27 18:22) [7]

Именно про нее, имена файлов сохраняются в TFileGroupDescriptor, который идет в hGlobal. В [1] я сразу попробовал отправить TFileGroupDescriptor в буфер обмена.
var
 Medium:TSTGMEDIUM;
//==========================
 hGl:=GlobalAlloc(GMEM_Share or GHND,SizeOf(TStgMedium));
 pMedium:=GlobalLock(hGl);
 Medium:=pMedium^;// мне так удобнее

 Medium.tymed:=Tymed_HGlobal;
 Medium.hGlobal:=GlobalAlloc(GMEM_Share or GHND,SizeOf(TFileGroupDescriptor)+1);
  if Medium.hGlobal=0 then
   begin
     GlobalUnlock(hGl);
     GlobalFree(hGl);
     exit;
   end;
   pFileGroup:=GlobalLock(Medium.HGlobal);
   pFileGroup^.cItems:=FFileContentsCount;
   { Fill FileDescriptor}
   for i:=0 to FFileContentsCount-1 do
     FillFileDescriptor(i,pFileGroup^.fgd[i]);// именно здесь заполняются FileNames

   GlobalUnLock(Medium.HGlobal);
   GlobalUnlock(hGl);
   SetClipboardData(CF_FILEGROUPDESCRIPTOR,hGl);


 
alpet ©   (2005-08-27 18:30) [8]

Хм. Вот структура TFileGroupDescriptor

_FILEGROUPDESCRIPTORA = record
   cItems: UINT;
   fgd: array[0..0] of TFileDescriptor; // one item in array !!!
 end;


Небезопасно ее создавать динамически, для кол-ва файлов > 1.


 
alpet ©   (2005-08-27 18:34) [9]

У тебя строка:

Medium.hGlobal:=GlobalAlloc(GMEM_Share or GHND,SizeOf(TFileGroupDescriptor)+1);

выделяет структуру только для одного файла.

А в цикле:

for i:=0 to FFileContentsCount-1 do
   FillFileDescriptor(i,pFileGroup^.fgd[i]);

может записываться гораздо больше.


 
kami ©   (2005-08-27 18:38) [10]

Ну да, кажется, с Игорем Шевченко мы уже разбирали этот случай - описание структуры прямиком перекочевало из С, а там при таком объявлении можно указывать любой элемент. Все решается переобъявлением fgd на динамический массив. Пользуюсь уже долго, никаких нареканий.
Ну а для тестовой задачи можно пользоваться и таким :)


 
kami ©   (2005-08-27 18:40) [11]

2 [9] alpet ©
В самом начале -
const
FFileContentsCount=1;


Мне пока не нужно "много" файлов, хотя бы один "запуздырить":)


 
kami ©   (2005-08-27 18:44) [12]

Вообще, по крайней мере при Drag&Drop сперва отправляется StgMedium с TFileGroupDescriptor, а потом идут запросы CFSTR_FILECONTENTS на содержимое каждого файла в (опять-таки) StgMedium. Как именно они отправлены - указывается в StgMedium.Tymed
Вот именно так я и попробовал - сперва в буфер отправляю StgMedium с TFileGroupDescriptor, а потом StgMedium, в котором stm - содержимое моего файла.
Увы, Clipboard этого не понимает :(.


 
alpet ©   (2005-08-27 18:56) [13]

А статус выполнения/ошибки у всех функций хороший?


 
kami ©   (2005-08-27 19:07) [14]

[13] alpet ©
Вроде, да. Правда, если SetClipboardData возвращает не INVALID_HANDLE_VALUE, GlobalAlloc, CloseClipboard - тоже отрабатывает нормально.


 
kami ©   (2005-08-27 19:08) [15]

[14] kami ©
Убрать Правда, если


 
kami ©   (2005-08-27 21:32) [16]

УРААА !!!!!

Как всегда, всем спасибо, особенно себе, любимому :)

Проблема решена с помощью OleSetClipboard и IDataObject !!!!
Все работает просто вЕлИкОлЕпнО :)).



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

Текущий архив: 2005.10.30;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.044 c
14-1128760068
Buss
2005-10-08 12:27
2005.10.30
Фраза


1-1128932639
BanderLog
2005-10-10 12:23
2005.10.30
RadioButton + onChecking (onChecked)


14-1128683529
y-soft
2005-10-07 15:12
2005.10.30
Очередное присуждение шНобелевской премии


14-1128107818
Loginov Dmitry
2005-09-30 23:16
2005.10.30
Matrix. Оцените новую систему матричных вычислений для Delphi


2-1128534097
The Sound
2005-10-05 21:41
2005.10.30
Ошибка, при использовании ShellApi.