Приветствую всех, сегодня в группе увидел сообщение от пользователя, который просил ему помочь. Смысл сводился к тому что у него программа, которую он написал, вы водит информацию в консоль. Но его не устраивали стандартные цвета консоли. Я лично еще из msdn знаю что там может отображаться только 16 цветов. Однако так как все варианты цветов можно посмотреть в самой студии:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
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#. Не будем терять время и перейдем к рассмотрению самого кода программы по изменению цвета шрифта в консоли.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
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(); } } } |