乘風破浪,遇見最佳跨平臺跨終端框架.Net Core/.Net生態 - WPF應用插上Windows 11流暢設計系統的翅膀,ModernWpf=>WPF UI

前言

談到Windows 11流暢設計系統(Fluent Design System),我們不得不提到Mica材質,有了它才能算現代的流暢性UI。

image

前戲方案(ModernWpf)

之前聊過通過微軟未公開的DWM文檔來實現它,但是沒多久系統一更新就失效了,較早使用ModernWpf的版本可見歷史博文:乘風破浪,遇見最美Windows 11之現代Windows桌面應用開發 - Microsoft Edge WebView2運行時 - 嘗試WPF上實現Windows 11的Mica風格,筆者重新試過這個方案,效果不是很完美。

image

雖然已經它也有公佈Windows 11 22523+之後的改進方案,但是效果仍然不理想,具體示例可見:dongle-the-gadget/SystemBackdropTypes

image

其核心還是通過"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)

簡介

image

WPF UI是一套WPF界面庫,一個簡單的方法來使你的WPF應用程序跟上現代設計的趨勢。該庫改變了基本的元素,如Page, ToggleButtonList,還包括了額外的控件,如Navigation, NumberBox, DialogSnackbar

視覺效果如下:

image

image

image

參考示例

官方還是給了不錯的示例./wpfui/tree/main/src

image

簡單使用

依賴包

https://www.nuget.org/packages/wpf-ui/

dotnet add package wpf-ui

image

App.xaml中引入下樣式字典資源: ui:ThemesDictionaryui: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
            );
        };
    }
}

看下效果

image

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章