kalek
kalek

Reputation: 51

How can I print text in two different colours (console) on the same line?

I am trying to write text in the same line with the colour changing mid way through the line. At the moment I have split it into two separate parts, changing the colour each time, just using Console.Write instead of WriteLine.

This is fine for procedural operations, but when I run async tasks, I am getting many synchronisation issues.

Is it possible change the text colour mid WriteLine without using external libraries?

Upvotes: 0

Views: 1144

Answers (1)

Idle_Mind
Idle_Mind

Reputation: 39152

Try this silly example out using a ConcurrentQueue:

public class Message
{
    public List<MessagePart> parts = new List<MessagePart>();

    public void Render()
    {
        parts.ForEach(p => p.Render());
    }

    public class MessagePart
    {

        public string text;
        public ConsoleColor color;

        public MessagePart(string text, ConsoleColor color)
        {
            this.text = text;
            this.color = color;
        }

        public void Render()
        {
            Console.ForegroundColor = color;
            Console.Write(text);
        }

    }

}

class Program
{

    static bool pause = false;
    static bool quit = false;
    static ConcurrentQueue<Message> messages = new ConcurrentQueue<Message>();

    static void Main(string[] args)
    {            
        Console.WriteLine("Press Space to Pause/UnPause.");
        Console.WriteLine("Press Enter to Quit when you are done.");
        Console.WriteLine("Press Enter to Start...");
        Console.ReadLine();

        Task.Run(() => RenderLoop());
        Task.Run(() => YellowAndBlue());
        Task.Run(() => RedAndBlue());

        while (!quit)
        {
            while (!Console.KeyAvailable)
            {
                System.Threading.Thread.Sleep(50);
            }
            switch(Console.ReadKey(false).Key)
            {
                case ConsoleKey.Enter:
                    quit = true;
                    break;
                case ConsoleKey.Spacebar:
                    pause = !pause;
                    break;
            }
        }            
    }

    static void YellowAndBlue()
    {
        Message msg = new Message();
        msg.parts.Add(new Message.MessagePart("Yellow", ConsoleColor.Yellow));
        msg.parts.Add(new Message.MessagePart(" and ", ConsoleColor.White));
        msg.parts.Add(new Message.MessagePart("Blue", ConsoleColor.Blue));
        msg.parts.Add(new Message.MessagePart(" make ", ConsoleColor.White));
        msg.parts.Add(new Message.MessagePart("Green\r\n", ConsoleColor.Green));

        while (!quit)
        {
            System.Threading.Thread.Sleep(25);
            messages.Enqueue(msg);
            while (pause)
            {
                System.Threading.Thread.Sleep(50);
            }
        }
    }

    static void RedAndBlue()
    {
        Message msg = new Message();
        msg.parts.Add(new Message.MessagePart("Red", ConsoleColor.Red));
        msg.parts.Add(new Message.MessagePart(" and ", ConsoleColor.White));
        msg.parts.Add(new Message.MessagePart("Blue", ConsoleColor.Blue));
        msg.parts.Add(new Message.MessagePart(" make ", ConsoleColor.White));
        msg.parts.Add(new Message.MessagePart("Magenta\r\n", ConsoleColor.Magenta));

        while (!quit)
        {
            System.Threading.Thread.Sleep(25);
            messages.Enqueue(msg);
            while (pause)
            {
                System.Threading.Thread.Sleep(50);
            }
        }
    }

    static void RenderLoop()
    {
        Message message;
        while (!quit)
        {                
            while (!messages.IsEmpty && !quit)
            {
                if (messages.TryDequeue(out message))
                {
                    message.Render();                        
                }
                while (pause)
                {
                    System.Threading.Thread.Sleep(50);
                }
            }
            if (!quit)
            {
                messages.Enqueue(new Message() { parts = { new Message.MessagePart("Queue Emptied!\r\n", ConsoleColor.White) } });
                System.Threading.Thread.Sleep(100);
            }                
        }
    }

}

Output (paused):

enter image description here

Upvotes: 1

Related Questions