先上效果图
可直接跳到完整代码
目录
先上效果图
开始教学
响应用户的更改
API讲解
读取深浅模式、主题颜色、十六进制颜色转换
完整代码
如果大家留意资源管理器的“文件”菜单的话就会发现它的底色就是你设置的主题色,在更改Windows颜色模式时,很多的应用例如“文件资源管理器explorer”、“edge浏览器msedge”等等,那么如何做到这种效果呢?
开始教学
响应用户的更改
这可以放在自己的应用程序中,来适应和实时更改用户的设置,例如用户更改成深色模式,窗体自动变为深色,使用.net的事件响应用户更改:
对于vb.net用户,需要在窗体加载时加入语句:
Sub ChangeTheme(sender As Object, e As UserPreferenceChangedEventArgs)
If e.Category = UserPreferenceCategory.General Then
GetThemeColor()
DwmSetWindowAttribute(Me.Handle, DwmWindowAttribute.UseImmersiveDarkMode, ThemeColor, Marshal.SizeOf(Of Integer))
color = GetSystemColor()
Label1.BackColor = color
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GetThemeColor()
color = GetSystemColor()
Label1.BackColor = color
AddHandler SystemEvents.UserPreferenceChanged, AddressOf ChangeTheme
DwmSetWindowAttribute(Me.Handle, DwmWindowAttribute.UseImmersiveDarkMode, ThemeColor, Marshal.SizeOf(Of Integer))
End Sub
API讲解
本次使用的API为 DwmSetWindowAttribute 函数,使用常量DwmWindowAttribute.UseImmersiveDarkMode
<DllImport("dwmapi.dll", PreserveSig:=True)>
Public Shared Function DwmSetWindowAttribute(ByVal hwnd As IntPtr, ByVal attr As DwmWindowAttribute, ByRef attrValue As Integer, ByVal attrSize As Integer) As Integer
End Function
Public Enum DwmWindowAttribute
NCRenderingEnabled = 1
NCRenderingPolicy
TransitionsForceDisabled
AllowNCPaint
CaptionButtonBounds
NonClientRtlLayout
ForceIconicRepresentation
Flip3DPolicy
ExtendedFrameBounds
HasIconicBitmap
DisallowPeek
ExcludedFromPeek
Cloak
Cloaked
FreezeRepresentation
PassiveUpdateMode
UseHostBackdropBrush
UseImmersiveDarkMode = 20
WindowCornerPreference = 33
BorderColor
CaptionColor
TextColor
VisibleFrameBorderThickness
SystemBackdropType
Last
End Enum
摘自:DWMWINDOWATTRIBUTE (dwmapi.h) - Win32 apps | Microsoft Learn
DWMWA_NCRENDERING_ENABLED
与 DwmGetWindowAttribute 一起使用。 发现是否启用了非客户端呈现。 检索到的值的类型为 BOOL。 如果启用非客户端呈现,则为 TRUE;否则为 FALSE。DWMWA_NCRENDERING_POLICY
与 DwmSetWindowAttribute 一起使用。 设置非客户端呈现策略。 pvAttribute 参数指向 DWMNCRENDERINGPOLICY 枚举中的值。DWMWA_TRANSITIONS_FORCEDISABLED
与 DwmSetWindowAttribute 一起使用。 启用或强制禁用 DWM 转换。 pvAttribute 参数指向 BOOL 类型的值。 如果为 TRUE ,则禁用转换; 如果为 FALSE ,则启用转换。DWMWA_ALLOW_NCPAINT
与 DwmSetWindowAttribute 一起使用。 使非工作区中呈现的内容在 DWM 绘制的框架上可见。 pvAttribute 参数指向 BOOL 类型的值。 如果为 TRUE ,则使非工作区中呈现的内容在框架上可见;否则为 FALSE。DWMWA_CAPTION_BUTTON_BOUNDS
与 DwmGetWindowAttribute 一起使用。 检索窗口相对空间中描述文字按钮区域的边界。 检索到的值的类型为 RECT。 如果窗口最小化或对用户不可见,则检索到的 RECT 的值是未定义的。 应检查检索到的 RECT 是否包含可以使用的边界,如果它不包含,则可以断定窗口已最小化或不可见。DWMWA_NONCLIENT_RTL_LAYOUT
与 DwmSetWindowAttribute 一起使用。 指定非客户端内容是否为从右到左 (RTL) 镜像。 pvAttribute 参数指向 BOOL 类型的值。 如果非客户端内容从右到左 (RTL) 镜像,则为 TRUE;否则为 FALSE。DWMWA_FORCE_ICONIC_REPRESENTATION
与 DwmSetWindowAttribute 一起使用。 强制窗口 (静态位图) 显示图标缩略图或速览表示形式,即使窗口的实时或快照表示形式可用也是如此。 此值通常在创建窗口期间设置,在窗口的整个生存期内不会更改。 但是,某些方案可能需要值随时间推移而更改。 pvAttribute 参数指向 BOOL 类型的值。 如果为 TRUE ,则需要图标缩略图或速览表示形式;否则为 FALSE。DWMWA_FLIP3D_POLICY
与 DwmSetWindowAttribute 一起使用。 设置 Flip3D 处理窗口的方式。 pvAttribute 参数指向DWMFLIP3DWINDOWPOLICY枚举中的值。DWMWA_EXTENDED_FRAME_BOUNDS
与 DwmGetWindowAttribute 一起使用。 检索屏幕空间中的扩展框架边界矩形。 检索到的值的类型为 RECT。DWMWA_HAS_ICONIC_BITMAP
与 DwmSetWindowAttribute 一起使用。 窗口将提供一个位图供 DWM 用作图标缩略图或速览表示形式, (窗口的静态位图) 。 可以使用 DWMWA_FORCE_ICONIC_REPRESENTATION 指定DWMWA_HAS_ICONIC_BITMAP。 DWMWA_HAS_ICONIC_BITMAP 通常在创建窗口期间设置,在窗口的整个生存期内不会更改。 但是,某些方案可能需要值随时间推移而更改。 pvAttribute 参数指向 BOOL 类型的值。 如果为 TRUE ,则告知 DWM 窗口将提供图标缩略图或速览表示形式;否则为 FALSE。
Windows Vista 及更早版本: 不支持此值。DWMWA_DISALLOW_PEEK
与 DwmSetWindowAttribute 一起使用。 不显示窗口的速览预览。 当鼠标悬停在任务栏中的窗口缩略图上时,速览视图将显示窗口的全尺寸预览。 如果设置了此属性,将鼠标指针悬停在窗口缩略图上会消除速览 (以防组中的另一个窗口具有显示) 的速览预览。 pvAttribute 参数指向 BOOL 类型的值。 如果为 TRUE ,则阻止速览功能,如果为 FALSE ,则允许它。
Windows Vista 及更早版本: 不支持此值。DWMWA_EXCLUDED_FROM_PEEK
与 DwmSetWindowAttribute 一起使用。 防止窗口在调用 peek 时褪色到玻璃板。 pvAttribute 参数指向 BOOL 类型的值。 如果为 TRUE ,则防止窗口在另一个窗口的速览期间褪色,对于正常行为, 则为 FALSE 。
Windows Vista 及更早版本: 不支持此值。DWMWA_CLOAK
与 DwmSetWindowAttribute 一起使用。 遮罩窗口,使其对用户不可见。 窗口仍由 DWM 组成。
将 与 DirectComposition 配合使用: 通过与分层子窗口关联的 DirectComposition 视觉对象对窗口内容的表示形式进行动画处理时,使用 DWMWA_CLOAK 标志遮蔽分层子窗口。 有关此用例的更多详细信息,请参阅 如何对分层子窗口的位图进行动画处理。
Windows 7 及更早版本: 不支持此值。DWMWA_CLOAKED
与 DwmGetWindowAttribute 一起使用。 如果窗口是隐藏的, 请提供以下值之一来解释原因。
DWM_CLOAKED_APP (值0x00000001) 。 窗口已被其所有者应用程序遮蔽。
DWM_CLOAKED_SHELL (值0x00000002) 。 窗户被壳牌遮蔽了。
DWM_CLOAKED_INHERITED (值0x00000004) 。 隐藏值继承自其所有者窗口。
Windows 7 及更早版本: 不支持此值。DWMWA_FREEZE_REPRESENTATION
与 DwmSetWindowAttribute 一起使用。 使用当前视觉对象冻结窗口的缩略图。 不要对缩略图进行进一步的实时更新,以匹配窗口的内容。
Windows 7 及更早版本: 不支持此值。DWMWA_USE_HOSTBACKDROPBRUSH
与 DwmSetWindowAttribute 一起使用。 允许非 UWP 窗口使用主机背景画笔。 如果设置了此标志,则调用 Windows::UI::Composition API 的 Win32 应用可以使用主机背景画笔生成透明度效果 (请参阅 Compositor.CreateHostBackdropBrush) 。 pvAttribute 参数指向 BOOL 类型的值。 如果为 TRUE ,则为窗口启用主机背景画笔,如果为 FALSE ,则禁用它。
从 Windows 11 版本 22000 开始支持此值。DWMWA_USE_IMMERSIVE_DARK_MODE
与 DwmSetWindowAttribute 一起使用。 启用深色模式系统设置时,允许以深色模式颜色绘制此窗口的窗口框架。 出于兼容性原因,无论系统设置如何,所有窗口都默认为浅色模式。 pvAttribute 参数指向 BOOL 类型的值。 TRUE 表示窗口采用深色模式, FALSE 表示始终使用浅色模式。
从 Windows 11 版本 22000 开始支持此值。DWMWA_WINDOW_CORNER_PREFERENCE
与 DwmSetWindowAttribute 一起使用。 指定窗口的圆角首选项。 pvAttribute 参数指向 DWM_WINDOW_CORNER_PREFERENCE 类型的值。
从 Windows 11 版本 22000 开始支持此值。DWMWA_BORDER_COLOR
与 DwmSetWindowAttribute 一起使用。 指定窗口边框的颜色。 pvAttribute 参数指向 COLORREF 类型的值。 应用负责根据状态更改(例如窗口激活中的更改)更改边框颜色。
为颜色 指定DWMWA_COLOR_NONE (值0xFFFFFFFE) 将禁止绘制窗口边框。 这样,就可以有一个没有边框的圆角窗口。
为颜色指定 DWMWA_COLOR_DEFAULT (值0xFFFFFFFF) 会将窗口重置回使用系统对边框颜色的默认行为。
从 Windows 11 内部版本 22000 开始支持此值。DWMWA_CAPTION_COLOR
与 DwmSetWindowAttribute 一起使用。 指定描述文字的颜色。 pvAttribute 参数指向 COLORREF 类型的值。
为颜色指定DWMWA_COLOR_DEFAULT (值0xFFFFFFFF) 会将窗口重置回使用系统对描述文字颜色的默认行为。
从 Windows 11 内部版本 22000 开始支持此值。DWMWA_TEXT_COLOR
与 DwmSetWindowAttribute 一起使用。 指定描述文字文本的颜色。 pvAttribute 参数指向 COLORREF 类型的值。
指定颜色DWMWA_COLOR_DEFAULT (值0xFFFFFFFF) 会将窗口重置回使用系统描述文字文本颜色的默认行为。
从 Windows 11 内部版本 22000 开始支持此值。DWMWA_VISIBLE_FRAME_BORDER_THICKNESS
与 DwmGetWindowAttribute 一起使用。 检索 DWM 将围绕此窗口绘制的外部边框的宽度。 该值可能因窗口的 DPI 而异。 pvAttribute 参数指向 UINT 类型的值。
从 Windows 11 内部版本 22000 开始支持此值。DWMWA_SYSTEMBACKDROP_TYPE
与 DwmGetWindowAttribute 或 DwmSetWindowAttribute 一起使用。 检索或指定窗口的系统绘制背景材料,包括在非工作区后面。 pvAttribute 参数指向 DWM_SYSTEMBACKDROP_TYPE 类型的值。
从 Windows 11 内部版本 22621 开始支持此值。DWMWA_LAST
最大识别的 DWMWINDOWATTRIBUTE 值,用于验证目的。
读取深浅模式、主题颜色、十六进制颜色转换
注意,ThemeColor是Bool值
Public ThemeColor As Boolean
Public color As Color
Private Sub GetThemeColor()
Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize")
If key IsNot Nothing Then
Dim appsUseLightTheme As Integer = CInt(key.GetValue("AppsUseLightTheme", -1))
If appsUseLightTheme = 0 Then
ThemeColor = 1
ElseIf appsUseLightTheme = 1 Then
ThemeColor = 0
Else
End If
key.Close()
End If
End Sub
Function GetSystemColor() As Color
Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\Microsoft\Windows\DWM")
If key IsNot Nothing Then
Dim value As Integer = CInt(key.GetValue("ColorizationColor"))
Dim HexColor = Convert.ToString(value, 16)
key.Close()
Return ConvertSystemColor(HexColor)
End If
End Function
Function ConvertSystemColor(HexColor As String) As Color
Return Color.FromArgb(Convert.ToInt32(HexColor.Substring(0, 2), 16), Convert.ToInt32(HexColor.Substring(2, 2), 16), Convert.ToInt32(HexColor.Substring(4, 2), 16), Convert.ToInt32(HexColor.Substring(6, 2), 16))
End Function
完整代码
Imports Microsoft.Win32
Imports System.Runtime.InteropServices
Public Class Form1
Public ThemeColor As Boolean
Public color As Color
Private Sub GetThemeColor()
Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize")
If key IsNot Nothing Then
Dim appsUseLightTheme As Integer = CInt(key.GetValue("AppsUseLightTheme", -1))
If appsUseLightTheme = 0 Then
ThemeColor = 1
ElseIf appsUseLightTheme = 1 Then
ThemeColor = 0
Else
End If
key.Close()
End If
End Sub
Function GetSystemColor() As Color
Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\Microsoft\Windows\DWM")
If key IsNot Nothing Then
Dim value As Integer = CInt(key.GetValue("ColorizationColor"))
Dim HexColor = Convert.ToString(value, 16)
key.Close()
Return ConvertSystemColor(HexColor)
End If
End Function
Function ConvertSystemColor(HexColor As String) As Color
Return Color.FromArgb(Convert.ToInt32(HexColor.Substring(0, 2), 16), Convert.ToInt32(HexColor.Substring(2, 2), 16), Convert.ToInt32(HexColor.Substring(4, 2), 16), Convert.ToInt32(HexColor.Substring(6, 2), 16))
End Function
Sub ChangeTheme(sender As Object, e As UserPreferenceChangedEventArgs)
If e.Category = UserPreferenceCategory.General Then
GetThemeColor()
DwmSetWindowAttribute(Me.Handle, DwmWindowAttribute.UseImmersiveDarkMode, ThemeColor, Marshal.SizeOf(Of Integer))
color = GetSystemColor()
Label1.BackColor = color
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GetThemeColor()
color = GetSystemColor()
Label1.BackColor = color
AddHandler SystemEvents.UserPreferenceChanged, AddressOf ChangeTheme
DwmSetWindowAttribute(Me.Handle, DwmWindowAttribute.UseImmersiveDarkMode, ThemeColor, Marshal.SizeOf(Of Integer))
End Sub
<DllImport("dwmapi.dll", PreserveSig:=True)>
Public Shared Function DwmSetWindowAttribute(ByVal hwnd As IntPtr, ByVal attr As DwmWindowAttribute, ByRef attrValue As Integer, ByVal attrSize As Integer) As Integer
End Function
Public Enum DwmWindowAttribute
NCRenderingEnabled = 1
NCRenderingPolicy
TransitionsForceDisabled
AllowNCPaint
CaptionButtonBounds
NonClientRtlLayout
ForceIconicRepresentation
Flip3DPolicy
ExtendedFrameBounds
HasIconicBitmap
DisallowPeek
ExcludedFromPeek
Cloak
Cloaked
FreezeRepresentation
PassiveUpdateMode
UseHostBackdropBrush
UseImmersiveDarkMode = 20
WindowCornerPreference = 33
BorderColor
CaptionColor
TextColor
VisibleFrameBorderThickness
SystemBackdropType
Last
End Enum
End Class