Я не могу заставить это работать для имен шрифтов, которые являются 16 символами или больше, но у самой консоли, очевидно, нет этого ограничения. Кто-нибудь знает программный способ установки шрифта, который будет работать со встроенной «Lucida Sans Typewriter» или с открытым исходным кодом «Fira Code Retina»?
Этот следующий код работает:
Я скопировал код PInvoke из разных мест, в частности хост консоли PowerShell и Microsoft Docs
Обратите внимание, что соответствующие документы для CONSOLE_FONT_INFOEX и SetCurrentConsoleFontEx не говорят об этом, и структура определяет грань шрифта как поле WCHAR размером 32 ...
Также обратите внимание на то, что не является ограничением, но является ограничением из диалогового окна консоли, заключается в том, что шрифт должен иметь контуры True Type и должен иметь действительно фиксированную ширину. Используя этот API, вы можете выбирать шрифты переменной ширины, такие как «Times New Roman» ...
Однако в API оно должно содержать меньше 16 символов в имени - это ограничение, которое отсутствует в самой консоли, и может быть ошибка в API, а не мой код ниже ? * 1025 *
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 символов в имени - и у меня немного больше кода, чем выше в Суть здесь , если вы хотите экспериментировать ...