[ColorPicker]Port UI from WPF-UI to .net 9 WPF (#37149)

* Initial implementation

* fix style

* Added border to popup

* More changes

* Now use accent color for select button

* Addressed feedback

* fix formatting

* Fix pressing the select in HC mode hiding its text

* Fix W10 hc1 and hc2 hover select button text invisible

* Update src/modules/colorPicker/ColorPickerUI/Controls/ColorPickerControl.xaml

Co-authored-by: Niels Laute <niels.laute@live.nl>

* Addresed feedback regarding FontFamily

* Made the titlebar part of the body

* fix wrong variable

* Added system menu option on right click on toolbar.
Fixed hide then show removing Mica effect

* Fix spell-check

* Fix xaml styling

---------

Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
This commit is contained in:
Ionuț Manța
2025-03-12 05:15:17 -07:00
committed by GitHub
parent 82bc3b7c85
commit 92fb931e1e
13 changed files with 500 additions and 245 deletions

View File

@@ -2,13 +2,11 @@
x:Class="ColorPickerUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
StartupUri="MainWindow.xaml">
StartupUri="MainWindow.xaml"
ThemeMode="System">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ThemesDictionary Theme="Dark" />
<ui:ControlsDictionary />
<ResourceDictionary Source="Resources/Styles.xaml" />
<ResourceDictionary Source="Resources/ViewModelViewMappings.xaml" />
</ResourceDictionary.MergedDictionaries>

View File

@@ -1,4 +1,4 @@
<ui:FluentWindow
<Window
x:Class="ColorPicker.ColorEditorWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -7,41 +7,51 @@
xmlns:e="http://schemas.microsoft.com/xaml/behaviors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:p="clr-namespace:ColorPicker.Properties"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
Width="440"
Height="380"
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
AutomationProperties.Name="{x:Static p:Resources.cp_editor}"
ExtendsContentIntoTitleBar="True"
ResizeMode="NoResize"
Topmost="True"
WindowCornerPreference="Default"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<e:Interaction.Behaviors>
<behaviors:CloseZoomWindowBehavior />
</e:Interaction.Behaviors>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ui:TitleBar
x:Name="TitleBar"
Title="{x:Static p:Resources.CP_Title}"
Grid.Row="0"
Height="32"
Padding="16,0,16,0"
ShowMaximize="False"
ShowMinimize="False">
<ui:TitleBar.Icon>
<ui:ImageIcon Source="pack://application:,,,/Assets/ColorPicker/icon.ico" />
</ui:TitleBar.Icon>
</ui:TitleBar>
<ContentPresenter
x:Name="contentPresenter"
Grid.Row="1"
Content="{Binding Content}" />
</Grid>
</ui:FluentWindow>
<Border x:Name="MainBorder" BorderBrush="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DockPanel
Grid.Row="0"
Background="Transparent"
MouseLeftButtonDown="TitleBar_MouseDown"
MouseRightButtonUp="TitleBar_MouseRightClick">
<Image
Width="20"
Height="20"
Margin="10,5,5,8"
Source="pack://application:,,,/Assets/ColorPicker/icon.ico" />
<TextBlock
Margin="10"
VerticalAlignment="Center"
Text="{x:Static p:Resources.CP_Title}" />
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button
Width="50"
Height="30"
Margin="10,-10,-2,1"
Click="Close_Click"
Content="&#xE711;"
FontFamily="{StaticResource IconFontFamily}"
Style="{StaticResource TitleBarCloseButtonStyle}" />
</StackPanel>
</DockPanel>
<ContentPresenter
x:Name="contentPresenter"
Grid.Row="1"
Content="{Binding Content}" />
</Grid>
</Border>
</Window>

View File

@@ -3,25 +3,31 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Drawing.Printing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Shell;
using ColorPicker.Helpers;
using ControlzEx.Theming;
using ManagedCommon;
using Wpf.Ui.Controls;
using Microsoft.Diagnostics.Tracing.Parsers.ClrPrivate;
using Microsoft.Win32;
using Windows.Graphics;
namespace ColorPicker
{
/// <summary>
/// Interaction logic for ColorEditorWindow.xaml
/// </summary>
public partial class ColorEditorWindow : FluentWindow
public partial class ColorEditorWindow : Window
{
private readonly AppStateHandler _appStateHandler;
public ColorEditorWindow(AppStateHandler appStateHandler)
{
InitializeComponent();
Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this);
WindowBackdropType = OSVersionHelper.IsWindows11() ? WindowBackdropType.Mica : WindowBackdropType = WindowBackdropType.None;
_appStateHandler = appStateHandler;
Closing += ColorEditorWindow_Closing;
@@ -35,7 +41,143 @@ namespace ColorPicker
protected override void OnSourceInitialized(EventArgs e)
{
WindowChrome.SetWindowChrome(
this,
new WindowChrome
{
CaptionHeight = 0,
CornerRadius = default,
GlassFrameThickness = new Thickness(-1),
ResizeBorderThickness = ResizeMode == ResizeMode.NoResize ? default : new Thickness(4),
UseAeroCaptionButtons = false,
});
if (OSVersionHelper.IsWindows11())
{
// ResizeMode="NoResize" removes rounded corners. So force them to rounded.
IntPtr hWnd = new WindowInteropHelper(GetWindow(this)).EnsureHandle();
DWMWINDOWATTRIBUTE attribute = DWMWINDOWATTRIBUTE.DWMWA_WINDOW_CORNER_PREFERENCE;
DWM_WINDOW_CORNER_PREFERENCE preference = DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_ROUND;
DwmSetWindowAttribute(hWnd, attribute, ref preference, sizeof(uint));
}
else
{
// On Windows10 ResizeMode="NoResize" removes the border so we add a new one.
MainBorder.BorderThickness = new System.Windows.Thickness(0.5);
}
// Hide then Show with WindowStyle="None" will remove the Mica effect. So manually remove the titlebar.
RemoveWindowTitlebarContents();
base.OnSourceInitialized(e);
}
public void RemoveWindowTitlebarContents()
{
IntPtr handle = new WindowInteropHelper(GetWindow(this)).EnsureHandle();
if (handle == IntPtr.Zero)
{
return;
}
int windowStyleLong = GetWindowLong(handle, GWLSTYLE);
windowStyleLong &= ~(int)WindowStyles.WS_SYSMENU;
IntPtr result = SetWindowLong(handle, GWLSTYLE, windowStyleLong);
if (result.ToInt64() == 0)
{
int error = Marshal.GetLastWin32Error();
Logger.LogError($"SetWindowLong error {error}");
}
}
private void Close_Click(object sender, RoutedEventArgs e)
{
Close();
}
private void TitleBar_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
this.DragMove();
}
}
private void TitleBar_MouseRightClick(object sender, MouseButtonEventArgs e)
{
IntPtr hwnd = new WindowInteropHelper(this).Handle;
// Get the mouse position relative to the screen
Point mousePosition = e.GetPosition(this);
Point screenPoint = PointToScreen(mousePosition);
// Display the system menu at the current mouse position
IntPtr hMenu = GetSystemMenu(hwnd, false);
if (hMenu != IntPtr.Zero)
{
int command = TrackPopupMenu(
hMenu,
TPMLEFTALIGN | TPMRETURNCMD,
(int)screenPoint.X,
(int)screenPoint.Y,
0,
hwnd,
IntPtr.Zero);
if (command > 0)
{
SendMessage(hwnd, WMSYSCOMMAND, new IntPtr(command), IntPtr.Zero);
}
}
}
private const int WMSYSCOMMAND = 0x0112;
private const int TPMLEFTALIGN = 0x0000;
private const int TPMRETURNCMD = 0x0100;
// The enum flag for DwmSetWindowAttribute's second parameter, which tells the function what attribute to set.
public enum DWMWINDOWATTRIBUTE
{
DWMWA_WINDOW_CORNER_PREFERENCE = 33,
}
public enum DWM_WINDOW_CORNER_PREFERENCE
{
DWMWCP_DEFAULT = 0,
DWMWCP_DONOTROUND = 1,
DWMWCP_ROUND = 2,
DWMWCP_ROUNDSMALL = 3,
}
// Import dwmapi.dll and define DwmSetWindowAttribute in C# corresponding to the native function.
[DllImport("dwmapi.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
internal static extern void DwmSetWindowAttribute(
IntPtr hwnd,
DWMWINDOWATTRIBUTE attribute,
ref DWM_WINDOW_CORNER_PREFERENCE pvAttribute,
uint cbAttribute);
[DllImport("user32.dll")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
private static extern int TrackPopupMenu(IntPtr hMenu, int uFlags, int x, int y, int nReserved, IntPtr hWnd, IntPtr prcRect);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", SetLastError = true)]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
public const int GWLSTYLE = -16;
[Flags]
public enum WindowStyles : uint
{
WS_SYSMENU = 0x00080000, // System menu (close/maximize/minimize button area)
}
}
}

View File

@@ -38,7 +38,6 @@
<PackageReference Include="System.IO.Abstractions" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" />
<PackageReference Include="System.Drawing.Common" />
<PackageReference Include="WPF-UI" />
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">

View File

@@ -6,7 +6,6 @@
xmlns:local="clr-namespace:ColorPicker"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:p="clr-namespace:ColorPicker.Properties"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
mc:Ignorable="d">
<UserControl.Resources>
<Style x:Key="ReadonlyTextBoxStyle" TargetType="{x:Type TextBox}">
@@ -66,7 +65,6 @@
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
IsTabStop="{TemplateBinding ScrollViewer.IsTabStop}"
Style="{StaticResource DefaultTextBoxScrollViewerStyle}"
TextElement.Foreground="{TemplateBinding Foreground}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" />
</Grid>
@@ -173,7 +171,7 @@
Style="{StaticResource SubtleButtonStyle}"
ToolTipService.ToolTip="{x:Static p:Resources.Copy_to_clipboard}">
<Button.Content>
<ui:SymbolIcon FontSize="20" Symbol="Copy20" />
<TextBlock FontFamily="{StaticResource IconFontFamily}" Text="&#xE8C8;" />
</Button.Content>
</Button>
</Grid>

View File

@@ -6,7 +6,6 @@
xmlns:helpers="clr-namespace:ColorPicker.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:p="clr-namespace:ColorPicker.Properties"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
AutomationProperties.Name="{x:Static p:Resources.Color_Palette}"
FocusManager.IsFocusScope="True"
KeyboardNavigation.TabNavigation="Once"
@@ -213,175 +212,177 @@
Style="{DynamicResource ColorShadeButtonStyle}"
ToolTipService.ToolTip="{x:Static p:Resources.Selected_color_tooltip}">
<ui:Flyout
<Popup
x:Name="DetailsFlyout"
Margin="24,0,0,0"
AllowsTransparency="True"
Closed="DetailsFlyout_Closed"
Opened="DetailsFlyout_Opened"
Placement="Top">
<Grid x:Name="detailsGrid" KeyboardNavigation.TabNavigation="Contained">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="44" />
<ColumnDefinition Width="86" />
<ColumnDefinition Width="86" />
<ColumnDefinition Width="86" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="8" />
<RowDefinition Height="Auto" />
<RowDefinition Height="8" />
<RowDefinition Height="Auto" />
<RowDefinition Height="12" />
<RowDefinition Height="Auto" />
<RowDefinition Height="12" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
Placement="Top"
StaysOpen="False">
<Border
Padding="15"
Background="{DynamicResource ApplicationBackgroundBrush}"
BorderBrush="{DynamicResource SurfaceStrokeColorFlyoutBrush}"
BorderThickness="1"
CornerRadius="16">
<Grid x:Name="detailsGrid" KeyboardNavigation.TabNavigation="Contained">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="44" />
<ColumnDefinition Width="86" />
<ColumnDefinition Width="86" />
<ColumnDefinition Width="86" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="8" />
<RowDefinition Height="Auto" />
<RowDefinition Height="8" />
<RowDefinition Height="Auto" />
<RowDefinition Height="12" />
<RowDefinition Height="Auto" />
<RowDefinition Height="12" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="H"
TextAlignment="Center" />
<TextBlock
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="H"
TextAlignment="Center" />
<Slider
x:Name="HueGradientSlider"
Grid.Column="1"
Grid.ColumnSpan="3"
VerticalAlignment="Center"
AutomationProperties.Name="{x:Static p:Resources.Hue_slider}"
IsMoveToPointEnabled="True"
Maximum="289"
Minimum="0"
ValueChanged="HueGradientSlider_ValueChanged" />
<Slider
x:Name="HueGradientSlider"
Grid.Column="1"
Grid.ColumnSpan="3"
VerticalAlignment="Center"
AutomationProperties.Name="{x:Static p:Resources.Hue_slider}"
IsMoveToPointEnabled="True"
Maximum="289"
Minimum="0"
ValueChanged="HueGradientSlider_ValueChanged" />
<TextBlock
Grid.Row="2"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="S"
TextAlignment="Center" />
<TextBlock
Grid.Row="2"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="S"
TextAlignment="Center" />
<Slider
x:Name="SaturationGradientSlider"
Grid.Row="2"
Grid.Column="1"
Grid.ColumnSpan="3"
AutomationProperties.Name="{x:Static p:Resources.Saturation_slider}"
IsMoveToPointEnabled="True"
Maximum="289"
Minimum="0"
ValueChanged="SaturationGradientSlider_ValueChanged">
<Slider.Background>
<LinearGradientBrush StartPoint="0, 0.5" EndPoint="1,0.5">
<GradientStop x:Name="SaturationStartColor" Color="Black" />
<GradientStop x:Name="SaturationStopColor" Offset="1" Color="Red" />
</LinearGradientBrush>
</Slider.Background>
</Slider>
<Slider
x:Name="SaturationGradientSlider"
Grid.Row="2"
Grid.Column="1"
Grid.ColumnSpan="3"
AutomationProperties.Name="{x:Static p:Resources.Saturation_slider}"
IsMoveToPointEnabled="True"
Maximum="289"
Minimum="0"
ValueChanged="SaturationGradientSlider_ValueChanged">
<Slider.Background>
<LinearGradientBrush StartPoint="0, 0.5" EndPoint="1,0.5">
<GradientStop x:Name="SaturationStartColor" Color="Black" />
<GradientStop x:Name="SaturationStopColor" Offset="1" Color="Red" />
</LinearGradientBrush>
</Slider.Background>
</Slider>
<TextBlock
Grid.Row="4"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="V"
TextAlignment="Center" />
<TextBlock
Grid.Row="4"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="V"
TextAlignment="Center" />
<Slider
x:Name="ValueGradientSlider"
Grid.Row="4"
Grid.Column="1"
Grid.ColumnSpan="3"
AutomationProperties.Name="{x:Static p:Resources.Value_slider}"
IsMoveToPointEnabled="True"
Maximum="289"
Minimum="0"
ValueChanged="ValueGradientSlider_ValueChanged">
<Slider.Background>
<LinearGradientBrush StartPoint="0, 0.5" EndPoint="1,0.5">
<GradientStop x:Name="ValueStartColor" Color="Black" />
<GradientStop x:Name="ValueStopColor" Offset="1" Color="Red" />
</LinearGradientBrush>
</Slider.Background>
</Slider>
<Slider
x:Name="ValueGradientSlider"
Grid.Row="4"
Grid.Column="1"
Grid.ColumnSpan="3"
AutomationProperties.Name="{x:Static p:Resources.Value_slider}"
IsMoveToPointEnabled="True"
Maximum="289"
Minimum="0"
ValueChanged="ValueGradientSlider_ValueChanged">
<Slider.Background>
<LinearGradientBrush StartPoint="0, 0.5" EndPoint="1,0.5">
<GradientStop x:Name="ValueStartColor" Color="Black" />
<GradientStop x:Name="ValueStopColor" Offset="1" Color="Red" />
</LinearGradientBrush>
</Slider.Background>
</Slider>
<TextBlock
Grid.Row="6"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="RGB"
TextAlignment="Center" />
<TextBlock
Grid.Row="6"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="RGB"
TextAlignment="Center" />
<ui:NumberBox
x:Name="RNumberBox"
Grid.Row="6"
Grid.Column="1"
AutomationProperties.Name="{x:Static p:Resources.Red_value}"
Maximum="255"
Minimum="0"
SpinButtonPlacementMode="Compact"
TextBoxBase.TextChanged="RGBNumberBox_TextChanged" />
<TextBox
x:Name="RNumberBox"
Grid.Row="6"
Grid.Column="1"
AutomationProperties.Name="{x:Static p:Resources.Red_value}"
PreviewTextInput="TextBox_PreviewTextInput"
TextBoxBase.TextChanged="RGBNumberBox_TextChanged" />
<TextBox
x:Name="GNumberBox"
Grid.Row="6"
Grid.Column="2"
Margin="4,0,0,0"
AutomationProperties.Name="{x:Static p:Resources.Green_value}"
PreviewTextInput="TextBox_PreviewTextInput"
TextBoxBase.TextChanged="RGBNumberBox_TextChanged" />
<TextBox
x:Name="BNumberBox"
Grid.Row="6"
Grid.Column="3"
Margin="4,0,0,0"
AutomationProperties.Name="{x:Static p:Resources.Blue_value}"
PreviewTextInput="TextBox_PreviewTextInput"
TextBoxBase.TextChanged="RGBNumberBox_TextChanged" />
<ui:NumberBox
x:Name="GNumberBox"
Grid.Row="6"
Grid.Column="2"
Margin="4,0,0,0"
AutomationProperties.Name="{x:Static p:Resources.Green_value}"
Maximum="255"
Minimum="0"
SpinButtonPlacementMode="Compact"
TextBoxBase.TextChanged="RGBNumberBox_TextChanged" />
<TextBlock
Grid.Row="8"
Width="38"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="HEX"
TextAlignment="Center" />
<TextBox
x:Name="HexCode"
Grid.Row="8"
Grid.Column="1"
Grid.ColumnSpan="3"
HorizontalAlignment="Stretch"
AutomationProperties.Name="{x:Static p:Resources.Hex_value}"
CharacterCasing="Lower"
GotKeyboardFocus="HexCode_GotKeyboardFocus"
MaxLength="7"
TextChanged="HexCode_TextChanged"
TextWrapping="Wrap" />
<ui:NumberBox
x:Name="BNumberBox"
Grid.Row="6"
Grid.Column="3"
Margin="4,0,0,0"
AutomationProperties.Name="{x:Static p:Resources.Blue_value}"
Maximum="255"
Minimum="0"
SpinButtonPlacementMode="Compact"
TextBoxBase.TextChanged="RGBNumberBox_TextChanged" />
<Button
x:Name="OKButton"
Grid.Row="9"
Grid.ColumnSpan="4"
Margin="0,32,0,0"
HorizontalAlignment="Stretch"
AutomationProperties.Name="{x:Static p:Resources.Select}"
Click="OKButton_Click"
Content="{x:Static p:Resources.Select}"
Style="{StaticResource CustomAccentButtonStyle}" />
<TextBlock
Grid.Row="8"
Width="38"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="HEX"
TextAlignment="Center" />
<TextBox
x:Name="HexCode"
Grid.Row="8"
Grid.Column="1"
Grid.ColumnSpan="3"
HorizontalAlignment="Stretch"
AutomationProperties.Name="{x:Static p:Resources.Hex_value}"
CharacterCasing="Lower"
GotKeyboardFocus="HexCode_GotKeyboardFocus"
MaxLength="7"
TextChanged="HexCode_TextChanged"
TextWrapping="Wrap" />
<ui:Button
x:Name="OKButton"
Grid.Row="9"
Grid.ColumnSpan="4"
Margin="0,32,0,0"
HorizontalAlignment="Stretch"
Appearance="Primary"
AutomationProperties.Name="{x:Static p:Resources.Select}"
Click="OKButton_Click"
Content="{x:Static p:Resources.Select}" />
</Grid>
</ui:Flyout>
</Grid>
</Border>
</Popup>
</Button>

View File

@@ -14,7 +14,6 @@ using System.Windows.Media.Animation;
using ColorPicker.Helpers;
using ManagedCommon;
using Wpf.Ui.Controls;
using static System.Net.Mime.MediaTypeNames;
@@ -76,9 +75,9 @@ namespace ColorPicker.Controls
control._ignoreRGBChanges = true;
control.HexCode.Text = ColorToHex(newColor);
control.RNumberBox.Value = newColor.R;
control.GNumberBox.Value = newColor.G;
control.BNumberBox.Value = newColor.B;
control.RNumberBox.Text = newColor.R.ToString(CultureInfo.InvariantCulture);
control.GNumberBox.Text = newColor.G.ToString(CultureInfo.InvariantCulture);
control.BNumberBox.Text = newColor.B.ToString(CultureInfo.InvariantCulture);
control.SetColorFromTextBoxes(System.Drawing.Color.FromArgb(newColor.R, newColor.G, newColor.B));
control._ignoreRGBChanges = false;
@@ -175,9 +174,9 @@ namespace ColorPicker.Controls
if (!_ignoreRGBChanges)
{
RNumberBox.Value = currentColor.R;
GNumberBox.Value = currentColor.G;
BNumberBox.Value = currentColor.B;
RNumberBox.Text = currentColor.R.ToString(CultureInfo.InvariantCulture);
GNumberBox.Text = currentColor.G.ToString(CultureInfo.InvariantCulture);
BNumberBox.Text = currentColor.B.ToString(CultureInfo.InvariantCulture);
}
_currentColor = currentColor;
@@ -231,7 +230,7 @@ namespace ColorPicker.Controls
{
SelectedColorChangedCommand.Execute(_currentColor);
SessionEventHelper.Event.EditorColorAdjusted = true;
DetailsFlyout.Hide();
DetailsFlyout.IsOpen = false;
}
private void DetailsFlyout_Closed(object sender, object e)
@@ -357,15 +356,19 @@ namespace ColorPicker.Controls
(sender as System.Windows.Controls.TextBox).SelectAll();
}
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
e.Handled = !System.Text.RegularExpressions.Regex.IsMatch(e.Text, "^[0-9]+$");
}
private void RGBNumberBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (!_ignoreRGBChanges)
{
var numberBox = sender as NumberBox;
byte r = numberBox.Name == "RNumberBox" ? GetValueFromNumberBox(numberBox) : (byte)RNumberBox.Value;
byte g = numberBox.Name == "GNumberBox" ? GetValueFromNumberBox(numberBox) : (byte)GNumberBox.Value;
byte b = numberBox.Name == "BNumberBox" ? GetValueFromNumberBox(numberBox) : (byte)BNumberBox.Value;
var numberBox = sender as TextBox;
byte r = numberBox.Name == "RNumberBox" ? GetValueFromNumberBox(numberBox, _currentColor.R) : _currentColor.R;
byte g = numberBox.Name == "GNumberBox" ? GetValueFromNumberBox(numberBox, _currentColor.G) : _currentColor.G;
byte b = numberBox.Name == "BNumberBox" ? GetValueFromNumberBox(numberBox, _currentColor.B) : _currentColor.B;
_ignoreRGBChanges = true;
SetColorFromTextBoxes(System.Drawing.Color.FromArgb(r, g, b));
@@ -379,22 +382,24 @@ namespace ColorPicker.Controls
/// </summary>
/// <param name="numberBox">numberBox control which value we want to get</param>
/// <returns>Validated value as per numberbox conditions, if content is invalid it returns previous value</returns>
private static byte GetValueFromNumberBox(NumberBox numberBox)
private static byte GetValueFromNumberBox(TextBox numberBox, byte previousValue)
{
int minimum = 0;
int maximum = 255;
double? parsedValue = ParseDouble(numberBox.Text);
if (parsedValue != null)
{
var parsedValueByte = (byte)parsedValue;
if (parsedValueByte >= numberBox.Minimum && parsedValueByte <= numberBox.Maximum)
if (parsedValueByte >= minimum && parsedValueByte <= maximum)
{
return parsedValueByte;
}
}
// not valid input, return previous value
return (byte)numberBox.Value;
return previousValue;
}
public static double? ParseDouble(string text)

View File

@@ -138,14 +138,6 @@ namespace ColorPicker.Helpers
Application.Current.MainWindow.Opacity = 0;
Application.Current.MainWindow.Visibility = Visibility.Visible;
_colorPickerShown = true;
// HACK: WPF UI theme watcher removes the composition target background color, among other weird stuff.
// https://github.com/lepoco/wpfui/blob/303f0aefcd59a142bc681415dc4360a34a15f33d/src/Wpf.Ui/Controls/Window/WindowBackdrop.cs#L280
// So we set it back with https://github.com/lepoco/wpfui/blob/303f0aefcd59a142bc681415dc4360a34a15f33d/src/Wpf.Ui/Controls/Window/WindowBackdrop.cs#L191
// And also reapply the intended backdrop.
// This hack fixes: https://github.com/microsoft/PowerToys/issues/31725
Wpf.Ui.Controls.WindowBackdrop.RemoveBackground(Application.Current.MainWindow);
Wpf.Ui.Controls.WindowBackdrop.ApplyBackdrop(Application.Current.MainWindow, Wpf.Ui.Controls.WindowBackdropType.None);
}
}

View File

@@ -7,7 +7,6 @@ using System.Windows;
using System.Windows.Interop;
using ColorPicker.ViewModelContracts;
using Wpf.Ui.Controls;
namespace ColorPicker
{
@@ -20,7 +19,6 @@ namespace ColorPicker
{
Closing += MainWindow_Closing;
Bootstrapper.InitializeContainer(this);
Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this, WindowBackdropType.None);
InitializeComponent();
DataContext = this;
Show(); // Call show just to make sure source is initialized at startup.

View File

@@ -3,6 +3,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:ColorPicker.Converters"
xmlns:helpers="clr-namespace:ColorPicker.Helpers">
<FontFamily x:Key="IconFontFamily">Segoe Fluent Icons, Segoe MDL2 Assets</FontFamily>
<!-- CONVERTERS -->
<BooleanToVisibilityConverter x:Key="bool2VisibilityConverter" />
<converters:BoolToInvertedVisibilityConverter x:Key="bool2InvertedVisibilityConverter" />
@@ -11,6 +13,102 @@
<converters:NumberToVisibilityConverter x:Key="numberToVisibilityConverter" />
<converters:NumberToInvertedVisibilityConverter x:Key="numberToInvertedVisibilityConverter" />
<!--
Copied from https://github.com/dotnet/wpf/blob/v9.0.1/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Styles/Button.xaml
This can be removed and use AccentButtonStyle when https://github.com/dotnet/wpf/issues/10413 gets fixed.
-->
<Style x:Key="CustomAccentButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{DynamicResource DefaultControlFocusVisualStyle}" />
<Setter Property="Background" Value="{DynamicResource AccentButtonBackground}" />
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForeground}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentControlElevationBorderBrush}" />
<Setter Property="BorderThickness" Value="{StaticResource ButtonBorderThemeThickness}" />
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="Border.CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border
x:Name="ContentBorder"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
MinWidth="{TemplateBinding MinWidth}"
MinHeight="{TemplateBinding MinHeight}"
Padding="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding Border.CornerRadius}">
<ContentPresenter
x:Name="ContentPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
TextElement.Foreground="{TemplateBinding Foreground}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ContentBorder" Property="Background" Value="{DynamicResource AccentButtonBackgroundPointerOver}" />
<Setter TargetName="ContentBorder" Property="BorderBrush" Value="{DynamicResource ControlElevationBorderBrush}" />
<Setter TargetName="ContentPresenter" Property="TextElement.Foreground" Value="{DynamicResource AccentButtonForegroundPointerOver}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="ContentBorder" Property="Background" Value="{DynamicResource AccentButtonBackgroundPressed}" />
<Setter TargetName="ContentBorder" Property="BorderBrush" Value="{DynamicResource AccentControlElevationBorderBrush}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="ContentBorder" Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" />
<Setter TargetName="ContentBorder" Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" />
<Setter TargetName="ContentPresenter" Property="TextElement.Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TitleBarCloseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border
x:Name="ContentBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding Border.CornerRadius}">
<ContentPresenter
x:Name="ContentPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
TextElement.Foreground="{TemplateBinding Foreground}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ContentBorder" Property="Background" Value="Red" />
<Setter TargetName="ContentPresenter" Property="TextElement.Foreground" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SubtleButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{DynamicResource DefaultControlFocusVisualStyle}" />
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />

View File

@@ -6,7 +6,6 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:p="clr-namespace:ColorPicker.Properties"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
x:Name="colorEditorControl"
mc:Ignorable="d">
<Grid>
@@ -22,21 +21,27 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ui:Button
<Button
Height="36"
VerticalAlignment="Top"
AutomationProperties.Name="{x:Static p:Resources.Pick_color}"
Command="{Binding OpenColorPickerCommand}"
TabIndex="0"
ToolTipService.ToolTip="{x:Static p:Resources.Pick_color}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<ui:SymbolIcon FontSize="18" Symbol="Eyedropper20" />
<TextBlock Margin="8,0,0,0" Text="{x:Static p:Resources.New_Label}" />
</StackPanel>
</Button.Content>
</ui:Button>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="0,4,0,0"
FontFamily="{StaticResource IconFontFamily}"
Text="&#xef3c;" />
<!-- The label text -->
<TextBlock
Margin="8,0,0,0"
VerticalAlignment="Center"
Text="{x:Static p:Resources.New_Label}" />
</StackPanel>
</Button>
<ListView
x:Name="HistoryColors"
@@ -67,19 +72,19 @@
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.SelectedItems}"
Header="{x:Static p:Resources.Remove}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="Delete24" />
<TextBlock FontFamily="{StaticResource IconFontFamily}" Text="&#xE74D;" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="{x:Static p:Resources.Export_by}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="ArrowExportLtr24" />
<TextBlock FontFamily="{StaticResource IconFontFamily}" Text="&#xEDE1;" />
</MenuItem.Icon>
<MenuItem
Command="{Binding ExportColorsGroupedByColorCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.SelectedItems}"
Header="{x:Static p:Resources.Export_by_color}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="Color20" />
<TextBlock FontFamily="{StaticResource IconFontFamily}" Text="&#xE790;" />
</MenuItem.Icon>
</MenuItem>
<MenuItem
@@ -87,7 +92,7 @@
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.SelectedItems}"
Header="{x:Static p:Resources.Export_by_format}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="Code20" />
<TextBlock FontFamily="{StaticResource IconFontFamily}" Text="&#xE943;" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
@@ -195,7 +200,10 @@
TabIndex="2"
ToolTipService.ToolTip="{x:Static p:Resources.Open_settings}">
<Button.Content>
<ui:SymbolIcon FontSize="18" Symbol="Settings20" />
<TextBlock
FontFamily="{StaticResource IconFontFamily}"
FontSize="18"
Text="&#xE713;" />
</Button.Content>
</Button>
</Grid>
@@ -263,7 +271,11 @@
VerticalAlignment="Center"
Orientation="Vertical"
Visibility="{Binding ColorsHistory.Count, Converter={StaticResource numberToInvertedVisibilityConverter}}">
<ui:SymbolIcon FontSize="40" Symbol="Eyedropper20" />
<TextBlock
HorizontalAlignment="Center"
FontFamily="{StaticResource IconFontFamily}"
FontSize="36"
Text="&#xEF3C;" />
<TextBlock
Margin="24,16,24,16"
HorizontalAlignment="Center"
@@ -281,23 +293,22 @@
Height="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Background="{DynamicResource {x:Static SystemColors.AccentColorBrushKey}}"
BorderBrush="{DynamicResource CardStrokeColorDefaultBrush}"
BorderThickness="0,1,0,0"
Opacity="0">
<Border.Background>
<SolidColorBrush Color="{DynamicResource SystemAccentColorPrimary}" />
</Border.Background>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
AutomationProperties.LiveSetting="Assertive"
AutomationProperties.Name="{x:Static p:Resources.Copied_to_clipboard}"
Orientation="Horizontal">
<ui:SymbolIcon
<TextBlock
Margin="0,0,8,0"
FontFamily="{StaticResource IconFontFamily}"
FontSize="20"
Foreground="{DynamicResource TextOnAccentFillColorPrimaryBrush}"
Symbol="Copy20" />
Text="&#xE8C8;" />
<TextBlock
FontSize="16"
Foreground="{DynamicResource TextOnAccentFillColorPrimaryBrush}"

View File

@@ -7,7 +7,6 @@
xmlns:e="http://schemas.microsoft.com/xaml/behaviors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:shaders="clr-namespace:ColorPicker.Shaders"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
Background="Transparent"
Focusable="False"
mc:Ignorable="d">
@@ -61,7 +60,7 @@
Width="40"
Height="40"
Background="Transparent">
<ui:SymbolIcon Symbol="Dismiss20" />
Text="&#xE094;" />
</Button>
</Border>
</Grid>