皮肤
这个主题解释了如何将DevExpress主题/皮肤应用到应用程序中,如何允许用户在运行时在主题之间切换,如何自定义现有的皮肤或创建自己的皮肤等等。
DevExpress WinForms控件包含许多基本控件的对应项:按钮、复选框、窗体、消息框、对话框等。我们实现所有这些控件的主要原因是为了支持的主题,使用DevExpress您可以获得各种外观和全面的控制库,来保证整个应用程序的视觉一致性。
要查看可用的主题/皮肤,打开任何演示应用程序。
如何应用皮肤
设计时间
打开项目设置页面并选择所需的 WinForms 主题,此页面在 .NET Core 项目中不可用,将组件放置在 Form 上并使用其智能标记菜单,或在代码中指定所需的外观。
运行时(在代码中)
调用UserLookAndFeel.SetSkinStyle方法。
C#:
using DevExpress.LookAndFeel; // ... UserLookAndFeel.Default.SetSkinStyle(SkinStyle.WXI);
VB.NET:
Imports DevExpress.LookAndFeel ' ... UserLookAndFeel.Default.SetSkinStyle(SkinStyle.WXI)
提示:矢量调色板适用于整个 Windows 窗体应用程序,您不能将不同的调色板应用于程序中的不同表单。
如何启用Bonus或自定义皮肤
DevExpress皮肤分为两大类:DevExpress推荐的最新皮肤,以及存储在单独库/包中的过时/主题皮肤。
当您使用模板库创建项目或将任何控件拖放到表单上时,现代皮肤立即可用。如果启动空白项目,则需要DevExpress.Utils手动添加库(或安装DevExpress.Utils NuGet package),对于blank .NET Core (. NET 5) 项目,请安装全局DevExpress.Win.Design。
过时的皮肤和主题皮肤存储在DevExpress.BonusSkins 库/NuGet 包中,这些皮肤必须先注册才能应用。如需注册奖励皮肤,请在项目设置页面查看相应设置,或在应用启动时Register调用该方法:
C#:
namespace WindowsFormsApplication1 { static class Program { [STAThread] static void Main() { DevExpress.UserSkins.BonusSkins.Register(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } }
VB.NET:
Public Class Form1 Shared Sub Main() DevExpress.UserSkins.BonusSkins.Register() Application.EnableVisualStyles() Application.SetCompatibleTextRenderingDefault(False) Application.Run(New Form1) End Sub End Class
注册奖励皮肤后,您可以像使用standard skins一样使用它们。
C#:
using DevExpress.LookAndFeel; UserLookAndFeel.Default.SetSkinStyle(SkinStyle.Pumpkin);
VB.NET:
Imports DevExpress.LookAndFeel UserLookAndFeel.Default.SetSkinStyle(SkinStyle.Pumpkin)
还必须注册 Skin Editor工具生成的库中的自定义皮肤。
如何让用户在运行时选择皮肤
DevExpress WinForms 订阅包括多个即用型栏项目,允许用户在皮肤和皮肤调色板之间切换,您可以将这些项目添加到工具栏表单和Fluent Design 表单的工具栏、功能区和标题栏。
下面的代码将 Skin Gallery 选择器添加到"ribbonPageGroup2"组中。
C#:
using DevExpress.XtraBars; // ... SkinRibbonGalleryBarItem skinGallery = new SkinRibbonGalleryBarItem(); ribbonPageGroup2.ItemLinks.Add(skinGallery);
VB.NET:
Imports DevExpress.XtraBars ' ... Private skinGallery As New SkinRibbonGalleryBarItem() ribbonPageGroup2.ItemLinks.Add(skinGallery)
请注意,如果SkinDropDownButtonItem在代码中创建选择器,则需要调用该InitDropDownSkinGallery方法来初始化该选择器的下拉列表。
C#:
using DevExpress.XtraBars; using DevExpress.XtraBars.Helpers; // Add the selector next to the standard "Close", "Maximize", and "Minimize" // buttons of the Toolbar Form SkinDropDownButtonItem skinSelector = new SkinDropDownButtonItem(); SkinHelper.InitDropDownSkinGallery(skinSelector); skinSelector.Alignment = BarItemLinkAlignment.Right; this.toolbarFormControl1.TitleItemLinks.Add(skinSelector);
VB.NET:
Imports DevExpress.XtraBars Imports DevExpress.XtraBars.Helpers ' Add the selector next to the standard "Close", "Maximize", and "Minimize" ' buttons of the Toolbar Form Private skinSelector As New SkinDropDownButtonItem() SkinHelper.InitDropDownSkinGallery(skinSelector) skinSelector.Alignment = BarItemLinkAlignment.Right Me.toolbarFormControl1.TitleItemLinks.Add(skinSelector)
要重命名和/或更改这些标准皮肤选择器项目的图标,请处理该SkinHelper.CreateGalleryItem事件。
C#:
using DevExpress.XtraBars; using DevExpress.XtraBars.Helpers; SkinHelper.CreateGalleryItem += (s, e) => { if (e.ItemName.Equals("DevExpress Style")) { e.GalleryItem.Image = e.UseLargeIcons ? MyCustomLargeIcon : MyCustomSmallIcon; e.GalleryItem.HoverImage = MyCustomLargeIcon; e.GalleryItem.Caption = "Moonlight"; } };
VB.NET:
Imports DevExpress.XtraBars Imports DevExpress.XtraBars.Helpers AddHandler SkinHelper.CreateGalleryItem, Sub(s, e) If e.ItemName.Equals("DevExpress Style") Then e.GalleryItem.Image = If(e.UseLargeIcons, MyCustomLargeIcon, MyCustomSmallIcon) e.GalleryItem.HoverImage = MyCustomLargeIcon e.GalleryItem.Caption = "Moonlight" End If End Sub
提示:
- 在不同的皮肤中,皮肤元素可以有不同的设置(例如填充、边距等)。有些皮肤包含了其他皮肤中不可用的元素。
- 在某些情况下,从一个皮肤切换到另一个皮肤可能会破坏表单的布局(例如,UI控件可能更短或更薄,内容可能被剪切),我们建议不要创建 pixel-perfect的布局,以避免在更改皮肤时出现UI问题。
皮肤调色板
DevExpress WinForms皮肤可以在UI元素上绘制光栅或矢量图像。栅格皮肤只有一个默认外观,而每个矢量皮肤都有一个选择的调色板(色板),用户可以选择调色板来修改当前皮肤的配色方案。下图展示了“The Bezier”矢量皮肤附带的一些调色板。
您可以采用与指定外观相同的方式应用调色板:打开项目设置页面或调用重载。
C#:
using DevExpress.LookAndFeel; // ... UserLookAndFeel.Default.SetSkinStyle(SkinSvgPalette.Bezier.Tokyo);
VB.NET:
Imports DevExpress.LookAndFeel ' ... UserLookAndFeel.Default.SetSkinStyle(SkinSvgPalette.Bezier.Tokyo)
默认应用程序模式(浅色/深色)
使用设置指定您的应用程序是否跟踪 Windows 操作系统中的默认应用程序模式设置并在外观库中仅显示浅色或深色调色板。
以下示例演示了如何启用该TrackWindowsAppMode设置:
C#:
static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); WindowsFormsSettings.TrackWindowsAppMode = DevExpress.Utils.DefaultBoolean.True; Application.Run(new Form1()); }
VB.NET:
Shared Sub Main() Application.EnableVisualStyles() Application.SetCompatibleTextRenderingDefault(False) WindowsFormsSettings.TrackWindowsAppMode = DevExpress.Utils.DefaultBoolean.True Application.Run(New Form1()) End Sub
注意:WindowsFormsSettings.TrackWindowsAppMode设置仅适用于“WXI”,“Basic”和“The Bezier”皮肤。
使用系统或自定义强调色
系统强调色
启用选项来使用 Windows 操作系统中的强调颜色设置,并将其应用到矢量外观的所有调色板(高对比度外观除外)。
C#:
using DevExpress.XtraEditors; static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); WindowsFormsSettings.TrackWindowsAccentColor = DevExpress.Utils.DefaultBoolean.True; Application.Run(new Form1()); }
VB.NET:
Imports DevExpress.XtraEditors Shared Sub Main() Application.EnableVisualStyles() Application.SetCompatibleTextRenderingDefault(False) WindowsFormsSettings.TrackWindowsAccentColor = DevExpress.Utils.DefaultBoolean.True Application.Run(New Form1()) End Sub
自定义强调色
使用SetAccentColor方法自定义强调色(优先于系统强调色)。
C#:
DevExpress.XtraEditors.WindowsFormsSettings.SetAccentColor(Color.FromArgb(16, 124, 65));
VB.NET:
DevExpress.XtraEditors.WindowsFormsSettings.SetAccentColor(Color.FromArgb(16, 124, 65))
提示:
- “The Bezier”皮肤支持第二种强调色,其他皮肤不支持第二种强调色。
- 使用方法指定第二个强调色。
重置强调色
以下示例演示了如何重置主要和次要强调色:
C#:
DevExpress.XtraEditors.WindowsFormsSettings.SetAccentColor(System.Drawing.Color.Empty); DevExpress.XtraEditors.WindowsFormsSettings.SetAccentColor2(System.Drawing.Color.Empty);
VB.NET:
DevExpress.XtraEditors.WindowsFormsSettings.SetAccentColor(System.Drawing.Color.Empty) DevExpress.XtraEditors.WindowsFormsSettings.SetAccentColor2(System.Drawing.Color.Empty)
当您禁用设置时,强调色不会自动重置。您应该调用该SetAccentColor(System.Drawing.Color.Empty)方法来重置强调色。
C#:
WindowsFormsSettings.TrackWindowsAccentColor = DefaultBoolean.False; WindowsFormsSettings.SetAccentColor(Color.Empty); WindowsFormsSettings.SetAccentColor2(Color.Empty);
VB.NET:
WindowsFormsSettings.TrackWindowsAccentColor = DefaultBoolean.False WindowsFormsSettings.SetAccentColor(Color.Empty) WindowsFormsSettings.SetAccentColor2(Color.Empty)
突出显示单独的控件
您可以为各个 DevExpress 控件(例如)设置自定义背景、边框和前景色,为此请访问Control.Appearance组中的设置。建议您使用DX Colors而不是系统颜色,这些颜色是从外观中检索的,并且当用户在运行时更改外观时会自动更新。
C#:
// Use DXSkinColors.FillColors for background colors simpleButton1.Appearance.BackColor = DXSkinColors.FillColors.Danger; // Use DXSkinColors.ForeColors for text colors simpleButton1.Appearance.ForeColor = DXSkinColors.ForeColors.Warning;
VB.NET:
' Use DXSkinColors.FillColors for background colors simpleButton1.Appearance.BackColor = DXSkinColors.FillColors.Danger ' Use DXSkinColors.ForeColors for text colors simpleButton1.Appearance.ForeColor = DXSkinColors.ForeColors.Warning
高对比度皮肤
“高对比度”矢量皮肤是为低视力障碍用户提供的无障碍主题。
该主题的外观和可用性取决于用户设置(Windows 中的“Personalize | High contrast settings菜单)。
- 如果Windows的高对比度模式是 off,用户可以像选择其他DevExpress主题一样选择High contrast 皮肤,皮肤调色板选择器也是可用的。
- 如果Windows高对比度模式的on,所有允许用户更改皮肤和调色板的UI选择器都被禁用,带有Default调色板的矢量High Contrast皮肤变得活跃。Default调色板使用与用户在Windows “ High contrast settings”屏幕中设置的颜色相同。
您可以禁用静态属性,以防止应用程序跟踪 Windows 高对比度模式的实际状态。在这种情况下,应用程序不会打开或关闭“High Contrast”皮肤,用户可以选择任何皮肤。
加厚表单边框
在“Office 2019 Colorful”等现代平面皮肤中,DevExpress Forms会显示薄边框,这对用户来说可能不方便,因为当他们试图调整表单的大小时,他们必须用鼠标指针瞄准那些细边框。为了改善用户体验,DevExpress Forms的调整大小区域包括边框和Form阴影/发光皮肤元素,这允许用户在鼠标指针悬停在窗体的阴影上时调整窗体的大小。
在以下情况下,表单无法显示阴影:
- 如果手动禁用属性。
- 如果表单是子 MDI 表单。
- 如果用户通过远程桌面连接访问应用程序。
在这些情况下,您可以增加表单边框宽度来扩大调整大小区域。
要增加边框宽度,请启用或属性,具体取决于您是要增加所有 DevExpress 窗体的边框大小,还是仅增加用作子 MDI 窗体的窗体的边框大小。
使用WindowsFormsSettings.ThickBorderWidth属性更改表单边框的宽度。
提示:当启用远程连接优化模式时,表单将切换为粗边框。启用此模式时,禁用FormThickBorder属性来保留基于皮肤的边框。
皮肤编辑器
DevExpress WinForms 安装附带了一个允许您创建、编辑和分发主题的工具:Skin Editor。
备忘表和故障排除
示例和最佳实践
如何获取当前活动的皮肤和调色板的名称
读取和属性的值。
C#:
var skinName = UserLookAndFeel.Default.ActiveSkinName; var paletteName = UserLookAndFeel.Default.ActiveSvgPaletteName;
VB.NET:
Dim skinName = UserLookAndFeel.Default.ActiveSkinName Dim paletteName = UserLookAndFeel.Default.ActiveSvgPaletteName
如何识别皮肤或调色板在运行时是否已更改
处理静态事件,每次用户应用不同的皮肤或皮肤调色板时都会引发此事件。
C#:
UserLookAndFeel.Default.StyleChanged += (s, e) => { // TODO };
VB.NET:
AddHandler UserLookAndFeel.Default.StyleChanged, Sub(s, e) ' TODO End Sub
如何从矢量皮肤调色板中获取颜色
使用以下代码检索调色板颜色的值:
C#:
var commonSkin = CommonSkins.GetSkin(UserLookAndFeel.Default); SvgPalette svgPalette = commonSkin.SvgPalettes[Skin.DefaultSkinPaletteName] as SvgPalette; Color keyPaintColor = svgPalette["Key Paint"].Value;
VB.NET:
Dim commonSkin = CommonSkins.GetSkin(UserLookAndFeel.Default) Dim svgPalette As SvgPalette = TryCast(commonSkin.SvgPalettes(Skin.DefaultSkinPaletteName), SvgPalette) Dim keyPaintColor As Color = svgPalette("Key Paint").Value
当应用程序重新启动时,如何重新应用上次活动的皮肤
Windows表单功能允许您在客户端计算机上创建、存储和维护自定义应用程序和用户首选项。此时可以使用此功能在应用程序重新启动时保存和恢复活动的皮肤和调色板。
双击 Visual Studio 解决方案资源管理器中的“Settings.settings”文件,并创建两个字符串类型的条目,将两个条目的范围设置为“User”。当应用程序即将关闭时,将和属性的值保存到应用程序设置。当应用程序启动时,读取这些保存的值并将它们作为参数传递给UserLookAndFeel.SetSkinStyle方法。
对于 v22.1 及更高版本的 DevExpress 安装,请在设置中添加额外的布尔条目,这一项应用于确定是采用常规版本还是精简版本的WXI皮肤。
xml:
<?xml version='1.0' encoding='utf-8'?> <SettingsFile xmlns="//schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="DXApplication1.Properties" GeneratedClassName="Settings"> <Profiles/> <Settings> <Setting Name="SkinName" Type="System.String" Scope="User"> <Value Profile="(Default)" /> </Setting> <Setting Name="Palette" Type="System.String" Scope="User"> <Value Profile="(Default)" /> </Setting> <Setting name="CompactMode" serializeAs="String"> <Value>False</value> </Setting> </Settings> </SettingsFile>
C#:
using DevExpress.LookAndFeel; private void Form1_FormClosing(object sender, FormClosingEventArgs e) { var settings = Properties.Settings.Default; settings.SkinName = UserLookAndFeel.Default.SkinName; settings.Palette = UserLookAndFeel.Default.ActiveSvgPaletteName; settings.CompactMode = UserLookAndFeel.Default.CompactUIModeForced; settings.Save(); } protected override void OnShown(EventArgs e) { base.OnShown(e); var settings = Properties.Settings.Default; if (!string.IsNullOrEmpty(settings.SkinName)) { if (settings.CompactMode) UserLookAndFeel.ForceCompactUIMode(true, false); if (!string.IsNullOrEmpty(settings.Palette)) UserLookAndFeel.Default.SetSkinStyle(settings.SkinName, settings.Palette); else UserLookAndFeel.Default.SetSkinStyle(settings.SkinName, "DefaultSkinPalette"); } }
VB.NET:
Imports DevExpress.LookAndFeel Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Dim settings_Renamed = My.Settings.Default settings_Renamed.SkinName = UserLookAndFeel.Default.SkinName settings_Renamed.Palette = UserLookAndFeel.Default.ActiveSvgPaletteName settings_Renamed.CompactMode = UserLookAndFeel.Default.CompactUIModeForced settings_Renamed.Save() End Sub Protected Overrides Sub OnShown(ByVal e As EventArgs) MyBase.OnShown(e) Dim settings_Renamed = My.Settings.Default If Not String.IsNullOrEmpty(settings_Renamed.SkinName) Then If settings_Renamed.CompactMode Then UserLookAndFeel.ForceCompactUIMode(True, False) End If If Not String.IsNullOrEmpty(settings_Renamed.Palette) Then UserLookAndFeel.Default.SetSkinStyle(settings_Renamed.SkinName, settings_Renamed.Palette) Else UserLookAndFeel.Default.SetSkinStyle(settings_Renamed.SkinName, "DefaultSkinPalette") End If End If End Sub
如何识别常规版本和精简版本的WXI皮肤是否活跃
读取UserLookAndFeel.Default.CompactUIModeForced属性值。
C#:
bool isCompact = UserLookAndFeel.Default.CompactUIModeForced;
VB.NET:
Dim isCompact As Boolean = UserLookAndFeel.Default.CompactUIModeForced
如何在代码中区分浅色皮肤和深色皮肤
所有 DevExpress 皮肤和调色板分为两类:深色和浅色。要识别活动主题请调用DevExpress.Utils.Frames.FrameHelper.IsDarkSkin方法。
C#:
using DevExpress.Utils.Frames; //... if (FrameHelper.IsDarkSkin(this.GetActiveLookAndFeel())) { // Current skin/palette is dark } else { // Current skin/palette is light }
VB.NET:
Imports DevExpress.Utils.Frames '... If FrameHelper.IsDarkSkin(Me.GetActiveLookAndFeel()) Then ' Current skin/palette is dark Else ' Current skin/palette is light End If
请注意,该IsDarkSkin方法根据“Paint High”调色板颜色的值来识别皮肤是浅色还是深色,因此,该方法的返回值可能与整体皮肤外观相反。例如,“Office 2019 深灰色”由于其浅“Paint High”颜色值而被识别为浅色皮肤,尽管该皮肤主要是深色的。
您可以用自己的方法来“修复”感到困惑的返回值。
C#:
VB.NET:bool IsDarkSkinEx() { var res = FrameHelper.IsDarkSkin(this.GetActiveLookAndFeel()); return res || UserLookAndFeel.Default.SkinName == "Office 2019 Dark Gray"; }
VB.NET:
Private Function IsDarkSkinEx() As Boolean Dim res = FrameHelper.IsDarkSkin(Me.GetActiveLookAndFeel()) Return res OrElse UserLookAndFeel.Default.SkinName = "Office 2019 Dark Gray" End Function
如何将皮肤应用到没有标题栏的表单
要隐藏表单的标题栏,请禁用其和图标,并删除表单的标题。
C#:
this.Text = null; this.IconOptions.ShowIcon = false; this.ControlBox = false;
VB.NET:
Me.Text = Nothing Me.IconOptions.ShowIcon = False Me.ControlBox = False
除非您重写它们的方法,否则此类表单不会设置皮肤GetAllowSkin。
C#:
protected override bool GetAllowSkin() { return true; }
VB.NET:
Protected Overrides Function GetAllowSkin() As Boolean Return True End Function