Кто может подсказать решение такой задачи? есть программа которая сворачивается в трей, в программе есть 3 выпадающих списка с выбором цвета, надо сделать в трее иконку которая будет видом в 3 колонки и каждая колонка должна закрашиваться в тот цвет который выбран в списках программы. Не знаю как это сделать думал как то использовать UserControl вместо иконки (графического элемента) но не знаю как это воплотить в жизнь
Дам вам пищу для размышления (возьму пример из своего приложения, по желанию можно и переделать). В главном окне приложения объявим вот такую переменную:
private System.Windows.Forms.NotifyIcon _notifyIcon;
В ресурсы приложения я добавил картинку (иконку) AppIcon
. И напишем вот такой метод создания иконки в трее и ее отображение:
private void SetIconToMainApplication()
{
_notifyIcon = new System.Windows.Forms.NotifyIcon();
_notifyIcon.Icon = Properties.Resources.ResourceManager.GetObject("AppIcon") as Icon;
_notifyIcon.Visible = true;
}
Который поместим внутрь конструктора окна сразу после InitializeComponent
:
public MainWindow()
{
InitializeComponent();
SetIconToMainApplication();
}
Да, когда приложение закрываете, нужно вызвать Dispose()
у NotifyIcon
, вот так:
if (_notifyIcon != null)
{
_notifyIcon.Dispose();
}
Думаю, что вы догадываетесь о том, что вам нужно создавать иконку, во время выбора цвета и выводить ее в трей. Касаемо этого вопроса - тут не подскажу...хотя, возможно стоит сделать заготовку нескольких иконок с разными цветами, но это будет достаточно сложно если много цветов, а если их не много, то будет проще. Возможно стоит покапать в строну динамического создания иконок, точнее не создания, а изменения.
Класс NotifyIcon
- указывает компонент, который создает значок в
области уведомлений. Этот класс не наследуется.
Возможно стоит инициализировать новый экземпляр класса NotifyIcon
с указанным контейнером через конструктор NotifyIcon (IContainer), а уже контейнер будет предоставлять функции. Контейнеры являются объектами, которые логически содержат нуль или более компонентов. Может быть можно с помощью контейнеров это сделать, тут нужно пробовать, увы, задача не из простых.
А также будет полезно:
Так как ТС не хочет пользоваться в WPF
тем что предложили ранее, или не хочет мешать WinForm
с WPF
.
Приступим
Для начала переопределим метод OnStartup
в App.xaml.cs
таким образом, что бы мы могли инициализировать TaskbarIcon
из библиотеки Hardcodet.NotifyIcon.Wpf
.
protected override void OnStartup(StartupEventArgs e)
{
TbIcon = new TaskbarIcon();
base.OnStartup(e);
}
Далее определим статическое поле для того что бы могли обращаться к нему из любого места приложения.
public static TaskbarIcon TbIcon { get; protected set; }
Так же переопределим метод OnExit
и в нем будем вызывать Dispose()
для иконки.
protected override void OnExit(ExitEventArgs e)
{
TbIcon?.Dispose();
base.OnExit(e);
}
Прежде чем продолжить предлагаю ознакомиться с тем, как в WPF
делается скриншот элементов. Думаю данный расширяющий класс достаточно локаничен к каждому кто его посмотрит:
public static partial class Extension
{
// расширение для FrameworkElement
public static ImageSource TakeScreenShoot(this FrameworkElement element)
{
var renderTargetBitmap = new RenderTargetBitmap((int) element.ActualWidth, (int) element.ActualHeight, 96,
96, PixelFormats.Default);
renderTargetBitmap.Render(element);
return renderTargetBitmap;
}
// расширение для RenderTargetBitmap преобразование в Bitmap
public static Bitmap ToBitmap(this RenderTargetBitmap source)
{
using (var memoryStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(source));
enc.Save(memoryStream);
var bitmap = new Bitmap(memoryStream);
return new Bitmap(bitmap);
}
}
// расширение для ImageSource преобразование в Bitmap
public static Bitmap ToBitmap(this ImageSource source)
{
if (!(source is RenderTargetBitmap temp))
throw new NotSupportedException(nameof(source));
using (var memoryStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(temp));
enc.Save(memoryStream);
var bitmap = new Bitmap(memoryStream);
return new Bitmap(bitmap);
}
}
}
Оригинал класса лежит здесь
Для чего же он нужен? Все очень просто, будем использовать его для получения скриншота контрола, и преобразования в System.Drawing.Icon
.
Далее нам понадобится любой удобный ColorPicker
, я использовал: WpfToolkit. Так же доступен Nuget
пакет.
Сделаем простейший контрол(UserControl), чем я не стал заниматься, а прямо сделал как показано ниже для ускорения разработки примера:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
SnapsToDevicePixels="True"
xmlns:xwpf="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="120" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Bottom">
<xwpf:ColorPicker SelectedColor="Red" Name="ColorPicker1" VerticalAlignment="Center"
HorizontalAlignment="Center" />
<xwpf:ColorPicker Name="ColorPicker2" VerticalAlignment="Center"
HorizontalAlignment="Center" SelectedColor="Green" />
<xwpf:ColorPicker SelectedColor="Blue" Name="ColorPicker3" VerticalAlignment="Center"
HorizontalAlignment="Center" />
</StackPanel>
<Border Visibility="Visible" x:Name="IconData" HorizontalAlignment="Left" Background="White"
BorderThickness="1" Width="120"
Height="120" BorderBrush="Black" Grid.Row="0" Grid.Column="0">
<Border BorderBrush="Black" BorderThickness="0,1,0,1" VerticalAlignment="Center"
HorizontalAlignment="Stretch" Height="40">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="40" />
<ColumnDefinition Width="40" />
</Grid.ColumnDefinitions>
<Border Width="39" HorizontalAlignment="Left" BorderBrush="Black"
BorderThickness="0,0,1,0">
<Border.Background>
<SolidColorBrush
Color="{Binding ElementName=ColorPicker1, Path=SelectedColor}" />
</Border.Background>
</Border>
<Border HorizontalAlignment="Left" Width="39" BorderBrush="Black" BorderThickness="0,0,1,0" Grid.ColumnSpan="2" Margin="39,0,0,0" >
<Border.Background>
<SolidColorBrush
Color="{Binding ElementName=ColorPicker2, Path=SelectedColor}" />
</Border.Background>
</Border>
<Border Width="40" HorizontalAlignment="Left" Grid.Column="1" Grid.ColumnSpan="2" Margin="38,0,0,0">
<Border.Background>
<SolidColorBrush Color="{Binding ElementName=ColorPicker3, Path=SelectedColor}" />
</Border.Background>
</Border>
</Grid>
</Border>
</Border>
</Grid>
</Window>
Получим что-то следующее:
CodeBehind окна будет выглядеть примерно так (все сделано просто для примера, над кодом нужна работа):
using System;
using System.Drawing;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Color = System.Windows.Media.Color;
namespace WpfApp1
{
/// <summary>
/// Логика взаимодействия для MainWindow.xaml
/// </summary>
///
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
ColorPicker1.SelectedColorChanged += ColorPicker1_SelectedColorChanged;
ColorPicker2.SelectedColorChanged += ColorPicker1_SelectedColorChanged;
ColorPicker3.SelectedColorChanged += ColorPicker1_SelectedColorChanged;
}
private void ColorPicker1_SelectedColorChanged(object sender, RoutedPropertyChangedEventArgs<Color?> e)
{
UpdateImage();
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
UpdateImage();
}
private void UpdateImage()
{
Icon = IconData.TakeScreenShoot();
App.TbIcon.Icon = System.Drawing.Icon.FromHandle(Icon.ToBitmap().GetHicon());
}
}
}
Ну что ж, теперь запускаем, и любуемся тому что у окна, и иконки в трее одинаковые значки, а так же при изменении цвета в них, меняется и иконка.
Результат:
Предупреждение
У данного подхода есть один минус, контрол с которого делается снимок, должен лежать по X/Y = 0
, иначе получим пустой снимок. Почему так происходит мне пока неизвестно
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Открываю в c# Excel, туда записываю данные в соответствующие строки и столбцы, необходимо по условию выделить строчку каким-то цветом, как это...
ошибка в этой строке SqlDataReader dr = sqlCommand1ExecuteReader(); остальной код программы
Возле menuitem всегда квадратная пустая иконкаКак ее убрать?