问题描述
我不能让它对16个字符或更长的字体名称起作用,但控制台本身显然没有这个限制。有没有人知道一种程序化的方法来设置字体,以便与内置的"Lucida Sans打字机"或开源的"Fira Code Retina"一起使用?
以下代码工作正常:
我从各个地方复制了PInvoke代码,特别是the PowerShell console host,Microsoft Docs
请注意,CONSOLE_FONT_INFOEX和SetCurrentConsoleFontEx的相关文档没有讨论这一点,结构将字体定义为大小为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不支持长字体名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!