Программируем панель задач Windows 7: списки переходов (ч.3)

Автор: Topol Четверг, Май 3rd, 2012 Нет комментариев

Рубрика: Операционные системы

К этому моменту вы, как я надеюсь, поняли, как создать собственный список переходов для вашего приложения. Вы также должны были оценить стандартную поддержку Windows 7  для категорий «Recent» и «Frequent» и понять, как создавать свои собственные категории. В этой статье мы рассмотрим другие возможности списков переходов и покажем, насколько просто добавлять новые задачи в список вашего приложения.

Задачи пользователя (User tasks) — это настраиваемые задачи, помещаемые в свою собственную категорию Tasks. Как разработчик вы можете установить заголовок отображаемой задачи, иконку слева и, что более важно, приложение, которое запускается, когда данная задача активируется. Вы можете представить себе задачи пользователя как ярлыки на функции, доступные в вашем приложении. Как вы помните, задачи пользователя в нашем словаре представляют собой глаголы; например, в списке Windows Media Player есть задача «Resume last playlist», а в Sticky Notes — задача «New note».

Задача пользователя обычно представляет собой объект IShellLink, который запускает любое указанное приложение (ваше приложение или любое другое, которое вы выберите) с соответствующим параметром командной строки. Хотя вы не можете распределять задачи по категориям, вы можете разделить их, используя специальный разделительный объект. Ниже приведен пример списка, который использует разделитель для разделения трех задач в группу из двух задач и еще одной дополнительной задачи:

Так что же требуется для добавления задач в список переходов? На самом деле, не так уж много. По существу, это один единственный вызов функции AddUserTasks в интерфейсе, с которым мы уже знакомы, в ICustomDestinationList (ICustomDestinationList::AddUserTasks(IObjectArray) Method). Рассматривая код, вы увидите одну единственную строку, hr = pcdl->AddUserTasks(poa);. Однако как всегда, кто-то должен создать этот poa, IObjectArray, параметр и заполнить его соответствующий информацией. Давайте рассмотрим этот процесс.

Мы создадим коллекцию IShellLinks. Эта коллекция будет позже приведена к требуемому параметру IObjectArray. Нижеприведенный код начинает этот процесс.

Код:
IObjectCollection *poc;
HRESULT hr = CoCreateInstance(
D_EnumerableObjectCollection, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&poc));
if (SUCCEEDED(hr))
{
IShellLink * psl;
hr = _CreateShellLink(L»/Task1″, L»Task 1″, &psl);
if (SUCCEEDED(hr))
{
hr = poc->AddObject(psl);
psl->Release();
}
}

Здесь вы можете видеть, что мы использовали COM (вновь) и CoCreate и IObjectCollection, poc. Далее мы вызываем вспомогательную функцию CreateShellLink, которой присваиваются три параметра:

  • Первый параметр — это аргумент командной строки для задачи
  • Второй параметр — это заголовок, который будет отображен
  • Третий параметр — это указатель на IShellLink

Затем объект заполняется соответствующей информацией.

Наконец, мы добавляем недавно созданный IShellLink в коллекцию объекта. Вы можете задаться вопросом, где же параметр, который указывает путь к исполняемому файлу, который мы планируем вызвать. Что же, это хороший вопрос. Для простоты, мы жестко задаем эту информацию, как показано в следующем фрагменте кода:

Код:
if (SUCCEEDED(hr))
{
hr = _CreateShellLink2(
L»C:Users<my user>Documents
ew text file.txt»,
L»NotePad»,
&psl);

if (SUCCEEDED(hr))
{
hr = poc->AddObject(psl);
psl->Release();
}
}

Здесь вы можете видеть, что мы вызывает жестко заданную функцию _CreateShellLink2. Ей присваиваем в качестве одного из параметров путь к текстовому файлу и запускаем Notepad (Блокнот).

Вот код для функции CreateShellLink2:

Код:
HRESULT _CreateShellLink2(
PCWSTR pszArguments, PCWSTR pszTitle,
IShellLink **ppsl)
{
IShellLink *psl;
HRESULT hr = CoCreateInstance(
CLSID_ShellLink,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&psl));
if (SUCCEEDED(hr))
{
hr = psl->SetPath(c_szNotePadExecPath);
if (SUCCEEDED(hr))
{
hr = psl->SetArguments(pszArguments);
if (SUCCEEDED(hr))
{
// Свойство заголовка требуется элементам списка,
// представленным как экземпляр IShelLink. Это значение используется
// как отображаемое имя в списке переходов.
IPropertyStore *pps;
hr = psl->QueryInterface(IID_PPV_ARGS(&pps));
if (SUCCEEDED(hr))
{
PROPVARIANT propvar;
hr = InitPropVariantFromString(pszTitle, &propvar);
if (SUCCEEDED(hr))
{
hr = pps->SetValue(PKEY_Title, propvar);
if (SUCCEEDED(hr))
{
hr = pps->Commit();
if (SUCCEEDED(hr))
{
hr = psl->QueryInterface
(IID_PPV_ARGS(ppsl));
}
}
PropVariantClear(&propvar);
}
pps->Release();
}
}
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
psl->Release();
}
return hr;
}

