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

Вниз

программно вырезать указанный файл в буфер обмена   Найти похожие ветки 

 
pest   (2009-06-15 16:47) [0]

привет всем.
есть путь к файлу. нужно программно вырезать этот файт в буфер обмена, чтобы вне программы пользователь мог просто нажать ctrl+v в какой-либо папке, и вырезанный файл вставился туда.
копировать в буфер умею, но вырезать не знаю как(
заранее благодарен за ответ


 
Сергей М. ©   (2009-06-15 16:53) [1]

"Вырезание" есть тоже самое копирование, но осуществляемое под контролем клипборд-вьюера в контексте приложения, инициировавшего "вырезание".


 
pest   (2009-06-15 17:08) [2]

Сергей, спасибо что откликнулись.

приведу пример кода:


procedure CopyFilesToClipboard(FileList: string);
var
 DropFiles: PDropFiles;
 hGlobal: THandle;
 iLen: Integer;
begin
 iLen := Length(FileList) + 2;
 FileList := FileList + #0#0;
 hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT,
   SizeOf(TDropFiles) + iLen);
 if (hGlobal = 0) then raise Exception.Create("Could not allocate memory.");
 begin
   DropFiles := GlobalLock(hGlobal);
   DropFiles^.pFiles := SizeOf(TDropFiles);
   Move(FileList[1], (PChar(DropFiles) + SizeOf(TDropFiles))^, iLen);
   GlobalUnlock(hGlobal);
   Clipboard.SetAsHandle(CF_HDROP, hGlobal);
 end;
end;


если я скопирую файл при помощи этого кода в буфер обмена, потом в любой папке windows нажму ctrl+v, то этот файл будет просто скопирован. а мне надо чтобы он переместился. тоесть чтобы после вставки его на прежнем месте больше не было.
но как мне это сделать, ведь вставку из буфера осуществляет сама винда, как мне ей сказать что файл вырезан а не скопирован?


 
Юрий Зотов ©   (2009-06-15 17:21) [3]

> pest

Вы не могли бы объяснить, зачем это надо?

Дело в том, что с учетом
http://delphimaster.net/view/2-1245065404/
Ваша странная затея сильно смахивает на какую-то вредительскую затею, а такие ветки подлежат истреблению.

Поэтому - поясните, плз. Кстати, не думайте, что постинги под разными никами затрудняют Вашу идентификацию. Нисколько.


 
pest   (2009-06-15 17:33) [4]

Юрий Зотов
я делаю фтп клиент. при нажатии ctrl+c на файлах, находящихся на FTP сервере, я запоминаю инфу о них. создаю специальный файлик в рабочей папке программы с этой инфой и хочу вырезать ее в буфер.
затем при вставке инфы из буфера, у меня есть возможность отследить изменение буфера (т.к. после копирования и вставки из буфера, не вызывается его изменение. а после вырезания и вставки - изменение вызывается). я определяю что это мой файл с моей инфой и начинаю скачивать файлы с фтп и сохранять их на компьютер.
возможно это не самый грамотный способ, но не профи..

на счет указанного вами поста, это инициатива моего коллеги помочь мне. я заметил непосредственно после своего поста. у нас один внешний ip провайдера.


 
Сергей М. ©   (2009-06-15 17:43) [5]

см. CFSTR_PREFERREDDROPEFFECT

http://msdn.microsoft.com/en-us/library/bb776902(VS.85).aspx#CFSTR_PREFERREDDROPEFFECT


 
pest   (2009-06-16 10:18) [6]

Сергей,
почитал, но.. все стало еще непонятнее. есть CFSTR_PREFERREDDROPEFFECT который может принимать значения DROPEFFECT_COPY / DROPEFFECT_CUT?
или как они связаны? и причем здесь IDataObject и PreferredDropEffect() и тд. также начитался:

Technical: What we are doing is adding the CFSTR_PREFERREDDROPEFFECT clipboard format with a data value DROPEFFECT_COPY. This will tell the drop source that we are intending to do a copy operation.

