Программируем Windows 7: Taskbar. Часть 5 – CustomWindowsManager

    Мы продолжаем изучать возможности панели задач в 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. Для видео хороший вариант – вызывать его по таймеру.



    Вот так вот легко и просто вы можете отображать нужно количество дочерних окон вашего приложения.

    Демонстрационное приложение:
    Taskbar-WindowsManager.zip
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 34

      0
      Отличные примеры! Спасибо!
        +3
        Мне не нравится группировка окон одного приложения. Всегда отключаю эту опцию. ИМХО.
          +15
          В ХР это сделано убого. В 7 это очень удобно.
            –2
            Если выключить стеклянный (прозрачный) вид, то будет тоже самое что и в ХР
            Выпрыгнет просто список, без предпросмотра (фотки окна)
              +4
              А зачем это делать?
              Если Порше снять колеса то будет бесполезная груда металла.
                0
                не у всех хотя бы 1 гб оперативы и 2 ядерный проц
            0
            Зато в IE, например, можно переключаться по страницам прямо из панели задач. Иногда очень удобно.
              –9
              Пользуюсь Хромом. Там закладки вверху.
                0
                какая разница?
                  0
                  дык и в ИЕ вверху. Удобство в том что можно открыть браузер сразу на нужной вкладке. 1 действие вместо двух
              • НЛО прилетело и опубликовало эту надпись здесь
                  0
                  в XP тоже отрубал. в 7-ке просто счастлив от этого :)
                  0
                  Какую литературу по программированию под Windows7 можете посоветовать?
                    +2
                    боюсь пока кроме msdn ничего нету :)
                      +1
                      рано еще.
                      Windows 7 еще даже не вышла :)
                        0
                        А в MSDN всё-таки есть это?
                        Если нет раздела, где описаны новые фичи, то как же разработчикам подстраиваться? Интерфейс-дизайнеры, зная о новшествах, могли бы ориентироваться на них. Особенно в долгосрочных проектах.
                      0
                      Блог Windows 7 для разработчиков: blogs.msdn.com/windev/default.aspx
                      +2
                      побыстрее бы в Оперу и Огнелис эту новинку.
                      +2
                      Я ни разу не программист, но ваши статьи по Таскбару в Win7 читаю постоянно. По скорее бы стали выходить в массы программы с подобным функционалом.
                      Очень понравилось отображение вкладов в IE через preview в панели задач. И с нетерпением жду, когда же это штатно реализуют в любимом мной Firefox.
                        +1
                        черт возьми, вы так вкусно описываете возможности, что мне даже захотелось поставить семерку:)
                          +1
                          Надеюсь будет: " Программируем Windows 7: Taskbar. Часть 726" :)
                            0
                            Я бы наложил картинку в обработчике PeekRequested, чтобы показать выделение preview окна при наведении мышью. А то получается что обработчики ThumbnailRequested (первый) и PeekRequested у Вас идентичны.
                            Хороший цикл статей на актуальную тематику. Ждем продолжения.
                              0
                              Согласен. Но цель примера не показать конкретное приложение, а показать что мы это можем сделать впринципе.
                              Дальше вариантов может быть множество, в т.ч. и ваш.
                              0
                              Одно плохо: если обновлять нечасто, то плавной анимации не выйдет. А если часто, то будет значительная нагрузка на процессор.
                                0
                                Кстати, может быть подскажите.
                                Давно заметил такую вещь — если запущен какой-то видеоплеер, но не свернут, то при наведении мышкой на пиктограмму в панели задач, появляется preview, в котом отображается видео в реальном времени, ровно также как в самом плеере. Но стоит свернуть окошко плеера, то в preview появляются только «скриншоты» видео.
                                Тут какие-то разные методы отображения применяются? Почему нельзя сделать, чтобы оно нормально отображалось даже когда окно свернуто?
                                  0
                                  когда окно свёрнуто, программа не отрисовывает содержимое окна, поэтому система и не может отобразить ничего, кроме последнего скриншота, имхо
                                  думаю, видеоплеер должен сам заботиться об отрисовке предпросмотра в свёрнутом состоянии
                                    0
                                    А ведь точно. Сам сразу не подумал. Видимо в состоянии «свернуто» сам плеер ничего не отображает (видимо из-за ненадобности), потому и ничего не показывает в preview.
                                    Большое спасибо =)
                                  0
                                  напишите про shell extensions! как подцепить свою панель к проводнику, как управлять (выделять, перемещать по окну) иконками файлов и т.п.
                                    0
                                    Спасибо за статью )

                                    По тексту было бы неплохо избавиться от лишних слов паразитов, например второй абзац:
                                    В этом случае фактически запущен один экземпляр IE8 (технические детали мы опустим) и много вкладок. В этом случае Internet Explorer отображает их в виде нескольких preview. В данном случае это очень полезно, т.к. прямо из панели задач можно сразу переключиться на нужную вкладку.

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                    Самое читаемое