Как сделать иконку wpf

Обновлено: 05.07.2024

Войти

Авторизуясь в LiveJournal с помощью стороннего сервиса вы принимаете условия Пользовательского соглашения LiveJournal

WPF: иконка в трее

В жизни каждого человека рано или поздно настает момент, когда требуется создать приложение, сворачивающееся в трей (системная панелька, "где часики"). Сейчас мы посмотрим, как это можно насишарпить © в 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. Среда от вас потребует только первого. А пятница первого, второго, пива и покурить.

// переопределяем обработчик запроса выхода из приложения
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(). На него же будет ссылаться и тот пункт главного меню, который вы создадите сами. А вот и его сложнейшая реализация:

Итак, мы создали типовое приложение, работающее с треем, которое можно использовать как шаблон для других WPF-решений.

Попутно реализованные вкусняшки:
1. Где только можно использован механизм WPF, даже в контекстом меню трея, которое мы чуть не потеряли, спускаясь на уровень Windows.Forms; а следовательно можно продолжать повсеместно использовать охрененную мощь WPF в построении интерфейса.
2. Необходимые обработчики реализованы переопределением стандартных protected-методов класса окна, таким образом не нужно помнить о них при навешивании своих обработок на события, предоставляемые окном в обычном приложении.

Скриншот пустого приложения с иконкой в трее и менюшкой, построенной на WPF:

Я создаю приложение WPF, и я хотел опубликовать его. Поэтому я создал новый проект установки и развертывания и добавил в него свое приложение. Теперь, когда я создал установочный файл и запустил его. он создал ярлык на рабочем столе. Но изображение на рабочем столе было по умолчанию для Windows, и я хочу изменить его на другой файл значков. Пожалуйста, скажите мне, как это сделать. Благодарю.

3 ответа

Сначала вам нужно будет добавить значок в ваш проект. В свойствах вашего значка установите Build Action в Resource.

Затем в главном файле Window.xaml установите свойство Icon.

Откройте окно свойств приложения. В разделе "Приложения" есть "Значок и манифест". Добавьте иконку туда. Более подробная информация здесь

А также вы можете добавить файл.ico в папку с программными файлами пользователя. После этого вы можете добавить ярлык на рабочий стол пользователя. Важным моментом является то, что вы должны настроить цель shourtcut на эту папку.ico.

Я использую значок в своем приложении в двух ситуациях.

    В XAML в качестве изображения для кнопки с использованием DynamicResource.

this.notifyIcon.Icon = новый SystemDrawing.Icon( "..//..//Shutdown.ico" );

Моя проблема в том, что я удалю изображение, которое приложение не работает. Как связать образ с exe файлом, чтобы приложение могло работать только с файлом exe?

Добавить значок в проект как ресурс (не встроенный ресурс, есть разница), затем получить его с помощью

Затем вы также сможете использовать его в своем XAML, я пока еще не могу вспомнить.

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

В прошлый раз, когда мне нужно было это сделать, изображение было настолько простым, что проще было просто создать линейный рисунок в XAML (аналогично SVG) вместо использования файла. Я пытался создать простой мастер в стиле Vista без повторного использования кода другого пользователя (чтобы узнать, могу ли я это сделать), и мне нужна стрелка командной кнопки, как это видно в Рекомендации UX в MSDN.

Ключевым элементом в системе графического интерфейса в WPF является окно, которое содержит все необходимые элементы управления. Окно в WPF представлено классом Window , который является производным от класса ContentControl. Поэтому окно является элементом управления содержимым, и как, к примеру, кнопка, может содержать в себе один дочерний элемент. Как правило, в его качестве выступает один из элементов компоновки, например, Grid.

Класс Window привносит ряд свойств, которые позволяют настроить окно приложения:

AllowsTransparency : при значении true позволяет установить прозрачный фон окна

Icon : представляет иконку, которая отображается в левом верхнем углу окна и в панели задач. Если иконка не установлена, то система будет использовать стандартную иконку по умолчанию.

Top : устанавливает отступ окна приложения от верхней границы экрана

Left : устанавливает отступ окна приложения от левой границы экрана

ResizeMode : задает режим изменения размеров окна. Может принимать следующие значения:

CanMinimize : окно можно только свернуть

NoResize : у окна нельзя изменить начальные размеры

CanResize : у окна можно изменять размеры

CanResizeWithGrip : в правом нижнем углу окна появляется визуализация того, что у окна можно изменять размеры

RestoreBounds : возвращает границы окна

ShowInTaskbar : при значении true иконка окна отображается на панели задач

SizeToContent : позволяет автоматически масштабировать размеры окна в зависимости от содержимого. Может принимать следующие значения:

Width : автоматически масштабируется только ширина

Height : автоматически масштабируется только высота

WidthAndHeight : автоматически масштабируются высота и ширина

Manual : автоматическое масштабирование отсутствует

Title : заголовок окна

Topmost : при значении true окно устанавливается поверх других окон приложения

WindowStartupLocation : устанавливает стартовую позицию окна. Может принимать следующие значения:

CenterOwner : если данное окно было запущено другим окном, то данное окно позиционируется относительно центра запустившего его окна

CenterScreen : окно помещается в центре экрана

Manual : позиция устанавливается вручную с помощью свойств Top и Left

WindowState : состояние окна. Возможные значения:

Maximized : раскрыто на весь экран

Normal : стандартное состояние

Жизненный цикл

В процессе работы окно в WPF проходит ряд этапов жизненного цикла, которые доступны нам через обработку событий класса Window:

Initialized : это событие возникает при инициализации окна, когда у него устанавливаются все свойства, но до применения к нему стилей и привязки данных. Это общее событие для всех элементов управления в WPF, поэтому следует учитывать, что сначала возникают события вложенных элементов, а затем их контейнеров. То есть событие Initialized окна приложения генерируется только после того, как отработает событие Initialized для всех вложенных элементов.

Loaded : возникает после полной инициализации окна и применения к нему стилей и привязки данных. После генерации этого события происходит визуализация элемента, и окно отображается на экране и становится видимым для пользователя

Closing : возникает при закрытии окна

Closed : возникает, когда окно становится закрытым

Unloaded : возникает после закрытия окна при выгрузке всех связанных ресурсов из памяти

Соответственно, если нам надо выполнить некоторые действия при загрузке или при закрытии окна, мы можем обработать события Loaded и Closing/Closed. Например, запишем в текстовый лог события жизненного цикла:

Microsoft Logo

Gray Pipe

Приносим извинения. Запрошенное содержимое было удалено. Вы будете автоматически перенаправлены через 1 секунду.

Лучший отвечающий

Вопрос

Подскажите пожалуйста, что мне нужно сделать в WPF Application, чтобы напротив menuItems была иконка формата .jpg?

Ответы

В появившемся окне ищем картинку (какая вам ближе по душе) и нажимаем ДОБАВИТЬ, потом в XAML-коде пишем названия вашей картинки вместо 1.jpg.

Вот примерно так:

  • Помечено в качестве ответа Yatajga Moderator 3 мая 2013 г. 16:00

Все ответы

Пишет что ошибок нет. компилирую иииии. иконки нет) хотя в хотя в конструкторе формы она отображается.

Читайте также: