Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Color picker wpf #37149

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/actions/spell-check/expect.txt
Original file line number Diff line number Diff line change
@@ -546,6 +546,7 @@ GUITHREADINFO
GValue
gwl
GWLP
GWLSTYLE
hangeul
Hanzi
Hardlines
@@ -1631,6 +1632,8 @@ tkconverters
TLayout
tlb
tlbimp
TPMLEFTALIGN
TPMRETURNCMD
TMPVAR
TNP
Toolhelp
@@ -1838,6 +1841,7 @@ WMI
WMICIM
wmimgmt
wmp
WMSYSCOMMAND
wnd
WNDCLASS
WNDCLASSEX
4 changes: 1 addition & 3 deletions src/modules/colorPicker/ColorPickerUI/App.xaml
Original file line number Diff line number Diff line change
@@ -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"
ThemeMode="System"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ThemesDictionary Theme="Dark" />
<ui:ControlsDictionary />
<ResourceDictionary Source="Resources/Styles.xaml" />
<ResourceDictionary Source="Resources/ViewModelViewMappings.xaml" />
</ResourceDictionary.MergedDictionaries>
53 changes: 27 additions & 26 deletions src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml
Original file line number Diff line number Diff line change
@@ -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,42 @@
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
<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 Source="pack://application:,,,/Assets/ColorPicker/icon.ico"
Width="20" Height="20"
Margin="10,5,5,8"/>
<TextBlock Text="{x:Static p:Resources.CP_Title}" VerticalAlignment="Center" Margin="10"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button
Content="&#xE711;"
FontFamily="{StaticResource IconFontFamily}"
Width="50"
Height="30"
Margin="10,-10,-2,1"
Style="{StaticResource TitleBarCloseButtonStyle}"
Click="Close_Click"/>
</StackPanel>
</DockPanel>
<ContentPresenter
x:Name="contentPresenter"
Grid.Row="1"
Content="{Binding Content}" />
</Grid>
</ui:FluentWindow>
</Grid>
</Border>
</Window>
152 changes: 147 additions & 5 deletions src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -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 @@ private void ColorEditorWindow_Closing(object sender, System.ComponentModel.Canc

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)
}
}
}
1 change: 0 additions & 1 deletion src/modules/colorPicker/ColorPickerUI/ColorPickerUI.csproj
Original file line number Diff line number Diff line change
@@ -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">
Original file line number Diff line number Diff line change
@@ -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,9 @@
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>
Loading
Oops, something went wrong.
Loading
Oops, something went wrong.