mrDarker
2025-10-22 e8a27bb203fe2aff70390a5eca002d7438da9b0f
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp
@@ -17,6 +17,7 @@
#define DeviceID 0
// 托盘图标 ID 与消息宏
#define ID_TRAY_OPEN_DIR      2000            // 打开目录
#define ID_TRAY_RESTORE         2001            // 恢复窗口
#define ID_TRAY_EXIT         2002            // 退出程序
#define WM_TRAY_ICON_NOTIFY    (WM_USER + 1000) // 托盘图标回调消息 ID
@@ -94,6 +95,7 @@
   , m_nTrayIconID(0)
   , m_bTrayIconCreated(FALSE)
   , m_bExitingFromTray(FALSE)
   , m_nAutoStart(TRUE)
{
   m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
@@ -131,6 +133,9 @@
   }
   m_plcListener.Stop();
   // 保存配置文件
   SaveConfig(GetConfigPath());
   DestroyWindow();
   CDialogEx::OnClose();
@@ -301,6 +306,149 @@
         strLine.Empty();
      }
   }
}
CString CSGMeasurementDlg::GetAppDirectory()
{
   TCHAR szPath[MAX_PATH] = { 0 };
   GetModuleFileName(NULL, szPath, MAX_PATH);
   CString strPath = szPath;
   int pos = strPath.ReverseFind('\\');
   if (pos != -1) {
      strPath = strPath.Left(pos + 1);
   }
   return strPath;
}
CString CSGMeasurementDlg::GetConfigPath()
{
   return GetAppDirectory() + _T("SGConfig.ini");
}
bool CSGMeasurementDlg::LoadConfig(const CString& strFile)
{
   CString strSection = _T("StorageConfig");
   TCHAR buf[256];
   GetPrivateProfileString(strSection, _T("UseTrigger"), _T("0"), buf, 256, strFile);
   m_nUseTrigger = _ttoi(buf);
   GetPrivateProfileString(strSection, _T("SavePointCount"), _T("100000"), buf, 256, strFile);
   m_nSavePointCount = _ttoi(buf);
   // 输出端口
   GetPrivateProfileString(strSection, _T("OutputPort"), _T("OUT1"), buf, 256, strFile);
   {
      int idx = m_comboOutputPort.FindStringExact(-1, buf);
      if (idx != CB_ERR) {
         m_comboOutputPort.SetCurSel(idx);
      }
      else {
         m_comboOutputPort.SetCurSel(0);
      }
   }
   // 跳变检测参数
   GetPrivateProfileString(strSection, _T("JumpThreshold"), _T("0.2"), buf, 256, strFile);
   m_fJumpThreshold = static_cast<float>(_tstof(buf));
   GetPrivateProfileString(strSection, _T("JumpWindow"), _T("3"), buf, 256, strFile);
   m_nJumpWindow = _ttoi(buf);
   GetPrivateProfileString(strSection, _T("ValleyMargin"), _T("0"), buf, 256, strFile);
   m_nValleyMargin = _ttoi(buf);
   GetPrivateProfileString(strSection, _T("MinGlass1Count"), _T("10"), buf, 256, strFile);
   m_nMinGlass1Count = _ttoi(buf);
   // 稳定区域参数
   GetPrivateProfileString(strSection, _T("FixedCount"), _T("5"), buf, 256, strFile);
   m_nFixedCount = _ttoi(buf);
   GetPrivateProfileString(strSection, _T("MaxDelta"), _T("0.05"), buf, 256, strFile);
   m_fMaxDelta = static_cast<float>(_tstof(buf));
   // 自启动
   GetPrivateProfileString(strSection, _T("AutoStart"), _T("1"), buf, 256, strFile);
   m_nAutoStart = _ttoi(buf);
   return true;
}
bool CSGMeasurementDlg::SaveConfig(const CString& strFile)
{
   CString strSection = _T("StorageConfig");
   WritePrivateProfileString(strSection, _T("UseTrigger"), std::to_wstring(m_nUseTrigger).c_str(), strFile);
   WritePrivateProfileString(strSection, _T("SavePointCount"), std::to_wstring(m_nSavePointCount).c_str(), strFile);
   // 输出端口下拉框
   CString strPort;
   m_comboOutputPort.GetWindowText(strPort);
   WritePrivateProfileString(strSection, _T("OutputPort"), strPort, strFile);
   // 跳变检测
   WritePrivateProfileString(strSection, _T("JumpThreshold"), std::to_wstring(m_fJumpThreshold).c_str(), strFile);
   WritePrivateProfileString(strSection, _T("JumpWindow"), std::to_wstring(m_nJumpWindow).c_str(), strFile);
   WritePrivateProfileString(strSection, _T("ValleyMargin"), std::to_wstring(m_nValleyMargin).c_str(), strFile);
   WritePrivateProfileString(strSection, _T("MinGlass1Count"), std::to_wstring(m_nMinGlass1Count).c_str(), strFile);
   // 稳定区
   WritePrivateProfileString(strSection, _T("FixedCount"), std::to_wstring(m_nFixedCount).c_str(), strFile);
   WritePrivateProfileString(strSection, _T("MaxDelta"), std::to_wstring(m_fMaxDelta).c_str(), strFile);
   // 自启动
   WritePrivateProfileString(strSection, _T("AutoStart"), std::to_wstring(m_nAutoStart).c_str(), strFile);
   return true;
}
bool CSGMeasurementDlg::SetAutoStart(bool bEnable)
{
   // 获取当前程序路径
   TCHAR szPath[MAX_PATH] = { 0 };
   GetModuleFileName(NULL, szPath, MAX_PATH);
   CString strAppPath = szPath;
   // 获取应用程序名称
   CString strAppName = ::PathFindFileName(strAppPath);
   strAppName = strAppName.Left(strAppName.ReverseFind('.'));
   HKEY hKey;
   LONG lRet = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), 0, KEY_READ | KEY_WRITE, &hKey);
   if (lRet != ERROR_SUCCESS) {
      return false;
   }
   DWORD dwType = 0;
   TCHAR szValue[MAX_PATH] = { 0 };
   DWORD dwSize = sizeof(szValue);
   lRet = RegQueryValueEx(hKey, strAppName, 0, &dwType, (LPBYTE)szValue, &dwSize);
   if (bEnable) {
      if (lRet != ERROR_SUCCESS || _tcsicmp(szValue, strAppPath) != 0) {
         // 设置自启
         lRet = RegSetValueEx(hKey, strAppName, 0, REG_SZ, (BYTE*)(LPCTSTR)strAppPath, (strAppPath.GetLength() + 1) * sizeof(TCHAR));
      }
      else {
         lRet = ERROR_SUCCESS;
      }
   }
   else {
      if (lRet == ERROR_SUCCESS) {
         // 取消自启
         lRet = RegDeleteValue(hKey, strAppName);
      }
      else {
         lRet = ERROR_SUCCESS;
      }
   }
   RegCloseKey(hKey);
   return (lRet == ERROR_SUCCESS);
}
bool CSGMeasurementDlg::ConnectToDevice()
@@ -715,7 +863,7 @@
   return false;
}
float CSGMeasurementDlg::AnalyzeStoredData(int nOutNo)
double CSGMeasurementDlg::AnalyzeStoredData(int nOutNo)
{
   MEASURE_FUNC_START();
@@ -724,27 +872,27 @@
   if (m_nUseTrigger) {
      UpdateControlStatus(m_bConnected, m_bSaving);
      AfxMessageBox(_T("当前是硬触发模式,请检查触发器状态。"), MB_ICONINFORMATION);
      return 0xFF;
      return DBL_MAX;
   }
   if (!m_bConnected) {
      AppendLogLineRichStyled(_T("设备未连接,请先连接设备。"), LOG_COLOR_WARNING);
      return 0xFF;
      return DBL_MAX;
   }
   if (m_bSaving) {
      AppendLogLineRichStyled(_T("数据存储正在进行中,请先停止存储。"), LOG_COLOR_WARNING);
      return 0xFF;
      return DBL_MAX;
   }
   if (nOutNo < 1 || nOutNo > 4) {
      AppendLogLineRichStyled(_T("输出端口编号无效,必须在 1 到 4 之间。"), LOG_COLOR_ERROR);
      return 0xFF;
      return DBL_MAX;
   }
   if (m_nSavePointCount < 0) {
      AppendLogLineRichStyled(_T("数据点数必须大于 0。"), LOG_COLOR_ERROR);
      return 0xFF;
      return DBL_MAX;
   }
   std::vector<float> vecBuffer(m_nSavePointCount, 0.0f);
@@ -755,7 +903,7 @@
      CString strError;
      strError.Format(_T("读取 OUT%d 数据失败,错误码:%#X"), nOutNo, nRet);
      AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
      return 0xFF;
      return DBL_MAX;
   }
   vecBuffer.resize(nReceived);
