562 lines
20 KiB
C#
562 lines
20 KiB
C#
using System;
|
||||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Drawing;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Windows.Forms;
|
|||
|
|
|
|||
|
|
namespace StandardScene.Charge
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 通讯监控窗体
|
|||
|
|
/// </summary>
|
|||
|
|
public partial class CommunicationMonitorForm : Form
|
|||
|
|
{
|
|||
|
|
private readonly CommunicationMessageService messageService;
|
|||
|
|
private bool isFormLoaded = false;
|
|||
|
|
private bool isFormMessageStop = false;
|
|||
|
|
private const int MaxDisplayRows = 100;
|
|||
|
|
private const int UiBatchSize = 20;
|
|||
|
|
private const int StatsRefreshMs = 500;
|
|||
|
|
private readonly Queue<CommunicationMessage> pendingMessages = new Queue<CommunicationMessage>();
|
|||
|
|
private readonly object pendingMessagesLock = new object();
|
|||
|
|
private readonly Timer uiFlushTimer;
|
|||
|
|
private readonly Timer statsRefreshTimer;
|
|||
|
|
private bool pendingStatsRefresh = false;
|
|||
|
|
private int lastDisplayCountForStats = 0;
|
|||
|
|
public CommunicationMonitorForm()
|
|||
|
|
{
|
|||
|
|
InitializeComponent();
|
|||
|
|
messageService = CommunicationMessageService.Instance;
|
|||
|
|
uiFlushTimer = new Timer { Interval = 500 };
|
|||
|
|
uiFlushTimer.Tick += UiFlushTimer_Tick;
|
|||
|
|
statsRefreshTimer = new Timer { Interval = StatsRefreshMs };
|
|||
|
|
statsRefreshTimer.Tick += StatsRefreshTimer_Tick;
|
|||
|
|
|
|||
|
|
// 订阅窗体关闭事件
|
|||
|
|
this.FormClosing += CommunicationMonitorForm_FormClosing;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void CommunicationMonitorForm_Load(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
InitializeForm();
|
|||
|
|
LoadMessages();
|
|||
|
|
|
|||
|
|
// 标记窗体已加载完成
|
|||
|
|
isFormLoaded = true;
|
|||
|
|
uiFlushTimer.Start();
|
|||
|
|
statsRefreshTimer.Start();
|
|||
|
|
|
|||
|
|
// 在窗体加载完成后再订阅报文添加事件(避免在初始化期间触发)
|
|||
|
|
messageService.MessageAdded += OnMessageAdded;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
MessageBox.Show($"窗体加载失败: {ex.Message}\r\n{ex.StackTrace}", "错误",
|
|||
|
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void InitializeForm()
|
|||
|
|
{
|
|||
|
|
this.Text = "通讯监控";
|
|||
|
|
this.Size = new Size(1400, 800);
|
|||
|
|
this.StartPosition = FormStartPosition.CenterScreen;
|
|||
|
|
this.MinimumSize = new Size(1200, 600);
|
|||
|
|
|
|||
|
|
// 初始化IP筛选下拉框
|
|||
|
|
RefreshIpFilter();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 刷新IP筛选下拉框
|
|||
|
|
/// </summary>
|
|||
|
|
private void RefreshIpFilter()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (cmbIpFilter == null || messageService == null)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
var selectedIp = cmbIpFilter.SelectedItem?.ToString();
|
|||
|
|
|
|||
|
|
cmbIpFilter.Items.Clear();
|
|||
|
|
cmbIpFilter.Items.Add("全部");
|
|||
|
|
|
|||
|
|
var ipAddresses = messageService.GetUniqueIpAddresses();
|
|||
|
|
if (ipAddresses != null)
|
|||
|
|
{
|
|||
|
|
foreach (var ip in ipAddresses)
|
|||
|
|
{
|
|||
|
|
if (!string.IsNullOrEmpty(ip))
|
|||
|
|
{
|
|||
|
|
cmbIpFilter.Items.Add(ip);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 恢复选中项
|
|||
|
|
if (!string.IsNullOrEmpty(selectedIp) && cmbIpFilter.Items.Contains(selectedIp))
|
|||
|
|
{
|
|||
|
|
cmbIpFilter.SelectedItem = selectedIp;
|
|||
|
|
}
|
|||
|
|
else if (cmbIpFilter.Items.Count > 0)
|
|||
|
|
{
|
|||
|
|
cmbIpFilter.SelectedIndex = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
System.Diagnostics.Debug.WriteLine($"刷新IP筛选失败: {ex.Message}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 加载报文列表
|
|||
|
|
/// </summary>
|
|||
|
|
private void LoadMessages()
|
|||
|
|
{
|
|||
|
|
var layoutSuspended = false;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (dgvMessages == null|| isFormMessageStop)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
var selectedIp = cmbIpFilter?.SelectedItem?.ToString();
|
|||
|
|
var messages = string.IsNullOrEmpty(selectedIp) || selectedIp == "全部"
|
|||
|
|
? messageService.GetAllMessages()
|
|||
|
|
: messageService.GetMessagesByIp(selectedIp);
|
|||
|
|
|
|||
|
|
dgvMessages.SuspendLayout();
|
|||
|
|
layoutSuspended = true;
|
|||
|
|
dgvMessages.Rows.Clear();
|
|||
|
|
|
|||
|
|
foreach (var msg in messages)
|
|||
|
|
{
|
|||
|
|
AddMessageRow(msg, false);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
UpdateStatistics(messages.Count);
|
|||
|
|
pendingStatsRefresh = false;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
MessageBox.Show($"加载报文失败: {ex.Message}", "错误",
|
|||
|
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
|
}
|
|||
|
|
finally
|
|||
|
|
{
|
|||
|
|
if (layoutSuspended && dgvMessages != null)
|
|||
|
|
{
|
|||
|
|
dgvMessages.ResumeLayout();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 定时批量刷新UI,避免每条报文都抢占UI线程
|
|||
|
|
/// </summary>
|
|||
|
|
private void UiFlushTimer_Tick(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
if (!isFormLoaded || isFormMessageStop)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
List<CommunicationMessage> batch = null;
|
|||
|
|
lock (pendingMessagesLock)
|
|||
|
|
{
|
|||
|
|
if (pendingMessages.Count == 0)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
int count = Math.Min(UiBatchSize, pendingMessages.Count);
|
|||
|
|
batch = new List<CommunicationMessage>(count);
|
|||
|
|
for (int i = 0; i < count; i++)
|
|||
|
|
{
|
|||
|
|
batch.Add(pendingMessages.Dequeue());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (batch == null || batch.Count == 0)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
dgvMessages.SuspendLayout();
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var selectedIp = cmbIpFilter?.SelectedItem?.ToString();
|
|||
|
|
bool displayChanged = false;
|
|||
|
|
|
|||
|
|
foreach (var message in batch)
|
|||
|
|
{
|
|||
|
|
EnsureIpInFilter(message.IpAddress);
|
|||
|
|
if (string.IsNullOrEmpty(selectedIp) || selectedIp == "全部" || selectedIp == message.IpAddress)
|
|||
|
|
{
|
|||
|
|
AddMessageRow(message, true);
|
|||
|
|
displayChanged = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (displayChanged)
|
|||
|
|
{
|
|||
|
|
RequestStatisticsRefresh(dgvMessages.Rows.Count);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
finally
|
|||
|
|
{
|
|||
|
|
dgvMessages.ResumeLayout();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 统计信息低频刷新(500ms)
|
|||
|
|
/// </summary>
|
|||
|
|
private void StatsRefreshTimer_Tick(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
if (!isFormLoaded || isFormMessageStop || !pendingStatsRefresh)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
pendingStatsRefresh = false;
|
|||
|
|
UpdateStatistics(lastDisplayCountForStats);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void RequestStatisticsRefresh(int displayCount)
|
|||
|
|
{
|
|||
|
|
lastDisplayCountForStats = displayCount;
|
|||
|
|
pendingStatsRefresh = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void EnsureIpInFilter(string ipAddress)
|
|||
|
|
{
|
|||
|
|
if (cmbIpFilter == null || string.IsNullOrWhiteSpace(ipAddress))
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
if (!cmbIpFilter.Items.Contains(ipAddress))
|
|||
|
|
{
|
|||
|
|
cmbIpFilter.Items.Add(ipAddress);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 向表格新增一条报文行(支持头部插入)
|
|||
|
|
/// </summary>
|
|||
|
|
private void AddMessageRow(CommunicationMessage msg, bool insertAtTop = true)
|
|||
|
|
{
|
|||
|
|
if (msg == null || dgvMessages == null)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
DataGridViewRow row;
|
|||
|
|
if (insertAtTop)
|
|||
|
|
{
|
|||
|
|
dgvMessages.Rows.Insert(0,
|
|||
|
|
msg.Timestamp.ToString("HH:mm:ss.fff"),
|
|||
|
|
msg.Direction == MessageDirection.Send ? "发送" : "接收",
|
|||
|
|
msg.IpAddress,
|
|||
|
|
msg.Port,
|
|||
|
|
msg.Length,
|
|||
|
|
msg.RawData,
|
|||
|
|
msg.StationId ?? "-",
|
|||
|
|
msg.Type);
|
|||
|
|
row = dgvMessages.Rows[0];
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
var index = dgvMessages.Rows.Add(
|
|||
|
|
msg.Timestamp.ToString("HH:mm:ss.fff"),
|
|||
|
|
msg.Direction == MessageDirection.Send ? "发送" : "接收",
|
|||
|
|
msg.IpAddress,
|
|||
|
|
msg.Port,
|
|||
|
|
msg.Length,
|
|||
|
|
msg.RawData,
|
|||
|
|
msg.StationId ?? "-",
|
|||
|
|
msg.Type);
|
|||
|
|
row = dgvMessages.Rows[index];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (msg.Direction == MessageDirection.Send)
|
|||
|
|
{
|
|||
|
|
row.DefaultCellStyle.BackColor = Color.FromArgb(232, 245, 233);
|
|||
|
|
row.DefaultCellStyle.ForeColor = Color.FromArgb(46, 125, 50);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
row.DefaultCellStyle.BackColor = Color.FromArgb(227, 242, 253);
|
|||
|
|
row.DefaultCellStyle.ForeColor = Color.FromArgb(13, 71, 161);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
while (dgvMessages.Rows.Count > MaxDisplayRows)
|
|||
|
|
{
|
|||
|
|
dgvMessages.Rows.RemoveAt(dgvMessages.Rows.Count - 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 更新统计信息
|
|||
|
|
/// </summary>
|
|||
|
|
private void UpdateStatistics(int displayCount)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (lblStatistics == null || messageService == null)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
var allMessages = messageService.GetAllMessages();
|
|||
|
|
if (allMessages == null)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
var sendCount = allMessages.Count(m => m.Direction == MessageDirection.Send);
|
|||
|
|
var receiveCount = allMessages.Count(m => m.Direction == MessageDirection.Receive);
|
|||
|
|
|
|||
|
|
lblStatistics.Text = $"显示: {displayCount} | 总数: {allMessages.Count} | 发送: {sendCount} | 接收: {receiveCount}";
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
System.Diagnostics.Debug.WriteLine($"更新统计信息失败: {ex.Message}");
|
|||
|
|
if (lblStatistics != null)
|
|||
|
|
{
|
|||
|
|
lblStatistics.Text = "统计信息加载失败";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 新报文添加事件处理(线程安全)
|
|||
|
|
/// </summary>
|
|||
|
|
private void OnMessageAdded(object sender, CommunicationMessage message)
|
|||
|
|
{
|
|||
|
|
// 如果窗体还未加载完成,忽略此事件
|
|||
|
|
if (!isFormLoaded || isFormMessageStop)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (message == null)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
lock (pendingMessagesLock)
|
|||
|
|
{
|
|||
|
|
pendingMessages.Enqueue(message);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
System.Diagnostics.Debug.WriteLine($"处理新报文失败: {ex.Message}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 解析报文数据
|
|||
|
|
/// </summary>
|
|||
|
|
private void ParseMessage(CommunicationMessage message)
|
|||
|
|
{
|
|||
|
|
if (message == null || txtParsedData == null)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var parsed = new System.Text.StringBuilder();
|
|||
|
|
parsed.AppendLine("=== 报文解析 ===");
|
|||
|
|
parsed.AppendLine($"时间: {message.Timestamp:yyyy-MM-dd HH:mm:ss.fff}");
|
|||
|
|
parsed.AppendLine($"方向: {(message.Direction == MessageDirection.Send ? "发送" : "接收")}");
|
|||
|
|
parsed.AppendLine($"地址: {message.IpAddress}:{message.Port}");
|
|||
|
|
parsed.AppendLine($"站点: {message.StationId ?? "未关联"}");
|
|||
|
|
parsed.AppendLine($"长度: {message.Length} 字节");
|
|||
|
|
parsed.AppendLine();
|
|||
|
|
parsed.AppendLine("=== 原始数据 (HEX) ===");
|
|||
|
|
parsed.AppendLine(message.RawData);
|
|||
|
|
// parsed.AppendLine(FormatHexString(message.RawData));
|
|||
|
|
parsed.AppendLine();
|
|||
|
|
parsed.AppendLine("=== 数据解析 ===");
|
|||
|
|
|
|||
|
|
// TODO: 根据实际协议进行解析
|
|||
|
|
parsed.AppendLine();
|
|||
|
|
if (message.Direction== MessageDirection.Send)
|
|||
|
|
{
|
|||
|
|
var sendDate = messageService.ParseSendRawData(message.RawData, message.Type);
|
|||
|
|
parsed.AppendLine("示例解析:");
|
|||
|
|
parsed.AppendLine($"充电指令:{sendDate.ChargeCommand}");
|
|||
|
|
parsed.AppendLine($"发送电压:{sendDate.SetVoltage}");
|
|||
|
|
parsed.AppendLine($"发送电流:{sendDate.SetCurrent}");
|
|||
|
|
parsed.AppendLine($"车辆ID:{sendDate.CurrentVehicleId}");
|
|||
|
|
parsed.AppendLine($"车辆电量:{sendDate.BatteryLevel}");
|
|||
|
|
parsed.AppendLine($"车辆电压:{sendDate.CarVoltage}");
|
|||
|
|
parsed.AppendLine($"车辆电流:{sendDate.CarCurrent}");
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
var recDate = messageService.ParseReceiveRawData(message.RawData, message.Type);
|
|||
|
|
string mechanismStatus = (int)recDate.MechanismStatus == 1 ? "伸出" : (int)recDate.MechanismStatus == 2 ? "缩回" : (int)recDate.MechanismStatus == 3 ? "运动中" : recDate.MechanismStatus.ToString();
|
|||
|
|
parsed.AppendLine("示例解析:");
|
|||
|
|
parsed.AppendLine($"机构状态:{mechanismStatus}");
|
|||
|
|
parsed.AppendLine($"实时电压:{recDate.RealTimeVoltage}");
|
|||
|
|
parsed.AppendLine($"实时电流:{recDate.RealTimeCurrent}");
|
|||
|
|
parsed.AppendLine($"充电量: {recDate.BatteryAH}");
|
|||
|
|
parsed.AppendLine($"是否报警:{recDate.HasAlarm}");
|
|||
|
|
parsed.AppendLine($"充电状态:{recDate.Status.ToString()}");
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
txtParsedData.Text = parsed.ToString();
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
txtParsedData.Text = $"解析失败: {ex.Message}";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 格式化十六进制字符串
|
|||
|
|
/// </summary>
|
|||
|
|
private string FormatHexString(string hexData)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrEmpty(hexData))
|
|||
|
|
return string.Empty;
|
|||
|
|
|
|||
|
|
var formatted = new System.Text.StringBuilder();
|
|||
|
|
for (int i = 0; i < hexData.Length; i += 2)
|
|||
|
|
{
|
|||
|
|
if (i > 0 && i % 32 == 0)
|
|||
|
|
formatted.AppendLine();
|
|||
|
|
else if (i > 0)
|
|||
|
|
formatted.Append(" ");
|
|||
|
|
|
|||
|
|
if (i + 1 < hexData.Length)
|
|||
|
|
formatted.Append(hexData.Substring(i, 2));
|
|||
|
|
else
|
|||
|
|
formatted.Append(hexData[i]);
|
|||
|
|
}
|
|||
|
|
return formatted.ToString();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== 事件处理 ====================
|
|||
|
|
|
|||
|
|
private void cmbIpFilter_SelectedIndexChanged(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
LoadMessages();
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
System.Diagnostics.Debug.WriteLine($"筛选改变失败: {ex.Message}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void dgvMessages_SelectionChanged(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (dgvMessages.SelectedRows.Count > 0)
|
|||
|
|
{
|
|||
|
|
var row = dgvMessages.SelectedRows[0];
|
|||
|
|
var rawData = row.Cells[5].Value?.ToString();
|
|||
|
|
var ipAddress = row.Cells[2].Value?.ToString();
|
|||
|
|
var port = int.Parse(row.Cells[3].Value?.ToString() ?? "0");
|
|||
|
|
var timeStr = row.Cells[0].Value?.ToString();
|
|||
|
|
var directionStr = row.Cells[1].Value?.ToString();
|
|||
|
|
var stationId = row.Cells[6].Value?.ToString();
|
|||
|
|
var type = row.Cells[7].Value?.ToString();
|
|||
|
|
|
|||
|
|
// 构造消息对象用于解析
|
|||
|
|
var message = new CommunicationMessage
|
|||
|
|
{
|
|||
|
|
RawData = rawData,
|
|||
|
|
IpAddress = ipAddress,
|
|||
|
|
Port = port,
|
|||
|
|
Direction = directionStr == "发送" ? MessageDirection.Send : MessageDirection.Receive,
|
|||
|
|
StationId = stationId == "-" ? null : stationId,
|
|||
|
|
Length = rawData.Split(' ')?.Length ?? 0,
|
|||
|
|
Type=type,
|
|||
|
|
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (DateTime.TryParse(timeStr, out DateTime timestamp))
|
|||
|
|
{
|
|||
|
|
message.Timestamp = timestamp;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ParseMessage(message);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
System.Diagnostics.Debug.WriteLine($"选择报文失败: {ex.Message}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void btnRefresh_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
RefreshIpFilter();
|
|||
|
|
LoadMessages();
|
|||
|
|
RequestStatisticsRefresh(dgvMessages?.Rows.Count ?? 0);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
MessageBox.Show($"刷新失败: {ex.Message}", "错误",
|
|||
|
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void btnClear_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var result = MessageBox.Show(
|
|||
|
|
"确定要清空所有报文记录吗?",
|
|||
|
|
"确认清空",
|
|||
|
|
MessageBoxButtons.YesNo,
|
|||
|
|
MessageBoxIcon.Question);
|
|||
|
|
|
|||
|
|
if (result == DialogResult.Yes)
|
|||
|
|
{
|
|||
|
|
messageService.Clear();
|
|||
|
|
RefreshIpFilter();
|
|||
|
|
LoadMessages();
|
|||
|
|
if (txtParsedData != null)
|
|||
|
|
{
|
|||
|
|
txtParsedData.Clear();
|
|||
|
|
}
|
|||
|
|
dgvMessages.Rows.Clear();
|
|||
|
|
RequestStatisticsRefresh(0);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
MessageBox.Show($"清空报文失败: {ex.Message}", "错误",
|
|||
|
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void btnClose_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
this.Close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void CommunicationMonitorForm_FormClosing(object sender, FormClosingEventArgs e)
|
|||
|
|
{
|
|||
|
|
// 取消订阅事件
|
|||
|
|
messageService.MessageAdded -= OnMessageAdded;
|
|||
|
|
uiFlushTimer.Stop();
|
|||
|
|
uiFlushTimer.Dispose();
|
|||
|
|
statsRefreshTimer.Stop();
|
|||
|
|
statsRefreshTimer.Dispose();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void button1_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
isFormMessageStop = !isFormMessageStop;
|
|||
|
|
if (sender is Button pauseButton)
|
|||
|
|
{
|
|||
|
|
pauseButton.Text = isFormMessageStop ? "继续" : "暂停";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|