[Решено] Перетаскивание (файла) НАРУЖУ

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Re: Перетаскивание (файла) НАРУЖУ

Сообщение скалогрыз » 15.08.2016 06:26:20

kotompazb писал(а):в старом обработчике MouseDown перед BeginDrag я смотрел Shift: TShiftState и при зажатом Shift менял курсор (и режим с переноса на копирование, но это тонкости). Вот где (в каком обработчике) это (изменять курсор и режим) лучше сделать сейчас (и как), я пока не понял. Если проверять

а разве Shift во время драга (MouseMove), не может поменяться?
я так преполагаю, что NativeDragDrop должен какие-то евенты на этот счёт иметь.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Перетаскивание (файла) НАРУЖУ

Сообщение kotompazb » 15.08.2016 11:55:00

скалогрыз писал(а):а разве Shift во время драга (MouseMove), не может поменяться?
я так преполагаю, что NativeDragDrop должен какие-то евенты на этот счёт иметь.

Там все очень упрощенно. Эвента там всего четыре: OnDragBegin, OnDragEnd, OnDragGetFileList, OnDragGetStringData.
В старом обработчике да, у меня было сделано довольно криво, надо было зажать до начала Drag, тогда же и курсор менялся и флаг режима переноса/копирования, в процессе переноса ни то, ни другое уже не менялось. Коряво, согласен, но достаточно юзабельно, если быть в курсе этой тонкости, а нужный тип курсора как раз и указывает какой режим задействован. В принципе, полтора моих пользователя на это ни разу не жаловались, я ж не коммерческую програмку пишу, все джаст фо фан, так сказать. А щас поменять курсор что-то совсем пока никак не выходит. Уже и не знаю, может просто стоит поспать :)
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Перетаскивание (файла) НАРУЖУ

Сообщение скалогрыз » 15.08.2016 17:04:56

kotompazb писал(а):Там все очень упрощенно. Эвента там всего четыре: OnDragBegin, OnDragEnd, OnDragGetFileList, OnDragGetStringData.

Понятно. Там только DataSource реализован, а DropTarget нет.

Предлагаю, сделать правильным путём, а не обходным! Займёт чуток больше времени, но в итоге дложно красиво получиться.

Добавлено спустя 3 часа 4 минуты:
вот "NativeDropTarget" компонент. Как использовать (после установки в Lazarus, доступен в закладке "System").

1) Положить на форму
2) Назначить "Control" (тот контрол в который файлы складываются)
3) Назначать OnDragAction - что делать при DragEnter, DragOver
4) Назначить OnDrop - что делать при дропе.

События OnDragAction и OnDrop имеют одинаковые параметры
* Sender: TObject; - (ссылка на TNativeDropTarget)
* Data: TNativeDataSource; - объект, которые показывает, что "притащили"
* X, Y: Integer; - коордианты мышки (относительно контрола)
* AShiftState: TShiftState; - состояние клавиатуры + мышки
* var AAction: TNativeDropAction - какое действие нужно соверщить при drop-е. (в завимисомти от Action-а поменяется и курсор). Возможные значения:
** ndaNodrop - файлы не принимаются
** ndaCopy - файлы "будут скопированы"
** ndaMove - файлы "будут перенесены"
** ndaLink - файлам "создаться линк"
В DragAction ешё дополнительно есть
* ADragAction: TDragState; - DragEnter, DragMove и DragLeave. Состояние добавлено параметром, вместо того чтобы плодить три метода.

У объекта Data есть два метода
* GetType() которые вернёт тип данных - либо dsFile (если файлы) либо dsOther (если что-то нещё)
* GetFiles() - получить список файлов.
Пример использования
Код: Выделить всё
procedure TForm1.NativeDropTarget1DragAction(Sender: TObject;
  Data: TNativeDataSource; ADragAction: TDragState; X, Y: Integer;
  AShiftState: TShiftState; var AAction: TNativeDropAction);
begin
  if Data.GetType=dsFiles then
    AAction:=ndaCopy
  else
    AAction:=ndaNodrop;
end;

procedure TForm1.NativeDropTarget1Drop(Sender: TObject;
  Data: TNativeDataSource; X, Y: Integer; AShiftState: TShiftState;
  var AAction: TNativeDropAction);
var
  st: TStringList;
begin
  st:=TStringList.Create;
  try
    Data.GetFiles(st);
    Memo1.Lines.Assign(st); 
  finally
    st.Free;
  end
end;

Работаем только под винду.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Перетаскивание (файла) НАРУЖУ

Сообщение kotompazb » 15.08.2016 21:32:06

Спасибо. А я уже с IDropTarget начал разбираться (туговато правда до меня все это доходит).
Ну попробую теперь NativeDropTarget.
Спасибо.

