1. Windows 11 的圓角
在直角統治了微軟的 UI 設計多年以后,微軟突然把直角罵了一頓,說還是圓角好看,於是 Windows 11 隨處都可看到圓角設計。Windows 11 使用 3 個級別的圓角,具體取決於要應用圓角的 UI 組件及該組件相對於相鄰元素的排列方式。
圓角半徑 | 使用情況 |
---|---|
8px | 窗體、Flyout 、彈出菜單等 。另外,當窗體最大化或使用對齊布局時不應用圓角。 |
4px | 頁面內的元素,如按鈕或列表等。 |
0px | 與其它直邊相交的直邊不使用圓角。 |
也就是說在 Windows 11 上窗體需要應用半徑為 8px 的圓角。
2. 處理 WindowChrome 的圓角
對於 WPF,如果使用原生 Window 的話不需要額外處理圓角,如果使用了 WindowChrome 自定義窗體樣式的話呢?
結論是,如果自定義的 Window 使用了 1 像素的窄邊框或無邊框的樣式,那就可能不需要額外處理。
下面這兩張圖是同一個自定義的 Window 分別在 Windows 11 和 10 上的樣子:
可以看到這是個模仿 Windows 10 的 Window 樣式,邊框只有 1 像素。在 Windows 11 里 WindowChrome 會自動裁剪最外層那 1 像素邊框和圓角的其它部分,然后補上一條灰色的邊框。這做法簡單粗暴但有效。被裁剪過后自定義的 Window 成了一個無邊框圓角窗口,看着還挺時髦的。
但這個簡單裁剪也可能遇到問題,如果 Window 里的內容正好有個直角的元素,而且這個直角還靠着圓角,就可能被裁剪掉;或者自定義的 Window 使用了無邊框的樣式,那么這個貼邊的邊框就會被裁剪掉一像素:
所以 Window 可能不需要額外處理,但內容可能需要,這取決於以前的設計。
還有一種情況,如果這個 Window 的邊框大於一個像素(像 Windows 8 那樣的粗邊框),那就需要修改 Window 樣式了:
3. 我就是喜歡直的,不想要圓角,怎么辦
上圖是 Aero2 的主題樣式,這是 Windows 8 以后 WPF 程序的默認主題,再之后微軟就沒有更新過 WPF 的主題。即使在 Windows 11 上,WPF 的主題也沒有獲得更新。所以,假使現有的 WPF 程序使用了默認主題,或者自定義的主題按照微軟一向的審美全使用了直角元素,那到了 Windows 11 上就會顯得格格不入。
微軟還是很貼心的,如果我們不想更改樣式,可以使用 DwmSetWindowAttribute 和 DWM_WINDOW_CORNER_PREFERENCE 控制 Window 的圓角。
using System.Runtime.InteropServices;
using System.Windows.Interop;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
IntPtr hWnd = new WindowInteropHelper(GetWindow(this)).EnsureHandle();
var attribute = DWMWINDOWATTRIBUTE.DWMWA_WINDOW_CORNER_PREFERENCE;
var preference = DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_ROUND;
DwmSetWindowAttribute(hWnd, attribute, ref preference, sizeof(uint));
// ...
// Perform any other work necessary
// ...
}
// The enum flag for DwmSetWindowAttribute's second parameter, which tells the function what attribute to set.
public enum DWMWINDOWATTRIBUTE
{
DWMWA_WINDOW_CORNER_PREFERENCE = 33
}
// The DWM_WINDOW_CORNER_PREFERENCE enum for DwmSetWindowAttribute's third parameter, which tells the function
// what value of the enum to set.
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, SetLastError = true)]
private static extern long DwmSetWindowAttribute(IntPtr hwnd,
DWMWINDOWATTRIBUTE attribute,
ref DWM_WINDOW_CORNER_PREFERENCE pvAttribute,
uint cbAttribute);
// ...
// Various other definitions
// ...
}
其中 DWM_WINDOW_CORNER_PREFERENCE 枚舉值的含義如下:
枚舉值 | 說明 |
---|---|
DWMWCP_DEFAULT | 讓系統決定是否對窗口采用圓角設置。 |
DWMWCP_DONOTROUND | 絕不對窗口采用圓角設置。 |
DWMWCP_ROUND | 適當時采用圓角設置。 |
DWMWCP_ROUNDSMALL | 適當時可采用半徑較小的圓角設置。 |
在 Windows 11 上,使用了上面 4 鍾枚舉值的窗口效果如下:
4. 最后
關於使用 WindowChrome 自定義窗體的內容,可以參考這幾篇文章:
-
Window(窗體)的UI元素及行為:這篇文章主要討論標准 Window 的 UI 元素和行為。
-
使用WindowChrome自定義Window Style:介紹使用 WindowChrome 自定義 Window 的原理及各種細節。
-
使用WindowChrome的問題:介紹如何處理使用 WindowChrome 自定義 Window 會遇到的各種問題。
-
WPF 制作高性能的透明背景異形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True)
另外,關於圓角我要抱怨一下:
在 Windows 11 中,我們對窗口邊框進行了圓角處理。 我們的用戶研究團隊發現,圓潤的幾何圖形在心理上提供一種安全感,並且使應用的 UI 更易於掃描。 這使用戶更少感覺威懾,也使應用更具吸引力。 圓角處理的量也是精心選擇的。 我們公司對此進行了研究,努力在專業性、柔和感和吸引度之間取得平衡。
微軟的文檔這樣聲稱,我是一個字都不信的,難道這么多年來區區 Windows 的直角就讓我感覺到威懾和沒有安全感了?微軟還有比 UWP 更能讓我沒有安全感的東西?我倒想看看幾年后又流行直角時微軟要怎么解釋。
5. 參考
在 Windows 11 上,為增強應用功能而可以執行的最常見的 11 種操作
6. 源碼
我做了個小 Demo 用戶看看這篇文章提到的不同邊框和 DWM_WINDOW_CORNER_PREFERENCE 設定下的效果,源碼可以從這里獲取: