Как свернуть приложение в трей wpf
Я полный новичок WPF и задаюсь вопросом, Может ли кто-нибудь дать мне несколько указателей, как написать приложение, которое начинает сворачиваться в лоток. Идея заключается в том, что он периодически извлекает RSS-канал и создает всплывающее окно тостера, когда появляются новые каналы.
приложение должно по-прежнему иметь главное окно (по сути, просто список, содержащий все записи фида), но это должно быть скрыто по умолчанию.
Я начал читать о XAML и WPF, и я знаю, что StartupUri в приложении.xaml должен указывать на мое главное окно, но я понятия не имею, как правильно сделать значок SysTray и скрыть главное окно (это также означает, что когда пользователь сворачивает окно, оно должно сворачиваться в лоток, а не на панель задач).
вы должны использовать NotifyIcon управления из системы.Окна.Формы, или в качестве альтернативы вы можете использовать API Notify Icon, предоставляемый API Windows. WPF не предоставляет такого эквивалента, и он был запрошен на Microsoft Connect несколько раз.
у меня есть код на GitHub, который использует System.Windows.Forms NotifyIcon компонент из приложения WPF, код можно просмотреть по адресу https://github.com/wilson0x4d/Mubox/blob/master/Mubox.QuickLaunch/AppWindow.xaml.cs
вот краткие биты:
создайте окно WPF с ShowInTaskbar=False, которое загружается в невидимом состоянии.
на уровне класса:
Во Время OnInitialize ():
Во Время OnLoaded ():
и для взаимодействия (показано как notifyIcon.Щелчок и двойной щелчок выше):
здесь вы можете возобновить использование элементов управления WPF и API, таких как контекстные меню, всплывающие окна и т. д.
Это очень просто. Вам точно не нужно окно WPF для размещения компонента, это просто самый удобный способ ввести его в приложение WPF (поскольку окно обычно является точкой входа по умолчанию, определенной через приложение.xaml), кроме того, вам не нужна оболочка WPF или сторонний элемент управления, так как компонент SWF гарантированно присутствует в любой платформе .NET Framework установка, которая также поддерживает WPF, поскольку она является частью .NET Framework (на которой основаны все текущие и будущие версии .NET Framework.) На сегодняшний день нет никаких указаний от Microsoft, что поддержка SWF будет удалена из .NET Framework в ближайшее время.
надеюсь, что это поможет.
это немного сыра, что вы должны использовать компонент Pre-3.0 Framework, чтобы получить значок в трее, но понятно, как Microsoft объяснила это, нет понятия системного трея в рамках WPF. WPF-это технология презентации, а значки уведомлений-это концепция операционной системы (а не "презентация").
проверить. Он поставляется с удивительным примером приложения тоже, очень проста в использовании, и вы можете иметь большой вид Windows Live Messenger стиль WPF всплывающие окна, подсказки и контекстные меню. Идеально подходит для отображения RSS-канала, я использую его для аналогичной цели.
Войти
Авторизуясь в LiveJournal с помощью стороннего сервиса вы принимаете условия Пользовательского соглашения LiveJournal
WPF: иконка в трее
В жизни каждого человека рано или поздно настает момент, когда требуется создать приложение, сворачивающееся в трей (системная панелька, "где часики"). Сейчас мы посмотрим, как это можно насишарпить © в WPF.Термин «свернуть в трей» не совсем правильный с точки зрения программирования. На самом деле окно никуда не сворачивается, оно просто перестает отображаться на экране. За эффект «сворачивания» отвечает API-функция drawAnimatedRects(), которая рисует анимацию окна из одного прямоугольника на экране, в другой произвольный прямоугольник; если приглядеться, XP даже не утруждала себя прорисовкой содержимого окна, там только заголовок и чисто символический бордюр. При желании, конечным прямоугольником, в который «улетит» окно, можно сделать системный трей или даже свою иконку в нем, но в данном примере мы не будем заморачиваться на спецэффектах, а только построим необходимый и достаточный интерфейс пользователя.
Иконка же в трее существует сама по себе, вне зависимости от текущего состояния «сворачивания» или «разворачивания» окна. Она добавляется туда другими функциями Windows. Помню, в Delphi для этого нужно было вызывать чистый API (хотя, наверное, позже кто-нибудь догадался накидать самодостаточный компонент), в Windows.Forms для этого есть готовый класс NotifyIcon, а в WPF решили вообще не отвлекаться на эту тему.
Первым делом, давайте договоримся, что постоянно отображать и прятать иконку в трее в зависимости от того, развернуто окно или свернуто, смысла нет.
Раньше так делали, когда трей был «не резиновый», и каждый, кто в него «понаехал», приближал смерть панели задач. В ХР проблему заполняемости лотка почти решили, добавив анимацию навроде баяна, которая может прятать лишние иконки, освобождая место в панели задач под приложения первой необходимости. Но это постоянно приходилось мучительно настраивать (на что пойдет не каждый пользователь), да и при «раскрытии мехов баяна» в панели задач творилось черти что. В семерке трей наконец-то научили разворачиваться вверх, т.е. теперь без особого на то желания пользователя, иконки лотка вообще никак и никогда не повлияют на панель, для них не предназначенную.Поэтому мы просто создадим иконку в начале работы приложения, а в конце уберем ее оттуда.
Иконку я стащил из первой попавшейся библиотеки Windows, сохранил, как файл .ico, и положил в ресурсы приложения под именем Icon1 (в Solution Explorer нужно открыть Properties - Resources.resx, слева вверху кнопка Add Resource. - Add Existing File. ). В реальной жизни вы, конечно, поступите умнее меня и дадите этому ресурсу осмысленное имя.
По правилам хорошего тона, иконка в трее должна по щелчку левой кнопкой мыши показывать приложение, а по щелчку правой кнопкой — отображать какое-нибудь меню. Без меню пользователь чувствует себя неуютно, постоянно оглядывается через плечо, недоумевает и в конце концов сходит с ума или деинсталлирует ваше приложение. Понятно, что второй вариант нас не устраивает, поэтому создадим меню в XAML-файле главного окна приложения:
< Window. Resources >< ContextMenu x : Key = "TrayMenu" >
< MenuItem Header = "Hide" Click = "ShowHideMainWindow" />
< MenuItem Header = "Item2" />
< Separator />
< MenuItem Header = "Exit" Click = "MenuExitClick" />
</ ContextMenu >
</ Window. Resources >
Как видно из кода, мы создаем экземпляр контекстного меню и храним его в ресурсах окна (x:Key необходим, чтобы потом достать этот экземпляр из кода). Первый пункт будет отвечать за показ или скрытие окна (для тех, кто любит все делать через пункты меню, а не через абстрактные щелчки по иконке); второй пункт символизирует все ваши пункты меню с функционалом, специфичным для вашего приложения; последний пункт отделен сепаратором, он будет выполнять выход из приложения. Отсутствие такого пункта меню (именно последнего в списке) раздражает пользователей чуть ли не сильнее ранее упомянутой мною причины деинсталляции. Чтобы прочувствовать, попробуйте менюшку от аутлука 2003, например. Там нет выхода. Т.е., прежде, чем вы сможете выгрузить приложение из памяти, вы обязаны отобразить его на экране. Это лишний шаг, глупость и нарушение конфиденциальности в некоторых случаях.
Итак, меню и иконка у нас есть. Запихиваем все это в трей в момент запуска приложения, (здесь и далее) правим класс главного окна приложения в файле MainWindow.xaml.cs:
// переопределяем обработку первичной инициализации приложенияprotected override void OnSourceInitialized( EventArgs e) base .OnSourceInitialized(e); // базовый функционал приложения в момент запуска
createTrayIcon(); // создание нашей иконки
>
private System.Windows.Forms. NotifyIcon TrayIcon = null ;
private ContextMenu TrayMenu = null ;
private bool createTrayIcon() bool result = false ;
if (TrayIcon == null ) < // только если мы не создали иконку ранее
TrayIcon = new System.Windows.Forms. NotifyIcon (); // создаем новую
TrayIcon. Icon = YourAppNamespace. Properties . Resources .icon1; // изображение для трея
// обратите внимание, за ресурсом с картинкой мы лезем в свойства проекта, а не окна,
// поэтому нужно указать полный namespace
TrayIcon. Text = "Here is tray icon text." ; // текст подсказки, всплывающей над иконкой
TrayMenu = Resources [ "TrayMenu" ] as ContextMenu ; // а здесь уже ресурсы окна и тот самый x:Key
// сразу же опишем поведение при щелчке мыши, о котором мы говорили ранее
// это будет просто анонимная функция, незачем выносить ее в класс окна
TrayIcon. Click += delegate ( object sender, EventArgs e) if ((e as System.Windows.Forms. MouseEventArgs ). Button == System.Windows.Forms. MouseButtons . Left ) // по левой кнопке показываем или прячем окно
ShowHideMainWindow(sender, null );
>
else // по правой кнопке (и всем остальным) показываем меню
TrayMenu. IsOpen = true ;
Activate(); // нужно отдать окну фокус, см. ниже
>
>;
result = true ;
>
else < // все переменные были созданы ранее
result = true ;
>
TrayIcon. Visible = true; // делаем иконку видимой в трее
return result;
>
В строке Activate() мы отдаем фокус главному окну приложения. Если вы этого не сделаете, менюшка в трее будет вести себя очень подозрительно. Она будет висеть там и ждать щелчка вечно. Вспомните, наверняка вы сталкивались с парой таких программ, меню которых отображаются над треем и ничем от них не избавишься, хоть куда мышью тыкай; а самое обидное, когда нельзя трогать ни один из пунктов этой маленькой заразы. Все всплывающие меню должны конечно же пропадать, когда пользователь теряет интерес к приложению и переключается на другое.
Строкой TrayIcon.Visible = true мы вызываем процедуру перерисовки иконки в трее. Она необходима для первичного показа иконки и не помешает в случае, если мы захотим использовать этот метод еще раз. Раньше многие операционные системы были склонны терять все содержимое лотка при вылете процесса explorer.exe, насчет XP и висты с семеркой точно не скажу, но на всякий случай оставим возможность перерисовать иконку без создания ее заново. Поэтому строка вынесена из блока проверки существования иконки. То же самое и с результатом функции. Если вы уверены, что вам это не надо, можно смело удалить.
Функция показа или скрытия главного окна:
private void ShowHideMainWindow( object sender, RoutedEventArgs e) <TrayMenu. IsOpen = false ; // спрячем менюшку, если она вдруг видима
if (IsVisible) < // если окно видно на экране
// прячем его
Hide();
// меняем надпись на пункте меню
(TrayMenu. Items [ 0 ] as MenuItem ). Header = "Show" ;
>
else < // а если не видно
// показываем
Show();
// меняем надпись на пункте меню
(TrayMenu. Items [ 0 ] as MenuItem ). Header = "Hide" ;
WindowState = CurrentWindowState;
Activate(); // обязательно нужно отдать фокус окну,
// иначе пользователь сильно удивится, когда увидит окно
// но не сможет в него ничего ввести с клавиатуры
>
>
Это обычный обработчик события OnClick (потому и набор аргументов такой) для любого элемента интерфейса. Мы его указали, как обработчик нажатия на верхний пункт меню. Он же использован в анонимной функции обработки щелчка по самой иконке.
Свойство CurrentWindowState описано в классе окна следующим образом:
private WindowState fCurrentWindowState = WindowState . Normal ;public WindowState CurrentWindowState get < return fCurrentWindowState; >
set < fCurrentWindowState = value; >
>
Оно нужно только затем, чтобы хранить текущее состояние окна (нормальное или развернутое на весь экран), когда мы прячем окно. В момент показа мы должны вернуть окно именно в это состояние. Почему нельзя воспользоваться вшитым в класс окна подобным свойством? Потому что там есть еще третье значение — минимизированное окно на панели задач, — которое нам совсем не нужно в момент возвращения из «спрятанного» состояния. При вызове демона из ада, вызывающий ожидает увидеть его перед собой, а не спрятанным в шкафу. То же самое и с окном. В этом месте текста аналогия с вызовом проституток показалась мне какой-то надуманной, поэтому я от нее отказался.
Итак, напишем маленькую обработку, которая будет убирать вкладку окна с панели задач, если окно минимизировано. Это типичное поведение для приложений, требующих наличия иконки в трее.
// переопределяем встроенную реакцию на изменение состоянияprotected override void OnStateChanged( EventArgs e) base .OnStateChanged(e); // системная обработка
if ( this .WindowState == System.Windows. WindowState . Minimized ) // если окно минимизировали, просто спрячем
Hide();
// и поменяем надпись на менюшке
(TrayMenu. Items [ 0 ] as MenuItem ). Header = "Show" ;
>
else // в противном случае запомним текущее состояние
CurrentWindowState = WindowState;
>
>
Здесь свойство окна WindowState конфликтует с одноименным типом из System.Windows.WindowState, поэтому я указал полный namspace и this. Среда от вас потребует только первого. А пятница первого, второго, пива и покурить.
Давайте еще научим приложение «сворачиваться в трей» и вместо закрытия окна. Это тоже типичное ожидаемое поведение для таких приложений. Выход из них обычно осуществляется с помощью нижнего пункта меню в трее (помните аутлук?) или с помощью пункта «Выход» в главном меню «Файл» (создать такой пункт вы можете самостоятельно в XAML-описании главного окна).
// переопределяем обработчик запроса выхода из приложения
protected override void OnClosing(System.ComponentModel. CancelEventArgs e) base .OnClosing(e); // встроенная обработка
if (!CanClose) < // если нельзя закрывать
e. Cancel = true ; выставляем флаг отмены закрытия
// запоминаем текущее состояние окна
CurrentWindowState = this . WindowState;
// меняем надпись в менюшке
(TrayMenu. Items [ 0 ] as MenuItem ). Header = "Show" ;
// прячем окно
Hide();
>
else < // все-таки закрываемся
// убираем иконку из трея
TrayIcon. Visible = false ;
>
>
Боже мой! Теперь мы никогда не сможем покинуть приложения! CanClose никогда не обратится в истину!
Не нужно паниковать. Вы же помните, что в самом начале последний пункт нашего контекстного меню ссылался на обработчик MenuExitClick(). На него же будет ссылаться и тот пункт главного меню, который вы создадите сами. А вот и его сложнейшая реализация:
private void MenuExitClick( object sender, RoutedEventArgs e) <CanClose = true ;
Close();
>
Итак, мы создали типовое приложение, работающее с треем, которое можно использовать как шаблон для других WPF-решений.
Приложение умеет:
1. Держать свою иконку в трее.
2. По щелчку на иконке левой кнопкой мыши прятать или показывать главное окно.
3. По щелчку на иконке правой кнопкой мыши отображать контекстное меню приложения, в котором реализованы обязательные пункты «Скрыть / Показать» и «Выход».
4. Прятать главное окно при его сворачивании.
5. Прятать главное окно вместо его закрытия.
Попутно реализованные вкусняшки:
1. Где только можно использован механизм WPF, даже в контекстом меню трея, которое мы чуть не потеряли, спускаясь на уровень Windows.Forms; а следовательно можно продолжать повсеместно использовать охрененную мощь WPF в построении интерфейса.
2. Необходимые обработчики реализованы переопределением стандартных protected-методов класса окна, таким образом не нужно помнить о них при навешивании своих обработок на события, предоставляемые окном в обычном приложении.
Скриншот пустого приложения с иконкой в трее и менюшкой, построенной на WPF:
Я новичок в WPF, и мне интересно, кто-нибудь может дать мне несколько советов, как написать приложение, которое будет свернуто в трей. Идея состоит в том, что он периодически выбирает RSS-канал и создает всплывающее окно с тостером при появлении новых каналов.
Приложение должно по-прежнему иметь главное окно (по сути, просто список, содержащий все записи фида), но оно должно быть скрыто по умолчанию.
Я начал читать о XAML и WPF и знаю, что StartupUri в App.xaml должен указывать на мое главное окно, но я понятия не имею, как правильно сделать значок SysTray и скрыть главное окно (это также означает, что когда пользователь сворачивает окно, оно должно быть свернуто в трей, а не в панель задач).
Спасибо за все предложения! WPF-NotifyIcon - это то, с чем я пойду, поскольку быстрый тест показывает, что он довольно многообещающий и безболезненный.Там нет NotifyIcon для WPF.
Мой коллега использовал эту свободно доступную библиотеку для хорошего эффекта:
Вы должны использовать элемент управления NotifyIcon из System.Windows.Forms или, в качестве альтернативы, вы можете использовать API значка уведомлений, предоставляемый Windows API. WPF не предоставляет такого эквивалента, и его несколько раз запрашивали в Microsoft Connect.
Вот краткие биты:
Создайте окно WPF с ShowInTaskbar = False, которое загружается в невидимом состоянии.
На уровне класса:
Во время OnInitialize ():
Во время OnLoaded ():
И для взаимодействия (показано как notifyIcon.Click и DoubleClick выше):
Отсюда вы можете возобновить использование элементов управления WPF и API, таких как контекстные меню, всплывающие окна и т. Д.
Надеюсь, это поможет.
Немного сыра, что для получения иконки в трее необходимо использовать компонент Framework до версии 3.0, но, как объяснила Microsoft, концепция System Tray в рамках WPF отсутствует. WPF - это технология презентации, а значки уведомлений - это концепция операционной системы (а не «презентация»).
Так же если у вас есть предложение о сотрудничестве, пожелания, указать на нарушения сайта или просто сказать слова благодарности, все это вы можете сделать через форму обратной связи. Читать дальше
Сворачиваем консольное приложение в область уведомлений(трей)
Бывает, необходимость свернуть приложение в область уведомлений, особенно когда выполняется большой код. Рассмотрим пример реализации данной задачи. Создайте проект консольного приложения в Microsoft Visual Studio.
Для сворачивания консольного приложения в область уведомлений, воспользуемся WinAPI функцией ShowWindow с параметром 1. Что бы отобразить консольное приложение в области уведомлений воспользуемся пространством имен System.Windows.Forms, которое содержит классы для создания приложений Windows, позволяющие наиболее эффективно использовать расширенные возможности пользовательского интерфейса, доступные в операционной системе Microsoft Windows.
Добавьте данное пространство имен в ваш проект.
И ссылку на его библиотеку.
Данное пространство имен содержит класс NotifyIcon. Класс указывает на компонент, который создает значок в области уведомлений.
Указываем создание нового компонента NotifyIcon, который создаст значок в области уведомлений.
Далее необходимо задать текущий значок, инициализируя новый экземпляр класса System.Drawing.Icon из указанного имени файла иконки формата *.ico. Данный значок будет отображаться в значок в области уведомлений. Файл значка необходимо положить в туже директорию, что и исполняемый файл.
Так же необходимо добавить ссылку на библиотеку System.Drawing.
Читайте также: