gpt4 book ai didi

c# - SetCurrentConsoleFontEx 不适用于长字体名称

转载 作者:可可西里 更新时间:2023-11-01 13:27:30 25 4
gpt4 key购买 nike

对于 16 个字符或更长的字体名称,我无法让它工作,但控制台本身显然没有此限制。有谁知道一种编程方式来设置将与内置“Lucida Sans Typewriter”或开源“Fira Code Retina”一起使用的字体?

以下代码有效:

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

请注意 CONSOLE_FONT_INFOEX 的相关文档和 SetCurrentConsoleFontEx不要谈论这个,结构将字体定义为大小为 32 的 WCHAR 字段...

另请注意,不是限制,而是来自控制台对话框的限制是字体必须具有 True Type 轮廓,并且必须真正固定宽度。使用此 API,您可以选择可变宽度字体,例如“Times New Roman”...

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

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);
}
}
}

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

[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

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

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

不管怎样,我发现了这个问题 Fira Code Retina ,一种名称中正好有 16 个字符的字体——我的代码比上面 a gist here 中的代码多一点如果您想尝试...

最佳答案

我找到了一个 bug在控制台 API 中。自 Windows 10(内部人员)build 18267 起已修复。

在那个版本之前,没有办法绕过它——除了使用名称较短的字体,或者使用实际的窗口属性面板来设置它。

原来的邮政编码现在可以使用了...

关于c# - SetCurrentConsoleFontEx 不适用于长字体名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52356843/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com