Preferred DropEffect (CFSTR_PREFERREDDROPEFFECT). This is just a "global" DWORD number which in this case is set to DROPEFFECT_COPY. This informs the target which pastes the data to create a copy of the file. If this was a cut operation then the preferred effect would be set to DROPEFFECT_MOVE, instructing the target to delete the original file after copying. Note that despite its name, this format is applicable for both clipboard and drag-drop transfers.

как все это связано и как мне практически реализовать вырезание файла так и не понял. можно ли показать для примера хоть пару строчек кода на delphi? я был бы очень благодарен. ато я не пойму (


 
oldman ©   (2009-06-16 11:30) [7]


> копировать в буфер умею, но вырезать не знаю как


Скопировать и удалить )


 
brother ©   (2009-06-16 11:31) [8]

> Скопировать и удалить )

аха и потом не вставить?) файло- прощай)


 
oldman ©   (2009-06-16 11:40) [9]


> brother ©   (16.06.09 11:31) [8]


С "вырезать" такая же беда :)


 
brother ©   (2009-06-16 11:41) [10]

> С "вырезать" такая же беда :)

если мы все еще про буфер обмена, то нет) только посветлеет)


 
Сергей М. ©   (2009-06-16 11:44) [11]


> pest   (16.06.09 10:18) [6]


Эксплорер при выполнении операции Paste From Clipboard смотрит, есть ли в клипборде DWORD-данные в формате, зарегистрированном под предопределенным именем CFSTR_PREFERREDDROPEFFECT = "Preffered DropEffect". Если есть, читает эти данные сравнивает прочитанное с одной из предопределенных констант, среди которых  DROPEFFECT_COPY = 1 и DROPEFFECT_MOVE = 2. Если это DROPEFFECT_MOVE, то при операции вставки из клипборда, т.е. после успешного создания копий "вырезанных" объектов Эксплорер самостоятельно удаляет оригиналы этих объектов.

Полагаю что так)


 
oldman ©   (2009-06-16 11:45) [12]


> brother ©   (16.06.09 11:41) [10]


Старый стал, помню плохо :(


 
pest   (2009-06-16 11:47) [13]

копировать и удалять не вариант.
кстати, процедура
procedure CopyFilesToClipboard(FileList: string);
которую я указал выше, не рабоотает (. возможно есть какието конфликты с юникодом? у меня delphi 2009.

зы уже несколько функций беру из инета, которые постят повсюду и вроде работающие, а у меня с ошибками..


 
pest   (2009-06-16 11:58) [14]


> Сергей М. ©   (16.06.09 11:44) [11]

допустим по теории это так, но вы, как программист делфи, как видете практическую реализацию вырезания файла, исходя из этой теории?

надо ведь както эти DWORD-данные установить вручную?


 
Сергей М. ©   (2009-06-16 12:08) [15]


> надо ведь както эти DWORD-данные установить вручную?


Конечно надо)

1. Регистрируем формат CFSTR_PREFERREDDROPEFFECT с пом. RegisterClipboardFormat()

2. Выделяем глоб.блок памяти размером в sizeof(dword), записываем в этот блок константу DROPEFFECT_MOVE

3. Записываем в клипборд хэндл глоб.блока, указав формат, полученный в п.1


 
pest   (2009-06-16 13:19) [16]


> Сергей М. ©   (16.06.09 12:08) [15]


имеется в виду что-то вроде этого?
procedure TForm1.Button2Click(Sender: TObject);
var
 hGlobal: THandle;
 f: Cardinal;
begin
 f := RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
 hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, sizeof(dword));
 hGlobal := DROPEFFECT_MOVE;
 Clipboard.SetAsHandle(f, hGlobal);
end;


скорее всего нет, поправьте меня плиз


 
clickmaker ©   (2009-06-16 13:31) [17]

> hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT,
> sizeof(dword));
> hGlobal := DROPEFFECT_MOVE;

жесть! присваивание имеет накопительный эффект? -)

procedure TForm1.Button2Click(Sender: TObject);
var
hGlobal: THandle;
f: Cardinal;
d: PCardinal;
begin
f := RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, sizeof(dword));
d := PCardinal(GlobalLock(hGlobal));
d^ := DROPEFFECT_MOVE;
SetClipboardData(f, hGlobal);
GlobalUnlock(hGlobal);
end;


 
pest   (2009-06-16 13:43) [18]


> clickmaker ©   (16.06.09 13:31) [17]

если учитывать что мне надо вырезать файл, то где я указываю имя файла?

аналогично вопрос решен в следующей процедуре:
procedure CopyFilesToClipboard(FileList: string);
var
DropFiles: PDropFiles;
hGlobal: THandle;
iLen: Integer;
begin
iLen := Length(FileList) + 2;
FileList := FileList + #0#0;
hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT,
  SizeOf(TDropFiles) + iLen);
if (hGlobal = 0) then raise Exception.Create("Could not allocate memory.");
begin
  DropFiles := GlobalLock(hGlobal);
  DropFiles^.pFiles := SizeOf(TDropFiles);
  Move(FileList[1], (PChar(DropFiles) + SizeOf(TDropFiles))^, iLen);
  GlobalUnlock(hGlobal);
  Clipboard.SetAsHandle(CF_HDROP, hGlobal);
end;
end;


но она почему-то не работает. может надо делать на ее примере и вместо d: PCardinal; использовать DropFiles: PDropFiles;? но в этом случае не могу занести DROPEFFECT_MOVE в DropFiles^.


 
имя   (2009-06-16 14:01) [19]

Удалено модератором


 
имя   (2009-06-16 14:03) [20]

Удалено модератором


 
Сергей М. ©   (2009-06-16 14:55) [21]


> pest   (16.06.09 13:43) [18]
>
>


> где я указываю имя файла?


В строке


> Clipboard.SetAsHandle(CF_HDROP, hGlobal);



> мне надо вырезать файл


Вот для этого и надо проделать дополнительные телодвижения, проиллюстрированные в [17]


 
pest   (2009-06-16 16:41) [22]

возился долго, но результата так и не достиг(.
так методом тыка у меня ничего не получится, я же не гигантские алгоритмы прошу, а всего-лишь доработку имеющейся небольшой процедуры копирования, которая не работает почемуто. для опытных это пара минут, а мне головняк уже несколько дней в форумах


 
clickmaker ©   (2009-06-16 16:54) [23]

> [22] pest   (16.06.09 16:41)
> возился долго, но результата так и не

так опубликуй, что получилось


 
Сергей М. ©   (2009-06-16 17:09) [24]


> pest   (16.06.09 16:41) [22]


procedure CopyFilesToClipboard(FileList: string);
var
 DropFiles: PDropFiles;
 hGlobal: THandle;
 iLen: Integer;
 f: Cardinal;
 d: PCardinal;
begin
 Clipboard.Open;

// это твой код один-в-один

 iLen := Length(FileList) + 2;
 FileList := FileList + #0#0;
 hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, SizeOf(TDropFiles) + iLen);
 Win32Check(hGlobal <> 0);
 DropFiles := GlobalLock(hGlobal);
 DropFiles^.pFiles := SizeOf(TDropFiles);
 Move(FileList[1], (PChar(DropFiles) + SizeOf(TDropFiles))^, iLen);
 GlobalUnlock(hGlobal);
 Clipboard.SetAsHandle(CF_HDROP, hGlobal);

// а это те самые дополнительные телодвижения, см. [15], [17]

 f := RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
 hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, sizeof(dword));
 d := PCardinal(GlobalLock(hGlobal));
 d^ := DROPEFFECT_MOVE;
 SetClipboardData(f, hGlobal);
 GlobalUnlock(hGlobal);

 Clipboard.Close;
end;


Сложно , да ?)


 
pest   (2009-06-16 17:41) [25]

моя возня:

procedure CopyFilesToClipboard(FileList: ansistring);
var
 DropFiles: PDropFiles;
 hGlobal: THandle;
 iLen: Integer;
