对于16个字符或更长的字体名,我无法做到这一点,但控制台本身显然没有这个限制。有没有人知道一种编程的方式来设置字体,它可以与内置的“Lucida Sans Typewriter”或开源的“Fira Code Retina”一起工作?
我从不同的地方复制了PInvoke代码,特别是
the PowerShell console host
Microsoft Docs
请注意
CONSOLE_FONT_INFOEX
和
SetCurrentConsoleFontEx
不要谈论这个,结构将字体定义为大小为32的WCHAR字段。。。
还要注意什么不是限制,而是
是
控制台对话框的一个限制是字体必须有真正的字体轮廓,并且必须是真正固定的宽度。使用这个API你可以选择可变宽度的字体,比如“Times New Roman”。。。
但是,在API中,它必须
名称中包含16个字符——这是控制台本身没有的限制,并且
可以
成为API中的一个bug,而不是我下面的代码
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)
Lucida Sans Typewriter
... 并尝试更改字体大小,指定相同的字体名称:
[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
你看到“before”值后面那个奇怪的字符了吗?每当字体长度超过16个字符时就会发生这种情况(由于API或封送处理中的问题,我得到的是垃圾数据)。
实际的控制台字体名称显然没有长度限制,但可能无法使用名称为16个字符或更长的字体?
Fira Code Retina
,一种名称中正好有16个字符的字体--我的代码比上面的要多一点
a gist here