@@ -764,7 +912,7 @@
   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 0xFF;
      return DBL_MAX;
   }
   std::vector<float> vecGlass1Filtered, vecGlass2Filtered;
@@ -815,6 +963,7 @@
   ON_WM_DRAWITEM()
   ON_WM_CLOSE()
   ON_MESSAGE(WM_TRAY_ICON_NOTIFY, &CSGMeasurementDlg::OnTrayIconClick)
   ON_COMMAND(ID_TRAY_OPEN_DIR, &CSGMeasurementDlg::OnTrayOpenDir)
   ON_COMMAND(ID_TRAY_RESTORE, &CSGMeasurementDlg::OnTrayRestore)
   ON_COMMAND(ID_TRAY_EXIT, &CSGMeasurementDlg::OnTrayExit)
   ON_BN_CLICKED(IDC_BUTTON_CONNECT, &CSGMeasurementDlg::OnBnClickedButtonConnect)
@@ -924,7 +1073,7 @@
   m_plcListener.SetAnalyzeCallback([this]() {
      if (!m_bConnected) {
         AppendLogLineRichStyled(_T("设备未连接,请先连接设备。"), LOG_COLOR_WARNING);
         return std::array<double, 4>{ 0xFF, 0xFF, 0xFF, 0xFF };
         return std::array<double, 4>{ DBL_MAX, DBL_MAX, DBL_MAX, DBL_MAX };
      }
      std::array<double, 4> result;
@@ -941,6 +1090,27 @@
      return result;
   });
   m_plcListener.Start();
   // 加载配置文件
   if (LoadConfig(GetConfigPath())) {
      AppendLogLineRichStyled(_T("配置已从 SGConfig.ini 加载成功"), LOG_COLOR_SUCCESS);
   }
   else {
      AppendLogLineRichStyled(_T("配置加载失败,使用默认参数"), LOG_COLOR_WARNING);
   }
   // 设置自动启动
   if (SetAutoStart(m_nAutoStart)) {
      if (m_nAutoStart) {
         AppendLogLineRichStyled(_T("已启用开机自启动"), LOG_COLOR_SUCCESS);
      }
      else {
         AppendLogLineRichStyled(_T("已取消开机自启动"), LOG_COLOR_WARNING);
      }
   }
   else {
      AppendLogLineRichStyled(_T("设置开机自启动失败,请检查权限"), LOG_COLOR_ERROR);
   }
   // 初始化日志框
   AppendLogLineRichStyled(_T("准备就绪..."), LOG_COLOR_SUCCESS);
@@ -1053,6 +1223,10 @@
   // 图标
   HICON hIcon = nullptr;
   if (id == ID_TRAY_OPEN_DIR) {
      hIcon = AfxGetApp()->LoadIcon(IDI_ICON_OPEN_DIR);
   }
   if (id == ID_TRAY_RESTORE) {
      hIcon = AfxGetApp()->LoadIcon(IDI_ICON_RESTORE);
   }
@@ -1067,6 +1241,10 @@
   // 文本
   CString str;
   if (id == ID_TRAY_OPEN_DIR) {
      str = _T("打开目录");
   }
   if (id == ID_TRAY_RESTORE) { 
      str = _T("恢复界面");
   }
@@ -1110,22 +1288,23 @@
         // 右键点击弹出菜单
         CMenu menu;
         menu.CreatePopupMenu();
         menu.AppendMenu(MF_OWNERDRAW, ID_TRAY_OPEN_DIR, (LPCTSTR)ID_TRAY_OPEN_DIR);
         menu.AppendMenu(MF_OWNERDRAW, ID_TRAY_RESTORE, (LPCTSTR)ID_TRAY_RESTORE);
         menu.AppendMenu(MF_OWNERDRAW, ID_TRAY_EXIT, (LPCTSTR)ID_TRAY_EXIT);
         // 加载图标
         HICON hIconRestore = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON_RESTORE), IMAGE_ICON, 16, 16, LR_SHARED);
         HICON hIconExit = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON_EXIT), IMAGE_ICON, 16, 16, LR_SHARED);
         // 设置图标到菜单项
         MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
         mii.fMask = MIIM_BITMAP;
         // 恢复菜单项图标
         // 打开目录菜单项图标
         mii.hbmpItem = HBMMENU_CALLBACK;
         menu.SetMenuItemInfo(ID_TRAY_OPEN_DIR, &mii);
         // 恢复窗口菜单项图标
         mii.hbmpItem = HBMMENU_CALLBACK;
         menu.SetMenuItemInfo(ID_TRAY_RESTORE, &mii);
         // 退出菜单项图标
         // 退出程序菜单项图标
         mii.hbmpItem = HBMMENU_CALLBACK;
         menu.SetMenuItemInfo(ID_TRAY_EXIT, &mii);
@@ -1139,6 +1318,18 @@
   return 0;
}
void CSGMeasurementDlg::OnTrayOpenDir()
{
   CString strDir = GetAppDirectory();
   if (PathFileExists(strDir)) {
      ShellExecute(NULL, _T("open"), strDir, NULL, NULL, SW_SHOWDEFAULT);
      AppendLogLineRichStyled(_T("已打开程序目录"), LOG_COLOR_SUCCESS);
   }
   else {
      AppendLogLineRichStyled(_T("目录不存在,无法打开"), LOG_COLOR_ERROR);
   }
}
void CSGMeasurementDlg::OnTrayRestore()
{
   ShowWindow(SW_SHOW);     // 恢复窗口