Присвоение цвета посреди вывода в консоль

148
24 января 2019, 12:10

У нас есть код:

Console.Write ("Что то");

Мне нужно, что бы "Что" было зеленым, а "то" красным. Да, можно разделить.

Console.ForegroundColoe = ConsoleColor.Green;
Console.Write ("Что");
Console.ForegroundColor = ConsoleColor.Red;
Console.Write ("то");

Но хотелось-бы менять цвет консоли "посреди" вывода в консоль. Для чего это нужно? В зависимости от условия нам нужно вывести некоторые значения в консоль повторно. Например (крас)1(зел)23, (зел)1(крас)2(зел)3, (зел)12(крас)3. Есть бы они нужны были одного цвета, то все просто:

Console.Write(new string ('123', колвораз));

А так... Да, можно создать несколько если, и... (Пример)

int writecount = 0;
if(чтото = чтото)
{ do
  {
   Console.ForegroundColor = ConsoleColor.Red
   Console.Write("1");
   Console.Fore...
   ++writecount;
  }while(writecount != чтото);

Но у меня не самое простое приложение, и большое повторение do (а у меня числа там большие) просто вешает консоль намертво. Как можно вклинится в вывод и прописать цвет? Или же подскажите другое решение данной проблемы, желательно как можно менее ресурсно затратное.

Answer 1

Как вариант:

using System;
namespace ColourOutput
{
    public static class ColourWriter
    {
        public static ConsoleColor defaultColor { get; set; } = ConsoleColor.White;
        public static void Write(string text)
        {
            foreach (var word in text.Split(',', ' '))
            {
                if (word[0] == '{')
                {
                    ColorHelper(word.Substring(3, word.Length - 3), word[1]);
                }
                else
                {
                    Console.Write(word + " ");
                }
            }
        }
        private static void ColorHelper(string word, char color)
        {
            switch (color)
            {
                case 'G':
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.Write(word + " ");
                    Console.ForegroundColor = defaultColor;
                    break;
                case 'R':
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.Write(word + " ");
                    Console.ForegroundColor = defaultColor;
                    break;
                case 'B':
                    Console.ForegroundColor = ConsoleColor.Blue;
                    Console.Write(word + " ");
                    Console.ForegroundColor = defaultColor;
                    break;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            ColourWriter.Write("{G}Зеленый,{R}Красный - {B}Это цвета \n (С)");
            Console.ReadKey();
        }
    }
}

До юзабельного вида думаю сами доведете)

Answer 2

Не уверен, что я понял вашу мысль, но в коммент много кода не засунешь, так что отпишу как ответ.

Я сделал небольшой потоконебезопасный писатель цветом в консоль (с буфером)

class ColoredConsoleWriter
{
    private List<WriteItem> _inner = new List<WriteItem>();
    public void Append(string text, ConsoleColor color)
    {
        var last = _inner.LastOrDefault();
        if (last != null && last.Color == color)
        {
            last.Text+=text;
            return;
        }
        _inner.Add(new WriteItem() {Text=text, Color = color});
    }
    public void AppendLine(string text, ConsoleColor color)
    {
        Append(text + Environment.NewLine, color);
    }
    public void Flush()
    {
        var local = _inner;
        foreach (var item in local)
        {
            Console.ForegroundColor = item.Color;
            Console.Write(item.Text);
        }
        _inner = new List<UserQuery.ColoredConsoleWriter.WriteItem>();      
    }
    class WriteItem
    {
        public string Text { get; set; }
        public ConsoleColor Color { get; set;}
    }
}

Залил в него 10000 элементов текста

void Sample()
{
    var writer = new ColoredConsoleWriter();
    var random = new Random();
    var colors = Enum.GetValues(typeof(ConsoleColor)).OfType<ConsoleColor>().ToArray();
    for (var i = 0; i < 10000; i++)
    {
        writer.Append(i.ToString(), colors[random.Next(colors.Length)]);
    }
    writer.Flush();
}

Запустил всё это добро

void Main()
{
    var sw = new Stopwatch();
    sw.Start();
    Sample();   
    sw.Stop();
    Console.ForegroundColor = ConsoleColor.White;
    Console.WriteLine();
    Console.WriteLine($"Elapsed: {sw.Elapsed}");
}

Отработало примерно за секунду

Надеюсь, это чем то поможет вам :)

Answer 3

Можно попробовать управляющие символы. Они поддерживаются в последних версиях Винды Десятки. Но сперва их поддержку нужно включить (пример взял отсюда).

using System;
using System.Runtime.InteropServices;
namespace ConApp1
{
    class Program
    {
        const int STD_OUTPUT_HANDLE = -11;
        const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr GetStdHandle(int nStdHandle);
        [DllImport("kernel32.dll")]
        static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
        [DllImport("kernel32.dll")]
        static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
        static void Main(string[] args)
        {
            var handle = GetStdHandle(STD_OUTPUT_HANDLE);
            uint mode;
            GetConsoleMode(handle, out mode);
            mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
            SetConsoleMode(handle, mode);
            const string UNDERLINE = "\x1B[4m";
            const string RESET = "\x1B[0m";
            const string RED = "\x1b[31m";
            const string GREEN = "\x1b[32m";
            Console.WriteLine("Some " + UNDERLINE + "underlined" + RESET + " text");
            Console.WriteLine(RED + "Привет " + GREEN + "Мир!" + RESET);
        }
    }
}
READ ALSO
Entity Framework 5. Illegal mix of collations for operation &#39;UNION&#39;

Entity Framework 5. Illegal mix of collations for operation 'UNION'

Создал в MySQL тестовую базуОдна таблица:

162
Проблема с Camera.main.ScreenToWorldPoint(touch.position) в Unty

Проблема с Camera.main.ScreenToWorldPoint(touch.position) в Unty

Как сделать в моей 2д игре, так, чтобы игра не отслеживала моё палец (тач), когда я нажимаю на кнопки ходьбыВ моей игре, оружие персонажа следит...

159
Не работает шаблон TreeViewItem

Не работает шаблон TreeViewItem

Я пытаюсь кастомизировать элемент TreeView с помощью шаблоновВ дереве будет 2 уровня узлов (родитель и дочерний)

189
SQLite error (5): database is locked C# Dapper

SQLite error (5): database is locked C# Dapper

Использую в проекте SQLite (устанавливал через NuGet) и DapperВ проекте используется пул потоков для чтения из БД, запись в БД производится из отдельного...

220