Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.02.2012, 11:39   #1
kuzduk
Пользователь
 
Регистрация: 02.01.2010
Сообщений: 58
Стрелка Как вырезать файл в буфер обмена?

Нужно вырезать файл в буфер обмена в моей программе. Так, чтобы потом можно было этот вырезанный файл вставить в любом файловом менеджере (Ctrl+V): проводник, TotalCommander, DubleCommander...

в прикреплённым ниже файле: все функции для копирования/вырезки/вставки через буфер обмена:

http://forum.sources.ru/index.php?ac...ttach_id=16203

Пользуйтесь на здоровье!
мой сайт: kuzduk.ru

Последний раз редактировалось kuzduk; 17.02.2012 в 11:54.
kuzduk вне форума Ответить с цитированием
Старый 10.08.2012, 23:32   #2
kuzduk
Пользователь
 
Регистрация: 02.01.2010
Сообщений: 58
Стрелка

Модуль усовершенсвовал. Качаем и радуемся жизни: http://kuzduk.narod.ru/UIP/kuShell.pas


Также заходим на мой сайт там много полезных модулей: http://kuzduk.narod.ru/_tvor.html
мой сайт: kuzduk.ru
kuzduk вне форума Ответить с цитированием
Старый 11.08.2012, 00:06   #3
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Хорошо. Но о комбинации Ctrl+X(команда "вырезать" в контекстном меню) вы не слышали?

Посмотрел KuModul функций много и есть полезные, НО комментариев нет даже к функционалу, а они должны быть как минимум! Молчу уже об комментах к коду...
Кроме того, есть некоторые поправки к некоторым, мягко говоря, функциям, которые сделаны убого....

Про KuLanguage я молчу, т.к. даже боюсь спрашивать, под каким кайфом его писали О том, что все контейнерные компоненты(формы, панели и.т.д.) имеют методы перебора содержимого и обращения к его методам, а уж тем более о RTTI, вы не слышали....

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

Прочитал про стиль комментирования кода, УВЫ... исходя из того, что в ваших модулях вообще нет осмысленных комментариев/ описаний того, чтоже делает такая-то функция/метод(молчу о комментированном коде т.к. таковой вообще не наблюдается) выводы сами сделаете, по своим же понятиям.
Человек_Борща вне форума Ответить с цитированием
Старый 11.08.2012, 00:46   #4
kuzduk
Пользователь
 
Регистрация: 02.01.2010
Сообщений: 58
По умолчанию

Цитата:
Человек_Борща;1085409]Хорошо. Но о комбинации Ctrl+X(команда "вырезать" в контекстном меню) вы не слышали?
Слышал и чё? Что вы хотели этим сказать? Я как раз и хотел научить свою прогу вырезать. С помощью kuShell это теперь лекго сделать благодаря имеющимся функциям.




Цитата:
Посмотрел KuModul функций много и есть полезные, НО комментариев нет даже к функционалу, а они должны быть как минимум! Молчу уже об комментах к коду...
Да. Пожалуй вы правы, комментариев очень мало. Буду коментировать.


Цитата:
Кроме того, есть некоторые поправки к некоторым, мягко говоря, функциям, которые сделаны убого....
Буду премного благодарен за критику с пояснениями.


Цитата:
Про KuLanguage я молчу, т.к. даже боюсь спрашивать, под каким кайфом его писали
Буду премного благодарен за критику с пояснениями.


Цитата:
О том, что все контейнерные компоненты(формы, панели и.т.д.) имеют методы перебора содержимого и обращения к его методам, а уж тем более о RTTI, вы не слышали....
Буду премного благодарен за критику с пояснениями.


Цитата:
Посмотрел все исходники. Увы где-то "странная" реализация, может это из-за того, что я вижу в несколько другом свете, более простой подход к решению некоторых задач в исходниках.
Буду премного благодарен за критику с пояснениями. Например что бы вы сделали по другому и почему?

Цитата:
Прочитал про стиль комментирования кода,
Про стиль оформления болков писал, а про "стиль комментирования" ни слова не писал. Не путайте и не подменитвайте понятия.

Цитата:
УВЫ... исходя из того, что в ваших модулях вообще нет осмысленных комментариев/ описаний того, чтоже делает такая-то функция/метод(молчу о комментированном коде т.к. таковой вообще не наблюдается) выводы сами сделаете, по своим же понятиям.
Да. комментариев негусто в моих модулях. Вывод простой: модули надо дорабатывать, коментировать. Зелено. Я их только-только оформил и выложил.





