1. SG精度检保存界面上的参数到配置文件
2. SG精度检允许设置开机自启动
3. 修改日志保存路径
已修改4个文件
230 ■■■■■ 文件已修改
SourceCode/Bond/SGMeasurement/Logger.cpp 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurement.vcxproj.user 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.h 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/Logger.cpp
@@ -21,8 +21,17 @@
{
    CSingleLock lock(&m_csLogLock, TRUE);
    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);
    }
    CTime now = CTime::GetCurrentTime();
    CString strLogDir = _T("Log");
    CString strLogDir = strPath + _T("Log");
    if (!PathFileExists(strLogDir)) {
        CreateDirectory(strLogDir, NULL);
@@ -37,8 +46,7 @@
            m_logFile.Close();
        }
        if (m_logFile.Open(strNewPath,
            CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::typeBinary)) {
        if (m_logFile.Open(strNewPath, CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::typeBinary | CFile::shareDenyWrite)) {
            if (m_logFile.GetLength() == 0) {
                WCHAR bom = 0xFEFF;
SourceCode/Bond/SGMeasurement/SGMeasurement.vcxproj.user
@@ -10,6 +10,6 @@
    <RemoteDebuggerCommand>\\DESKTOP-IODBVIQ\SGMeasurement\$(ProjectName).exe</RemoteDebuggerCommand>
    <RemoteDebuggerWorkingDirectory>\\DESKTOP-IODBVIQ\SGMeasurement</RemoteDebuggerWorkingDirectory>
    <RemoteDebuggerServerName>DESKTOP-IODBVIQ</RemoteDebuggerServerName>
    <DebuggerFlavor>WindowsRemoteDebugger</DebuggerFlavor>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
</Project>
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp
@@ -94,6 +94,7 @@
    , m_nTrayIconID(0)
    , m_bTrayIconCreated(FALSE)
    , m_bExitingFromTray(FALSE)
    , m_nAutoStart(TRUE)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
@@ -131,6 +132,9 @@
    }
    m_plcListener.Stop();
    // 保存配置文件
    SaveConfig(GetConfigPath());
    DestroyWindow();
    CDialogEx::OnClose();
@@ -301,6 +305,134 @@
            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_WRITE, &hKey);
    if (lRet != ERROR_SUCCESS) {
        return false;
    }
    if (bEnable) {
        // 设置自启
        lRet = RegSetValueEx(hKey, strAppName, 0, REG_SZ, (BYTE*)(LPCTSTR)strAppPath, (strAppPath.GetLength() + 1) * sizeof(TCHAR));
    }
    else {
        // 取消自启
        lRet = RegDeleteValue(hKey, strAppName);
    }
    RegCloseKey(hKey);
    return (lRet == ERROR_SUCCESS);
}
bool CSGMeasurementDlg::ConnectToDevice()
@@ -942,6 +1074,27 @@
    });
    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);
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.h
@@ -118,6 +118,60 @@
    void PrintSampleData(int nOutNo, const std::vector<float>& vecBuffer);
    /**
     * @brief 获取当前应用程序所在的目录路径。
     *
     * 通过 GetModuleFileName 获取当前可执行文件的完整路径,
     * 并截取掉文件名部分,返回目录路径,末尾自带反斜杠。
     *
     * @return CString 应用程序所在目录,例如 "C:\\Program Files\\SGMeasurement\\"
     */
    CString GetAppDirectory();
    /**
     * @brief 获取配置文件的完整路径。
     *
     * 配置文件名固定为 "config.ini",位于应用程序目录下。
     *
     * @return CString 配置文件完整路径,例如 "C:\\Program Files\\SGMeasurement\\config.ini"
     */
    CString GetConfigPath();
    /**
     * @brief 从 ini 配置文件加载存储与分析参数。
     *
     * 读取指定 ini 文件中的参数值,并更新对话框类中的成员变量,
     * 包括存储设置(触发方式、采样点数)、跳变检测参数、稳定区提取参数等。
     * 若文件中缺少某些字段,将使用默认值。
     *
     * @param strFile ini 文件路径。
     * @return true 表示加载成功,false 表示加载失败(如文件不存在)。
     */
    bool LoadConfig(const CString& strFile);
    /**
     * @brief 将当前存储与分析参数保存到 ini 配置文件。
     *
     * 把对话框类中的成员变量(存储设置、跳变检测、稳定区提取等参数)
     * 序列化并写入到指定的 ini 文件中,以便下次启动时恢复。
     *
     * @param strFile ini 文件路径。
     * @return true 表示保存成功,false 表示保存失败。
     */
    bool SaveConfig(const CString& strFile);
    /**
     * @brief 设置或取消当前程序的开机自启动。
     *
     * 该函数会在注册表 `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run`
     * 下写入或删除当前程序的路径,从而控制是否随 Windows 启动自动运行。
     *
     * @param bEnable 是否启用自启动。true 表示设置开机自启,false 表示取消自启。
     *
     * @return true 表示操作成功;false 表示操作失败(如注册表权限不足)。
     */
    bool SetAutoStart(bool bEnable);
    /**
     * @brief 尝试连接到测量设备。
     *
     * @return true 表示连接成功,false 表示连接失败。
@@ -335,6 +389,13 @@
     */
    BOOL m_bExitingFromTray;
    // === 自启动相关 ===
    /**
     * @brief 是否开机自启动
     */
    BOOL m_nAutoStart;
    // === PLC 信号监听器 ===
    /**