Delphi programming blog
Источник: http://teran.karelia.pro/articles/item_4407.html
 

Windows 7, списки переходов и Delphi

Опубликовано 18.03.2010 г. 22:52

Одним из расширений панели задачи в Windows 7 являются списки переходов (JumpLists). Управление данными списками в Delphi осуществляется с помощью COM интерфейса ICustomDestinationList. Как и в прошлый раз расширим функциональность нашей программы. Элементы списков переходов сгруппированы в категории. Существуют 3 вида стандартный категорий: Последние/Recent, часто используемые/Frequent и Задачи/Tasks. Также существует возможность добавлять свои категории, что правда у меня так и не получилось. Для приложений в категориях Последние и Часто используемые содержаться ссылки на документы соответствующего характера, при этом за приложением должны быть закреплены типы файлов. В категории Задачи формируются списки наподобие ярлыков, т.е путь к исполняемому файлу и строка параметров запуска. Таким образом, с помощью списка задач можно запускать либо какие то приложения, либо запускать собственное приложение, с помощью чего можно например добиться изменения какого нить статуса приложения или т.п. В скайпе (skype) например с помощью задач организовано переключение статусов (в сети/оффлайн и т.п). Элементы списков могут быть представлены двумя типами это IShellItem и IShellLink. Вообще, изначально я хотел реализовать список задач, в котором будут перечислены статусы из прошлого примера, и собственно чтобы при клике на элементы списка статус переключался. Поскольку подобные вещи я раньше никогда не реализовывал, и не знаю как это вообще делается, то сейчас рассмотрим только методы формирования списка. Остальное в следующий раз, мб к тому времени разберусь почему у меня и Произвольные категории не создаются в списке. Собственно для формирования списка задач добавим в раздел private описания класса TMainForm процедуру создания списков

procedure CreateJumpList();

вызов которой добавим в конце обработчика OnCreate формы. Итак рассмотрим непосредственно саму процедуру по порядку. Для начала нам нужен объект с помощью которого можно манипулировать списками переходов.

var cdl : ICustomDestinationList;
    cdl := CreateComObject(CLSID_DestinationList) as ICustomDestinationList;

вся работа со списком перехода заключена между двумя вызовами данного объекта: методы beginList начинает сессию изменения, и в конце вызывается CommitList, вообще еще есть AbortList. метод beginList возвращает при этом максимальное возможное количество отображаемых элементов списка maxSlots, которое задается в системе, а также массив элементов (из категорий частых и последних), которые пользователь собственноручно удалил из данных списков removed.

var maxSlots : Cardinal;
    removed : IObjectArray;

    cdl.BeginList(maxSlots,IID_IObjectArray,removed);

после этого нам потребуется собственная коллекция/массив элементов в который мы будем добавлять наши новые задачи.

var oc : IObjectCollection;

    oc := CreateComObject(CLSID_EnumerableObjectCollection) as IObjectCollection;

теперь пробежимся по нашему массиву состояний taskStates и на его основе создадим задачи.

 var state : TTaskState;
    for state in taskStates do begin
         ....
    end;

Собственно в теле цикла описывается создание и добавление в нашу коллекцию элементов. Для этого надо создать объекта IShellLink. Установить для него путь к исполняемому файлу (команду), описание для подсказки, аргументы командной строки, еще можно добавить иконку. Командой будет собственно сама наша программа, аргументом строки (для последщей реализации переключения состояний) будет значение/код состояния.

 var link : IShellLink;
        link := CreateComObject(CLSID_ShellLink) as IShellLink;
        link.SetPath(pChar(application.ExeName));
        link.SetDescription(pChar(state.name + ' description'));
        link.SetArguments(pChar(intToStr(state.value)));
        link.SetIconLocation(pChar('Shell32.dll'),2);

что касается заголовков для отображения элемента IShellLink, то тут все немного сложнее. (IShellItem можно просто добавлять в список). Нам понадобится получить интерфейс IPropertyStore, с помощью которого можно установить значение TPropVariant для ключа PKEY_Title (TPropertyKey).

const PKEY_TITLE : TPropertyKey = ( fmtID : '{F29F85E0-4FF9-1068-AB91-08002B27B3D9}'; pID : 2);
var    propStore : IPropertyStore;
    titleValue : TPropVariant;

        propStore := link as IPropertyStore;

        titleValue.vt := VT_LPWSTR;
        titleValue.pwszVal := pChar(state.name);

        propStore.SetValue(PKEY_Title, titleValue);
        propStore.Commit;

после чего добавить наш объект ShellLink в коллекцию OC.

    oc.AddObject(link);

На этом тело цикла заканчивается. После всего с помощью метода addUserTasks нашу коллекцию мы добавим в список переходов, и завершим изменения списка методмо commitList

    cdl.AddUserTasks(oc as IObjectArray);
    cdl.CommitList;

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

Собственно теоретически, добавление собственной категории и элементов в нее должно осуществлять следующим кодом перед CommitList:

        oc.clear();
        SHCreateItemFromParsingName(pChar(application.exeName),nil,IID_IShellItem,item);
        oc.AddObject(Item);
        oArray := oc as IShellItem;
        hr := cdl.AppendCategory('My Custom Category',oArray);

в моем случае функция добавления категории возвращает E_ACCESSDENIED. MSDN говорит что это из за групповых политик. мне сдается что это мб из за того что у меня отключены recent&frequent в настройках панели задач. хотя если их включить то данный код вобще выдает access violation :) надо поизучать.

Метки:  windows 7  |  jumplists  |  tasks 

Комментарии

Владислав
29.12.2010 в 11:50
Можешь выложить проэкт в котором реализованы списки переходов.
Санёк
17.09.2012 в 11:24
не работает код...
прошел по ветке выше..
в первой статье темы тоже не работает - но есть исходник., скачал исходник, там кстати тоже народ жаловался что не работает. оказалось не все приписал в разделе uses, походу и здесь тоже самое - например не ясно откуда взялся интерфейс removed : IObjectArray, я об имени типа в переменной. Потом вобщемто не понятно еще в паре мест - вот исходник точно бы все непонятки разогнал. исходничек плиз.
а так - респект и уважуха! подругому назвать никак. просто до меня не доходит. туповат.
Qwerty
02.10.2012 в 23:59
Тоже не заработал. Ждём исходники. Спасибо за статью!
teran
06.10.2012 в 22:24
исходник прицепил.
к сожалению боюсь код там не особо качественный, ибо слишком давно это было все.
- Имя
- e-mail*
- Сайт
вы можете использовать теги [i],[b],[code],[quote]
Дополнительно