如何在.NET 6 WPF桌面应用中使用FontDialog?
.NET 6 WPF 中实现字体选择对话框的几种可行方案
方案1:调用Win32原生字体对话框(无第三方依赖)
WPF本身没有内置字体选择对话框,但可以通过P/Invoke直接调用系统原生的ChooseFont函数,这是最轻量化的方式,无需额外依赖。
核心代码示例:
using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Media; public class Win32FontDialog { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] private struct CHOOSEFONT { public int lStructSize; public IntPtr hwndOwner; public IntPtr hDC; public IntPtr lpLogFont; public int iPointSize; public uint Flags; public IntPtr rgbColors; public IntPtr lCustData; public IntPtr lpfnHook; public string lpTemplateName; public IntPtr hInstance; public string lpszStyle; public short nFontType; public short ___MISSING_ALIGNMENT__; public int nSizeMin; public int nSizeMax; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] private struct LOGFONT { public int lfHeight; public int lfWidth; public int lfEscapement; public int lfOrientation; public int lfWeight; public byte lfItalic; public byte lfUnderline; public byte lfStrikeOut; public byte lfCharSet; public byte lfOutPrecision; public byte lfClipPrecision; public byte lfQuality; public byte lfPitchAndFamily; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string lfFaceName; } [DllImport("comdlg32.dll", CharSet = CharSet.Auto)] private static extern bool ChooseFont(ref CHOOSEFONT lpcf); public static bool ShowDialog(Window owner, out FontFamily fontFamily, out double fontSize, out FontWeight fontWeight, out FontStyle fontStyle) { fontFamily = null; fontSize = 0; fontWeight = FontWeights.Normal; fontStyle = FontStyles.Normal; var logFont = new LOGFONT(); var cf = new CHOOSEFONT(); cf.lStructSize = Marshal.SizeOf(cf); cf.hwndOwner = new System.Windows.Interop.WindowInteropHelper(owner).Handle; cf.lpLogFont = Marshal.AllocHGlobal(Marshal.SizeOf(logFont)); cf.Flags = 0x00000001 | 0x00000400; // CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS cf.iPointSize = 12 * 10; // 12pt try { Marshal.StructureToPtr(logFont, cf.lpLogFont, false); if (ChooseFont(ref cf)) { logFont = (LOGFONT)Marshal.PtrToStructure(cf.lpLogFont, typeof(LOGFONT)); fontFamily = new FontFamily(logFont.lfFaceName); fontSize = cf.iPointSize / 10.0; fontWeight = logFont.lfWeight >= 700 ? FontWeights.Bold : FontWeights.Normal; fontStyle = logFont.lfItalic == 1 ? FontStyles.Italic : FontStyles.Normal; return true; } return false; } finally { Marshal.FreeHGlobal(cf.lpLogFont); } } } // 调用方式(在WPF窗口的按钮点击事件中): private void Button_Click(object sender, RoutedEventArgs e) { if (Win32FontDialog.ShowDialog(this, out var fontFamily, out var fontSize, out var fontWeight, out var fontStyle)) { // 应用选中的字体到控件 MyTextBlock.FontFamily = fontFamily; MyTextBlock.FontSize = fontSize; MyTextBlock.FontWeight = fontWeight; MyTextBlock.FontStyle = fontStyle; } }
方案2:引用System.Windows.Forms包(快速实现)
虽然是Windows Forms组件,但.NET 6支持通过NuGet安装System.Windows.Forms包,在WPF项目中直接使用FontDialog,只需注意UI线程兼容性:
步骤:
- 在NuGet包管理器中安装
System.Windows.Forms包 - 在应用启动时初始化WinForms样式(可选,但能让对话框更美观):
// 在App.xaml.cs的OnStartup方法中添加 System.Windows.Forms.Application.EnableVisualStyles();
- 调用FontDialog:
using System.Windows.Forms; private void Button_Click(object sender, RoutedEventArgs e) { using var fontDialog = new FontDialog(); fontDialog.ShowColor = true; // 可选:启用颜色选择 if (fontDialog.ShowDialog() == DialogResult.OK) { // 转换为WPF可用的字体属性 MyTextBlock.FontFamily = new FontFamily(fontDialog.Font.Name); MyTextBlock.FontSize = fontDialog.Font.Size * 96 / 72; // 将WinForms的点转换为WPF的设备无关单位 MyTextBlock.FontWeight = fontDialog.Font.Bold ? FontWeights.Bold : FontWeights.Normal; MyTextBlock.FontStyle = fontDialog.Font.Italic ? FontStyles.Italic : FontStyles.Normal; MyTextBlock.Foreground = new SolidColorBrush(Color.FromRgb(fontDialog.Color.R, fontDialog.Color.G, fontDialog.Color.B)); } }
方案3:自定义WPF字体选择控件(完全原生)
如果需要完全贴合WPF的设计风格,可以自己实现一个字体选择对话框,核心是利用WPF的Fonts.SystemFontFamilies获取系统字体列表,结合基础控件构建UI:
简单示例XAML(自定义对话框):
<Window x:Class="WpfFontDialog.CustomFontDialog" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="选择字体" Height="400" Width="500" WindowStyle="ToolWindow" ResizeMode="NoResize"> <Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Margin="0 0 0 10"> <TextBlock Text="字体:" VerticalAlignment="Center" Width="60"/> <ListBox x:Name="FontListBox" ItemsSource="{x:Static Fonts.SystemFontFamilies}" Width="200" SelectionChanged="FontListBox_SelectionChanged"/> <TextBlock Text="字号:" VerticalAlignment="Center" Margin="10 0" Width="40"/> <ComboBox x:Name="SizeComboBox" Width="80" SelectedIndex="4"> <sys:Double>8</sys:Double> <sys:Double>9</sys:Double> <sys:Double>10</sys:Double> <sys:Double>11</sys:Double> <sys:Double>12</sys:Double> <sys:Double>14</sys:Double> <sys:Double>16</sys:Double> <sys:Double>18</sys:Double> </ComboBox> </StackPanel> <StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Top"> <CheckBox x:Name="BoldCheckBox" Content="粗体" Margin="0 0 10 0"/> <CheckBox x:Name="ItalicCheckBox" Content="斜体"/> <TextBlock x:Name="PreviewTextBlock" Text="预览文本" Margin="20 0" FontSize="16"/> </StackPanel> <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 10 0 0"> <Button x:Name="OKButton" Content="确定" Width="80" Margin="0 0 10 0" Click="OKButton_Click"/> <Button x:Name="CancelButton" Content="取消" Width="80" Click="CancelButton_Click"/> </StackPanel> </Grid> </Window>
后台代码:
using System.Windows; using System.Windows.Media; namespace WpfFontDialog { public partial class CustomFontDialog : Window { public FontFamily SelectedFontFamily { get; private set; } public double SelectedFontSize { get; private set; } public FontWeight SelectedFontWeight { get; private set; } public FontStyle SelectedFontStyle { get; private set; } public CustomFontDialog() { InitializeComponent(); // 默认选中第一个字体 if (FontListBox.Items.Count > 0) FontListBox.SelectedIndex = 0; } private void FontListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) { UpdatePreview(); } private void UpdatePreview() { if (FontListBox.SelectedItem is FontFamily family) { PreviewTextBlock.FontFamily = family; SelectedFontFamily = family; } if (double.TryParse(SizeComboBox.SelectedItem?.ToString(), out var size)) { PreviewTextBlock.FontSize = size; SelectedFontSize = size; } PreviewTextBlock.FontWeight = BoldCheckBox.IsChecked == true ? FontWeights.Bold : FontWeights.Normal; SelectedFontWeight = PreviewTextBlock.FontWeight; PreviewTextBlock.FontStyle = ItalicCheckBox.IsChecked == true ? FontStyles.Italic : FontStyles.Normal; SelectedFontStyle = PreviewTextBlock.FontStyle; } private void OKButton_Click(object sender, RoutedEventArgs e) { DialogResult = true; Close(); } private void CancelButton_Click(object sender, RoutedEventArgs e) { DialogResult = false; Close(); } } }
调用方式:
private void Button_Click(object sender, RoutedEventArgs e) { var dialog = new CustomFontDialog(); if (dialog.ShowDialog() == true) { MyTextBlock.FontFamily = dialog.SelectedFontFamily; MyTextBlock.FontSize = dialog.SelectedFontSize; MyTextBlock.FontWeight = dialog.SelectedFontWeight; MyTextBlock.FontStyle = dialog.SelectedFontStyle; } }
内容的提问来源于stack exchange,提问作者Gaurang Dave
相关产品推荐
相关产品推荐

