From becfe3ed286385d7f3282df86ff95112fef0cce3 Mon Sep 17 00:00:00 2001
From: Tienyu Yang <53754724+lingrottin@users.noreply.github.com>
Date: Sun, 1 Oct 2023 17:09:03 -0700
Subject: [PATCH] beautify & fix Windows11 acrylic
---
MapTP.App/AboutWindow.xaml.cs | 1 -
MapTP.App/App.config | 12 +-
MapTP.App/BlurManager.cs | 261 +++++++++++++++++++++++++++
MapTP.App/CalibrateWindow.xaml.cs | 2 -
MapTP.App/MainWindow.xaml | 6 +-
MapTP.App/MainWindow.xaml.cs | 47 +++--
MapTP.App/MapTP.App.csproj | 136 ++++++++++++--
MapTP.App/Properties/AssemblyInfo.cs | 55 ++++++
MapTP.App/ScreenManager.cs | 9 +-
MapTP.sln | 11 +-
10 files changed, 498 insertions(+), 42 deletions(-)
create mode 100644 MapTP.App/BlurManager.cs
create mode 100644 MapTP.App/Properties/AssemblyInfo.cs
diff --git a/MapTP.App/AboutWindow.xaml.cs b/MapTP.App/AboutWindow.xaml.cs
index d1533fd..4cf4aa8 100644
--- a/MapTP.App/AboutWindow.xaml.cs
+++ b/MapTP.App/AboutWindow.xaml.cs
@@ -3,7 +3,6 @@
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
-using Walterlv.Windows.Effects;
namespace MapTP.App
{
diff --git a/MapTP.App/App.config b/MapTP.App/App.config
index 4bfa005..bcb2ae2 100644
--- a/MapTP.App/App.config
+++ b/MapTP.App/App.config
@@ -1,6 +1,14 @@
-
+
-
+
+
+
+
+
+
+
+
+
diff --git a/MapTP.App/BlurManager.cs b/MapTP.App/BlurManager.cs
new file mode 100644
index 0000000..56e6588
--- /dev/null
+++ b/MapTP.App/BlurManager.cs
@@ -0,0 +1,261 @@
+using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Interop;
+using System.Windows.Media;
+
+namespace MapTP.App
+{
+ internal class BlurManager
+ {
+ // Completely from Walterlv
+
+ private readonly Window _window;
+ private bool _isEnabled;
+ private int _blurColor;
+
+ ///
+ /// 创建 的一个新实例。
+ ///
+ /// 要创建模糊特效的窗口实例。
+ public BlurManager(Window window) => _window = window ?? throw new ArgumentNullException(nameof(window));
+
+ ///
+ /// 获取或设置此窗口模糊特效是否生效的一个状态。
+ /// 默认为 false,即不生效。
+ ///
+ [DefaultValue(false)]
+ public bool IsEnabled
+ {
+ get => _isEnabled;
+ set
+ {
+ _isEnabled = value;
+ OnIsEnabledChanged(value);
+ }
+ }
+
+ ///
+ /// 获取或设置此窗口模糊特效叠加的颜色。
+ ///
+ public Color Color
+ {
+ get => Color.FromArgb(
+ // 取出红色分量。
+ (byte)((_blurColor & 0x000000ff) >> 0),
+ // 取出绿色分量。
+ (byte)((_blurColor & 0x0000ff00) >> 8),
+ // 取出蓝色分量。
+ (byte)((_blurColor & 0x00ff0000) >> 16),
+ // 取出透明分量。
+ (byte)((_blurColor & 0xff000000) >> 24));
+ set => _blurColor =
+ // 组装红色分量。
+ value.R << 0 |
+ // 组装绿色分量。
+ value.G << 8 |
+ // 组装蓝色分量。
+ value.B << 16 |
+ // 组装透明分量。
+ value.A << 24;
+ }
+
+ private void OnIsEnabledChanged(bool isEnabled)
+ {
+ Window window = _window;
+ var handle = new WindowInteropHelper(window).EnsureHandle();
+ Composite(handle, isEnabled);
+ }
+
+ private void Composite(IntPtr handle, bool isEnabled)
+ {
+ // 操作系统版本判定。
+ var osVersion = Environment.OSVersion.Version;
+ var windows10_1809 = new Version(10, 0, 17763);
+ var windows10 = new Version(10, 0);
+ var windows11_buildver = 22000;
+
+ // 创建 AccentPolicy 对象。
+ var accent = new AccentPolicy();
+
+ // 设置特效。
+ if (!isEnabled)
+ {
+ accent.AccentState = AccentState.ACCENT_DISABLED;
+ }
+ else if(Environment.OSVersion.Version.Build >= windows11_buildver)
+ {
+ accent.AccentState = AccentState.ACCENT_INVALID_STATE; // disable Acrylic and do nothing
+ }
+ else if (osVersion > windows10_1809)
+ {
+ // 如果系统在 Windows 10 (1809) 以上,则启用亚克力效果,并组合已设置的叠加颜色和透明度。
+ // 请参见《在 WPF 程序中应用 Windows 10 真•亚克力效果》
+ // https://blog.walterlv.com/post/using-acrylic-in-wpf-application.html
+ accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND;
+ accent.GradientColor = _blurColor;
+ }
+ else if (osVersion > windows10)
+ {
+ // 如果系统在 Windows 10 以上,则启用 Windows 10 早期的模糊特效。
+ // 请参见《在 Windows 10 上为 WPF 窗口添加模糊特效》
+ // https://blog.walterlv.com/post/win10/2017/10/02/wpf-transparent-blur-in-windows-10.html
+ accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND;
+ }
+ else
+ {
+ // 暂时不处理其他操作系统:
+ // - Windows 8/8.1 不支持任何模糊特效
+ // - Windows Vista/7 支持 Aero 毛玻璃效果
+ return;
+ }
+
+ // 将托管结构转换为非托管对象。
+ var accentPolicySize = Marshal.SizeOf(accent);
+ var accentPtr = Marshal.AllocHGlobal(accentPolicySize);
+ Marshal.StructureToPtr(accent, accentPtr, false);
+
+ // 设置窗口组合特性。
+ try
+ {
+ // 设置模糊特效。
+ var data = new WindowCompositionAttributeData
+ {
+ Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY,
+ SizeOfData = accentPolicySize,
+ Data = accentPtr,
+ };
+ SetWindowCompositionAttribute(handle, ref data);
+ }
+ finally
+ {
+ // 释放非托管对象。
+ Marshal.FreeHGlobal(accentPtr);
+ }
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
+ private static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);
+
+ private enum AccentState
+ {
+ ///
+ /// 完全禁用 DWM 的叠加特效。
+ ///
+ ACCENT_DISABLED = 0,
+
+ ///
+ ///
+ ///
+ ACCENT_ENABLE_GRADIENT = 1,
+ ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
+ ACCENT_ENABLE_BLURBEHIND = 3,
+ ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
+ ACCENT_INVALID_STATE = 5,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct AccentPolicy
+ {
+ public AccentState AccentState;
+ public int AccentFlags;
+ public int GradientColor;
+ public int AnimationId;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct WindowCompositionAttributeData
+ {
+ public WindowCompositionAttribute Attribute;
+ public IntPtr Data;
+ public int SizeOfData;
+ }
+
+ private enum WindowCompositionAttribute
+ {
+ // 省略其他未使用的字段
+ WCA_ACCENT_POLICY = 19,
+ // 省略其他未使用的字段
+ }
+
+ ///
+ /// 当前操作系统支持的透明模糊特效级别。
+ ///
+ public enum BlurSupportedLevel
+ {
+ ///
+ ///
+ ///
+ NotSupported,
+ Aero,
+ Blur,
+ Acrylic,
+ }
+ }
+
+ ///
+ /// enables Mica for Windows 11 users
+ ///
+ internal class Mica
+ {
+ //this is from Difegue/Mica-WPF-Sample
+ #region Win32
+ [DllImport("dwmapi.dll")]
+ public static extern int DwmSetWindowAttribute(IntPtr hwnd, DwmWindowAttribute dwAttribute, ref int pvAttribute, int cbAttribute);
+
+ [Flags]
+ public enum DwmWindowAttribute : uint
+ {
+ DWMWA_USE_IMMERSIVE_DARK_MODE = 20,
+ DWMWA_MICA_EFFECT = 1029,
+ DWMA_SYSTEMBACKDROP_TYPE=38,
+ }
+ #endregion
+
+ // Enable Mica on the given HWND.
+ public static void EnableMica(HwndSource source, bool darkThemeEnabled)
+ {
+ int trueValue = 0x01;
+ int falseValue = 0x00;
+ int systemBackdropType_Main = 3;
+
+ // Set dark mode before applying the material, otherwise you'll get an ugly flash when displaying the window.
+ if (darkThemeEnabled)
+ DwmSetWindowAttribute(source.Handle, DwmWindowAttribute.DWMWA_USE_IMMERSIVE_DARK_MODE, ref trueValue, Marshal.SizeOf(typeof(int)));
+ else
+ DwmSetWindowAttribute(source.Handle, DwmWindowAttribute.DWMWA_USE_IMMERSIVE_DARK_MODE, ref falseValue, Marshal.SizeOf(typeof(int)));
+
+ DwmSetWindowAttribute(source.Handle, DwmWindowAttribute.DWMWA_MICA_EFFECT, ref trueValue, Marshal.SizeOf(typeof(int)));
+ DwmSetWindowAttribute(source.Handle, DwmWindowAttribute.DWMA_SYSTEMBACKDROP_TYPE, ref systemBackdropType_Main, Marshal.SizeOf(typeof(int)));
+ }
+
+ private HwndSource hwndSource;
+
+ private bool _enable;
+ public bool enable
+ {
+ get => _enable;
+ set
+ {
+ _enable = value;
+ if (enable)
+ {
+ EnableMica(hwndSource, false);
+ }
+ }
+ }
+
+ public Mica(HwndSource _hwndSource)
+ {
+ this.hwndSource = _hwndSource;
+ }
+ }
+}
+
diff --git a/MapTP.App/CalibrateWindow.xaml.cs b/MapTP.App/CalibrateWindow.xaml.cs
index e01877c..057132f 100644
--- a/MapTP.App/CalibrateWindow.xaml.cs
+++ b/MapTP.App/CalibrateWindow.xaml.cs
@@ -2,8 +2,6 @@
using System;
using System.Windows;
using System.Windows.Interop;
-using System.Windows.Media;
-using Walterlv.Windows.Effects;
namespace MapTP.App
{
diff --git a/MapTP.App/MainWindow.xaml b/MapTP.App/MainWindow.xaml
index 0081d84..9a32e0a 100644
--- a/MapTP.App/MainWindow.xaml
+++ b/MapTP.App/MainWindow.xaml
@@ -7,9 +7,11 @@
xmlns:local="clr-namespace:MapTP.App"
mc:Ignorable="d"
Title="MapTP" Height="500" Width="800"
- Background="{x:Null}">
+ Foreground="{DynamicResource SystemControlPageTextBaseHighBrush}"
+ WindowStyle="None"
+ Background="#33aaaaff">
-
+
diff --git a/MapTP.App/MainWindow.xaml.cs b/MapTP.App/MainWindow.xaml.cs
index 1bc3a0c..81e994c 100644
--- a/MapTP.App/MainWindow.xaml.cs
+++ b/MapTP.App/MainWindow.xaml.cs
@@ -8,7 +8,6 @@
using System.Windows.Media;
using System.Xml;
using System.Xml.Serialization;
-using Walterlv.Windows.Effects;
namespace MapTP.App
{
@@ -98,9 +97,12 @@ public void ReceiveTouchpadSize(int X, int Y)
{
this.TouchpadSizeX = X;
this.TouchpadSizeY = Y;
- TpAreaRect.Width = CalculateRectangle(TouchpadSizeX, TouchpadSizeY);
- TpRectGrid.Width = CalculateRectangle(TouchpadSizeX, TouchpadSizeY);
- TouchpadSizeTB.Text = $"Touchpad size: {TouchpadSizeX}x{TouchpadSizeY}";
+ if (TouchpadSizeX != 0 && TouchpadSizeY != 0)
+ {
+ TpAreaRect.Width = CalculateRectangle(TouchpadSizeX, TouchpadSizeY);
+ TpRectGrid.Width = CalculateRectangle(TouchpadSizeX, TouchpadSizeY);
+ TouchpadSizeTB.Text = $"Touchpad size: {TouchpadSizeX}x{TouchpadSizeY}";
+ }
return;
}
@@ -190,19 +192,42 @@ protected override void OnSourceInitialized(EventArgs e)
private void OnLoaded(object sender, RoutedEventArgs e)
{
- var WalterlvCompositor = new WindowAccentCompositor(this)
+
+ if (!(Environment.OSVersion.Version > new Version(10, 0, 17763)))
+ {
+ this.Background = Brushes.White;
+ }
+ else if (Environment.OSVersion.Version.Build >= 22000) // Mica
{
- Color = Color.FromArgb(0x33, 0x87, 0xce, 0xfa)
- };
- WalterlvCompositor.IsEnabled = true;
- if (!(Environment.OSVersion.Version > new Version(10, 0, 17763)))
+ // Get PresentationSource
+ PresentationSource presentationSource = PresentationSource.FromVisual((Visual)sender);
+
+ // Subscribe to PresentationSource's ContentRendered event
+ presentationSource.ContentRendered += (s,ev)=>OnRendered(PresentationSource.FromVisual((Visual)sender) as HwndSource);
+
+ }
+ else
{
- this.Background = Brushes.Aqua;
- WalterlvCompositor.IsEnabled = false;
+
+ var WalterlvCompositor = new BlurManager(this)
+ {
+ Color = Color.FromArgb(0x33, 0x87, 0xce, 0xfa)
+ };
+ WalterlvCompositor.IsEnabled = true;
}
}
+ ///
+ /// Enable Mica when the window is rendered
+ ///
+ ///
+ ///
+ private void OnRendered(HwndSource src)
+ {
+ var mica = new Mica(src);
+ mica.enable = true;
+ }
///
/// This method is for limiting TextBoxes only to accept numbers
diff --git a/MapTP.App/MapTP.App.csproj b/MapTP.App/MapTP.App.csproj
index a2673f4..ac3b388 100644
--- a/MapTP.App/MapTP.App.csproj
+++ b/MapTP.App/MapTP.App.csproj
@@ -1,20 +1,134 @@
-
+
+
+
- net7.0-windows10.0.18362.0
+ Debug
+ AnyCPU
+ {B640177C-8B8A-4E97-931A-8C13EF816C12}
WinExe
- false
- true
- true
+ MapTP.App
+ MapTP.App
+ v4.8
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+ true
+
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
app.manifest
- 10.0.18362.0
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ AboutWindow.xaml
+
+
+ App.xaml
+ Code
+
+
+
+ CalibrateWindow.xaml
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+ 3.4.0
+
+
+ 7.0.0
+
+
\ No newline at end of file
diff --git a/MapTP.App/Properties/AssemblyInfo.cs b/MapTP.App/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..51cc4c0
--- /dev/null
+++ b/MapTP.App/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("MapTP.App")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MapTP.App")]
+[assembly: AssemblyCopyright("Copyright © 2023")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+//若要开始生成可本地化的应用程序,请设置
+//.csproj 文件中的 CultureYouAreCodingWith
+//在 中。例如,如果你使用的是美国英语。
+//使用的是美国英语,请将 设置为 en-US。 然后取消
+//对以下 NeutralResourceLanguage 特性的注释。 更新
+//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //主题特定资源词典所处位置
+ //(未在页面中找到资源时使用,
+ //或应用程序资源字典中找到时使用)
+ ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
+ //(未在页面中找到资源时使用,
+ //、应用程序或任何主题专用资源字典中找到时使用)
+)]
+
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/MapTP.App/ScreenManager.cs b/MapTP.App/ScreenManager.cs
index b10d97a..c1f397a 100644
--- a/MapTP.App/ScreenManager.cs
+++ b/MapTP.App/ScreenManager.cs
@@ -1,11 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Interop;
+using System.Drawing;
using System.Windows;
-using System.Drawing;
+using System.Windows.Interop;
namespace MapTP.App
diff --git a/MapTP.sln b/MapTP.sln
index efd7f33..6b54fdb 100644
--- a/MapTP.sln
+++ b/MapTP.sln
@@ -1,9 +1,8 @@
-
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.34031.279
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MapTP.App", "MapTP.App\MapTP.App.csproj", "{F5217DE5-48E8-404D-A4F0-15B88C21B5E4}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapTP.App", "MapTP.App\MapTP.App.csproj", "{B640177C-8B8A-4E97-931A-8C13EF816C12}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -11,10 +10,10 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {F5217DE5-48E8-404D-A4F0-15B88C21B5E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F5217DE5-48E8-404D-A4F0-15B88C21B5E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F5217DE5-48E8-404D-A4F0-15B88C21B5E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F5217DE5-48E8-404D-A4F0-15B88C21B5E4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B640177C-8B8A-4E97-931A-8C13EF816C12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B640177C-8B8A-4E97-931A-8C13EF816C12}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B640177C-8B8A-4E97-931A-8C13EF816C12}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B640177C-8B8A-4E97-931A-8C13EF816C12}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE