Решено: Как изменить цвет шрифта в консоли.

Приветствую всех, сегодня в группе увидел сообщение от пользователя, который просил ему помочь. Смысл сводился к тому что у него программа, которую он написал, вы водит информацию в консоль. Но его не устраивали стандартные цвета консоли. Я лично еще из msdn знаю что там может отображаться только 16 цветов. Однако так как все варианты цветов можно посмотреть в самой студии:

  public enum ConsoleColor
    {
        //
        // Сводка:
        //     Черный цвет.
        Black = 0,
        //
        // Сводка:
        //     Темно-синий цвет.
        DarkBlue = 1,
        //
        // Сводка:
        //     Темно-зеленый цвет.
        DarkGreen = 2,
        //
        // Сводка:
        //     Темно-голубой цвет (темный сине-зеленый).
        DarkCyan = 3,
        //
        // Сводка:
        //     Темно-красный цвет.
        DarkRed = 4,
        //
        // Сводка:
        //     Темно-пурпурный цвет (темный фиолетово-красный).
        DarkMagenta = 5,
        //
        // Сводка:
        //     Темно-желтый цвет (коричнево-желтый).
        DarkYellow = 6,
        //
        // Сводка:
        //     Серый цвет.
        Gray = 7,
        //
        // Сводка:
        //     Темно-серый цвет.
        DarkGray = 8,
        //
        // Сводка:
        //     Синий цвет.
        Blue = 9,
        //
        // Сводка:
        //     Зеленый цвет.
        Green = 10,
        //
        // Сводка:
        //     Голубой цвет (сине-зеленый).
        Cyan = 11,
        //
        // Сводка:
        //     Красный цвет.
        Red = 12,
        //
        // Сводка:
        //     Пурпурный цвет (фиолетово-красный).
        Magenta = 13,
        //
        // Сводка:
        //     Желтый цвет.
        Yellow = 14,
        //
        // Сводка:
        //     Белый цвет.
        White = 15
    }