begin
 iLen := Length(FileList) + 2;
 FileList := FileList + #0#0;
 hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT,
   SizeOf(TDropFiles) + iLen);
 if (hGlobal = 0) then raise Exception.Create("Could not allocate memory.");
 begin
   DropFiles := GlobalLock(hGlobal);
   DropFiles^.pFiles := SizeOf(TDropFiles);
   Move(FileList[1], (PChar(DropFiles) + SizeOf(TDropFiles))^, iLen);

   GlobalUnlock(hGlobal);
   Clipboard.SetAsHandle(CF_HDROP, hGlobal);
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
//  CopyFilesToClipboard("C:\boot.ini"#0"C:\AutoExec.Bat");
 CopyFilesToClipboard(Edit1.Text);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 hGlobal: THandle;
 f: Cardinal;
 d: PCardinal;
begin
 f := RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
 hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, sizeof(dword));
 d := PCardinal(GlobalLock(hGlobal));
 d^ := DROPEFFECT_MOVE;
 GlobalUnlock(hGlobal);
 SetClipboardData(f, hGlobal);
end;


нажимаю по очереди первую и вторую кнопки.

но получаю ошибку на строке Clipboard.SetAsHandle(CF_HDROP, hGlobal); которая выглядит так:
Инструкция по адресу "0x7c911f6c" обратилась к памяти по адресу "0x00000002". Память не может быть "read".

эта же ошибка возникает на той же строке в коде, приведенном Сергеем:

procedure CopyFilesToClipboard(FileList: string);
var
DropFiles: PDropFiles;
hGlobal: THandle;
iLen: Integer;
f: Cardinal;
d: PCardinal;
begin
Clipboard.Open;

// это твой код один-в-один

iLen := Length(FileList) + 2;
FileList := FileList + #0#0;
hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, SizeOf(TDropFiles) + iLen);
Win32Check(hGlobal <> 0);
DropFiles := GlobalLock(hGlobal);
DropFiles^.pFiles := SizeOf(TDropFiles);
Move(FileList[1], (PChar(DropFiles) + SizeOf(TDropFiles))^, iLen);
GlobalUnlock(hGlobal);
Clipboard.SetAsHandle(CF_HDROP, hGlobal);

// а это те самые дополнительные телодвижения, см. [15], [17]

f := RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, sizeof(dword));
d := PCardinal(GlobalLock(hGlobal));
d^ := DROPEFFECT_MOVE;
SetClipboardData(f, hGlobal);
GlobalUnlock(hGlobal);

Clipboard.Close;
end;


 
clickmaker ©   (2009-06-16 17:49) [26]

а так?

Move(FileList[1], (PChar(DropFiles) + SizeOf(TDropFiles))^, iLen);
SetClipboardData(CF_HDROP, hGlobal);
GlobalUnlock(hGlobal);


 
pest   (2009-06-16 17:53) [27]


> clickmaker ©   (16.06.09 17:49) [26]