Жду ответов на мои вопросы по поводу аргументированной критики с примерами как и что keit сделать - буду очень признателен.
мой сайт: kuzduk.ru

Последний раз редактировалось kuzduk; 11.08.2012 в 00:50.
kuzduk вне форума Ответить с цитированием
Старый 11.08.2012, 00:51   #5
kuzduk
Пользователь
 
Регистрация: 02.01.2010
Сообщений: 58
По умолчанию

В этой теме давайте будем общаться только про модуль kuShell - про вырезания/копирования и вставляния.

Я потом отдельные темы создам по другим модулям.
По другим модулям всю критику пожалуйста в личку или на почту
мой сайт: kuzduk.ru
kuzduk вне форума Ответить с цитированием
Старый 11.08.2012, 01:14   #6
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Цитата:
Буду премного благодарен за критику с пояснениями.
Компоненты-контейнеры имеют свойства:
ComponentCount
Components
ControlCount
Controls

со всеми вытекающими...

Код:
for i:=0 to Form1.ComponentCount -1 do
  begin
    //Находим все кнопки на форме
    if (Components[i] is TButton) then
    begin
      (Components[i] as TButton).<Обращение к кнопке>
    end;
  end;
Там же есть и метод FindComponent

Об Run-Time Type Information в сети много написано. Да и поиск по форуму никто не отменил.

Цитата:
"Реализованы убого"
Хм.. ну допустим ваша:
Код:
function RandomName(NameLength: integer) : string;
из KuModul.

я бы написал её вот так:
Код:
function GenPass(aLength:SmallInt): string;
const
  Buff = 'qwertyuiopasdfghjklzxcvbnmZXCVBNMASDFGHJKLQWERTYUIOP1234567890';
var
  i: smallInt;
  pwd: string;
begin
  for i := 1 to aLength do
  begin
    pwd := pwd + Buff[RandomRange(1, Length(Buff))]; //uses System.Math;
  end;
  Result := pwd;
end;
Почему? Потому что строка - это уже массив символов. А вы делаете массив из массивов символов, что вообще не нужно делать.

Далее по KuShell....
Код:
function Shell_Str(Strs: TStrings) : string;
1. У TStrings есть свойство Text.
2. Также есть нуль-терминальные строки именуемые PChar.

Посему работа функции сводится к простому:
Result:=PChar(Str.Text);

Так же есть мнение, что система сама заботится о признаке конца строки при помещении текста в буфер.

По поводу работы БО(Буффер обмена).
Не надо его очищать ибо кроме текста тамможет находится куча всего(картинки к примеру). И система сама разбирается, что и куда можно вставить без последствий и epic win'а.

Нету блоков Try Finally, Try Except.

Последний раз редактировалось Человек_Борща; 11.08.2012 в 01:21.
Человек_Борща вне форума Ответить с цитированием
Старый 11.08.2012, 09:34   #7
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

По интерфейсу модуля...

Shell_Str/Shell_DataOperations не имеет смысла выносить в interface, поскольку это низкоуровневые функции, которыми пользуются другие (высокоуровневые) функции модуля.

Неочевидное название Clipboard_DataSend. Возможно, было бы лучше использовать имена вроде ClipboardFilesCopy/ClipboardFilesPaste.

Неправильно спроектирована ClipBoard_GetDataList:
1). Непонятно, где взять описатель для её параметра. Лучше, чтобы она получала параметр сама.
2). Возврат создаваемого объекта результатом функции - плохое решение.

Неочевидный параметр MoveType.

Итого:
Код:
unit kuShell;

interface

uses
  Classes;

type
  TClipboardFileMove = (cfmCut, cfmCopy);

// Копирует или вырезает файлы в буфер обмена
procedure ClipboardFilesCopy(const AFiles: TStrings; const AMoveType: TClipboardFileMove = cfmCopy);
// Возвращает список файлов из буфера обмена
procedure ClipboardFilesEnum(const AFiles: TStrings);
// Вставляет файлы из буфера обмена в указанную папку
procedure ClipboardFilesPaste(const ATargetFolder: String);

implementation
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 11.08.2012, 10:11   #8
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

По реализации...

Нестандартный стиль оформления.

Отсутствует обработка ошибок.

ClipBoard_GetDataList:

Перепутаны байты и символы в вызове DragQueryFile.

По этой же причине, статический буфер - не самая удачная идея.

Итого:
Код:
procedure ClipboardFilesEnum(const AFiles: TStrings);
var
  ClipHandle: THandle;
  i, FileCount: Integer;
  FileName: String;
