Оболочка (shell) даёт вам для этого IDataObject; всё, что вам нужно сделать - просто перетаскивать его (это первая часть в серии из пяти постов).
Начните с пустого VCL-приложения, и добавьте функцию GetUIObjectOfFile из предыдущей статьи. Также вам нужно будет добавить вызовы OleInitialize и OleUninitialize (вызовы CoInitialize(Ex) и CoUninitialize в предыдущей статье за нас делал модуль ComObj) - поскольку теперь мы собираемся использовать полноценный OLE, а не просто COM:
unit Unit1;Чтобы начать операцию drag/drop, нам понадобится источник для это операции (drop source):
interface
...
implementation
...
var
SaveInitProc: Pointer;
NeedToUninitialize: Boolean;
procedure InitComObj;
begin
if SaveInitProc <> nil then
TProcedure(SaveInitProc);
NeedToUninitialize := Succeeded(OleInitialize(nil));
end;
initialization
SaveInitProc := InitProc;
InitProc := @InitComObj;
finalization
if NeedToUninitialize then
OleUninitialize;
end.
type
TDropSource = class(TInterfacedObject, IDropSource)
protected
// *** IDropSource ***
function QueryContinueDrag(fEscapePressed: BOOL; grfKeyState: Longint): HResult; stdcall;
function GiveFeedback(dwEffect: Longint): HResult; stdcall;
end;
function TDropSource.QueryContinueDrag(fEscapePressed: BOOL; grfKeyState: Longint): HResult;
begin
if fEscapePressed then
Exit(DRAGDROP_S_CANCEL);
if (grfKeyState and (MK_LBUTTON or MK_RBUTTON)) = 0 then
Exit(DRAGDROP_S_DROP);
Result := S_OK;
end;
function TDropSource.GiveFeedback(dwEffect: Longint): HResult;
begin
Result := DRAGDROP_S_USEDEFAULTCURSORS;
end;
Как вы можете видеть, реализация источника необычайно скучна. Даже интересные методы не интересны.
Метод IDropSource.QueryContinueDrag довольно стереотипен. Если была нажата кнопка Escape - тогда мы отменяем операцию перетаскивания. Если кнопки мыши были отпущены, то мы завершаем операцию. В противном случае - просто продолжаем перетаскивание.
Метод IDropSource.GiveFeedback ещё менее интересен. Он просто возвращает DRAGDROP_S_USEDEFAULTCURSORS, чтобы указать, что мы хотим использовать визуальное оформление по-умолчанию.
Верите вы или нет, но теперь у нас есть всё, чтобы перетащить файл.
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;Чтобы перетащить объект, вам нужны две вещи: перетаскиваемый объект (data object) и источник (drop source). Мы создали наш источник выше, а перетаскиваемый объект приходит к нам из оболочки. Всё, что осталось сделать - начать операцию перетаскивания, вызовом функции DoDragDrop.
Shift: TShiftState; X, Y: Integer);
var
pdto: IDataObject;
pds: IDropSource;
dwEffect: DWORD;
begin
// В настоящей программе, конечно же, вы не будете использовать
// жёстко зашитые пути.
if SUCCEEDED(GetUIObjectOfFile(Handle, 'C:\Windows\clock.avi', IID_IDataObject, pdto)) then
begin
pds := TDropSource.Create;
DoDragDrop(pdto, pds, DROPEFFECT_COPY or DROPEFFECT_LINK, dwEffect);
end;
end;
Заметьте, что мы указали, что мы разрешаем операции DROPEFFECT_COPY и DROPEFFECT_LINK. Мы специально запретили DROPEFFECT_MOVE, потому что наша программа не представляет собой окно типа папки в Проводнике; пользователь не ожидает, что операция drag/drop приведёт к перемещению файла.
В следующий раз мы добавим поддержку перемещения, просто посмотреть, как это работает.

1 комментарий(ев):
Хочу дополнить эту статью ссылкой компоненты dragdrop для Delphi
Отправить комментарий
Можно использовать некоторые HTML-теги, например:
<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>
Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).
Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.
Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.