能否获取/设置控制台字体大小?

21

我看到过有关更改控制台真实类型字体和控制台颜色(RGB)的帖子,但没有关于设置或获取控制台字体大小的内容。

我想要更改字体大小的原因是因为网格被打印到控制台上,而且该网格有许多列,所以使用较小的字体更适合。我想知道是否可以在运行时更改字体大小,而不是允许默认或配置的字体优先/覆盖继承。


1
这个应该留给用户选择,对吧?当然,用户可以通过应用程序上下文菜单随时更改它。 - Noldorin
1
为什么你明确要求一篇文章?虽然我在这个问题上真的找不到任何东西。 - Teo Klestrup Röijezon
1
我没有明确要求一篇文章,问题是:在 c# .net 中是否“可以更改控制台字体大小?” - Chris
1
@Chris,你在最初的问题中问道“有人看到这方面的文章吗?”。在我看来,这是明确要求一篇文章。不过,现在重新措辞后就没问题了。 - Teo Klestrup Röijezon
你应该使用控制台的宽度来决定如何格式化你的表格,而不是尝试调整字体大小或窗口大小。这只是我的个人意见。 - Paul Wheeler
也许这篇文章可以帮助你。 - Yitzhak Weinberg
4个回答

11

也许这篇文章可以帮助你。

ConsoleHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;

namespace ConsoleExtender {
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct ConsoleFont {
        public uint Index;
        public short SizeX, SizeY;
    }

    public static class ConsoleHelper {
        [DllImport("kernel32")]
        public static extern bool SetConsoleIcon(IntPtr hIcon);

        public static bool SetConsoleIcon(Icon icon) {
            return SetConsoleIcon(icon.Handle);
        }

        [DllImport("kernel32")]
        private extern static bool SetConsoleFont(IntPtr hOutput, uint index);

        private enum StdHandle {
            OutputHandle = -11
        }

        [DllImport("kernel32")]
        private static extern IntPtr GetStdHandle(StdHandle index);

        public static bool SetConsoleFont(uint index) {
            return SetConsoleFont(GetStdHandle(StdHandle.OutputHandle), index);
        }

        [DllImport("kernel32")]
        private static extern bool GetConsoleFontInfo(IntPtr hOutput, [MarshalAs(UnmanagedType.Bool)]bool bMaximize, 
            uint count, [MarshalAs(UnmanagedType.LPArray), Out] ConsoleFont[] fonts);

        [DllImport("kernel32")]
        private static extern uint GetNumberOfConsoleFonts();

        public static uint ConsoleFontsCount {
            get {
                return GetNumberOfConsoleFonts();
            }
        }

        public static ConsoleFont[] ConsoleFonts {
            get {
                ConsoleFont[] fonts = new ConsoleFont[GetNumberOfConsoleFonts()];
                if(fonts.Length > 0)
                    GetConsoleFontInfo(GetStdHandle(StdHandle.OutputHandle), false, (uint)fonts.Length, fonts);
                return fonts;
            }
        }

    }
}

以下是如何使用它来列出控制台的TrueType字体:

static void Main(string[] args) {
   var fonts = ConsoleHelper.ConsoleFonts;
   for(int f = 0; f < fonts.Length; f++)
      Console.WriteLine("{0}: X={1}, Y={2}",
         fonts[f].Index, fonts[f].SizeX, fonts[f].SizeY);

   ConsoleHelper.SetConsoleFont(5);
   ConsoleHelper.SetConsoleIcon(SystemIcons.Information);
}

关键函数:SetConsoleFontGetConsoleFontInfoGetNumberOfConsoleFonts。它们没有文档支持,因此使用时需谨慎。


3
未记录的特性很有趣!但说真的,答案很好。 - Paul Wheeler
29
可以尝试对其进行概括解释,而非只指向另一页。这样更容易让人理解它的作用。 - the Tin Man
9
虽然这个回答理论上能够回答问题,但更好的做法是在这里包含答案的关键部分,并提供链接作为参考。 - Kev
4
欢迎您提供潜在解决方案的链接,但请在链接周围添加上下文,以便其他用户了解它是什么以及为什么存在。请引用重要链接中最相关的部分,以防目标网站无法访问或永久离线。请注意,仅仅提供外部链接可能是为什么和如何删除某些答案?的一个可能原因。 - elixenide
2
对我来说是个坏链接,而且不支持Mac/Linux :I - Max
显示剩余2条评论

9

这个线程中,我发现了一个更加优雅的解决方案,现在已经完美地运行。

ConsoleHelper.cs:

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

这样您就可以只需执行以下操作:

ConsoleHelper.SetCurrentFont("Consolas", 10);

1
这是一个非常出色的解决方案,按预期运行! - Kata

1
在运行应用程序(Ctrl + F5)后,右键单击控制台的标题(应该会显示类似于C:Windows\system32\cmd.exe的内容),然后选择属性。选择“字体”选项卡,您将看到调整字体大小的选项。

OP正在寻找一种编程方式来设置字体大小,因此您的答案无法满足需求。 - Guy Levy

0

控制台不支持在运行时更改字体大小。可以在MSDN上找到修改当前控制台窗口设置的可用方法列表。 我的理解是这样的:

  1. 控制台不是富文本界面,意味着它无法显示多种字体或字体大小。
  2. 正如Noldorin所说,这应该由用户决定,例如视力问题的人可能会选择大字体大小。

16
真正的程序员会打破常规思维。 - Chris
如果用户更改字体大小,即使是因为他们的显示器非常大,因为他们的眼睛比普通人的眼睛大两倍,那么我的计算也会受到影响。当设置控制台全屏(即在Win7上最大化并具有自定义缓冲区大小)时,如果用户篡改了默认配置,则不会相同。 - Chris
@Chris,看起来Console实际上包含了设置最大窗口大小的选项。 - Teo Klestrup Röijezon
啊,我之前有些问题,但现在看起来它能够正常工作并且字体大小也不会影响显示效果: Console.SetWindowSize(Console.LargestWindowWidth - 3, Console.LargestWindowHeight - 1); int hWnd = Process.GetCurrentProcess().MainWindowHandle.ToInt32(); Console.SetBufferSize(Console.LargestWindowWidth - 3, Console.LargestWindowHeight - 1); Move(); ShowWindow(hWnd, SW_MAXIMIZE); - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接