C#如何在运行时修改控制台字体和字体大小?

3
我正在制作一个类似地牢游戏,为了确保我的游戏正确显示,我希望在运行时更改控制台字体和字体大小。我对编程和c#非常陌生,因此我希望以一种我或其他人可以轻松实现的方式进行解释。这个资源列出了CONSOLE_FONT_INFOEX结构的完整语法。
typedef struct _CONSOLE_FONT_INFOEX {
  ULONG cbSize;
  DWORD nFont;
  COORD dwFontSize;
  UINT  FontFamily;
  UINT  FontWeight;
  WCHAR FaceName[LF_FACESIZE];
} CONSOLE_FONT_INFOEX, *PCONSOLE_FONT_INFOEX;

我想在运行时将控制台字体更改为NSimSum,并将字体大小更改为32。

编辑1:请说明如何使用SetCurrentConsoleFontEx function函数,来自this帖子。我不明白函数需要处于什么上下文中。我尝试了Console.SetCurrentConsoleFontEx,但vs没有给我任何选项。

编辑2:this论坛帖子似乎详细介绍了一种简单的更改字体大小的方法,但它是否特定于c ++?

void setFontSize(int FontSize)
{
    CONSOLE_FONT_INFOEX info = {0};
    info.cbSize       = sizeof(info);
    info.dwFontSize.Y = FontSize; // leave X as zero
    info.FontWeight   = FW_NORMAL;
    wcscpy(info.FaceName, L"Lucida Console");
    SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), NULL, &info);
}

可能是在.NET中更改控制台窗口的字体的重复问题。 - The Bearded Llama
在.NET中更改控制台窗口的字体中,并没有解释如何实现代码,这就是我在字体类型上遇到困难的地方。帖子中没有回答字体大小的问题。 - Trr1ppy
我认为我的帖子应该被删除,因为它不够清晰,也缺乏新的信息。相关的答案是从 MSDN 复制粘贴的,并解释了“你尝试过这个吗?”另一个答案只适用于 WinForms。我计划发布一个新帖子,感谢那些试图帮助我理解模糊帖子的人。 - Trr1ppy
2个回答

3

另一种选择是创建一个WinForms应用程序,使用RichTextBox。我想这取决于您有多少需要依赖任何内置控制台功能。

请注意使用了一些自定义函数来使编写彩色文本更加容易。

您可以尝试类似以下的内容:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    RichTextBox console = new RichTextBox();

    private void Form1_Load(object sender, EventArgs e)
    {
        console.Size = this.ClientSize;
        console.Top = 0;
        console.Left = 0;
        console.BackColor = Color.Black;
        console.ForeColor = Color.White;
        console.WordWrap = false;
        console.Font = new Font("Consolas", 12);            

        this.Controls.Add(console);
        this.Resize += Form1_Resize;

        DrawDiagram();
    }

    private void DrawDiagram()
    {
        WriteLine("The djinni speaks. \"I am in your debt. I will grant one wish!\"--More--\n");
        Dot(7);
        Diamond(2);
        WriteLine("....╔═══════╗..╔═╗");
        Dot(8);
        Diamond(2);
        WriteLine("...║..|....║..║.╠══════╦══════╗");
        Dot(9);
        Diamond(2);
        Write("..║.|.....║..║.║      ║.");
        Write('&', Color.DarkRed);
        Dot(4);
        WriteLine("║");
    }

    private void Dot(int qty)
    {
        Write('.', qty);
    }

    private void WriteLine(string text)
    {
        Write($"{text}\n");
    }

    private void Diamond(int qty)
    {
        Write('♦', qty, Color.Blue);
    }

    private void Write(char character, Color color)
    {
        Write(character, 1, color);
    }

    private void Write(char character, int qty)
    {
        Write(character, qty, Color.White);
    }

    private void Write(char character, int qty, Color color)
    {
        Write(new string(character, qty), color);
    }

    private void Write(string text)
    {
        Write(text, Color.White);
    }

    private void Write(string text, Color color)
    {
        var originalColor = console.SelectionColor;
        console.SelectionColor = color;
        console.AppendText(text);
        console.SelectionColor = originalColor;
    }

    private void Form1_Resize(object sender, EventArgs e)
    {
        console.Size = this.ClientSize;
    }
}

输出

不解释


