如何为双向通信聊天系统添加文本对齐与时间戳功能
实现聊天消息左右对齐与时间戳功能的解决方案
我帮你调整了代码,实现了接收消息左对齐、发送消息右对齐以及添加时间戳的功能,核心是用RichTextBox替代原来的TextBox(因为TextBox无法实现局部文本对齐),同时在收发消息时嵌入时间戳,并且处理了跨线程UI更新的问题:
修改后的服务器代码
namespace Full_Chatt_Server { public partial class Form1 : Form { TcpListener listener; TcpClient klient; int port; public Form1() { InitializeComponent(); // 确保tbxMessage是RichTextBox控件 tbxMessage.SelectionAlignment = HorizontalAlignment.Left; } private string GetTimestamp() { return $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}]"; } private void btnStartServer_Click(object sender, EventArgs e) { btnTaEmot.Enabled = false; if (!int.TryParse(tbxPort.Text, out port)) { MessageBox.Show("请输入有效的端口号", Text); return; } try { listener = new TcpListener(IPAddress.Any, port); listener.Start(); } catch (Exception error) { MessageBox.Show(error.Message, Text); return; } StartAccepting(); } public async void StartAccepting() { try { klient = await listener.AcceptTcpClientAsync(); } catch (Exception error) { MessageBox.Show(error.Message, Text); return; } StartReading(klient); } public async void StartReading(TcpClient k) { byte[] buffer = new byte[1024]; int n = 0; try { n = await k.GetStream().ReadAsync(buffer, 0, 1024); } catch (Exception error) { MessageBox.Show(error.Message, Text); return; } if (n > 0) { string receivedMsg = Encoding.Unicode.GetString(buffer, 0, n); UpdateChatMessage($"{GetTimestamp()} 对方: {receivedMsg}", HorizontalAlignment.Left); } StartReading(k); } private void btnSend_Click(object sender, EventArgs e) { string chatt = tbxChatt.Text.Trim(); if (string.IsNullOrEmpty(chatt)) return; StartSending(chatt); tbxChatt.Clear(); UpdateChatMessage($"{GetTimestamp()} 我: {chatt}", HorizontalAlignment.Right); } public async void StartSending(string message) { if (klient?.Connected ?? false) { byte[] OutStream = Encoding.Unicode.GetBytes(message); try { await klient.GetStream().WriteAsync(OutStream, 0, OutStream.Length); } catch (Exception error) { MessageBox.Show(error.Message, Text); return; } } } // 安全更新聊天消息(处理跨线程UI访问) private void UpdateChatMessage(string message, HorizontalAlignment alignment) { if (tbxMessage.InvokeRequired) { tbxMessage.Invoke(new Action<string, HorizontalAlignment>(UpdateChatMessage), message, alignment); return; } tbxMessage.SelectionStart = tbxMessage.TextLength; tbxMessage.SelectionLength = 0; tbxMessage.SelectionAlignment = alignment; tbxMessage.AppendText($"{message}\r\n"); tbxMessage.ScrollToCaret(); // 自动滚动到最新消息 } } }
修改后的客户端代码
namespace Full_Chatt_Klient { public partial class Form1 : Form { TcpClient klient = new TcpClient(); int port; public Form1() { InitializeComponent(); // 确保tbxMessage是RichTextBox控件 tbxMessage.SelectionAlignment = HorizontalAlignment.Left; } private string GetTimestamp() { return $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}]"; } private void btnConnect_Click(object sender, EventArgs e) { if (!klient.Connected) { Connect(); } } public async void Connect() { if (!IPAddress.TryParse(tbxIP.Text, out IPAddress address)) { MessageBox.Show("请输入有效的IP地址", Text); return; } if (!int.TryParse(tbxPort.Text, out port)) { MessageBox.Show("请输入有效的端口号", Text); return; } try { await klient.ConnectAsync(address, port); StartReading(klient); } catch (Exception error) { MessageBox.Show(error.Message, Text); return; } btnSkicka.Enabled = true; btnAnslut.Enabled = false; } private void btnSend_Click(object sender, EventArgs e) { string chatt = tbxChatt.Text.Trim(); if (string.IsNullOrEmpty(chatt)) return; StartSending(chatt); tbxChatt.Clear(); UpdateChatMessage($"{GetTimestamp()} 我: {chatt}", HorizontalAlignment.Right); } public async void StartSending(string message) { if (klient?.Connected ?? false) { byte[] OutStream = Encoding.Unicode.GetBytes(message); try { await klient.GetStream().WriteAsync(OutStream, 0, OutStream.Length); } catch (Exception error) { MessageBox.Show(error.Message, Text); return; } } } public async void StartReading(TcpClient k) { byte[] buffer = new byte[1024]; int n = 0; try { n = await k.GetStream().ReadAsync(buffer, 0, 1024); } catch (Exception error) { MessageBox.Show(error.Message, Text); return; } if (n > 0) { string receivedMsg = Encoding.Unicode.GetString(buffer, 0, n); UpdateChatMessage($"{GetTimestamp()} 对方: {receivedMsg}", HorizontalAlignment.Left); } StartReading(k); } // 安全更新聊天消息(处理跨线程UI访问) private void UpdateChatMessage(string message, HorizontalAlignment alignment) { if (tbxMessage.InvokeRequired) { tbxMessage.Invoke(new Action<string, HorizontalAlignment>(UpdateChatMessage), message, alignment); return; } tbxMessage.SelectionStart = tbxMessage.TextLength; tbxMessage.SelectionLength = 0; tbxMessage.SelectionAlignment = alignment; tbxMessage.AppendText($"{message}\r\n"); tbxMessage.ScrollToCaret(); // 自动滚动到最新消息 } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { if (klient != null) { klient.Close(); } } } }
关键修改说明
- 替换控件类型:把原来的
TextBox(tbxMessage)换成RichTextBox,因为只有RichTextBox支持对局部文本设置对齐方式。 - 时间戳生成:新增
GetTimestamp()方法,生成格式为[yyyy-MM-dd HH:mm:ss]的时间字符串,方便查看消息发送/接收时间。 - 跨线程UI更新:添加
UpdateChatMessage()方法,用Invoke处理异步线程中更新UI的问题,避免WinForms跨线程访问异常。 - 消息对齐控制:发送消息时设置
HorizontalAlignment.Right(右对齐),接收消息时设置HorizontalAlignment.Left(左对齐),模拟真实聊天软件布局。 - 输入校验:新增端口号、IP地址的合法性校验,避免无效输入导致的异常。
- 自动滚动:添加
ScrollToCaret()方法,确保最新消息始终可见。
内容的提问来源于stack exchange,提问作者EricC
相关产品推荐
相关产品推荐