Добавлено спустя 6 часов 56 минут 52 секунды:
В общем все должно (играюсь в тестовом проекте, чтобы ничего не поломать) работать КРОМЕ:
никак не выходит изменить TNativeDropAction действие. Работает только ndaCopy. При попытке назначить в обработчике DragAction любого другого действия, происходит запрет Drop. Особенно обидно, что в моем случае мне всего-то нужно поменять курсор (сам тип операции я храню в отдельном флаге). Похоже тут загвоздка в NativeDragSource...
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Перетаскивание (файла) НАРУЖУ

Сообщение скалогрыз » 16.08.2016 06:35:58

kotompazb писал(а):Похоже тут загвоздка в NativeDragSource...

DragDropWin32.pas
строчка 135
Код: Выделить всё
  DoDragDrop(DataObject, DropSource, DROPEFFECT_COPY, @DWEffect);

Третий параметр, это список тех действий, которые разрашены. Если тебе нужен Move, то нужно поменять строчку на:
Код: Выделить всё
  DoDragDrop(DataObject, DropSource, DROPEFFECT_COPY or DROPEFFECT_MOVE, @DWEffect);

ну либо тупо все перечислить,
Код: Выделить всё
const
  AllowedMoves = DROPEFFECT_COPY or DROPEFFECT_MOVE or DROPEFFECT_LINK;
...

  DoDragDrop(DataObject, DropSource, AllowedMoves, @DWEffect);

а можно попробовать брутально: $FFFFFFFF :) (сработает, но от греха подальше я бы так не делал)
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Перетаскивание (файла) НАРУЖУ

Сообщение kotompazb » 16.08.2016 07:41:49

Вот. Спасибо. Вроде теперь все должно работать, как и должно :)
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Перетаскивание (файла) НАРУЖУ

Сообщение скалогрыз » 16.08.2016 07:57:51

kotompazb писал(а):Вот. Спасибо. Вроде теперь все должно работать, как и должно

heaptrc бы тебе натравить на эту новую сборку... для верности!
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Перетаскивание (файла) НАРУЖУ

Сообщение kotompazb » 16.08.2016 08:14:21

И еще вот такой вопрос (точнее просьба совета):
Временные файлы для копирования будут создаваться в обработчике OnDragGetFileList, а удалять их лучше в OnClose формы, правильно?
скалогрыз писал(а):heaptrc бы тебе натравить на эту новую сборку... для верности!

У меня он подключен в режиме сборки Debug. Так что натравлю:)
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Перетаскивание (файла) НАРУЖУ

Сообщение скалогрыз » 16.08.2016 08:40:20

kotompazb писал(а):Временные файлы для копирования будут создаваться в обработчике OnDragGetFileList, а удалять их лучше в OnClose формы, правильно?

смотря куда они потом упали :)
но если упали наружу, то боюсь, то да - только при OnClose (информации от "наружи" когда она закончила с этими файлами работать у тебя нет)

Дополнительное колдунство с IDataObject поидее может тебе разрешить забыть про эти файлы вообще, НО самый кратчайший путь - чистить на OnClose. Конечно, проблема в том, что программу можно закрыть ещё до завершения копирования.

Можно применить "серверный подход". Файлы чистить не на OnClose, а на OnIdle или OnStart. Причём чистить только временные файлы, которым по возрасту больше 24 часов (для верности)

... или вообще заставить систему их чистить при перезапуске :D
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Перетаскивание (файла) НАРУЖУ

Сообщение kotompazb » 16.08.2016 09:11:53

скалогрыз писал(а):heaptrc бы тебе натравить на эту новую сборку... для верности!

Даааа... Есть такое, причем даже если ничего не делать. Просто открыть приложение, и закрыть.
31 unfreed memory blocks...


скалогрыз писал(а):Дополнительное колдунство с IDataObject поидее может тебе разрешить забыть про эти файлы вообще

Это если создавать их в памяти? Через CFSTR_FILECONTENTS и CFSTR_FILEDESCRIPTOR?

Добавлено спустя 14 минут 17 секунд:
kotompazb писал(а):31 unfreed memory blocks...

В общем так. Если просто бросить на форму NativeDropTarget, то все еще нормально. А вот если назначить ему Contol, то завершение с ошибкой External: SIGSEGV и последующая ругань от heaptrc. Очищаем свойство, прога снова начинает закрываться молча и спокойно.

Добавлено спустя 19 минут 9 секунд:
Так. Сменил тип отладочной информации на Автоматический (-g), раньше там было -gw -godwarfsets, получил номер строки с ошибкой:
1830 в control.inc, тут:
Код: Выделить всё
  if FControlHandlers[HandlerType]=nil then
    FControlHandlers[HandlerType]:=TMethodList.Create;

При этом тестовое приложение валится немного в другом месте, строка 7927 в wincontrol.inc
Код: Выделить всё
HandleAllocated := (FHandle <> 0);


