Программирование панели задач в Windows 7 Сергей Звездин

advertisement
Программирование
панели задач в Windows 7
Сергей Звездин
Microsoft
Microsoft MVP
Regional
Director
http://blogs.gotdotnet.ru/personal/sergun
sergey.zwezdin@gmail.com
Май, 2009 г.
Операционная система Windows 7 содержит большое количество нововведений и
улучшений. Эти улучшения касаются безопасности, производительности, надежности и т.д.
Серьезное внимание также уделено и пользовательскому интерфейсу. Для разработчиков
приложений на платформе Windows эта операционная система также представляет интерес,
т.к. в ней содержатся элементы, на которые можно воздействовать программно.
Программирование панели задач в Windows 7
Первое что бросается в глаза при работе с Windows 7 – это, конечно, обновленная панель
задач. В новой панели задач действительно много концептуальных изменений. На
протяжении этой статьи мы поговорим об основных нововведениях, касаемых новой панели
задач, и программной модели для них.
2
.NET Sample Interop Library
С точки зрения разработчика клиентских приложений для Windows, процесс
использования данной функциональности в собственных приложениях представляется
достаточно просто. Взаимодействие с ОС происходит на неуправляемом уровне через COMобъекты. Именно поэтому для .NET приложений необходима реализация управляемых
оберток. Всю эту работу уже проделали разработчики из Microsoft и поместили это в
библиотеку .NET Interop Sample Library.
Библиотека .NET Interop Sample Library состоит из множества компонентов и
демонстрационных приложений. Мы не будем подробно останавливаться на каждом из них.
Для нас важно, что в ее состав входят проект «Vista Bridge Sample Library» и
«Windows7.DesktopIntegration».
В составе проекта «Windows7.DesktopIntegration» есть класс WindowsFormsExtensions. Этот
класс реализует набор методов-расширений для формы Windows Forms. К сожалению, на
момент написания статьи в этом классе не было реализована поддержка приложений WPF.
Однако этот недочет очень просто исправить самостоятельно. Все что потребуется сделать в
этом случае – это изменить способ получения описателя (handle) окна.
.NET Sample Interop Library
Мы будем использовать эту библиотеку для построения всех демонстрационных
приложений на протяжении все статьи.
3
Progress Bar
Одно из наиболее заметных изменений в панели задач Windows 7 – это возможность
отображения прогресса выполнения задачи (progress bar) прямо в панели задач.
На этом рисунке хорошо видно, что на панели задач отображается информация о процессе
копирования. Такая функциональность реализована в Windows 7 для копирования файлов,
загрузки данных из сети (Internet Explorer) и в других приложениях. Эту функциональность мы
можем использовать и для своих приложений. Сценариев может быть огромное количество –
отображение процесса преобразования данных, копирования, формирования данных,
построение отчетов, генерация изображений, и т.д.
Класс WindowsFormsExtensions содержит два метода, которые понадобятся нам в этом
случае – SetTaskbarProgress и SetTaskbarProgressState. Вызов первого метода позволяет
указать процент выполнения текущей задачи.
// процесс выполнения = 35%
// вызов метода расширения
WindowsFormsExtensions.SetTaskbarProgress(this, 35);
// или так (this = Form)
this.SetTaskbarProgress(35);
Метод SetTaskbarProgressState позволяет задать текущее состояние прогресс-бара.
WindowsFormsExtensions.SetTaskbarProgressState(this,
Windows7Taskbar.ThumbnailProgressState.Normal);
// или так
this.SetTaskbarProgressState(Windows7Taskbar.ThumbnailProgressState.Normal);
Progress Bar
Всего доступно четыре режима: Normal, Indeterminate (мерацие), Error (отображается
красным цветом) и Paused (отображается желтым цветом).
4
ThumbButtons
Другой интересной возможностью новой панели задач Windows 7 является возможность
добавлять собственные кнопки управления приложением в окно предварительного
просмотра. Подобную функциональность вы уже могли заметить при использовании Windows
7. Например, подобные кнопки существуют для Windows Media Player. Они позволяют
переключать треки, а также останавливать воспроизведение. Всего таких кнопок можно
создать не более семи.
Несомненно, такая функциональность может быть полезна не только для Media Player, но
и для наших приложений. Давайте посмотрим, как можно реализовать это в нашем
приложении. Создание наших кнопок должно происходить в момент обработки события
WM_TaskbarButtonCreated. Поэтому в форме необходимо переопределить метод WndProc и
обрабатывать моменты появления этого события.
protected override void WndProc(ref Message m)
{
if (m.Msg == Windows7Taskbar.TaskbarButtonCreatedMessage)
{
// initialize buttons
}
base.WndProc(ref m);
}
ThumbButtons
Для инициализации кнопок необходим объект ThumbButtonManager. Этот объект
управляет поведением и отображением этих кнопок. Этот объект можно создать, используя
метод расширения CreateThumbButtonManager. После этого необходимо воспользоваться
методом CreateThumbButton и создать объект кнопки. После того, как все кнопки будут
созданы, необходимо добавить их на панель задач при помощи метода AddThumbButtons.
5
protected override void WndProc(ref Message m)
{
if (m.Msg == Windows7Taskbar.TaskbarButtonCreatedMessage)
{
InitializeThumbButtons();
}
base.WndProc(ref m);
}
protected void InitializeThumbButtons()
{
ThumbButtonManager thumbButtonManager =
WindowsFormsExtensions.CreateThumbButtonManager( this);
var decreaseThumbButton = thumbButtonManager.CreateThumbButton(1,
Icons.Navigation_First_2, "To reduce the progress");
decreaseThumbButton.Clicked += delegate
{
// ..
};
thumbButtonManager.AddThumbButtons(decreaseThumbButton);
}
ThumbButtons
Теперь, при запуске приложения можно увидеть, что появилась одна кнопка управления.
Однако если мы попробуем нажать на нее, то увидим, что обработчик события не
срабатывает. Для того чтобы обработчик начал работать необходимо в методе WndProc явно
передать возможность объекту ThumbButtonManager обрабатывать события. В итоге получим
следующий несложный код.
6
private ThumbButtonManager _thumbButtonManager;
protected override void WndProc(ref Message m)
{
if (m.Msg == Windows7Taskbar.TaskbarButtonCreatedMessage)
{
InitializeThumbButtons();
}
if (_thumbButtonManager != null)
_thumbButtonManager.DispatchMessage(ref m);
base.WndProc(ref m);
}
protected void InitializeThumbButtons()
{
if (_thumbButtonManager == null)
{
_thumbButtonManager =
WindowsFormsExtensions.CreateThumbButtonManager(this);
}
var decreaseThumbButton = _thumbButtonManager.CreateThumbButton(1,
Icons.Navigation_First_2, "To reduce the progress");
decreaseThumbButton.Clicked += delegate
{
Progress.Text = (float.Parse(Progress.Text) 10).ToString();
WindowsFormsExtensions.SetTaskbarProgress(this,
float.Parse(Progress.Text));
};
// other buttons
_thumbButtonManager.AddThumbButtons(decreaseThumbButton,
normalStateThumbButton, indeterminateStateThumbButton, pauseStateThumbButton,
errorStateThumbButton, increaseThumbButton);
}
ThumbButtons
Это приложение содержит кнопки для управления прогрессом (как и в прошлом случае) и
содержит 6 кнопок.
7
OverlayIcons
Эта возможность исключительно полезна для приложений, которые обладают каким-то
состоянием с точки зрения пользователя. К таким приложениям можно отнести программы
для обмена мгновенными сообщениями (IM). Например, Windows Live Messanger активно
использует эту возможность. Если мы откроем Windows Live Messanger и будем изменять
состояние, то можно увидеть, как оно отображается на панели задач.
Чтобы добавить иконку состояния к основному значку приложения, необходимо добавить
файл ресурсов в проект и разместить там нужные иконки. Также, мы можем получить
объекты Icon из другого места, если это необходимо.
Теперь необходимо воспользоваться методами расширения, позволяющими задавать
иконки для нашего приложения. Для этих целей определен метод SetTaskbarOverlayIcon. Мы
должны передать ему в параметрах нашу форму, иконку и описание. Таким образом
установка новой иконки из кода будет выглядеть следующим образом.
WindowsFormsExtensions.SetTaskbarOverlayIcon(this, Icons.Error, "Error");
Также мы можем удалить этот значок. Для этого необходимо передать значение null
вместо самой иконки.
Можно также представить себе другой сценарий, в котором на месте дополнительной
иконки отображается какая-то информация. К примеру, это может быть текущая скорость
закачки, если ваше ПО что-то загружает из сети. Либо это может быть количество новых
писем в почтовом ящике, если это почтовый клиент.
В качестве второго параметра в методе SetTaskbarOverlayIcon передается объект Icon.
Однако кто нам мешает генерировать этот объект динамически? Давайте воспользуемся
OverlayIcons
WindowsFormsExtensions.SetTaskbarOverlayIcon(this, null, String.Empty);
8
нехитрым кодом и сделаем это. Я создам метод, который будет генерировать такое
изображение, и покажу эту иконку.
private static Icon BuildIcon(int param)
{
Bitmap image = Icons.BLANK2334242;
Graphics.FromImage(image).DrawString(param.ToString( @"D2"), new
Font("Arial", 54), Brushes.White, 10, 25);
return Icon.FromHandle(image.GetHicon());
}
private void ShowStatus(object sender, EventArgs e)
{
WindowsFormsExtensions.SetTaskbarOverlayIcon(this, BuildIcon(50,
"Status");
}
Таким образом, при помощи метода BuildIcon будет сгенерирована новая иконка, которая
будет отображена на панели задач.
OverlayIcons
В этом пример хорошо видно, что к стандартному значку мы добавили текст и отобразили
результат на панели задач. В демонстрационном приложении присутствует таймер, который
имитирует работу менеджера загрузки, выдавая постоянно разную “скорость” загрузки.
9
Windows manager
Наверняка вы обратили внимание на то, что если одно и то же приложение запустить
несколько раз, Windows 7 автоматически сгруппирует их в одну кнопку на панели задач.
Кроме того при наведении на значок этого приложения панель задач покажет набор
уменьшенных представлений для этих окон. Однако, мы видим, что такое же поведение
реализовано для открытых вкладок в Internet Explorer 8. В этом случае фактически запущен
один экземпляр IE8 и много вкладок в рамках основого окна. В этом случае Internet Explorer
отображает их в виде нескольких областей предварительного просмотра. В данном случае
это очень полезно, т.к. прямо из панели задач можно сразу переключиться на нужную
вкладку.
Как можно догадаться, такую функциональность несложно реализовать и для своего
приложения. Это актуально, если в вашем окне содержится набор других окон (как в случае с
IE8). Для этих целей в .NET Interop Sample Library присутствует класс CustomWindowsManager.
Давайте создадим небольшое приложение для этих целей. Пусть это приложение будет
работать в режиме MDI. Наша цель – добиться того, чтобы все дочерние окна этого
приложения также отображались в панели задач. После создания основного и дочернего
окна давайте займемся последним.
Нам необходим момент отображения окна, когда это окно уже создано и готово к работе.
Очень хорошо для этих целей подходит событие OnShown. В обработчике этого события мы
должны создать экземпляр объекта CustomWindowsManager и передать ему описатель
(handle) дочернего окна, а также родительского окна, с точки зрения модели MDI.
CustomWindowsManager _windowsManager;
protected override void OnShown(EventArgs args)
{
_windowsManager =
CustomWindowsManager.CreateWindowsManager(Handle, MdiParent.Handle);
base.OnShown(args);
Мы сохраним ссылку на объект CustomWindowsManager, она понадобится нам позже.
Однако, этих действий недостаточно для корректной работы. Во-первых, мы должны
подписаться на событие ThumbnailRequested, в котором сгенерировать изображение (Bitmap),
содержащее отображение нашего окна для всплывающих окон в панели задач. Во-вторых, мы
должны подписаться на событие PeekRequested, в котором сгенерировать изображение,
содержащее отображение нашего окна его в момент наведения курсора мыши на его
уменьшенное представление в панели задач.
Windows manager
}
10
Событие ThumbnailRequested содержит параметр типа BitmapRequestedEventArgs. Этот
объект будет управлять тем, что будет отображаться на панели задач. Самое простое, что мы
можем сделать, это указать параметр UseWindowScreenshot равным true. В этом случае будет
сделан скриншот окна без вашего участия. Если же хочется отобразить какую-то собственную
картинку в области предварительного просмотра, то можно воспользоваться параметром
Bitmap, куда положить свой объект Bitmap, который должен быть отображен. Однако нужно
понимать, что этот объект должен иметь строго заданные размеры. Эти размеры мы также
можем получить из параметра типа BitmapRequestedEventArgs.
_windowsManager.PeekRequested += (o, e) =>
{
var result = new Bitmap(e.Width, e.Height);
DrawToBitmap(result, new Rectangle(0, 0, e.Width, e.Height));
e.Bitmap = result;
};
Обратите внимание, что в этих примерах используется метод формы DrawToBitmap.
Однако можно выводить уменьшенное представление любого другого элемента управления.
Например, можно отображать TextBox. Ну и, наконец, необходимо вызвать метод
WindowClosed когда окно закрывается. Для этого хорошо подходит событие OnClosed.
protected override void OnClosed(EventArgs e)
{
if (_windowsManager != null)
{
_windowsManager.WindowClosed();
}
base.OnClosed(e);
}
После этого мы получили следующее приложение.
Windows manager
Если мы посмотрим на панель задач, то увидим следующее.
11
Однако если мы начнем изменять внешний вид формы, то увидим, что область
предварительного просмотра не изменилась. Это вызвано тем, что Windows 7 не
генерировала заново событие получения уменьшенного изображения. Это особенно
критично, если на форме находится содержание, которое постоянно изменяется, например,
видео. В этом случае есть способ обновить это представление принудительно. Для этого
необходимо вызвать метод InvalidatePreviews.
private void InvalidateButton_Click(object sender, EventArgs e)
{
_windowsManager.InvalidatePreviews();
}
Этот метод в каждом конкретном случае необходимо вызывать в определенные моменты
времени. Например, при обновлении текста в TextBox. Для видео хороший вариант –
вызывать его по таймеру.
Однако, аналогичного эффекта можно добиться если мы запустим несколько экземпляров
одного и того же нашего приложения. В этом случае Windows 7 определит, что это одно и то
же приложение и сгруппирует окна в один значок.
В этом случае в основе этого механизма лежит такое понятие как Application ID. Для
каждого окна мы можем задать свой ID. Эту особенность также можно использовать тогда,
когда необходимо избежать такого поведения. В этом случае нужно задать различные AppId
для каждого такого окна. Сделать это можно используя .NET Interop Sample Library. Для этого
необходимо вызвать метод SetAppId у класса-обертки.
Таким образом, мы можем задать различные AppId для каждого окна и они не будут
группироваться.
Windows manager
private void SetAppIdButton_Click(object sender, EventArgs e)
{
WindowsFormsExtensions.SetAppId(this, “SomeAppId”);
}
12
Windows manager
Аналогичным образом также возможно сгруппировать несколько окон от разных
приложений. Для этого необходимо задать одинаковый AppId для каждого из окон. И в этом
случае панель задач Windows 7 сгруппирует эти приложения в один значок. Например, в
данном случае заданы одинаковые AppId для разных окон из разных приложений и эти окна
оказались сгруппированными в панели задач Windows 7.
13
ThumbnailPreview
Как мы уже могли убедиться, Windows 7 обладает удобной функциональностью по
отображению окон предварительного просмотра для приложений. При наведении мыши на
значок окна в панели задач можно посмотреть уменьшенное представление окна за
считанные секунды. Это очень удобно, когда у пользователя открыто большое количество
окон. По умолчанию в этих мини-окнах отображается все содержимое окна. Однако для
некоторых приложений было бы гораздо удобнее показывать не все содержимое окна, а
только его часть. Такая функциональность также предусмотрена для панели задач Windows 7,
и мы можем использовать ее для своих приложений.
В рамках оберток для функций из системных библиотек Windows присутствует метод
SetThumbnailClip, который поможет нам в реализации данной функциональности. При вызове
данного метода в параметрах необходимо передать текущий экземпляр формы и
координаты, ограничивающие область окна.
private void Clip5_Click(object sender, EventArgs e)
{
WindowsFormsExtensions.SetThumbnailClip(this, new Rectangle(10, 10, 145,
145));
}
Давайте создадим небольшое приложение, где посмотрим на возможности этой
функциональности. Для этого создадим пустое приложение, в которое добавим несколько
элементов управления. После запуска приложения окно предварительного просмотра будет
выглядеть следующим образом.
ThumbnailPreview
Видно, что изначально отображается все окно. Давайте ограничим область отображения
при помощи метода SetThumbnailClip. Отобразим, например, только поля ввода, которые
находятся на форме.
14
Что интересно, если у нас на форме имеется динмическое содержимое (например, видео),
то оно будет отображаться в динамике. В демонстрационном приложении находится
несколько анимированных изображений, и оно отображается их в рамках области
предварительного просмотра. При этом нет необходимости для этого делать что-то еще.
Важно, что в процессе работы приложения мы можем изменять содержимое окна
предварительного просмотра. Например, в какой-то момент времени нам может
понадобиться отобразить содержимое какого-то важного поля ввода, а в другой момент отобразить изображение с формы. Такая динамичность может дать пользователю
возможность получать актуальную для него информацию. Наконец, если нам необходимо
отобразить все содержимое формы можно использовать тот же самый метод, но передать
ему размеры всей формы. В этом случае в области предварительного просмотра снова будет
отображаться все окно.
private void NoClip_Click(object sender, EventArgs e)
{
WindowsFormsExtensions.SetThumbnailClip(this, new Rectangle(new Point(0,
0), Size));
}
Однако в определенных ситуациях гораздо полезнее может быть отображение не части
окна, а совершенно другой картинки, отображающей состояние приложения. Например, этой
возможностью пользуется Windows Live Messanger. Если мы наведем курсор мыши на значок
Windows Live Messanger, то во всплывающем окне он отобразит аватар текущего
пользователя.
public Form1()
{
InitializeComponent();
WindowsFormsExtensions.EnableCustomWindowPreview(this);
}
Стоит сказать, что размеры изображения, которые мы хотим отобразить в области
предварительного просмотра, ограничены. Это логично. Представьте себе, что было бы, если
в эту область мы могли бы задать изображение размером 1024x768. Эти размеры ограничены
значениями 200x120. Изображение может быть меньше этого размера, в этом случае область
ThumbnailPreview
Для реализации подобного поведения в .NET Interop Sample Library существует метод
SetIconicThumbnail. Именно с его помощью мы можем легко и просто создать собственный
вид области предварительного просмотра для нашего окна. Однако прежде чем мы начнем
его использовать мы должны разрешить это поведение с помощью метода
EnableCustomWindowPreview. В противном случае при выполнении метода SetIconicThumbnail
мы получим соответствующее исключение. Сделать это можно прямо в конструкторе формы.
15
предварительного просмотра также будет уменьшена. Если изображение больше этих
размеров, то будет сгенерировано исключение.
В параметрах метода SetIconicThumbnail передается ссылка на текущую форму и
изображение (Bitmap), которое нужно отобразить. Наша задача – сгенерировать этот Bitmap.
И в этом случае у нас полностью развязаны руки – мы можем сгенерировать все, что нам
необходимо. Это может быть снимок окна, с каким-то дополнительным текстом поверх. Это
может быть какая-то собственная картинка, содержащая информацию. Это может быть текст с
некоторой статистикой.
В демонстрационном приложении мы будем генерировать изображение, отображающее
состояние приложения текстом и графически, а также небольшой снимок окна. Для этого
создадим изображение (Bitmap) нужных размеров и зальем его фоном. После этого нарисуем
там изображение состояния и снимок окна. Затем напишем на этом изображении текст
состояния, и результат передадим в метод SetIconicThumbnail.
private static void SetState(Form form, string stateText, Image stateImage)
{
// blank image
var preview = new Bitmap(200, 120);
var g = Graphics.FromImage(preview);
// fill background
g.DrawImage(Images.background, 0, 0);
// file image of state
if (stateImage != null)
{
g.DrawImage(stateImage.GetThumbnailImage(100, 100, null,
IntPtr.Zero), 100, 10);
}
// fill image of form
g.DrawImage(GetFormImage(form, 50, 60), 10, 10);
// draw text
g.DrawString(stateText, new Font("Verdana", 18), Brushes.White, 10, 70);
// setting thumbnail
WindowsFormsExtensions.SetIconicThumbnail(form, preview);
}
ThumbnailPreview
Как видим, код получился достаточно лаконичный. В результате мы увидим следующее
представление.
16
Что интересно, наше приложение может само в фоне изменять это состояние. При этом
если мышь находится на значке приложения и окно предварительного просмотра в данный
момент отображается, то смена изображения во всплывающем окне происходит плавно, без
каких-либо побочных эффектов. Так, например, можно создать таймер, в обработчике
которого через определенные промежутки времени изменять состояние.
Стоит также отметить, что у Windows 7 есть такая приятная особенность, что если мы
наведем курсор мыши на область предварительного просмотра окна, то все остальные окна
скроются, а выделенное окно будет отображаться. Выглядит это следующим образом.
Панель задач Windows 7 в этом случае также позволяет нам задать собственное
поведение. В этом случае мы имеем возможность задать содержимое нашей формы нашим
собственным изображением. Например, там мы можем написать какой-то полезный текст. В
этом случае сценарий работы может выглядеть следующим образом. У пользователя в
панели задач находится приложение, которое что-то выполняет. Он может отслеживать его
состояние на основе ProgressBar и OverlayIcon, которые мы обсудили ранее. Если этой
информации ему недостаточно, он может навести курсор мыши на иконку приложение. В
этом случае ему отобразится область предварительного просмотра, в котором содержится
дополнительная информация. Пользователь может навести на область предварительного
просмотра нужного окна и в этом случае все окна скроются, и на экране останется только
выделенное окно. В этом окне мы можем вывести еще больше информации, которая
необходима пользователю.
Для того, чтобы реализовать подобный сценарий в нашем приложении мы воспользуемся
.NET Interop Sample Library. Для этих целей предназначен метод SetPeekBitmap классаобертки. Генерировать изображение необходимо в момент времени, когда пользователь
наводит мышь на область предварительного просмотра окна. Для этих целей переопределим
метод WndProc и отловим событие WM_DWMSENDICONICLIVEPREVIEWBITMAP. Как раз в этот
момент времени необходимо генерировать изображение.
ThumbnailPreview
Вообще, по умолчанию в таком сценарии при скрытии остальных окон выведется само
содержимое окна. Переопределение содержания окна в этот момент может быть полезно,
если на форме информация разрознена и сразу непонятно что происходит в приложении.
17
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_DWMSENDICONICLIVEPREVIEWBITMAP)
{
WindowsFormsExtensions.SetPeekBitmap(this, GeneratePeekBitmap(this,
Images._111), true);
}
base.WndProc(ref m);
}
В данном случае мы вызываем метод, который будет генерировать нужное изображение.
Генерация этого изображения также не представляет какой-либо сложности. В общем случае
мы можем скопировать в этот Bitmap снимок нашего окна и поверх этого нарисовать нужную
нам информацию. Давайте в демонстрационном приложении заполним эту область фоном и
нарисую значок состояния поверх этого.
private static Bitmap GeneratePeekBitmap(Form form, Image stateImage)
{
var preview = new Bitmap(form.ClientSize.Width, form.ClientSize.Height);
var g = Graphics.FromImage(preview);
g.DrawImage(Images.background.GetThumbnailImage(form.ClientSize.Width,
form.ClientSize.Height, null, IntPtr.Zero), 0, 0);
if (stateImage != null)
{
Size thumbSize = new Size(100, 100);
g.DrawImage(stateImage.GetThumbnailIma ge(thumbSize.Width,
thumbSize.Height, null, IntPtr.Zero), form.ClientSize.Width / 2 thumbSize.Width / 2, form.ClientSize.Height / 2 - thumbSize.Height / 2);
}
return preview;
}
На самом деле, такое изображение можно устанавливать из любого места приложения.
Главное, чтобы это изображение, в том числе, генерировалось в момент обработки
ThumbnailPreview
Обратите внимание, что для корректного отображения такого представления размеры
этого изображения должны совпадать с размером формы. После этого у нас получится
приложение, которое выглядит следующим образом.
18
указанного выше события. Например, в демонстрационном приложении мы также
устанавливаем это изображение в таймере. Таким образом, мы можем навести курсор мыши
на область предварительного просмотра и наблюдать за тем, как изменяется сама форма при
срабатывании таймера.
ThumbnailPreview
Кроме того, у метода SetPeekBitmap существует третий параметр логического типа
(boolean). Изменяя этот параметр, можно указать, нужно ли убирать рамку приложения, когда
осуществляется подобный просмотр.
19
JumpLists
Одной из важнейших функций панели задач в Windows 7 являются списки переходов (Jump
Lists). Списки переходов отображаются, если выделить значок приложения в панели задач и
нажать правую кнопку мыши. Если приложение использует функциональность списков
перехода, то кроме стандартных действий (pin, close) появятся еще ряд дополнительных
действий, которые облегчают повседневную работу с приложением.
Этой функциональностью панели задач активно пользуются различные приложения.
Например, Windows Media Player отображает опции переключения плейлистов. Internet
Explorer и Windows Explorer содержат в списках переходов ссылки на последние места, куда
мы заходили. Windows Live Messanger отображает опции переключения состояния.
JumpLists
В списках переходов могут присутствовать несколько различных типов элементов: задачи,
ссылки на последние открытые документы и ссылки на постоянные документы. Кроме того,
эти позиции могут быть закреплены. Такие элементы не исчезнут из списков переходов со
временем. Это удобно, например, если мы часто работаем с одним и тем же документом.
Схематично Jump List в Windows 7 можно представить следующим образом.
20
По сути, каждый пункт в списках переходов представляет собой ссылку на программу или
файл. Так, например, мы можем запустить калькулятор, или какой-либо документ заданного
формата. К сожалению, у нас нет возможности напрямую перехватить событие нажатия на
пункт в списках перехода в нашем приложении. Каждый раз, когда мы выбираем очередной
пункт, будет запускаться новый экземпляр приложения. Это связано в первую очередь с тем,
что со списками переходов можно работать даже тогда, когда приложение не запущено. В
этом случае оно должно быть закреплено (pinned) на панели задач. Например, на следующем
рисунке видно, что Internet Explorer в данный момент не запущен, но списки переходов мы
использовать можем.
JumpLists
Итак, давайте посмотрим, каким образом подобная функциональность может быть
реализована в наших приложениях. Для работы со списками переходов нам понадобится
объект типа JumpListManager, который входит в состав .NET Interop Sample Library. Создавать
его необходимо в момент создания кнопки нашего приложения на панели задач. Для этих
целей можно переопределить метод WndProc следующим образом.
21
protected override void WndProc(ref Message m)
{
if (m.Msg == Windows7Taskbar.TaskbarButtonCreatedMessage)
{
_jumpListManager =
WindowsFormsExtensions.CreateJumpListManager(this);
_jumpListManager.UserRemovedItems += (o, e) =>
{
e.CancelCurrentOperation = false;
};
// add items
_jumpListManager.Refresh();
}
base.WndProc(ref m);
}
Обратите внимание на вызов метода Refresh после создания объекта JumpListManager.
Вызов этого метода необходим для обновления позиций в списках переходов. Также
обязательным действием является подписка на событие UserRemovedItems. Оно исполняется,
когда производится попытка удаления устаревших пунктов из списков переходов. Давайте
теперь попробуем добавить новые позиции. Для этих целей существуют классы-обертки и
нужные методы у объекта JumpListManager.
Самый простой тип позиций в списках переходов – задачи. Задачей может быть запуск
внешнего приложения или нашего приложения с какими-то параметрами. В Windows Live
Messanger в виде задач реализовано переключение состояния пользователя. Для создания
задачи в списках переходов используется метод AddUserTask.
_jumpListManager.AddUserTask(new ShellLink
{
Path =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
"calc.exe"),
Title = "Calculator",
Category = "Applications",
IconLocation =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
"calc.exe"),
IconIndex = 0
});
JumpLists
Как видим, здесь создается новый объект типа ShellLink, в который передается путь до
приложения, заголовок и значок. Добавим в свое приложение две задачи и получим
следующий результат.
22
Другой вариант заполнения списков переходов – ссылки на документы, которые были
загружены ранее. Для этих целей создадим несколько текстовых файлов с расширением
“.myapp” и ассоциируем этот тип файлов со своим приложением. При запуске приложения
проверим, передано ли имя файла в качестве параметра при запуске приложения. Если имя
задано, то считаем этот файл и добавим его в список ранее загруженных файлов. Для этих
целей существует метод AddToRecent.
if (File.Exists(Environment.GetCommandLineArgs().Skip(1).FirstOrDefault() ??
String.Empty) == true)
{
_jumpListManager.AddToRecent(Environment.GetCommandLineArgs().Skip(1).FirstOr
Default() ?? String.Empty);
}
JumpLists
Теперь из Windows Explorer откроем эти файлы. При этом будет запускаться
демонстрационное приложение (если мы правильно ассоциировали данный тип файлов с
приложением). При этом при вызове списков переходов мы увидим, что в категории “Recent”
появились ссылки на ранее открытые файлы.
23
Другой способ размещения позиций в списках переходов – создание ссылок на
постоянные документы/программы. В этом случае мы также можем сгруппировать эти
позиции по категориям. Для этих целей существует метод AddCustomDestination.
_jumpListManager.AddCustomDestination(new ShellLink
{
Path = @"about.txt",
Title = "About",
Category = "My application",
IconLocation =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
"shell32.dll"),
IconIndex = 11
});
Добавим несколько таких ссылок в списки переходов и получим следующий результат.
На этом рисунке видно, что появились две дополнительные группы со ссылками внутри.
JumpLists
Замечательной особенностью списков переходов является то, что их содержимое также
доступно в меню “Пуск”. Так, например, если мы активно пользуемся этой
функциональностью, то этим можно использоваться и из стартового меню.
24
JumpLists
Таким образом, мы можем использовать дополнительную функциональность, которую
нам предоставляет панель задач Windows 7 для обеспечения максимально комфортной
работы пользователя.
25
Заключение
На протяжении всей статьи мы рассмотрели основные возможности по
программированию панели задач для операционной системы Windows 7. Несомненно,
реализация этих возможностей в ваших приложениях потребует определенных усилий.
Однако эти усилия не сравнить с тем, насколько удобнее становится работать с вашим
приложением и какого количества лишних действий при работе с вашим приложением
можно избежать.
Заключение
Надеюсь, эта информация окажется полезной для вас и ваших приложений. Успехов вам в
построении ваших приложений для Windows7!
26
Ссылки

