mrDarker
2025-08-01 61ac290c2897f69db9d879ea4968304ddcd23d40
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp
@@ -8,6 +8,7 @@
#include "SGMeasurementDlg.h"
#include "afxdialogex.h"
#include "SGIF.h"
#include "Logger.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -175,7 +176,7 @@
   m_editLog.ReplaceSel(_T(""));   // 删除
}
void CSGMeasurementDlg::AppendLogLineRichStyled(const CString& content, COLORREF color /*= RGB(0, 0, 0)*/)
void CSGMeasurementDlg::AppendLogLineRichStyled(const CString& strContent, COLORREF color /*= RGB(0, 0, 0)*/)
{
   if (!::IsWindow(GetSafeHwnd()) || !::IsWindow(m_editLog.GetSafeHwnd())) {
      return;
@@ -197,16 +198,41 @@
   m_editLog.SetSelectionCharFormat(cfTime);
   m_editLog.ReplaceSel(strTimestamp);
   // 生成日志级别标签
   CString strLevel;
   if (color == LOG_COLOR_WARNING) {
      strLevel = _T("[警告]");
   }
   else if (color == LOG_COLOR_ERROR) {
      strLevel = _T("[错误]");
   }
   else if (color == LOG_COLOR_NORMAL) {
      strLevel = _T("[信息]");
   }
   else if (color == LOG_COLOR_SUCCESS) {
      strLevel = _T("[成功]");
   }
   else {
      strLevel = _T("[未知]");
   }
   // 插入日志正文(传入颜色)
   CHARFORMAT2 cfMsg = {};
   cfMsg.cbSize = sizeof(cfMsg);
   cfMsg.dwMask = CFM_COLOR;
   cfMsg.crTextColor = color;
   m_editLog.SetSelectionCharFormat(cfMsg);
   m_editLog.ReplaceSel(content + _T("\r\n"));
   m_editLog.ReplaceSel(strLevel + strContent + _T("\r\n"));
   // 限制最大行数
   TrimRichEditLineLimit(100);
   // 拼接完整日志行
   CString strFullLogLine;
   strFullLogLine.Format(_T("%s %s"), strLevel, strContent);
   // 写入日志文件
   LOG_LINE(strFullLogLine);
}
void CSGMeasurementDlg::HighlightAllMatches(const CString& strSearch, COLORREF clrHighlight/* = RGB(255, 165, 0)*/)
@@ -520,6 +546,146 @@
   return true;
}
bool CSGMeasurementDlg::InitDataStorage()
{
   if (!m_bConnected) {
      AppendLogLineRichStyled(_T("设备未连接,请先连接设备。"), LOG_COLOR_WARNING);
      return false;
   }
   if (m_bSaving) {
      AppendLogLineRichStyled(_T("数据存储正在进行中,请先停止存储。"), LOG_COLOR_WARNING);
      return false;
   }
   RC nRet = SGIF_DataStorageInit(DeviceID);
   if (nRet == RC_OK) {
      AppendLogLineRichStyled(_T("数据存储已清除。"), LOG_COLOR_SUCCESS);
      return true;
   }
   CString strError;
   strError.Format(_T("清除数据存储失败,错误码:%#X"), nRet);
   AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
   return false;
}
bool CSGMeasurementDlg::StartDataStorage()
{
   if (m_bSaving) {
      AppendLogLineRichStyled(_T("数据存储已在进行中,请先停止存储。"), LOG_COLOR_WARNING);
      return false;
   }
   RC nRet = SGIF_DataStorageStart(DeviceID);
   if (nRet == RC_OK) {
      m_bSaving = TRUE;
      AppendLogLineRichStyled(_T("数据存储已开始。"), LOG_COLOR_SUCCESS);
      return true;
   }
   CString strError;
   strError.Format(_T("开始数据存储失败,错误码:%#X"), nRet);
   AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
   return false;
}
bool CSGMeasurementDlg::StopDataStorage()
{
   if (!m_bSaving) {
      AppendLogLineRichStyled(_T("数据存储未在进行中,请先开始存储。"), LOG_COLOR_WARNING);
      return false;
   }
   RC nRet = SGIF_DataStorageStop(DeviceID);
   if (nRet == RC_OK) {
      m_bSaving = FALSE;
      AppendLogLineRichStyled(_T("数据存储已停止。"), LOG_COLOR_SUCCESS);
      return true;
   }
   CString strError;
   strError.Format(_T("停止数据存储失败,错误码:%#X"), nRet);
   AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
   return false;
}
float CSGMeasurementDlg::AnalyzeStoredData(int nOutNo)
{
   UpdateData(TRUE);
   if (m_nUseTrigger) {
      UpdateControlStatus(m_bConnected, m_bSaving);
      AfxMessageBox(_T("当前是硬触发模式,请检查触发器状态。"), MB_ICONINFORMATION);
      return -1.0f;
   }
   if (!m_bConnected) {
      AppendLogLineRichStyled(_T("设备未连接,请先连接设备。"), LOG_COLOR_WARNING);
      return -1.0f;
   }
   if (m_bSaving) {
      AppendLogLineRichStyled(_T("数据存储正在进行中,请先停止存储。"), LOG_COLOR_WARNING);
      return -1.0f;
   }
   if (nOutNo < 1 || nOutNo > 4) {
      AppendLogLineRichStyled(_T("输出端口编号无效,必须在 1 到 4 之间。"), LOG_COLOR_ERROR);
      return -1.0f;
   }
   if (m_nSavePointCount < 0) {
      AppendLogLineRichStyled(_T("数据点数必须大于 0。"), LOG_COLOR_ERROR);
      return -1.0f;
   }
   clock_t startClock = clock();  // 记录开始时间
   std::vector<float> vecBuffer(m_nSavePointCount, 0.0f);
   int nReceived = 0;
   RC nRet = SGIF_DataStorageGetData(DeviceID, nOutNo, m_nSavePointCount, vecBuffer.data(), &nReceived);
   if (nRet != RC_OK) {
      CString strError;
      strError.Format(_T("读取 OUT%d 数据失败,错误码:%#X"), nOutNo, nRet);
      AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
      return -1.0f;
   }
   vecBuffer.resize(nReceived);
   CleanInvalidValuesInPlace(nOutNo, vecBuffer);
   std::vector<float> vecGlass1, vecGlass2;
   if (!SplitGlassSegments(nOutNo, vecBuffer, vecGlass1, vecGlass2, m_fJumpThreshold, m_nJumpWindow, m_nValleyMargin, m_nMinGlass1Count)) {
      AppendLogLineRichStyled(_T("未能识别出两片玻璃的数据。"), LOG_COLOR_WARNING);
      return -1.0f;
   }
   std::vector<float> vecStable1, vecStable2;
   bool bStable1 = ExtractStableRegionFixed(nOutNo, vecGlass1, vecStable1, m_nFixedCount, m_fMaxDelta);
   bool bStable2 = ExtractStableRegionFixed(nOutNo, vecGlass2, vecStable2, m_nFixedCount, m_fMaxDelta);
   float fAvg1 = 0.0f, fAvg2 = 0.0f, fOffset = 0.0f;
   if (bStable1 && bStable2) {
      AppendLogLineRichStyled(_T("成功提取到两片玻璃的稳定区数据。"), LOG_COLOR_SUCCESS);
      CalcGlassOffset(vecStable1, vecStable2, fAvg1, fAvg2, fOffset);
   }
   else {
      AppendLogLineRichStyled(_T("未能提取到稳定区数据,尝试使用原始分段数据计算偏移。"), LOG_COLOR_WARNING);
      CalcGlassOffset(vecGlass1, vecGlass2, fAvg1, fAvg2, fOffset);
   }
   clock_t endClock = clock();  // 记录结束时间
   double dElapsedMs = 1000.0 * (endClock - startClock) / CLOCKS_PER_SEC;
   CString strElapsed;
   strElapsed.Format(_T("AnalyzeStoredData 执行耗时:%.1f ms"), dElapsedMs);
   AppendLogLineRichStyled(strElapsed, LOG_COLOR_SUCCESS);
   return fOffset;
}
BEGIN_MESSAGE_MAP(CSGMeasurementDlg, CDialogEx)
   ON_WM_SYSCOMMAND()
   ON_WM_PAINT()
@@ -827,120 +993,30 @@
void CSGMeasurementDlg::OnBnClickedButtonClearStore()
{
   // TODO: 在此添加控件通知处理程序代码
   if (!m_bConnected) {
      AppendLogLineRichStyled(_T("设备未连接,请先连接设备。"), LOG_COLOR_WARNING);
      return;
   }
   if (m_bSaving) {
      AppendLogLineRichStyled(_T("数据存储正在进行中,请先停止存储。"), LOG_COLOR_WARNING);
      return;
   }
   RC nRet = SGIF_DataStorageInit(DeviceID);
   if (nRet == RC_OK) {
      AppendLogLineRichStyled(_T("数据存储已清除。"), LOG_COLOR_SUCCESS);
   }
   else {
      CString strError;
      strError.Format(_T("清除数据存储失败,错误码:%#X"), nRet);
      AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
   }
   InitDataStorage();
}
void CSGMeasurementDlg::OnBnClickedButtonStartStore()
{
   // TODO: 在此添加控件通知处理程序代码
   if (m_bSaving) {
      AppendLogLineRichStyled(_T("数据存储已在进行中,请先停止存储。"), LOG_COLOR_WARNING);
      return;
   }
   RC nRet = SGIF_DataStorageStart(DeviceID);
   if (nRet == RC_OK) {
      m_bSaving = TRUE;
      AppendLogLineRichStyled(_T("数据存储已开始。"), LOG_COLOR_SUCCESS);
   }
   else {
      CString strError;
      strError.Format(_T("开始数据存储失败,错误码:%#X"), nRet);
      AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
   }
   StartDataStorage();
   UpdateControlStatus(m_bConnected, m_bSaving);
}
void CSGMeasurementDlg::OnBnClickedButtonStopStore()
{
   // TODO: 在此添加控件通知处理程序代码
   UpdateData(TRUE);
   StopDataStorage();
   UpdateControlStatus(m_bConnected, m_bSaving);
   if (!m_bSaving) {
      AppendLogLineRichStyled(_T("数据存储未在进行中,请先开始存储。"), LOG_COLOR_WARNING);
   int nSel = m_comboOutputPort.GetCurSel();
   if (CB_ERR == nSel) {
      AppendLogLineRichStyled(_T("请选择一个有效的输出端口。"), LOG_COLOR_WARNING);
      return;
   }
   RC nRet = SGIF_DataStorageStop(DeviceID);
   if (nRet == RC_OK) {
      m_bSaving = FALSE;
      AppendLogLineRichStyled(_T("数据存储已停止。"), LOG_COLOR_SUCCESS);
      if (m_nUseTrigger) {
         UpdateControlStatus(m_bConnected, m_bSaving);
         AfxMessageBox(_T("当前是硬触发模式,请检查触发器状态。"), MB_ICONINFORMATION);
         return;
      }
      int nReceived = 0;
      std::vector<float> vecBuffer(m_nSavePointCount, 0.0f);
      int nSel = m_comboOutputPort.GetCurSel();
      if (CB_ERR == nSel) {
         AppendLogLineRichStyled(_T("请选择一个有效的输出端口。"), LOG_COLOR_WARNING);
         return;
      }
      int nOutNo = nSel + 1;
      nRet = SGIF_DataStorageGetData(DeviceID, nOutNo, m_nSavePointCount, vecBuffer.data(), &nReceived);
      CString strLog;
      if (nRet == RC_OK) {
         vecBuffer.resize(nReceived);
         CleanInvalidValuesInPlace(nOutNo, vecBuffer);
         std::vector<float> vecGlass1, vecGlass2;
         if (SplitGlassSegments(nOutNo, vecBuffer, vecGlass1, vecGlass2, m_fJumpThreshold, m_nJumpWindow, m_nValleyMargin, m_nMinGlass1Count)) {
            std::vector<float> vecStableGlass1, vecStableGlass2;
            bool bStable1 = ExtractStableRegionFixed(nOutNo, vecGlass1, vecStableGlass1, m_nFixedCount, m_fMaxDelta);
            bool bStable2 = ExtractStableRegionFixed(nOutNo, vecGlass2, vecStableGlass2, m_nFixedCount, m_fMaxDelta);
            float fAvg1 = 0.0f, fAvg2 = 0.0f, fOffset = 0.0f;
            if (bStable1 && bStable2) {
               AppendLogLineRichStyled(_T("成功提取到两片玻璃的稳定区数据。"), LOG_COLOR_SUCCESS);
               CalcGlassOffset(vecStableGlass1, vecStableGlass2, fAvg1, fAvg2, fOffset);
            }
            else {
               AppendLogLineRichStyled(_T("未能提取到稳定区数据,无法正常计算偏移。"), LOG_COLOR_WARNING);
               CalcGlassOffset(vecGlass1, vecGlass2, fAvg1, fAvg2, fOffset);
            }
         }
         else {
            AppendLogLineRichStyled(_T("未能识别出两片玻璃的数据。"), LOG_COLOR_WARNING);
         }
      }
      else {
         strLog.Format(_T("读取 OUT%d 数据失败,错误码:%#X"), nOutNo, nRet);
         AppendLogLineRichStyled(strLog, LOG_COLOR_ERROR);
      }
   }
   else {
      CString strError;
      strError.Format(_T("停止数据存储失败,错误码:%#X"), nRet);
      AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
   }
   UpdateControlStatus(m_bConnected, m_bSaving);
   int nOutNo = nSel + 1;
   AnalyzeStoredData(nOutNo);
}
void CSGMeasurementDlg::OnBnClickedButtonClearLog()