суббота, 31 октября 2009 г.

Перетаскивание объекта оболочки, часть 5: заставляем кого-нибудь делать за нас работу

Это перевод Dragging a shell object, part 5: Making somebody else do the heavy lifting. Автор: Реймонд Чен.

Создание изображения для перетаскивания было делом непростым. К счастью, элемент управления ListView более чем готов сделать часть работы для нас.

Выбросите весь код из обработчика FormMouseDown. Вместо этого, мы заставим ListView делать всю работу.
procedure TForm1.FormCreate(Sender: TObject);
begin
FListView := CreateWindow(WC_LISTVIEW, nil, WS_CHILD or WS_VISIBLE or LVS_ICON or LVS_SHAREIMAGELISTS, -1, -1, 1, 1, Handle, 1, HInstance, nil);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
DestroyWindow(FListView);
end;

function TForm1.SetFileName(const ATarget: String): Boolean;
var
sfi: SHFILEINFO;
item: TLVItem;
himl: HIMAGELIST;
begin
if FListView <> 0 then
begin
ListView_DeleteItem(FListView, 0);

himl := SHGetFileInfo(PChar(ATarget), 0, sfi, SizeOf(sfi), SHGFI_SYSICONINDEX or SHGFI_DISPLAYNAME or SHGFI_LARGEICON);
if himl = 0 then
Exit(False);

ListView_SetImageList(FListView, himl, LVSIL_NORMAL);

item.iSubItem := 0;
item.mask := LVIF_TEXT or LVIF_IMAGE;
item.pszText := sfi.szDisplayName;
item.iImage := sfi.iIcon;
Result := (ListView_InsertItem(FListView, Item) >= 0);
if Result then
ListView_SetItemState(FListView, 0, LVIS_SELECTED, LVIS_SELECTED);
end
else
Result := False;
end;
Теперь мы навешиваем всё на ListView. В том числе и иконку для перетаскивания:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
pdto: IDataObject;
pds: IDropSource;
dwEffect: Integer;
FileName: String;
pdsh: IDragSourceHelper;
begin
FileName := Edit1.Text;
if SUCCEEDED(GetUIObjectOfFile(Handle, FileName, IID_IDataObject, pdto)) then
begin
if SetFileName(FileName) then
if SUCCEEDED(CoCreateInstance(CLSID_DragDropHelper, nil, CLSCTX_ALL, IID_IDragSourceHelper, pdsh)) then
pdsh.InitializeFromWindow(FListView, TPoint(nil^), pdto);

pds := TDropSource.Create;
if Succeeded(DoDragDrop(pdto, pds, DROPEFFECT_COPY or DROPEFFECT_LINK or DROPEFFECT_MOVE, dwEffect)) then
begin
if (dwEffect and DROPEFFECT_MOVE) <> 0 then
DeleteFile(FileName);
CheckPerformedEffect(pdto);
end;
end;
end;
Вместо самостоятельного получения изображения, мы добавляем элемент в ListView и создаём изображение, передавая его в метод IDragSourceHelper.InitializeFromWindow.

Элемент управления ListView делает всю работу по созданию изображения для перетаскивания и установки его в объект. В нашем конкретном случае это может и не намного проще предыдущего варианта, но если вы добавите возможность множественного перетаскивания, то использование метода IDragSourceHelper.InitializeFromWindow будет намного проще, потому что тогда ListView будет делать всю работу по генерации списка иконок.

Прим. пер.: ну, в оригинале тут стояло создание видимого ListView, добавление в него элемента и таскание иконок из него, а не отдельной командой. От этого, кстати, зависит вид изображения при перетаскивании нескольких объектов.

Ну вот и всё по теме инициации операции drag/drop. Возвращаемся к обычным темам на один день.

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

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