有没有更简单的方法来做这件事?有没有几行代码可以只改变字体和字号? - Trr1ppy
在上面的代码中,是这一行:console.Font = new Font("Consolas", 20);。但我不知道在常规控制台中有什么作用。 - Rufus L
我之前不知道什么是winform,直到我谷歌了一下。我决定在控制台中制作它,但我猜这段代码在控制台中无法运行? - Trr1ppy
如果我无法弄清如何从控制台设置字体/大小,我将切换到WinForms,感谢您的答案。 - Trr1ppy
谢谢Rufus L,这真是非常有创意。 - Udesh
这是一个很棒的想法! - Xonatron

0

你试过这个吗

using System;
using System.Runtime.InteropServices;

public class Example
{
   [DllImport("kernel32.dll", SetLastError = true)]
   static extern IntPtr GetStdHandle(int nStdHandle);

   [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
   static extern bool GetCurrentConsoleFontEx(
          IntPtr consoleOutput, 
          bool maximumWindow,
          ref CONSOLE_FONT_INFO_EX lpConsoleCurrentFontEx);

   [DllImport("kernel32.dll", SetLastError = true)]
   static extern bool SetCurrentConsoleFontEx(
          IntPtr consoleOutput, 
          bool maximumWindow,
          CONSOLE_FONT_INFO_EX consoleCurrentFontEx);

   private const int STD_OUTPUT_HANDLE = -11;
   private const int TMPF_TRUETYPE = 4;
   private const int LF_FACESIZE = 32;
   private static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);

   public static unsafe void Main()
   {
      string fontName = "Lucida Console";
      IntPtr hnd = GetStdHandle(STD_OUTPUT_HANDLE);
      if (hnd != INVALID_HANDLE_VALUE) {
         CONSOLE_FONT_INFO_EX info = new CONSOLE_FONT_INFO_EX();
         info.cbSize = (uint) Marshal.SizeOf(info);
         bool tt = false;
         // First determine whether there's already a TrueType font.
         if (GetCurrentConsoleFontEx(hnd, false, ref info)) {
            tt = (info.FontFamily & TMPF_TRUETYPE) == TMPF_TRUETYPE;
            if (tt) {
               Console.WriteLine("The console already is using a TrueType font.");
               return;
            }
            // Set console font to Lucida Console.
            CONSOLE_FONT_INFO_EX newInfo = new CONSOLE_FONT_INFO_EX();
            newInfo.cbSize = (uint) Marshal.SizeOf(newInfo);          
            newInfo.FontFamily = TMPF_TRUETYPE;
            IntPtr ptr = new IntPtr(newInfo.FaceName);
            Marshal.Copy(fontName.ToCharArray(), 0, ptr, fontName.Length);
            // Get some settings from current font.
            newInfo.dwFontSize = new COORD(info.dwFontSize.X, info.dwFontSize.Y);
            newInfo.FontWeight = info.FontWeight;
            SetCurrentConsoleFontEx(hnd, false, newInfo);
         }
      }    
    }

   [StructLayout(LayoutKind.Sequential)]
   internal struct COORD
   {
      internal short X;
      internal short Y;

      internal COORD(short x, short y)
      {
         X = x;
         Y = y;
      }
   }

   [StructLayout(LayoutKind.Sequential)]
   internal unsafe struct CONSOLE_FONT_INFO_EX 
   {
      internal uint cbSize;
      internal uint nFont;
      internal COORD dwFontSize;
      internal int FontFamily;
      internal int FontWeight;
      internal fixed char FaceName[LF_FACESIZE];
   } 
}

请参考https://msdn.microsoft.com/zh-cn/library/system.console(v=vs.110).aspx以获取更多详细信息


1
在所有的代码中,有几行可以用来仅更改字体和字号吗?很抱歉,我不理解大部分代码是如何运作的。 - Trr1ppy
你需要从Main方法中过滤代码,其余部分是完全必需的,请尝试运行并调试它,这将有助于你理解它的工作原理,而不仅仅是运行它。 - Ipsit Gaur
我不知道如何将这个实现到我的代码中,我觉得我在试图改变字体大小时有些力不从心。有点震惊的是没有 Console.SetCurrentConsoleFontSize(32) 这样的方法,但我猜如果那么容易我就不会卡住了。 - Trr1ppy
1
它在@SetCurrentConsoleFontEx@行上使用受保护的内存,导致了一个异常。 - Zéiksz
1
在构建中必须启用“不安全”代码(这很重要,应该在答案中提到)。在Visual Studio中,可以在项目属性构建选项卡中完成此操作(在解决方案资源管理器中右键单击项目>属性)。您可以在Main方法中设置它(像往常一样),其余的是Interop相关内容,您只需要将其复制到您的项目中即可。 - Adam Plocher
我总是收到“控制台已经在使用TrueType字体”的错误信息。 - miran80

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