Windows 7 Developer Guide
http://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=Win7DeveloperGuide&R
eleaseId=1702

Microsoft Windows SDK for Windows 7
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=f75f2ca8 -c1e4-48019281-2f5f28f12dbd

.NET Interop Sample Library
http://code.msdn.microsoft.com/Windows7Taskbar/Release/ProjectReleases.aspx?ReleaseId=2246
Исходные коды

Progress bar
o http://bl ogs .gotdotnet.ru/pers onal/sergun/ct.ashx?id=08a 1e197-64b1-477a-8f409343c06776e6&url =http%3a%2f%2fblogs .gotdotnet.ru%2fpersonal %2fsergun%2fcontent%2fbina ry%2fWin
dows Li veWri ter%2fWindows 7Taskba r.1Progressbar_11A60%2fTaskba r-Progress.zip

ThumbButtons
o http://bl ogs .gotdotnet.ru/pers onal/sergun/ct.ashx?id=1b9603a 2-b31f-46d9-a 46b7b30e5b3f472&url =http%3a%2f%2fblogs .gotdotnet.ru%2fpersonal %2fsergun%2fcontent%2fbi nary%2fWind
ows Li veWri ter%2fWindows 7Taskba r.2ThumbButtons_97CC%2fThumbButtons.zip

Overlay Icons
o http://bl ogs .gotdotnet.ru/pers onal/sergun/ct.ashx?id=8799e7f7-5765-4b9c-abf05d3dfa 911cb9&url =http%3a%2f%2fblogs .gotdotnet.ru%2fpersonal %2fsergun%2fcontent%2fbi nary%2fWind
ows Li veWri ter%2fWindows 7Taskba r.3Overla yIcon_C7CC%2fTaskba r-Icons .zi p
o http://bl ogs .gotdotnet.ru/pers onal/sergun/ct.ashx?id=8291d3b4-5e68-4b2a-8ee856b37e95be93&url =http%3a%2f%2fblogs .gotdotnet.ru%2fpersonal%2fsergun%2fcontent%2fbina ry%2fWin
dows Li veWri ter%2fWindows 7Taskba r.4Cus tomOverla yIcon_F66%2fTaskba r-Cus tomIcons .zip

Windows Manager
o http://bl ogs .gotdotnet.ru/pers onal/sergun/ct.ashx?id=465c2867-17fb-434c-b694b413b33a 22cc&url =http%3a%2f%2fblogs .gotdotnet.ru%2fpersonal%2fsergun%2fcontent%2fbina ry%2fWind
ows Li veWri ter%2fWindows 7Taskba r.5CustomWindows Mana ger_C51B%2fTaskba r-Wi ndows Manager.zip
o http://bl ogs .gotdotnet.ru/pers onal/sergun/ct.ashx?id=8348e8de -6a 20-4cc2-ae82436e08408f02&url =http%3a %2f%2fblogs.gotdotnet.ru%2fpersonal%2fsergun%2fcontent%2fbina ry%2fWi nd
ows Li veWri ter%2fWindows 7Taskba r.6AppId_DD99%2fTaskba r-AppId.zip

Thumbnail
o http://bl ogs .gotdotnet.ru/pers onal/sergun/ct.ashx?id=f62cce30-db9d-4966-ab4763d0219fe828&url =http%3a %2f%2fblogs .gotdotnet.ru%2fpersonal%2fsergun%2fcontent%2fbina ry%2fWind
ows Li veWri ter%2fWindows 7Taskba r.5Thumbnail Clip_86CD%2fTaskba r-ThumbnailClip.zip
o http://bl ogs .gotdotnet.ru/pers onal/sergun/ct.ashx?id=b99f8d8a-46cb-4dba -9ec41a 05fad11b5d&url =http%3a %2f%2fblogs .gotdotnet.ru%2fpersonal%2fsergun%2fcontent%2fbina ry%2fWind
ows Li veWri ter%2fWindows 7Taskba r.8Thumbnail Clip_A017%2fTaskbar-Iconi cThumbnail .zip
o http://bl ogs .gotdotnet.ru/pers onal/sergun/ct.ashx?id=3b500561-a 385-4048-b350471235991df6&url =http%3a %2f%2fblogs .gotdotnet.ru%2fpersonal%2fsergun%2fcontent%2fbina ry%2fWind
ows Li veWri ter%2fWindows 7Taskba r.9IconicThumbnail_DDE8%2fTaskba r-PeekBi tmap.zip
Jump Lists
o http://bl ogs .gotdotnet.ru/pers onal/sergun/ct.ashx?id=5187122a-3c4f-4e1c-b66cad41e7233166&url =http%3a %2f%2fblogs .gotdotnet.ru%2fpersonal%2fsergun%2fcontent%2fbina ry%2fWin
dows Li veWri ter%2fWindows 7Taskba r.10JumpLis ts_140B6%2fTaskba r-JumpLis ts .zip
Ссылки

27
<
28
Содержание
Программирование панели задач в Windows 7..................................................................... 1
.NET Sample Interop Library .................................................................................................... 3
Progress Bar ........................................................................................................................... 4
ThumbButtons ....................................................................................................................... 5
OverlayIcons .......................................................................................................................... 8
Windows manager................................................................................................................ 10
ThumbnailPreview ................................................................................................................ 14
JumpLists ............................................................................................................................. 20
Содержание
Заключение......................................................................................................................... 26
29
Download