Сначала нам вновь следует использовать COM и CoCreate для создания COM-объекта IShellLink. Даже беглый просмотр SDK обнаруживает, что у объекта IShellLink есть множество функций. Вот несколько из них, которые мы будем использовать:

  • GetPath Получает путь и имя файла объекта, которые являются путем к исполняемому файлу
  • GetShowCmd Получает команду объекта Shell link, имя исполняемого файла
  • SetArguments Устанавливает аргументы командной строки для объекта Shell link
  • SetDescription Устанавливает описание для объекта Shell link; описание может быть любой определенной приложением строкой
  • SetIconLocation Устанавливает размещение (путь и индекс) иконки объекта Shell link
  • SetPath Устанавливает путь и имя файла для объекта Shell link
  • SetWorkingDirectory Устанавливает имя рабочей папки для объекта Shell link

Как видите, для каждого параметра мы должны получить и установить соответствующие методы. Есть и дополнительные параметры; просмотрите раздел IShellLink в SDK, если хоте узнать больше.

В примере выше мы установили путь к Notepad (при установке Windows 7 по умолчанию, c:windows
otepad.exe). Мы также жестко задали (не самая лучшая привычка) аргумент командной строки, указывающий на текстовой файл в моей папке документов (C:Users<my user>Documents
ew text file.txt). Оставшаяся часть кода устанавливает свойство заголовка, требующееся для элементов списка.

Мы вызываем CreateShellLink2 и CreateShellLink еще несколько раз, чтобы добавить все три ярлыка, как показано на скриншоте выше.

Теперь давайте добавим разделитель.

Для добавления разделителя в наш TaskList, нам необходимо создать IShellLink и установить свойство PKEY_AppUserModel_IsDestListSeparator, используя свойство COM, как показано во фрагменте кода ниже:

Код:
// Категория Tasks в списке переходов поддерживает разделительные элементы.
// Это простые экземпляры IShellLink, у которых
//  Свойство PKEY_AppUserModel_IsDestListSeparator установлено на TRUE.
// Все другие значения игрорируются.
HRESULT _CreateSeparatorLink(IShellLink **ppsl)
{
IPropertyStore *pps;
HRESULT hr = CoCreateInstance(
CLSID_ShellLink,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pps));
if (SUCCEEDED(hr))
{
PROPVARIANT propvar;
hr = InitPropVariantFromBoolean(TRUE, &propvar);
if (SUCCEEDED(hr))
{
hr = pps->SetValue(PKEY_AppUserModel_IsDestListSeparator, propvar);
if (SUCCEEDED(hr))
{
hr = pps->Commit();
if (SUCCEEDED(hr))
{
hr = pps->QueryInterface(IID_PPV_ARGS(ppsl));
}
}
PropVariantClear(&propvar);
}
pps->Release();
}
return hr;
}

Здесь вы можете видеть, что мы использовали CoCreate для создания объекта IShellLink. Далее мы установили PROPVARIANT, propvar на TRUE и установили свойство PKEY_AppUserModel_IsDestListSeparator объекта IShellLink на TRUE. Это прикажет ОС показать ISHellLinkкак разделитель, а не как обычный IShellLink.

Что ж, это было не так уж сложно. Тем не менее, давайте взглянем на укороченную версию, используя .NET. Для этого мы воспользуемсяWindows API Code pack for the .NET Framework.

Как и следует ожидать от .NET, мы получаем абстракцию большей части требуемого COM-кода. Пространство именMicrosoft.WindowsAPICodePack.Shell.Taskbar включает объект JumpListLink, который расширяет объект ShellLink и встраиваетIJumpListTasks.

Класс JumpList содержит UserTasks-коллекцию IJumpListTasks, к которой вы можете просто добавить новые объекты JumpListLink, как показано в следующем фрагменте кода:

Код:
// Путь к системному каталогу Windows
string systemFolder =
Environment.GetFolderPath(Environment.SpecialFolder.System);

jumpList.UserTasks.Add(new JumpListLink
{
Title = «Open Notepad»,
Path = Path.Combine(systemFolder, «notepad.exe»),
IconReference = new IconReference(
(systemFolder, «notepad.exe»), 0)
});

Используя синтаксис C# 3.0, мы инициализируем новый объект JumpListLink и добавляем его в коллекцию UserTasks. Как вы видите, управляемый код JumpListLink имеет очень схожие с неуправляемым свойства (что очень разумно). Мы также добавили иконку к ярлыку Блокнота в коде выше, но не указали никаких параметров командной строки.

Вы хотите добавить разделитель? Что же, это также очень просто: просто добавьте объект JumpListSeparator к коллекции UserTasks.

Код:
jumpList.UserTasks.Add(new JumpListSeparator());

Заметьте, пожалуйста, что, как всегда, работая с Windows Code pack API Taskbar, вы должны вызвать функцию «refresh», чтобы подтвердить изменения, как мы объяснили это в предыдущей статье.

Код:
Taskbar.JumpList.RefreshTaskbarList();

После обновления список выглядит следующим образом:

Я скомпилировал пример в неуправляемом коде из Windows 7 SDK. Вы можете получить копию этого кода здесь. Вы можете загрузить Windows API Code Pack, который включает примеры управляемого кода, который мы использовали в этой статье.

Это завершает наш разговор о списках перехода. Наша следующая статья о панели задач будет посвящена Icon Overlay.

Источник: thevista.ru

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

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты