Оболочка (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 приведёт к перемещению файла.
В следующий раз мы добавим поддержку перемещения, просто посмотреть, как это работает.
Хочу дополнить эту статью ссылкой компоненты dragdrop для Delphi
ОтветитьУдалитьКак сделать под win8 (64bit)?
ОтветитьУдалитьТочно так же.
ОтветитьУдалить