У меня было свободное время и интерес понять почему именно 16 цветов и можно ли как то помочь человеку. Все мои попытки понять такое ограничение сводились к тому что консоль не поддерживает отображение других цветов еще с DOS. Однако потратив некоторое время я наткнулся на один пример, который меня потряс решением этой проблемы. В нем действительно рассматривалась возможность изменения цветовой палитры из класса Color для консоли. По факту там можно было выбрать или задать любой цвет. Код не мой, но посидев разобрав его, пришел к выводу что применяется изменения цвета фона и шрифта, тем самым вывод в консоль шрифта в RGB цветах. Так делали еще при работе C++ и видимо код переделали и под C#. Не будем терять время и перейдем к рассмотрению самого кода программы по изменению цвета шрифта в консоли.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace SetScreenColorsApp
{
    class Program
    {
        class SetScreenColorsApp
        {
            [StructLayout(LayoutKind.Sequential)]
            internal struct COORD
            {
                internal short X;
                internal short Y;
            }

            [StructLayout(LayoutKind.Sequential)]
            internal struct SMALL_RECT
            {
                internal short Left;
                internal short Top;
                internal short Right;
                internal short Bottom;
            }

            [StructLayout(LayoutKind.Sequential)]
            internal struct COLORREF
            {
                internal uint ColorDWORD;

                internal COLORREF(Color color)
                {
                    ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16);
                }

                internal COLORREF(uint r, uint g, uint b)
                {
                    ColorDWORD = r + (g << 8) + (b << 16);
                }

                internal Color GetColor()
                {
                    return Color.FromArgb((int)(0x000000FFU & ColorDWORD),
                                          (int)(0x0000FF00U & ColorDWORD) >> 8, (int)(0x00FF0000U & ColorDWORD) >> 16);
                }

                internal void SetColor(Color color)
                {
                    ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16);
                }
            }


            [StructLayout(LayoutKind.Sequential)]
            internal struct CONSOLE_SCREEN_BUFFER_INFO_EX
            {
                internal int cbSize;
                internal COORD dwSize;
                internal COORD dwCursorPosition;
                internal ushort wAttributes;
                internal SMALL_RECT srWindow;
                internal COORD dwMaximumWindowSize;
                internal ushort wPopupAttributes;
                internal bool bFullscreenSupported;
                internal COLORREF black;
                internal COLORREF darkBlue;
                internal COLORREF darkGreen;
                internal COLORREF darkCyan;
                internal COLORREF darkRed;
                internal COLORREF darkMagenta;
                internal COLORREF darkYellow;
                internal COLORREF gray;
                internal COLORREF darkGray;
                internal COLORREF blue;
                internal COLORREF green;
                internal COLORREF cyan;
                internal COLORREF red;
                internal COLORREF magenta;
                internal COLORREF yellow;
                internal COLORREF white;
            }


            const int STD_OUTPUT_HANDLE = -11;                                        // per WinBase.h
            internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);    // per WinBase.h

            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern IntPtr GetStdHandle(int nStdHandle); // тип консольного потока

            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern bool GetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX csbe);

            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern bool SetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX csbe);

            // Set a specific console color to an RGB color
            // The default console colors used are gray (foreground) and black (background)
            public static int SetColor(ConsoleColor consoleColor, Color targetColor)
            {
                return SetColor(consoleColor, targetColor.R, targetColor.G, targetColor.B);
            }

            public static int SetColor(ConsoleColor color, uint r, uint g, uint b)
            {
                CONSOLE_SCREEN_BUFFER_INFO_EX csbe = new CONSOLE_SCREEN_BUFFER_INFO_EX();
                csbe.cbSize = (int)Marshal.SizeOf(csbe);                    // 96 = 0x60
                IntPtr hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);    // 7
                if (hConsoleOutput == INVALID_HANDLE_VALUE)
                {
                    return Marshal.GetLastWin32Error();
                }
                bool brc = GetConsoleScreenBufferInfoEx(hConsoleOutput, ref csbe);
                if (!brc)
                {
                    return Marshal.GetLastWin32Error();
                }

                // Цвета (флаги)
                switch (color)
                {
                    case ConsoleColor.Black:
                        csbe.black = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.DarkBlue:
                        csbe.darkBlue = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.DarkGreen:
                        csbe.darkGreen = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.DarkCyan:
                        csbe.darkCyan = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.DarkRed:
                        csbe.darkRed = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.DarkMagenta:
                        csbe.darkMagenta = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.DarkYellow:
                        csbe.darkYellow = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.Gray:
                        csbe.gray = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.DarkGray:
                        csbe.darkGray = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.Blue:
                        csbe.blue = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.Green:
                        csbe.green = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.Cyan:
                        csbe.cyan = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.Red:
                        csbe.red = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.Magenta:
                        csbe.magenta = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.Yellow:
                        csbe.yellow = new COLORREF(r, g, b);
                        break;
                    case ConsoleColor.White:
                        csbe.white = new COLORREF(r, g, b);
                        break;
                }
                ++csbe.srWindow.Bottom;
                ++csbe.srWindow.Right;
                brc = SetConsoleScreenBufferInfoEx(hConsoleOutput, ref csbe);
                if (!brc)
                {
                    return Marshal.GetLastWin32Error();
                }
                return 0;
            }


            public static int SetScreenColors(Color foregroundColor, Color backgroundColor)
            {
                int irc;
                irc = SetColor(ConsoleColor.Gray, foregroundColor);
                if (irc != 0) return irc;
                irc = SetColor(ConsoleColor.Black, backgroundColor);
                if (irc != 0) return irc;

                return 0;
            }
        }
        static void Main(string[] args)
        {




            Color screenTextColor = Color.Orchid;
            Color screenBackgroundColor = Color.Black;
            int irc = SetScreenColorsApp.SetScreenColors(screenTextColor, screenBackgroundColor);
         
            Console.WriteLine("Nookery.ru");
    
    
        
            Console.ReadKey();
        }
    }
}

 

Обновлено: 28.03.2018 — 17:58

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.