И да у меня не последний Lazarus - 1.4.4, FPC - 2.6.4
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Перетаскивание (файла) НАРУЖУ

Сообщение скалогрыз » 16.08.2016 16:43:26

kotompazb писал(а):В общем так. Если просто бросить на форму NativeDropTarget, то все еще нормально. А вот если назначить ему Contol, то завершение с ошибкой External: SIGSEGV и последующая ругань от heaptrc. Очищаем свойство, прога снова начинает закрываться молча и спокойно

Чуть-чуть сократил код, чтобы не надется на LCL-ые эвенты. Сейчас должно стать чисто.

А ведь NativeDragAndDrop таких проблем избежал, именно потому, что Control ему в design-time не назачить (что есть нарушение RAD концпеции - поводил мышкой - срубил копусты)

kotompazb писал(а):Это если создавать их в памяти? Через CFSTR_FILECONTENTS и CFSTR_FILEDESCRIPTOR?

может быть... а размеры файлов большие? и как они в самой программе храняться?
У вас нет необходимых прав для просмотра вложений в этом сообщении.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Перетаскивание (файла) НАРУЖУ

Сообщение kotompazb » 17.08.2016 07:16:15

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

Там 2 варианта. Прога работает с образами дисков CP/M.
Так вот. В первом варианте, если это образ гибкого диска, то само собой суммарный объем файлов не очень большой. Поэтому файлы вычитываются в память и все манипуляции с ними происходят именно там. Пока не нажата кнопка "Сохранить".
А вот во втором варианте, когда работа происходит с образом HDD, суммарный объем может быть очень большим. Поэтому в память считывается только информация о файлах и их расположении в образе. А при необходимости что-либо сделать с файлом, он временно загружается в буфер в памяти, там с ним делается все, что нужно, сразу после этого файл из этого буфера сохраняется обратно в образ. Так это CP/M, то объем одного файла может быть не таким уж и большим, а вот всех сразу...
Пользователю же никто не запретит выделить все файлы и попытаться их перетащить мышью в TC или проводник. В текущем виде, эти файлы просто "распаковываются" в Temp, а затем приемник получает список их путей.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Перетаскивание (файла) НАРУЖУ

Сообщение скалогрыз » 17.08.2016 07:57:42

kotompazb писал(а):Там 2 варианта.

пока имеет смысл остановится на том, что есть :)
Но в твоём случае, т.к. ты оперируешь с образом, использование CFSTR_FILECONTENTS с CFSTR_FILEDESCRIPTOR будет в разы эффективнее.

Но на закрытие программы скорей всего придёться хитрить. Вместо закрытия, нужно будет просто её прятать, в том случае если операция с порождённым IDataObject всё ещё идёт.

И да - нужно допиливать NativeDragDrop, чтобы он выдавал информацию о том используется ли IDataObject, а так же мог использовать в качестве источника данных TStream.
Соответственно нужно допиливать NativeDrop чтобы он умел принимать не только CF_HDROP формат.
Непочатый край работы :D
Кстати, гер Бернд, сказал что поддерживать компонент не планирует, т.к. сил и желания нет.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Перетаскивание (файла) НАРУЖУ

Сообщение kotompazb » 17.08.2016 08:44:02

Да оставлю уже как есть. Работает вроде вполне.
скалогрыз писал(а):Но в твоём случае, т.к. ты оперируешь с образом, использование CFSTR_FILECONTENTS с CFSTR_FILEDESCRIPTOR будет в разы эффективнее.

Это наверное только для FDD-образов. Насколько я понял, для CFSTR_FILECONTENTS с CFSTR_FILEDESCRIPTOR все перетаскиваемые файлы должны находиться в памяти сразу.
скалогрыз писал(а):И да - нужно допиливать NativeDragDrop, чтобы он выдавал информацию о том используется ли IDataObject

Ну в данный момент это было бы полезно, чтобы подчищать Temp оперативно, а не в onClose.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Перетаскивание (файла) НАРУЖУ

Сообщение скалогрыз » 17.08.2016 16:43:52

kotompazb писал(а):Это наверное только для FDD-образов. Насколько я понял, для CFSTR_FILECONTENTS с CFSTR_FILEDESCRIPTOR все перетаскиваемые файлы должны находиться в памяти сразу.

должно храниться описание к этим файлам.
А тела файлов будут доступны через IStream. Что в случае HDD должно существенно сэкономить место, т.к. не нужно делать временный файл, а копировать прямо из образа.

ЗЫ: смотрю сейчас на документацию в MSDN-е. Толи это я повзрослел, и теперь осознанно читаю документацию (сказыавется накопленный опыт), то ли MS привело документацию в порядок. Потому что во времена "закрытой библиотеки на Делфи" офф-лайн документация понятностью не блистала.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Пред.След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 240

Рейтинг@Mail.ru