You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.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线程兼容性:

步骤:

  1. 在NuGet包管理器中安装System.Windows.Forms包
  2. 在应用启动时初始化WinForms样式(可选,但能让对话框更美观):
// 在App.xaml.cs的OnStartup方法中添加
System.Windows.Forms.Application.EnableVisualStyles();
  1. 调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:32:17