前言
談到Windows 11流暢設計系統(Fluent Design System
),我們不得不提到Mica材質,有了它才能算現代的流暢性UI。
前戲方案(ModernWpf)
之前聊過通過微軟未公開的DWM文檔來實現它,但是沒多久系統一更新就失效了,較早使用ModernWpf的版本可見歷史博文:乘風破浪,遇見最美Windows 11之現代Windows桌面應用開發 - Microsoft Edge WebView2運行時 - 嘗試WPF上實現Windows 11的Mica風格,筆者重新試過這個方案,效果不是很完美。
雖然已經它也有公佈Windows 11 22523+之後的改進方案,但是效果仍然不理想,具體示例可見:dongle-the-gadget/SystemBackdropTypes
其核心還是通過"DwmApi.dll"
來實現枚舉賦值調用,也還是可以做到Mica效果的。
public static class Methods
{
[DllImport("DwmApi.dll")]
static extern int DwmExtendFrameIntoClientArea(
IntPtr hwnd,
ref ParameterTypes.MARGINS pMarInset);
[DllImport("dwmapi.dll")]
static extern int DwmSetWindowAttribute(IntPtr hwnd, ParameterTypes.DWMWINDOWATTRIBUTE dwAttribute, ref int pvAttribute, int cbAttribute);
public static int ExtendFrame(IntPtr hwnd, ParameterTypes.MARGINS margins)
=> DwmExtendFrameIntoClientArea(hwnd, ref margins);
public static int SetWindowAttribute(IntPtr hwnd, ParameterTypes.DWMWINDOWATTRIBUTE attribute, int parameter)
=> DwmSetWindowAttribute(hwnd, attribute, ref parameter, Marshal.SizeOf<int>());
}
public class ParameterTypes
{
/*
[Flags]
enum DWM_SYSTEMBACKDROP_TYPE
{
DWMSBT_MAINWINDOW = 2, // Mica
DWMSBT_TRANSIENTWINDOW = 3, // Acrylic
DWMSBT_TABBEDWINDOW = 4 // Tabbed
}
*/
[Flags]
public enum DWMWINDOWATTRIBUTE
{
DWMWA_USE_IMMERSIVE_DARK_MODE = 20,
DWMWA_SYSTEMBACKDROP_TYPE = 38
}
[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
public int cxLeftWidth; // width of left border that retains its size
public int cxRightWidth; // width of right border that retains its size
public int cyTopHeight; // height of top border that retains its size
public int cyBottomHeight; // height of bottom border that retains its size
};
}
var flag = 2;
SetWindowAttribute(
new WindowInteropHelper(this).Handle,
DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE,
flag);
最新方案(WPF UI)
簡介
WPF UI是一套WPF界面庫,一個簡單的方法來使你的WPF應用程序跟上現代設計的趨勢。該庫改變了基本的元素,如Page
, ToggleButton
或List
,還包括了額外的控件,如Navigation
, NumberBox
, Dialog
或Snackbar
。
視覺效果如下:
參考示例
官方還是給了不錯的示例./wpfui/tree/main/src
簡單使用
依賴包
dotnet add package wpf-ui
在App.xaml
中引入下樣式字典資源: ui:ThemesDictionary
、ui:ControlsDictionary
。
<Application
x:Class="ConvertHybirdContent.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="OnStartup"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ThemesDictionary Theme="Light" />
<ui:ControlsDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
接下來在MainView.xaml
窗體的Window
也要改造下,從原來的Window
換成ui:UiWindow
。
<ui:UiWindow
x:Class="SuperConvert.Hybirding.Interface.Pages.MainView"
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:ui="http://schemas.lepo.co/wpfui/2022/xaml"
mc:Ignorable="d"
Height="600"
Width="1024"
WindowStartupLocation="CenterScreen"
ExtendsContentIntoTitleBar="True"
WindowBackdropType="Mica"
WindowCornerPreference="Round"
>
</ui:UiWindow>
記得同步換掉MainView.xaml.cs
繼承的。
/// <summary>
/// MainView.xaml 的交互邏輯
/// </summary>
public partial class MainView : UiWindow
{
}
新增支持窗體設置
ui:UiWindow
這裏可以設置三個屬性:
- 擴展內容到標題欄(
ExtendsContentIntoTitleBar
),開啓後會覆蓋原來窗體的標題欄,可以重寫界面。 - 窗體背景效果類型(
WindowBackdropType
),這裏可以設置爲Mica
代表Windows 11 Mica效果,淡雅的味道,其它可選的值還有None
代表無效果、Auto
代表自動模式,實測白茫茫一片、Acrylic
代表亞克力效果,熟悉的半透明磨砂玻璃效果,Windows 10老基友的最愛、Tabbed
代表Windows 11 Tabbed效果,看來接近亞克力,但是要模糊更多,不透。 - 窗體圓角樣式(
WindowCornerPreference
),這裏可以設置爲Round
代表Windows 11圓角窗體,其它可選值還有RoundSmall
代表更數值更小的圓角,DoNotRound
代表沒有圓角,沒錯其實就是直角。
窗體背景效果類型(
WindowBackdropType
)定義:
/// <summary>
/// Collection of fluent background types.
/// </summary>
public enum BackgroundType
{
/// <summary>
/// Unknown background type.
/// </summary>
Unknown,
/// <summary>
/// No backdrop effect.
/// </summary>
None,
/// <summary>
/// Sets <c>DWMWA_SYSTEMBACKDROP_TYPE</c> to <see langword="0"></see>.
/// </summary>
Auto,
/// <summary>
/// Windows 11 Mica effect.
/// </summary>
Mica,
/// <summary>
/// Windows Acrylic effect.
/// </summary>
Acrylic,
/// <summary>
/// Windows 11 wallpaper blur effect.
/// </summary>
Tabbed
}
窗體圓角樣式(
WindowCornerPreference
)定義:
/// <summary>
/// Ways you can round windows.
/// </summary>
public enum WindowCornerPreference
{
/// <summary>
/// Determined by system or application preference.
/// </summary>
Default,
/// <summary>
/// Do not round the corners.
/// </summary>
DoNotRound,
/// <summary>
/// Round the corners.
/// </summary>
Round,
/// <summary>
/// Round the corners slightly.
/// </summary>
RoundSmall
}
監聽系統主題變化
考慮到用戶會切淺色和暗色主題,那麼能不能自動響應呢?答案是可以的。
我們在MainView.xaml.cs
構造函數中的窗體Loaded
事件來監聽變化,並且自動響應。
/// <summary>
/// MainView.xaml 的交互邏輯
/// </summary>
public partial class MainView : UiWindow
{
public MainView()
{
InitializeComponent();
Loaded += (sender, args) =>
{
Wpf.Ui.Appearance.Watcher.Watch(
this,
Wpf.Ui.Appearance.BackgroundType.Mica,
true
);
};
}
}