You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WinForms:如何在窗体中嵌入可输出的控制台?

WinForms内嵌支持ASCII颜色的控制台实现方案

核心思路

基于RichTextBox构建自定义控件,解析WebSocket传来的ANSI ASCII颜色转义代码,将其转换为富文本格式展示,同时实现文本输入发送功能。

实现步骤

1. 自定义控制台控件

创建继承自RichTextBox的控件,封装颜色解析和文本追加逻辑:

using System;
using System.Text.RegularExpressions;
using System.Windows.Forms;

public class EmbeddedConsole : RichTextBox
{
    private static readonly Regex AnsiColorRegex = new Regex(@"(\x1b\[[0-9;]*m)", RegexOptions.Compiled);

    public EmbeddedConsole()
    {
        ReadOnly = false;
        Multiline = true;
        ScrollBars = RichTextBoxScrollBars.Vertical;
        WordWrap = false;
        Font = new System.Drawing.Font("Consolas", 9);
    }

    public void AppendConsoleText(string text)
    {
        if (InvokeRequired)
        {
            Invoke(new Action<string>(AppendConsoleText), text);
            return;
        }

        var segments = AnsiColorRegex.Split(text);
        foreach (var segment in segments)
        {
            if (string.IsNullOrEmpty(segment)) continue;

            if (segment.StartsWith("\x1b["))
            {
                ApplyAnsiColor(segment);
                continue;
            }

            AppendText(segment);
        }

        SelectionStart = TextLength;
        ScrollToCaret();
    }

    private void ApplyAnsiColor(string ansiCode)
    {
        var codePart = ansiCode.Substring(2, ansiCode.Length - 3);
        var codes = codePart.Split(';');

        foreach (var code in codes)
        {
            switch (code)
            {
                case "0":
                    SelectionColor = System.Drawing.Color.Black;
                    SelectionBackColor = System.Drawing.Color.White;
                    break;
                case "30": SelectionColor = System.Drawing.Color.Black; break;
                case "31": SelectionColor = System.Drawing.Color.Red; break;
                case "32": SelectionColor = System.Drawing.Color.Green; break;
                case "33": SelectionColor = System.Drawing.Color.Yellow; break;
                case "34": SelectionColor = System.Drawing.Color.Blue; break;
                case "35": SelectionColor = System.Drawing.Color.Magenta; break;
                case "36": SelectionColor = System.Drawing.Color.Cyan; break;
                case "37": SelectionColor = System.Drawing.Color.Gray; break;
            }
        }
    }

    public string GetAndClearInput()
    {
        var currentLine = GetLineFromCharIndex(SelectionStart);
        var lineStart = GetFirstCharIndexFromLine(currentLine);
        var inputText = Text.Substring(lineStart);

        Select(lineStart, TextLength - lineStart);
        SelectedText = "";

        return inputText.Trim();
    }
}

2. 集成WebSocket收发逻辑

在窗体中初始化WebSocket,对接自定义控制台控件:

using System.Net.WebSockets;
using System.Text;
using System.Threading;

public partial class MainForm : Form
{
    private ClientWebSocket _webSocket;
    private EmbeddedConsole _consoleBox;

    public MainForm()
    {
        InitializeComponent();

        _consoleBox = new EmbeddedConsole();
        _consoleBox.Dock = DockStyle.Fill;
        Controls.Add(_consoleBox);

        var sendBtn = new Button { Text = "发送", Dock = DockStyle.Bottom };
        sendBtn.Click += SendBtn_Click;
        Controls.Add(sendBtn);

        ConnectWebSocketAsync();
    }

    private async void ConnectWebSocketAsync()
    {
        _webSocket = new ClientWebSocket();
        try
        {
            await _webSocket.ConnectAsync(new Uri("ws://your-websocket-server-url"), CancellationToken.None);
            _consoleBox.AppendConsoleText("已连接到WebSocket服务器\n");

            var buffer = new byte[1024 * 4];
            while (_webSocket.State == WebSocketState.Open)
            {
                var result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
                _consoleBox.AppendConsoleText(message);
            }
        }
        catch (Exception ex)
        {
            _consoleBox.AppendConsoleText($"连接异常:{ex.Message}\n");
        }
    }

    private async void SendBtn_Click(object sender, EventArgs e)
    {
        if (_webSocket?.State != WebSocketState.Open)
        {
            _consoleBox.AppendConsoleText("WebSocket未连接\n");
            return;
        }

        var inputText = _consoleBox.GetAndClearInput();
        if (string.IsNullOrEmpty(inputText)) return;

        var buffer = Encoding.UTF8.GetBytes(inputText + "\n");
        await _webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
    }
}

3. 关键注意事项

  • 线程安全:WebSocket接收在后台线程,必须通过Invoke切换到UI线程操作控件,避免跨线程异常。
  • ANSI扩展支持:示例仅实现基础前景色,可扩展ApplyAnsiColor方法支持背景色、粗体、下划线等更多ANSI样式。
  • 性能优化:若消息量较大,可批量缓存文本后再一次性追加,减少UI更新频率避免卡顿。

内容的提问来源于stack exchange,提问作者user19969621

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 23:26:10