аналогично (
запускаю через exe выдает ошибку.
запускаю через делфи, выкидывает в дебагер


 
clickmaker ©   (2009-06-16 18:25) [28]

в принципе, вот это лишнее - FileList := FileList + #0#0;
поскольку и так GMEM_ZEROINIT, а строку можно передавать как const, т.е. не создавать лишних копий.


 
clickmaker ©   (2009-06-16 18:26) [29]

а как заполняется FileList?


 
DVM ©   (2009-06-16 18:32) [30]

Ошибка скорее всего в том, как заполняется список файлов.


 
pest   (2009-06-16 19:01) [31]


> clickmaker ©   (16.06.09 18:26) [29]
> а как заполняется FileList?


берется из Edit1.Text.
там путь к картинке. довольно короткий и даже без русских символов


 
Сергей М. ©   (2009-06-16 22:42) [32]


> нажимаю .. первую ..получаю ошибку на строке Clipboard.SetAsHandle(CF_HDROP, hGlobal)


Что-то я не понял .. Откуда она у тебя взялась, эта ошибка ?
Ты же сам сказал - "копировать в буфер умею".
Значит этот код как работал у тебя, так и должен работать, ибо никаких изменений он не претерпел ..


 
pest ©   (2009-06-16 23:05) [33]


> Сергей М. ©   (16.06.09 22:42) [32]


я нашел эту процедуту в инете ее очень много в неизменном виде. и сразу начал искать именно то, что мне нужно...а именно - вырезать.
потом начал тестить и отписался что код не работает. см pest   (16.06.09 11:47) [13]

и нигде не видел обсуждения этой процедуры, вроде как четко должна была работать..


 
Сергей М. ©   (2009-06-17 08:15) [34]


> pest ©   (16.06.09 23:05) [33]
>
>


Код , приведенный в [24], у меня успешно работает. Именно в D7.


 
pest ©   (2009-06-17 09:39) [35]


> Код , приведенный в [24], у меня успешно работает. Именно
> в D7.

ясно. значит дело всетаки в delphi 2009, скорее всего юникод. надо теперь туда копать


 
clickmaker ©   (2009-06-17 10:57) [36]

> надо теперь туда копать

DropFiles.fWide := 1;


 
clickmaker ©   (2009-06-17 10:58) [37]

ну и iLen * 2


 
pest ©   (2009-06-17 11:05) [38]

Общими усилиями мы добились результата. Не знаю как в D7, но в Delph&#305; 2009 работает нормально.
Собственно, сабж:

uses ...
 ShlObj, ClipBrd, ActiveX;


procedure CopyFilesToClipboard(const AFiles: TStringList; MoveFiles: Boolean = false);
var
 DropFiles: PDropFiles;
 hGlobal: THandle;
 iLen: Integer;
 f: Cardinal;
 d: PCardinal;
 FileList: string;
begin
 Clipboard.Open;

 FileList := StringReplace(AFiles.Text, #13#10, #0, [rfReplaceAll]);
 FileList := trim(FileList) + #0#0;
 iLen := Length(FileList) * SizeOf(char);
 hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, SizeOf(TDropFiles) + iLen);
 Win32Check(hGlobal <> 0);
 DropFiles := GlobalLock(hGlobal);
 DropFiles^.pFiles := SizeOf(TDropFiles);

 {$IFDEF UNICODE}
  DropFiles^.fWide := true;
 {$ENDIF}

 Move(FileList[1], (PansiChar(DropFiles) + SizeOf(TDropFiles))^, iLen);
 SetClipboardData(CF_HDROP, hGlobal);
 GlobalUnlock(hGlobal);

 if MoveFiles then
   begin
     f := RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
     hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, sizeof(dword));
     d := PCardinal(GlobalLock(hGlobal));
     d^ := DROPEFFECT_MOVE;
     SetClipboardData(f, hGlobal);
     GlobalUnlock(hGlobal);
   end;

 Clipboard.Close;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
 List: TStringList;
begin
 List := TStringList.Create;
 List.Add(Edit1.Text);
 List.Add(Edit2.Text);
 CopyFilesToClipboard(List, true);
end;


Всем участникам спасибо за помощь


 
pest ©   (2009-06-17 11:07) [39]


> clickmaker


немного опоздал, но всеравно спасибо


 
Gnomus   (2009-07-06 02:22) [40]

А как это перефразировать?



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

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

Наверх





Память: 0.56 MB
Время: 0.005 c
15-1246869777
b/@.
2009-07-06 12:42
2009.09.06
Простой вопрос по Format


2-1246968716
cyber-pilot
2009-07-07 16:11
2009.09.06
Формат даты


15-1246528418
DelphiN!
2009-07-02 13:53
2009.09.06
Определить замыкание 2х ножек com порта


2-1246964960
rassl
2009-07-07 15:09
2009.09.06
Классы форм


2-1246706971
NIIL
2009-07-04 15:29
2009.09.06
ADO + MySQL кодировка





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский