Текущий архив: 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.49 MB
Время: 0.042 c