begin
  AFiles.BeginUpdate;
  try
    AFiles.Clear;

    Clipboard.Open;
    try
      ClipHandle := Clipboard.GetAsHandle(CF_HDROP);
      if ClipHandle = 0 then
        Exit;

      FileCount := DragQueryFile(ClipHandle, $FFFFFFFF, nil, 0);
      for i := 0 to FileCount - 1 do
      begin
        SetLength(FileName, MAX_PATH);
        SetLength(FileName, DragQueryFile(ClipHandle, i, PChar(FileName), Length(FileName)));
        if FileName <> 0 then
          AFiles.Add(FileName);
      end;
    finally
      Clipboard.Close;
    end;
  finally
    AFiles.EndUpdate;
  end;
end;
ClipBoard_DataPaste:

Вместо if h <> 0 then { большой кусок кода } лучше использовать if h = 0 then exit;

Утечка памяти (не удаляется TStringList) из-за вышеупомянутого неверного дизайна ClipBoard_GetDataList.

Вместо Copy(Sourse, 0, Pos(#0, Sourse) - 1) лучше просто взять первый файл в списке от ClipBoard_GetDataList.

Вместо IncludeTrailingBackslash нужно использовать IncludeTrailingPathDelimiter.

При сравнении имён файлов (и путей) нужно использовать не "равно", а SameFileName.

Обе ветки if можно (и нужно) объединить, введя параметризацию.

Clipboard_SendType не используется нигде более и должна быть сделана локальной.

Аналогично, case нужно параметризировать и свернуть.

Clipboard_SendType:

Не понятно, чего это здесь используется OpenClipboard, хотя в остальном коде - Clipboard.Open.

Вместо 'Preferred DropEffect' нужно использовать CFSTR_PERFORMEDDROPEFFECT.

Вообще, я не спец в буфере обмена, но зачем надо перечислять форматы, если можно просто сделать IsClipboardFormatAvailable/Clipboard.HasFormat?

Итого:
Код:
procedure ClipboardFilesPaste(const ATargetFolder: String);

  function ClipboardFilesType: TClipboardFileMove;
  var
    DropEffect: THandle;
    ClipHandle: THandle;
    Mem: Pointer;
  begin
    DropEffect := RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT);
    Win32Check(DropEffect <> 0);

    ClipHandle := Clipboard.GetAsHandle(DropEffect);
    if ClipHandle = 0 then
    begin
      Result := cfmCopy;
      Exit;
    end;

    Mem := GlobalLock(ClipHandle);
    try
      if PLongword(Mem)^ = 2 then
        Result := cfmCut
      else
        Result := cfmCopy;
    finally
      GlobalUnlock(ClipHandle);
    end;
  end;

var
  ClipHandle: THandle;
  Files: TStringList;
  FilesStr: String;
  SourceFolder: String;
  TargetFolder: String;
  Operation: DWORD;
  CopyFlags: DWORD;
begin
  if not Clipboard.HasFormat(CF_HDROP) then
    Exit;

  Clipboard.Open;
  try
    ClipHandle := Clipboard.GetAsHandle(CF_HDROP);
    if ClipHandle = 0 then
      Exit;

    Files := TStringList.Create;
    try
      ClipboardFilesEnum(Files);
      if Files.Count = 0 then
        Exit;
      SourceFolder := ExtractFilePath(Files[0]);
      FilesStr := Shell_Str(Files);
    finally
      FreeAndNil(Files);
    end;

    TargetFolder := IncludeTrailingPathDelimiter(ATargetFolder);
    CopyFlags := FOF_SIMPLEPROGRESS;
    case ClipboardFilesType of
      cfmCopy:
      begin
        Operation := FO_COPY;
        if SameFileName(SourceFolder, TargetFolder) then
          CopyFlags := FOF_RENAMEONCOLLISION
        else
          CopyFlags := 0;
      end;
      cfmCut:
        Operation := FO_MOVE;
    else
      Assert(False);
    end;

    Shell_DataOperations(FilesStr, ATargetFolder, Operation, CopyFlags);
  finally
    Clipboard.Close;
  end;
end;
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 11.08.2012, 10:17   #9
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Вместо волшебных констант 2, 5 и т.п. нужно использовать DROPEFFECT_NONE, DROPEFFECT_COPY, DROPEFFECT_MOVE, DROPEFFECT_LINK. И откуда там вообще 5 взялось?
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 12.08.2012, 16:00   #10
kuzduk
Пользователь
 
Регистрация: 02.01.2010
Сообщений: 58
По умолчанию

Цитата:
Компоненты-контейнеры имеют свойства:
ComponentCount
Components
ControlCount
Controls

со всеми вытекающими...

Код:
for i:=0 to Form1.ComponentCount -1 do
  begin
    //Находим все кнопки на форме
    if (Components[i] is TButton) then
    begin
      (Components[i] as TButton).<Обращение к кнопке>
    end;
  end;
Там же есть и метод FindComponent

Об Run-Time Type Information в сети много написано. Да и поиск по форуму никто не отменил.
не знаю абсолютно что сие значит RTTI и зачем оно, но обязательно почитаю. Спасибо!



Цитата:
Хм.. ну допустим ваша из KuModul.:
Код:
function RandomName(NameLength: integer) : string;


я бы написал её вот так:
Код:
function GenPass(aLength:SmallInt): string;
const
  Buff = 'qwertyuiopasdfghjklzxcvbnmZXCVBNMASDFGHJKLQWERTYUIOP1234567890';
var
  i: smallInt;
  pwd: string;
begin
  for i := 1 to aLength do
  begin
    pwd := pwd + Buff[RandomRange(1, Length(Buff))]; //uses System.Math;
  end;
  Result := pwd;
end;
Почему? Потому что строка - это уже массив символов. А вы делаете массив из массивов символов, что вообще не нужно делать.
Абсолютно согласен! Спасибо! так намного лучше.



Цитата:
Далее по KuShell....
Код:
function Shell_Str(Strs: TStrings) : string;
1. У TStrings есть свойство Text.
2. Также есть нуль-терминальные строки именуемые PChar.

Посему работа функции сводится к простому:
Result:=PChar(Str.Text);
Не работает! не меняет ваша функиция #13#10 на #0, а надо бы.



Цитата:
Так же есть мнение, что система сама заботится о признаке конца строки при помещении текста в буфер.
Думаю, лучше всё таки отправлять как полагается по стандарту, а то мало ли!



Цитата:
По поводу работы БО(Буффер обмена).
Не надо его очищать ибо кроме текста тамможет находится куча всего(картинки к примеру). И система сама разбирается, что и куда можно вставить без последствий и epic win'а.
Согласен. Спасибо. НО если удалить строчку Clipboard.Clear из Clipboard_DataSend, то данные не копируются/вырезаются в буфер...



Цитата:
Нету блоков Try Finally, Try Except.
Точно. Пока их не вставлял особо. Потом доработаю.



Цитата:
Shell_Str/Shell_DataOperations не имеет смысла выносить в interface, поскольку это низкоуровневые функции, которыми пользуются другие (высокоуровневые) функции модуля.
Не правы вы! Эти функции можно исползовать не только внутри модуля. Например если вы хотите скопировать файлы средсвами винды с системным окошком прогресса и анимацией:
Shell_DataOperations(Shell_Str(Sour seStrs), Shell_Str(TargetStrs), FO_COPY, 0)

или удалить:
Shell_DataOperations( Shell_Str(SourceStrs), 'КОРЗЫНА!', FO_DELETE, FOF_ALLOWUNDO )





Цитата:
Неправильно спроектирована ClipBoard_GetDataList:
1). Непонятно, где взять описатель для её параметра. Лучше, чтобы она получала параметр сама.
Это сделано специально чтоб этот парметр можно было подсовывать с разных мест, напиример при DragDrop формируется свой список данных которые начали тащить и чтоб его оперделить надо внешний хэндл в функцию пихать.


Цитата:
2). Возврат создаваемого объекта результатом функции - плохое решение.
Аракак иначе сделать? Впринципе работает номально чем плохо то?



Цитата:
Вместо волшебных констант 2, 5 и т.п. нужно использовать DROPEFFECT_NONE, DROPEFFECT_COPY, DROPEFFECT_MOVE, DROPEFFECT_LINK. И откуда там вообще 5 взялось?
дык ведь попробуйте сами! скопируйте в проводнике файл в буфер и сделайте ShowMessage(inttostr(Clipboard_Send Type)); будет 5...
мой сайт: kuzduk.ru
kuzduk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
скопировать файл в буфер обмена Rolls Общие вопросы Delphi 15 17.02.2012 01:03
Как макросом Vba определить содержит ли буфер обмена рисунок? roborrr Microsoft Office Excel 2 27.02.2011 14:24
КАк поместить файл в буфер обмена? Paul Hindenburg Общие вопросы Delphi 1 16.07.2009 10:17
Как очистить буфер обмена? StasSv Microsoft Office Excel 2 11.08.2008 17:38