本文介绍了SetCurrentConsoleFontEx不支持长字体名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不能让它对16个字符或更长的字体名称起作用,但控制台本身显然没有这个限制。有没有人知道一种程序化的方法来设置字体,以便与内置的"Lucida Sans打字机"或开源的"Fira Code Retina"一起使用?

以下代码工作正常:

我从各个地方复制了PInvoke代码,特别是the PowerShell console hostMicrosoft Docs

请注意,CONSOLE_FONT_INFOEXSetCurrentConsoleFontEx的相关文档没有讨论这一点,结构将字体定义为大小为32的WCHAR字段...

还请注意,不是限制,但来自控制台对话框的限制,即字体必须具有True Type轮廓,并且宽度必须真正固定。使用此API,您可以选择像"Times New Roman"这样的可变宽度字体...

但是,在接口中,它的名称必须少于16个字符--这是控制台本身没有的限制,可能是接口中的错误,而不是我在🤔下面的代码

using System;
using System.Runtime.InteropServices;

public static class ConsoleHelper
{
    private const int FixedWidthTrueType = 54;
    private const int StandardOutputHandle = -11;

    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern IntPtr GetStdHandle(int nStdHandle);

    [return: MarshalAs(UnmanagedType.Bool)]
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    internal static extern bool SetCurrentConsoleFontEx(IntPtr hConsoleOutput, bool MaximumWindow, ref FontInfo ConsoleCurrentFontEx);

    [return: MarshalAs(UnmanagedType.Bool)]
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    internal static extern bool GetCurrentConsoleFontEx(IntPtr hConsoleOutput, bool MaximumWindow, ref FontInfo ConsoleCurrentFontEx);


    private static readonly IntPtr ConsoleOutputHandle = GetStdHandle(StandardOutputHandle);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct FontInfo
    {
        internal int cbSize;
        internal int FontIndex;
        internal short FontWidth;
        public short FontSize;
        public int FontFamily;
        public int FontWeight;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        //[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.wc, SizeConst = 32)]
        public string FontName;
    }

    public static FontInfo[] SetCurrentFont(string font, short fontSize = 0)
    {
        Console.WriteLine("Set Current Font: " + font);

        FontInfo before = new FontInfo
        {
            cbSize = Marshal.SizeOf<FontInfo>()
        };

        if (GetCurrentConsoleFontEx(ConsoleOutputHandle, false, ref before))
        {

            FontInfo set = new FontInfo
            {
                cbSize = Marshal.SizeOf<FontInfo>(),
                FontIndex = 0,
                FontFamily = FixedWidthTrueType,
                FontName = font,
                FontWeight = 400,
                FontSize = fontSize > 0 ? fontSize : before.FontSize
            };

            // Get some settings from current font.
            if (!SetCurrentConsoleFontEx(ConsoleOutputHandle, false, ref set))
            {
                var ex = Marshal.GetLastWin32Error();
                Console.WriteLine("Set error " + ex);
                throw new System.ComponentModel.Win32Exception(ex);
            }

            FontInfo after = new FontInfo
            {
                cbSize = Marshal.SizeOf<FontInfo>()
            };
            GetCurrentConsoleFontEx(ConsoleOutputHandle, false, ref after);

            return new[] { before, set, after };
        }
        else
        {
            var er = Marshal.GetLastWin32Error();
            Console.WriteLine("Get error " + er);
            throw new System.ComponentModel.Win32Exception(er);
        }
    }
}

您可以在PowerShell窗口中使用Add-Type该代码,然后执行以下操作:

[ConsoleHelper]::SetCurrentFont("Consolas", 16)
[ConsoleHelper]::SetCurrentFont("Lucida Console", 12)
然后,使用您的控制台"属性"对话框手动切换到...并尝试更改字体大小,指定相同的字体名称:

[ConsoleHelper]::SetCurrentFont("Lucida Sans Typewriter", 12)

您将得到如下所示的输出(显示三个设置:之前、我们尝试了什么和我们获得了什么):

Set Current Font: Lucida Sans Typewriter

FontSize FontFamily FontWeight FontName
-------- ---------- ---------- --------
      14         54        400 Lucida Sans Typeʈ
      12         54        400 Lucida Sans Typewriter
      12         54        400 Courier New

您看到"之前"值末尾的奇怪字符了吗?每当字体超过16个字符时就会发生这种情况(由于API或编组中的问题,我收到了垃圾数据)。

实际的控制台字体名称显然没有长度限制,但可能无法使用名称为16个字符或更长的字体?

不管怎样,我在Fira Code Retina中发现了这个问题,这是一种名称中正好有16个字符的字体--我的代码比a gist here中的代码要多一点,如果您愿意尝试一下...

推荐答案

我在控制台接口中发现了一个bug。自Windows10(Insider)18267版起已修复。

在该版本之前,除了使用名称较短字体或使用实际的窗口属性面板来设置它之外,没有其他方法可以绕过它。

原始邮政编码现在起作用...

这篇关于SetCurrentConsoleFontEx不支持长字体名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 11:19