Программируем панель задач Windows 7 (ч.5)
Мы продолжаем изучать возможности панели задач в Windows 7. Наверняка все вы обратили внимание на то, что если одно и то же приложение запустить несколько раз, Windows 7 автоматически сгруппирует их в одну кнопку на панели задач. Кроме того при наведении на значок этого приложения панель задач покажет набор preview для этих окон.
Однако, мы видим, что такое же поведение реализовано для открытых вкладок в Internet Explorer 8. В этом случае фактически запущен один экземпляр IE8 (технические детали мы опустим) и много вкладок. В этом случае Internet Explorer отображает их в виде нескольких preview. В данном случае это очень полезно, т.к. прямо из панели задач можно сразу переключиться на нужную вкладку.
Как можно догадаться, такую функциональность несложно реализовать и для своего приложения. Это актуально, если в вашем окне содержится набор других окон (как в случае с 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, в котором сгенерировать Bitmap, содержащий отображения нашего окна для выделения его в момент наведения курсора мыши на preview окна в панели задач.
Событие ThumbnailRequested содержит параметр типа BitmapRequestedEventArgs. Этот объект будет управлять тем, что будет отображаться на панели задач. Самое простое, что мы можем сделать, это указать параметр UseWindowScreenshot равным true. В этом случае будет сделан скриншот окна без вашего участия. Если же хочется отобразить какую-то собственную картинку в preview окна, то можно воспользоваться параметром Bitmap, куда положить свой объект Bitmap, который должен быть отображен. Однако, нужно понимать, что этот объект должен иметь строго заданные размеры. Эти размеры мы также можем получить из BitmapRequestedEventArgs.
_windowsManager.ThumbnailRequested += (o, e) =>
{
Bitmap bmp = new Bitmap(e.Width, e.Height);
this.DrawToBitmap(bmp, new Rectangle(0, 0, e.Width, e.Height));
e.Bitmap = bmp;
};
Понятно, что здесь мы можем манипулировать этим объектом так как нам удобно. Например, можем наложить на preview нашу картинку.
_windowsManager.ThumbnailRequested += (o, e) =>
{
Bitmap bmp = new Bitmap(e.Width, e.Height);
this.DrawToBitmap(bmp, new Rectangle(0, 0, e.Width, e.Height));
Graphics.FromImage(bmp).DrawImage(Images.coffeecup, 35, 5);
e.Bitmap = bmp;
};
Событие PeekRequested предназначено для того, чтобы выделить окно при наведении мыши на его preview в панели задач. Здесь также присутствует параметр типа BitmapRequestedEventArgs. Аналогичным образом можно использовать свойства UseWindowScreenshot и Bitmap.
_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 формы. Однако, я могу выводить previewлюбого другого элемента управления. Например, я могу отображать TextBox.
Ну и, наконец, необходимо вызвать метод WindowClosed когда окно закрывается. Для этого хорошо подходит событие OnClosed.
protected override void OnClosed(EventArgs e)
{
if (_windowsManager != null)
{
_windowsManager.WindowClosed();
}
base.OnClosed(e);
}
После этого мы получили следующее приложение.
Если мы посмотрим на панель задач, то увидим следующее.
Однако, если мы начнем изменять внешний вид формы, то увидим, что preview не изменилось. Это вызвано тем, что Windows 7 не запрашивала событие получения preview. Это особенно критично, если на форме находится контент, который постоянно изменяется, например видео. В этом случае есть способ обновить preview принудительно. Для этого необходимо вызвать метод InvalidatePreviews.
private void InvalidateButton_Click(object sender, EventArgs e){ _windowsManager.InvalidatePreviews();}
Этот метод в каждом конкретном случае надо вызывать в нужные моменты времени. Например, при обновлении текста в TextBox. Для видео хороший вариант - вызывать его по таймеру.
Вот так вот легко и просто вы можете отображать нужно количество дочерних окон вашего приложения.
Microsoft Most Valuable Professional, Microsoft Regional Director
июнь 2009
Комментарии
Статьи переводные, а источников нет. Как-то странно стали последнее время публиковать... Может стоит поправить, чтобы корректнее было?
2 cos: недавно же писАлось, что с thevista.ru будет сотрудничать региональный директор майкрософт (точнее российский). Таким образом статьи идут от его имени и исключительно на русском языке.
Так значит реализовать вывод изображения свёрнутого окна в эскиз в реальном времени всё-таки можно? Хотя то что это возможно, я знал итак: WMP12 это умеет делать (включите видео и свыерните плеер - на эскизе видео будеть продолжать воспроизводиться в реальном времени, в отличие от остальных приложений, где картинка замрёт на момент сворачивания окна). Но увы, других приложений, умеющих в свёрнутом состоянии выводить картинку в эскиз супербара я не встречал. Я очень надеялся, что после висты этот недочёт исправят, но всё осталось по прежнему...
Johny-electric писал:Я очень надеялся, что после висты этот недочёт исправят, но всё осталось по прежнему...
Нечего справлять. Это сделано специально.
Ребят, а как же Media Player Classic - он свернутый в эскизе воспроизводит видео...
По теме
- Видео-курсы от MS: Разработка приложений виртуальной и расширенной реальности на платформе Microsoft
- ECMA JavaScript 6: Объекты
- Как просто создать приложение для iPhone
- Разработка приложений под Windows Phone 8
- Индексированное хранилище, часть 2
- Индексированное хранилище, часть 1
- Начала Metro-программирования: создание настраиваемых приложений (ч.2)
- Начала Metro-программирования: создание настраиваемых приложений (ч.1)
- Начала Metro-программирования: создание компонентов WinRT (ч.3)
- Начала Metro-программирования: создание компонентов WinRT (ч.2)