From 72f3802bd7ab24b672c951a287787b5dea253f3b Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期六, 02 八月 2025 10:48:36 +0800
Subject: [PATCH] Merge branch 'clh' into liuyang
---
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp | 1150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1,150 insertions(+), 0 deletions(-)
diff --git a/SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp b/SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp
new file mode 100644
index 0000000..7529194
--- /dev/null
+++ b/SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp
@@ -0,0 +1,1150 @@
+锘�
+// SGMeasurementDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "pch.h"
+#include "framework.h"
+#include "SGMeasurement.h"
+#include "SGMeasurementDlg.h"
+#include "afxdialogex.h"
+#include "SGIF.h"
+#include "Logger.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+#define DeviceID 0
+
+// 鎵樼洏鍥炬爣 ID 涓庢秷鎭畯
+#define ID_TRAY_RESTORE 2001 // 鎭㈠绐楀彛
+#define ID_TRAY_EXIT 2002 // 閫�鍑虹▼搴�
+#define WM_TRAY_ICON_NOTIFY (WM_USER + 1000) // 鎵樼洏鍥炬爣鍥炶皟娑堟伅 ID
+
+// 鎵樼洏鎻愮ず鏂囨湰瀹�
+#define TRAY_ICON_TOOLTIP_TEXT _T("SGMeasurement")
+
+// 鏃ュ織棰滆壊瀹忓畾涔�
+#define LOG_COLOR_NORMAL RGB(0, 0, 0) // 鏅�氾細榛戣壊
+#define LOG_COLOR_SUCCESS RGB(0, 128, 0) // 鎴愬姛锛氱豢鑹�
+#define LOG_COLOR_ERROR RGB(255, 0, 0) // 閿欒锛氱孩鑹�
+#define LOG_COLOR_WARNING RGB(255, 165, 0) // 璀﹀憡锛氭鑹�
+#define LOG_COLOR_TIME RGB(0, 0, 255) // 鏃堕棿鎴筹細钃濊壊
+
+// 瀹氭椂鍣ㄧ浉鍏冲畯瀹氫箟
+#define TIMER_INTERVAL_MS 500
+#define TIMER_ID_OUTPUT_UPDATE 1
+
+// 璁℃椂瀹忓畾涔�
+#define MEASURE_FUNC_START() \
+ clock_t __startClock = clock();
+
+#define MEASURE_FUNC_END() \
+ do { \
+ clock_t __endClock = clock(); \
+ double __elapsedMs = 1000.0 * (__endClock - __startClock) / CLOCKS_PER_SEC; \
+ CString __strElapsed; \
+ __strElapsed.Format(_T("%s 鎵ц鑰楁椂锛�%.1f ms"), _T(__FUNCTION__), __elapsedMs); \
+ AppendLogLineRichStyled(__strElapsed, LOG_COLOR_SUCCESS); \
+ } while (0)
+
+class CAboutDlg : public CDialogEx
+{
+public:
+ CAboutDlg();
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+ enum { IDD = IDD_ABOUTBOX };
+#endif
+
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 鏀寔
+
+// 瀹炵幇
+protected:
+ DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
+{
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialogEx::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
+END_MESSAGE_MAP()
+
+CSGMeasurementDlg::CSGMeasurementDlg(CWnd* pParent /*=nullptr*/)
+ : CDialogEx(IDD_SGMEASUREMENT_DIALOG, pParent)
+ , m_bConnected(false)
+ , m_bSaving(false)
+ , m_dOutValues{ 0.0, 0.0, 0.0, 0.0 }
+ , m_nUseTrigger(0)
+ , m_nSavePointCount(100000)
+ , m_fJumpThreshold(0.2f)
+ , m_nJumpWindow(3)
+ , m_nValleyMargin(0)
+ , m_nMinGlass1Count(10)
+ , m_nFixedCount(5)
+ , m_fMaxDelta(0.05f)
+ , m_nTrayIconID(0)
+ , m_bTrayIconCreated(FALSE)
+ , m_bExitingFromTray(FALSE)
+{
+ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+}
+
+void CSGMeasurementDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialogEx::DoDataExchange(pDX);
+ DDX_Text(pDX, IDC_EDIT_OUT1, m_dOutValues[0]);
+ DDX_Text(pDX, IDC_EDIT_OUT2, m_dOutValues[1]);
+ DDX_Text(pDX, IDC_EDIT_OUT3, m_dOutValues[2]);
+ DDX_Text(pDX, IDC_EDIT_OUT4, m_dOutValues[3]);
+ DDX_Control(pDX, IDC_RICHEDIT_LOG, m_editLog);
+ DDX_Check(pDX, IDC_CHECK_USE_TRIGGER, m_nUseTrigger);
+ DDX_Control(pDX, IDC_COMBO_OUTPUT_PORT, m_comboOutputPort);
+ DDX_Text(pDX, IDC_EDIT_STORE_COUNT, m_nSavePointCount);
+ DDX_Text(pDX, IDC_EDIT_JUMP_WINDOW, m_nJumpWindow);
+ DDX_Text(pDX, IDC_EDIT_VALLEY_MARGIN, m_nValleyMargin);
+ DDX_Text(pDX, IDC_EDIT_MIN_GLASS_COUNT, m_nMinGlass1Count);
+ DDX_Text(pDX, IDC_EDIT_FIXED_COUNT, m_nFixedCount);
+ DDX_Text(pDX, IDC_EDIT_JUMP_THRESHOLD, m_fJumpThreshold);
+ DDX_Text(pDX, IDC_EDIT_MAX_DELTA, m_fMaxDelta);
+}
+
+void CSGMeasurementDlg::ExitApplication()
+{
+ // 鏂紑璁惧杩炴帴锛堝宸茶繛鎺ワ級
+ if (m_bConnected) {
+ DisconnectFromDevice();
+ }
+
+ // 鍒犻櫎鎵樼洏鍥炬爣锛堝宸叉坊鍔狅級
+ if (m_bTrayIconCreated) {
+ Shell_NotifyIcon(NIM_DELETE, &m_trayIconData);
+ m_bTrayIconCreated = FALSE;
+ }
+
+ DestroyWindow();
+ CDialogEx::OnClose();
+}
+
+void CSGMeasurementDlg::UpdateControlStatus(BOOL bConnected, BOOL bStoring/* = FALSE*/)
+{
+ // 杩炴帴鎸夐挳鍜屾柇寮�鎸夐挳鐘舵�佷簰鏂�
+ GetDlgItem(IDC_BUTTON_CONNECT)->EnableWindow(!bConnected);
+ GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(bConnected);
+
+ // IP鍦板潃杈撳叆鍙厑璁稿湪鏈繛鎺ユ椂淇敼
+ GetDlgItem(IDC_IPADDRESS)->EnableWindow(!bConnected);
+
+ // 瀛樺偍閰嶇疆鎺т欢浠呭湪宸茶繛鎺ヤ笖鏈紑濮嬪瓨鍌ㄦ椂鍏佽鎿嶄綔
+ BOOL bCanConfigure = bConnected && !bStoring;
+ /*GetDlgItem(IDC_CHECK_USE_TRIGGER)->EnableWindow(bCanConfigure);*/
+ GetDlgItem(IDC_COMBO_OUTPUT_PORT)->EnableWindow(bCanConfigure);
+ GetDlgItem(IDC_EDIT_STORE_COUNT)->EnableWindow(bCanConfigure);
+ GetDlgItem(IDC_EDIT_JUMP_THRESHOLD)->EnableWindow(bCanConfigure);
+ GetDlgItem(IDC_EDIT_JUMP_WINDOW)->EnableWindow(bCanConfigure);
+ GetDlgItem(IDC_EDIT_VALLEY_MARGIN)->EnableWindow(bCanConfigure);
+ GetDlgItem(IDC_EDIT_MIN_GLASS_COUNT)->EnableWindow(bCanConfigure);
+ GetDlgItem(IDC_EDIT_FIXED_COUNT)->EnableWindow(bCanConfigure);
+ GetDlgItem(IDC_EDIT_MAX_DELTA)->EnableWindow(bCanConfigure);
+
+ // 瀛樺偍鐩稿叧鎸夐挳
+ GetDlgItem(IDC_BUTTON_RECEIVE_FROM_CTRL)->EnableWindow(bCanConfigure);
+ GetDlgItem(IDC_BUTTON_SEND_TO_CTRL)->EnableWindow(bCanConfigure);
+ GetDlgItem(IDC_BUTTON_CLEAR_STORE)->EnableWindow(bCanConfigure);
+ GetDlgItem(IDC_BUTTON_START_STORE)->EnableWindow(bCanConfigure);
+ GetDlgItem(IDC_BUTTON_STOP_STORE)->EnableWindow(bStoring);
+}
+
+void CSGMeasurementDlg::AppendLogLineBatchBegin()
+{
+ m_editLog.SetRedraw(FALSE);
+ m_editLog.SetEventMask(0); // 闃叉瑙﹀彂涓嶅繀瑕佺殑閫氱煡
+}
+
+void CSGMeasurementDlg::AppendLogLineBatchEnd()
+{
+ m_editLog.SetRedraw(TRUE);
+ m_editLog.Invalidate(); // 寮哄埗閲嶇粯
+ m_editLog.SetEventMask(ENM_CHANGE | ENM_SELCHANGE);
+}
+
+void CSGMeasurementDlg::TrimRichEditLineLimit(int nMaxLines)
+{
+ int nLineCount = m_editLog.GetLineCount();
+ if (nLineCount < nMaxLines) {
+ return;
+ }
+
+ // 鑾峰彇澶氫綑琛岀殑瀛楃鏁拌寖鍥�
+ int charIndex = m_editLog.LineIndex(nMaxLines);
+ m_editLog.SetSel(0, charIndex); // 閫変腑澶氫綑鍐呭
+ m_editLog.ReplaceSel(_T("")); // 鍒犻櫎
+}
+
+void CSGMeasurementDlg::AppendLogLineRichStyled(const CString& strContent, COLORREF color /*= RGB(0, 0, 0)*/)
+{
+ if (!::IsWindow(GetSafeHwnd()) || !::IsWindow(m_editLog.GetSafeHwnd())) {
+ return;
+ }
+
+ // 鏃堕棿鎴�
+ CString strTimestamp;
+ CTime now = CTime::GetCurrentTime();
+ strTimestamp.Format(_T("[%02d:%02d:%02d] "), now.GetHour(), now.GetMinute(), now.GetSecond());
+
+ // 鎻掑叆鐐圭Щ鍒版渶鍚庯紙涔熷彲浠ヨ涓� 0 琛ㄧず椤堕儴锛�
+ m_editLog.SetSel(-1, -1);
+
+ // 鎻掑叆鏃堕棿锛堣摑鑹诧級
+ CHARFORMAT2 cfTime = {};
+ cfTime.cbSize = sizeof(cfTime);
+ cfTime.dwMask = CFM_COLOR;
+ cfTime.crTextColor = LOG_COLOR_TIME;
+ 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("[鏈煡]");
+ }
+
+ // 鎻掑叆鏃ュ織姝f枃锛堜紶鍏ラ鑹诧級
+ CHARFORMAT2 cfMsg = {};
+ cfMsg.cbSize = sizeof(cfMsg);
+ cfMsg.dwMask = CFM_COLOR;
+ cfMsg.crTextColor = color;
+ m_editLog.SetSelectionCharFormat(cfMsg);
+ 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)*/)
+{
+ if (strSearch.IsEmpty()) {
+ return;
+ }
+
+ long nStart = 0;
+ long nEnd = m_editLog.GetTextLength();
+ FINDTEXTEX ft = { 0 };
+ ft.chrg.cpMin = 0;
+ ft.chrg.cpMax = nEnd;
+ ft.lpstrText = strSearch.GetString();
+
+ // 楂樹寒鍓嶄笉娓呴櫎鍏ㄦ枃棰滆壊锛岄伩鍏嶅巻鍙插鑹叉贩娣�
+ while (m_editLog.FindText(FR_DOWN, &ft) != -1) {
+ m_editLog.SetSel(ft.chrgText.cpMin, ft.chrgText.cpMax);
+
+ CHARFORMAT2 cf = {};
+ cf.cbSize = sizeof(cf);
+ cf.dwMask = CFM_COLOR;
+ cf.crTextColor = clrHighlight;
+ m_editLog.SetSelectionCharFormat(cf);
+
+ // 涓嬫鎼滅储浠庡悗闈㈠紑濮�
+ ft.chrg.cpMin = ft.chrgText.cpMax;
+ }
+ m_editLog.SetSel(-1, 0);
+}
+
+void CSGMeasurementDlg::PrintSampleData(int nOutNo, const std::vector<float>& vecBuffer)
+{
+ int nReceived = static_cast<int>(vecBuffer.size());
+ if (vecBuffer.empty() || nReceived < 0) {
+ CString strError;
+ strError.Format(_T("OUT%d: 鎺ユ敹鏁版嵁涓虹┖鎴栨棤鏁堬紝鏃犳硶鎵撳嵃銆�"), nOutNo);
+ AppendLogLineRichStyled(strError, LOG_COLOR_WARNING);
+ return;
+ }
+
+ CString strLine;
+ for (int i = 0; i < nReceived; ++i) {
+ CString strOne;
+ strOne.Format(_T("%10.3f "), vecBuffer[i]);
+ strLine += strOne;
+
+ // 姣� 7 涓�艰緭鍑轰竴琛�
+ if ((i + 1) % 7 == 0 || i == nReceived - 1) {
+ AppendLogLineRichStyled(strLine, LOG_COLOR_NORMAL);
+ strLine.Empty();
+ }
+ }
+}
+
+bool CSGMeasurementDlg::ConnectToDevice()
+{
+ if (m_bConnected) {
+ AppendLogLineRichStyled(_T("璁惧宸茶繛鎺ワ紝璇峰厛鏂紑杩炴帴銆�"), LOG_COLOR_WARNING);
+ return false;
+ }
+
+ SGIF_OPENPARAM_ETHERNET stIpAddress = { 0 };
+
+ CIPAddressCtrl* pIPCtrl = (CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS);
+ if (!::IsWindow(pIPCtrl->GetSafeHwnd())) {
+ AppendLogLineRichStyled(_T("IP 鎺т欢鏃犳晥锛岃繛鎺ュけ璐ワ紒"), LOG_COLOR_ERROR);
+ return false;
+ }
+
+ pIPCtrl->GetAddress(
+ stIpAddress.IPAddress.S_un.S_un_b.s_b1,
+ stIpAddress.IPAddress.S_un.S_un_b.s_b2,
+ stIpAddress.IPAddress.S_un.S_un_b.s_b3,
+ stIpAddress.IPAddress.S_un.S_un_b.s_b4
+ );
+
+ RC nRet = SGIF_OpenDeviceETHER(DeviceID, &stIpAddress);
+ if (nRet == RC_OK) {
+ AppendLogLineRichStyled(_T("鎵撳紑杩炴帴鎴愬姛锛�"), LOG_COLOR_SUCCESS);
+
+ m_bConnected = TRUE;
+ UpdateControlStatus(TRUE, FALSE);
+ SetTimer(TIMER_ID_OUTPUT_UPDATE, TIMER_INTERVAL_MS, nullptr);
+ return true;
+ }
+ else {
+ CString strError;
+ strError.Format(_T("鎵撳紑杩炴帴澶辫触锛岄敊璇爜锛�%#X"), nRet);
+ AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
+
+ m_bConnected = FALSE;
+ UpdateControlStatus(FALSE, FALSE);
+ return false;
+ }
+}
+
+bool CSGMeasurementDlg::DisconnectFromDevice()
+{
+ if (!m_bConnected) {
+ AppendLogLineRichStyled(_T("璁惧鏈繛鎺ワ紝鏃犻渶鏂紑銆�"), LOG_COLOR_WARNING);
+ return false;
+ }
+
+ // 鍋滄瀹氭椂鍣紝閬垮厤鍦ㄦ柇寮�鍚庝粛灏濊瘯鏇存柊杈撳嚭鏁版嵁
+ KillTimer(TIMER_ID_OUTPUT_UPDATE);
+
+ // 鍏堝仠姝㈡暟鎹瓨鍌紙濡傛灉姝e湪杩涜锛�
+ RC nRet;
+ if (m_bConnected && m_bSaving) {
+ nRet = SGIF_DataStorageStop(DeviceID);
+ if (nRet == RC_OK) {
+ m_bSaving = FALSE;
+ AppendLogLineRichStyled(_T("鏁版嵁瀛樺偍宸插仠姝€��"), LOG_COLOR_SUCCESS);
+ }
+ else {
+ CString strError;
+ strError.Format(_T("鍋滄鏁版嵁瀛樺偍澶辫触锛岄敊璇爜锛�%#X"), nRet);
+ AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
+ }
+ }
+
+ // 鏂紑璁惧杩炴帴
+ nRet = SGIF_CloseDevice(DeviceID);
+ if (nRet == RC_OK) {
+ AppendLogLineRichStyled(_T("鏂紑杩炴帴鎴愬姛锛�"), LOG_COLOR_SUCCESS);
+
+ m_bConnected = FALSE;
+ UpdateControlStatus(FALSE, FALSE);
+ return true;
+ }
+ else {
+ CString strError;
+ strError.Format(_T("鏂紑杩炴帴澶辫触锛岄敊璇爜锛�%#X"), nRet);
+ AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
+ AppendLogLineRichStyled(_T("淇濇寔褰撳墠鐘舵�侊紝鏂紑澶辫触銆�"), LOG_COLOR_ERROR);
+
+ UpdateControlStatus(m_bConnected, m_bSaving);
+ return false;
+ }
+}
+
+void CSGMeasurementDlg::CleanInvalidValuesInPlace(int nOutNo, std::vector<float>& vecData, float fInvalid/* = -999.0f*/)
+{
+ MEASURE_FUNC_START();
+
+ // 鎵惧埌绗竴涓湁鏁堝��
+ auto itStart = std::find_if(vecData.begin(), vecData.end(), [=](float v) { return v > fInvalid; });
+
+ // 鎵惧埌鏈�鍚庝竴涓湁鏁堝��
+ auto itEnd = std::find_if(vecData.rbegin(), vecData.rend(), [=](float v) { return v > fInvalid; }).base();
+
+ // 妫�鏌ユ槸鍚︽湁鏈夋晥鏁版嵁
+ if (itStart < itEnd) {
+ // 鍏堣杈�
+ std::vector<float> vecTrimmed(itStart, itEnd);
+
+ // 鍐嶇Щ闄や腑闂寸殑鏃犳晥鍊�
+ auto itNewEnd = std::remove_if(vecTrimmed.begin(), vecTrimmed.end(), [=](float v) { return v == fInvalid; });
+ vecTrimmed.erase(itNewEnd, vecTrimmed.end());
+
+ vecData = std::move(vecTrimmed);
+
+ CString strLog;
+ strLog.Format(_T("OUT%d: 宸茶鍓棤鏁堣竟鐣屾暟鎹紝鍓╀綑鏈夋晥鏁版嵁 %d 涓��"), nOutNo, static_cast<int>(vecData.size()));
+ AppendLogLineRichStyled(strLog, LOG_COLOR_NORMAL);
+
+ if (vecData.size() < 20) {
+ AppendLogLineRichStyled(_T("璀﹀憡锛氭湁鏁堟暟鎹噺杩囧皯锛屽彲鑳藉奖鍝嶅悗缁鐞嗐��"), LOG_COLOR_WARNING);
+ }
+ else {
+ CString strInfo;
+ strInfo.Format(_T("OUT%d: 鏈夋晥鏁版嵁鑼冨洿 [%f, %f]"), nOutNo, *std::min_element(vecData.begin(), vecData.end()), *std::max_element(vecData.begin(), vecData.end()));
+ AppendLogLineRichStyled(strInfo, LOG_COLOR_NORMAL);
+ }
+
+ PrintSampleData(nOutNo, vecData);
+ }
+ else {
+ vecData.clear();
+ }
+
+ MEASURE_FUNC_END();
+}
+
+bool CSGMeasurementDlg::SplitGlassSegments(int nOutNo, const std::vector<float>& vecData, std::vector<float>& vecGlass1, std::vector<float>& vecGlass2, float fJumpThreshold /*= 0.2f*/, int nWindow /*= 3*/, int nValleyMargin /*= 0*/, int nMinGlassCount /*= 10*/)
+{
+ MEASURE_FUNC_START();
+
+ CString strLog;
+ const int nTotal = static_cast<int>(vecData.size());
+
+ if (nTotal < 2 * nWindow + 1 + nMinGlassCount) {
+ strLog.Format(_T("OUT%d: 鏁版嵁閲忎笉瓒筹紝鑷冲皯闇�瑕� %d 涓偣鎵嶈兘鍒囧壊銆�"), nOutNo, 2 * nWindow + 1 + nMinGlassCount);
+ AppendLogLineRichStyled(strLog, LOG_COLOR_WARNING);
+ return false;
+ }
+
+ // 浠庝腑闂村悜涓よ竟鏌ユ壘 valley 鍊欓�夌偣
+ int nMid = nTotal / 2;
+ int nValleyLeft = -1, nValleyRight = -1;
+
+ // 鍚戝乏鏌ユ壘 valley
+ for (int i = nMid; i >= nWindow; --i) {
+ float fDelta = std::fabs(vecData[i] - vecData[i - nWindow]);
+ if (fDelta > fJumpThreshold &&
+ vecData[i] < vecData[i - 1] &&
+ vecData[i] < vecData[i + 1]) {
+ nValleyLeft = i;
+ break;
+ }
+ }
+
+ // 鍚戝彸鏌ユ壘 valley
+ for (int i = nMid; i <= nTotal - nWindow - 2; ++i) {
+ float fDelta = std::fabs(vecData[i + nWindow] - vecData[i]);
+ if (fDelta > fJumpThreshold &&
+ vecData[i] < vecData[i - 1] &&
+ vecData[i] < vecData[i + 1]) {
+ nValleyRight = i;
+ break;
+ }
+ }
+
+ // 閫夊畾 valley 鐐�
+ int nValleyIdx = -1;
+ if (nValleyLeft > 0 && nValleyRight > 0) {
+ nValleyIdx = (vecData[nValleyLeft] < vecData[nValleyRight]) ? nValleyLeft : nValleyRight;
+ }
+ else if (nValleyLeft > 0) {
+ nValleyIdx = nValleyLeft;
+ }
+ else if (nValleyRight > 0) {
+ nValleyIdx = nValleyRight;
+ }
+
+ // fallback: valley 鏈壘鍒帮紝浣跨敤涓棿鍒囧壊娉�
+ if (nValleyIdx < 0) {
+ AppendLogLineRichStyled(_T("鏈壘鍒� valley 璺冲彉鐐癸紝浣跨敤涓棿浣嶇疆鍒囧壊銆�"), LOG_COLOR_WARNING);
+ nValleyIdx = nMid;
+ }
+
+ // 搴旂敤鍒囧壊浣嶇疆锛岄檺鍒惰竟鐣�
+ int nCutPos = max(1, min(nTotal - 1, nValleyIdx + nValleyMargin));
+
+ vecGlass1.assign(vecData.begin(), vecData.begin() + nCutPos);
+ vecGlass2.assign(vecData.begin() + nCutPos, vecData.end());
+
+ int nGlass1Count = static_cast<int>(vecGlass1.size());
+ int nGlass2Count = static_cast<int>(vecGlass2.size());
+
+ // 鏃ュ織杈撳嚭
+ strLog.Format(_T("OUT%d: 鍒囧壊鎴愬姛锛岀涓�鐗囩幓鐠� %d 鐐癸紝绗簩鐗囩幓鐠� %d 鐐广��"), nOutNo, nGlass1Count, nGlass2Count);
+ AppendLogLineRichStyled(strLog, LOG_COLOR_SUCCESS);
+
+ if (nGlass1Count < nMinGlassCount) {
+ strLog.Format(_T("OUT%d: 绗竴鐗囩幓鐠冩暟鎹噺灏戜簬 %d 鐐癸紝鍙兘褰卞搷璁$畻銆�"), nOutNo, nMinGlassCount);
+ AppendLogLineRichStyled(strLog, LOG_COLOR_WARNING);
+ }
+
+ if (nGlass2Count < nMinGlassCount) {
+ strLog.Format(_T("OUT%d: 绗簩鐗囩幓鐠冩暟鎹噺灏戜簬 %d 鐐癸紝鍙兘褰卞搷璁$畻銆�"), nOutNo, nMinGlassCount);
+ AppendLogLineRichStyled(strLog, LOG_COLOR_WARNING);
+ }
+
+ AppendLogLineRichStyled(_T("绗竴鐗囩幓鐠冩暟鎹細"), LOG_COLOR_NORMAL);
+ PrintSampleData(nOutNo, vecGlass1);
+
+ AppendLogLineRichStyled(_T("绗簩鐗囩幓鐠冩暟鎹細"), LOG_COLOR_NORMAL);
+ PrintSampleData(nOutNo, vecGlass2);
+
+ MEASURE_FUNC_END();
+
+ return true;
+}
+
+bool CSGMeasurementDlg::FilterDominantGroup(int nOutNo, const std::vector<float>& vecInput, std::vector<float>& vecOutput)
+{
+ MEASURE_FUNC_START();
+
+ if (vecInput.empty()) {
+ AppendLogLineRichStyled(_T("杈撳叆鏁版嵁涓虹┖锛屾棤娉曡繘琛屽垎缁勭瓫閫夈��"), LOG_COLOR_WARNING);
+ return false;
+ }
+
+ // 鍒嗙粍锛歮ap<int鏁存暟閮ㄥ垎, vector<float>>
+ std::map<int, std::vector<float>> mapGroup;
+ for (float fVal : vecInput) {
+ int nKey = static_cast<int>(fVal);
+ mapGroup[nKey].push_back(fVal);
+ }
+
+ // 鎵惧嚭鏁伴噺鏈�澶氱殑閭g粍
+ size_t nMaxCount = 0;
+ auto itMaxGroup = mapGroup.begin();
+ for (auto it = mapGroup.begin(); it != mapGroup.end(); ++it) {
+ if (it->second.size() > nMaxCount) {
+ nMaxCount = it->second.size();
+ itMaxGroup = it;
+ }
+ }
+
+ if (nMaxCount == 0) {
+ AppendLogLineRichStyled(_T("鎵�鏈夋暟鎹兘琚繃婊ゆ垨涓虹┖锛屾棤娉曠瓫閫夊嚭涓昏鍒嗙粍銆�"), LOG_COLOR_WARNING);
+ return false;
+ }
+
+ vecOutput = itMaxGroup->second;
+
+ CString strLog;
+ strLog.Format(_T("鎴愬姛浠� %d 涓粍涓瓫閫夊嚭涓昏鍒嗙粍锛氬�肩害涓� %d锛屽叡 %zu 涓偣銆�"), static_cast<int>(mapGroup.size()), itMaxGroup->first, nMaxCount);
+ AppendLogLineRichStyled(strLog, LOG_COLOR_SUCCESS);
+
+ // 鎵撳嵃绛涢�夊悗鐨勬暟鎹�
+ AppendLogLineRichStyled(_T("绛涢�夊悗鐨勪富瑕佸垎缁勬暟鎹細"), LOG_COLOR_NORMAL);
+ PrintSampleData(nOutNo, vecOutput);
+
+ MEASURE_FUNC_END();
+
+ return true;
+}
+
+bool CSGMeasurementDlg::ExtractStableRegionFixed(int nOutNo, const std::vector<float>& vecIn, std::vector<float>& vecOut, int nFixedCount/* = 5*/, float fMaxDelta/* = 0.04f*/)
+{
+ MEASURE_FUNC_START();
+
+ const int n = static_cast<int>(vecIn.size());
+ if (n < nFixedCount) {
+ CString strError;
+ strError.Format(_T("OUT%d: 鏁版嵁閲忎笉瓒筹紝鑷冲皯闇�瑕� %d 涓偣鎵嶈兘鎻愬彇绋冲畾鍖恒��"), nOutNo, nFixedCount);
+ return false;
+ }
+
+ int nBestStart = -1;
+ float fBestRange = FLT_MAX;
+
+ for (int i = 0; i <= n - nFixedCount; ++i) {
+ auto first = vecIn.begin() + i;
+ auto last = first + nFixedCount;
+
+ float fMinVal = *std::min_element(first, last);
+ float fMaxVal = *std::max_element(first, last);
+ float fRange = fMaxVal - fMinVal;
+
+ if (fRange <= fMaxDelta && fRange < fBestRange) {
+ fBestRange = fRange;
+ nBestStart = i;
+ }
+ }
+
+ if (nBestStart < 0) {
+ return false;
+ }
+
+ vecOut.assign(vecIn.begin() + nBestStart, vecIn.begin() + nBestStart + nFixedCount);
+
+ CString strLog;
+ strLog.Format(_T("OUT%d: 鎻愬彇绋冲畾鍖烘垚鍔燂紝璧峰鐐圭储寮� %d锛岃寖鍥� %.3f銆�"), nOutNo, nBestStart, fBestRange);
+ AppendLogLineRichStyled(strLog, LOG_COLOR_SUCCESS);
+
+ if (vecOut.size() < nFixedCount) {
+ CString strWarning;
+ strWarning.Format(_T("OUT%d: 鎻愬彇鐨勭ǔ瀹氬尯鏁版嵁閲忎笉瓒筹紝鍙兘褰卞搷鍚庣画澶勭悊銆�"), nOutNo);
+ AppendLogLineRichStyled(strWarning, LOG_COLOR_WARNING);
+ }
+
+ // 鎵撳嵃鎻愬彇鐨勭ǔ瀹氬尯鏁版嵁
+ AppendLogLineRichStyled(_T("鎻愬彇鐨勭ǔ瀹氬尯鏁版嵁锛�"), LOG_COLOR_NORMAL);
+ PrintSampleData(nOutNo, vecOut);
+
+ MEASURE_FUNC_END();
+
+ return true;
+}
+
+bool CSGMeasurementDlg::CalcGlassOffset(const std::vector<float>& vecGlass1, const std::vector<float>& vecGlass2, float& fAvg1, float& fAvg2, float& fOffset)
+{
+ MEASURE_FUNC_START();
+
+ if (vecGlass1.empty() || vecGlass2.empty()) {
+ AppendLogLineRichStyled(_T("绋冲畾鍖烘暟鎹负绌猴紝鏃犳硶璁$畻骞冲潎鍊煎拰鍋忕Щ銆�"), LOG_COLOR_WARNING);
+ return false;
+ }
+
+ auto CalcAverage = [](const std::vector<float>& data) -> float {
+ float sum = std::accumulate(data.begin(), data.end(), 0.0f);
+ return sum / static_cast<float>(data.size());
+ };
+
+ fAvg1 = CalcAverage(vecGlass1);
+ fAvg2 = CalcAverage(vecGlass2);
+ fOffset = std::fabs(fAvg2 - fAvg1); // 绗簩鐗� - 绗竴鐗�
+
+ CString strLog;
+ strLog.Format(_T("绗竴鐗囩幓鐠冨钩鍧囧��: %.3f锛岀浜岀墖鐜荤拑骞冲潎鍊�: %.3f锛屽亸绉婚噺: %.3f"), fAvg1, fAvg2, fOffset);
+ AppendLogLineRichStyled(strLog, LOG_COLOR_SUCCESS);
+
+ MEASURE_FUNC_END();
+
+ return true;
+}
+
+bool CSGMeasurementDlg::InitDataStorage()
+{
+ if (!m_bConnected) {
+ AppendLogLineRichStyled(_T("璁惧鏈繛鎺ワ紝璇峰厛杩炴帴璁惧銆�"), LOG_COLOR_WARNING);
+ return false;
+ }
+
+ if (m_bSaving) {
+ AppendLogLineRichStyled(_T("鏁版嵁瀛樺偍姝e湪杩涜涓紝璇峰厛鍋滄瀛樺偍銆�"), 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)
+{
+ MEASURE_FUNC_START();
+
+ 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("鏁版嵁瀛樺偍姝e湪杩涜涓紝璇峰厛鍋滄瀛樺偍銆�"), 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;
+ }
+
+ 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> vecGlass1Filtered, vecGlass2Filtered;
+ bool bGlass1Filtered = FilterDominantGroup(nOutNo, vecGlass1, vecGlass1Filtered);
+ bool bGlass2Filtered = FilterDominantGroup(nOutNo, vecGlass2, vecGlass2Filtered);
+
+ if (!bGlass1Filtered) {
+ AppendLogLineRichStyled(_T("Glass1 鍒嗘涓湭鑳借瘑鍒嚭涓绘暟鎹粍锛屼娇鐢ㄥ師濮嬫暟鎹��"), LOG_COLOR_WARNING);
+ vecGlass1Filtered = vecGlass1;
+ }
+ else {
+ AppendLogLineRichStyled(_T("Glass1 涓绘暟鎹粍宸叉彁鍙栥��"), LOG_COLOR_SUCCESS);
+ }
+
+ if (!bGlass2Filtered) {
+ AppendLogLineRichStyled(_T("Glass2 鍒嗘涓湭鑳借瘑鍒嚭涓绘暟鎹粍锛屼娇鐢ㄥ師濮嬫暟鎹��"), LOG_COLOR_WARNING);
+ vecGlass2Filtered = vecGlass2;
+ }
+ else {
+ AppendLogLineRichStyled(_T("Glass2 涓绘暟鎹粍宸叉彁鍙栥��"), LOG_COLOR_SUCCESS);
+ }
+
+ std::vector<float> vecStable1, vecStable2;
+ bool bStable1 = ExtractStableRegionFixed(nOutNo, vecGlass1Filtered, vecStable1, m_nFixedCount, m_fMaxDelta);
+ bool bStable2 = ExtractStableRegionFixed(nOutNo, vecGlass2Filtered, 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);
+ }
+
+ MEASURE_FUNC_END();
+
+ return fOffset;
+}
+
+BEGIN_MESSAGE_MAP(CSGMeasurementDlg, CDialogEx)
+ ON_WM_SYSCOMMAND()
+ ON_WM_PAINT()
+ ON_WM_QUERYDRAGICON()
+ ON_WM_TIMER()
+ ON_WM_MEASUREITEM()
+ ON_WM_DRAWITEM()
+ ON_WM_CLOSE()
+ ON_MESSAGE(WM_TRAY_ICON_NOTIFY, &CSGMeasurementDlg::OnTrayIconClick)
+ ON_COMMAND(ID_TRAY_RESTORE, &CSGMeasurementDlg::OnTrayRestore)
+ ON_COMMAND(ID_TRAY_EXIT, &CSGMeasurementDlg::OnTrayExit)
+ ON_BN_CLICKED(IDC_BUTTON_CONNECT, &CSGMeasurementDlg::OnBnClickedButtonConnect)
+ ON_BN_CLICKED(IDC_BUTTON_DISCONNECT, &CSGMeasurementDlg::OnBnClickedButtonDisconnect)
+ ON_BN_CLICKED(IDC_BUTTON_RECEIVE_FROM_CTRL, &CSGMeasurementDlg::OnBnClickedButtonReceiveFromCtrl)
+ ON_BN_CLICKED(IDC_BUTTON_SEND_TO_CTRL, &CSGMeasurementDlg::OnBnClickedButtonSendToCtrl)
+ ON_BN_CLICKED(IDC_BUTTON_CLEAR_STORE, &CSGMeasurementDlg::OnBnClickedButtonClearStore)
+ ON_BN_CLICKED(IDC_BUTTON_START_STORE, &CSGMeasurementDlg::OnBnClickedButtonStartStore)
+ ON_BN_CLICKED(IDC_BUTTON_STOP_STORE, &CSGMeasurementDlg::OnBnClickedButtonStopStore)
+ ON_BN_CLICKED(IDC_BUTTON_CLEAR_LOG, &CSGMeasurementDlg::OnBnClickedButtonClearLog)
+END_MESSAGE_MAP()
+
+BOOL CSGMeasurementDlg::OnInitDialog()
+{
+ CDialogEx::OnInitDialog();
+
+ // 灏嗏�滃叧浜�...鈥濊彍鍗曢」娣诲姞鍒扮郴缁熻彍鍗曚腑銆�
+
+ // IDM_ABOUTBOX 蹇呴』鍦ㄧ郴缁熷懡浠よ寖鍥村唴銆�
+ ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+ ASSERT(IDM_ABOUTBOX < 0xF000);
+
+ CMenu* pSysMenu = GetSystemMenu(FALSE);
+ if (pSysMenu != nullptr)
+ {
+ BOOL bNameValid;
+ CString strAboutMenu;
+ bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
+ ASSERT(bNameValid);
+ if (!strAboutMenu.IsEmpty())
+ {
+ pSysMenu->AppendMenu(MF_SEPARATOR);
+ pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
+ }
+ }
+
+ // 璁剧疆姝ゅ璇濇鐨勫浘鏍囥�� 褰撳簲鐢ㄧ▼搴忎富绐楀彛涓嶆槸瀵硅瘽妗嗘椂锛屾鏋跺皢鑷姩
+ // 鎵ц姝ゆ搷浣�
+ SetIcon(m_hIcon, TRUE); // 璁剧疆澶у浘鏍�
+ SetIcon(m_hIcon, FALSE); // 璁剧疆灏忓浘鏍�
+
+ // TODO: 鍦ㄦ娣诲姞棰濆鐨勫垵濮嬪寲浠g爜
+ UpdateData(FALSE);
+ UpdateControlStatus(FALSE, FALSE);
+
+ // 鎵樼洏鍥炬爣鍒濆鍖�
+ m_trayIconData.cbSize = sizeof(NOTIFYICONDATA); // 璁剧疆鎵樼洏鍥炬爣鏁版嵁缁撴瀯鐨勫ぇ灏�
+ m_trayIconData.hWnd = m_hWnd; // 璁剧疆绐楀彛鍙ユ焺
+ m_trayIconData.uID = m_nTrayIconID; // 璁剧疆鎵樼洏鍥炬爣 ID
+ m_trayIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; // 璁剧疆鎵樼洏鍥炬爣鐨勬爣蹇楋紙鍥炬爣銆佹秷鎭�佹彁绀烘枃鏈級
+ m_trayIconData.uCallbackMessage = WM_TRAY_ICON_NOTIFY; // 璁剧疆鍥炶皟娑堟伅 WM_TRAY_ICON_NOTIFY
+ m_trayIconData.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); // 鍔犺浇鎵樼洏鍥炬爣
+ lstrcpy(m_trayIconData.szTip, TRAY_ICON_TOOLTIP_TEXT); // 璁剧疆鎵樼洏鎻愮ず鏂囨湰
+
+ // 娣诲姞鎵樼洏鍥炬爣
+ Shell_NotifyIcon(NIM_ADD, &m_trayIconData);
+ m_bTrayIconCreated = TRUE;
+
+ for (int i = 0; i < 4; i++) {
+ CString str;
+ str.Format(_T("OUT%d"), i + 1);
+ m_comboOutputPort.AddString(str);
+ }
+ m_comboOutputPort.SetCurSel(0);
+
+ // 鍒濆鍖朓P鍦板潃鎺т欢锛岃缃负榛樿IP鍦板潃
+ ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS))->SetAddress(192, 168, 0, 10);
+
+ // 鍒濆鍖栨棩蹇楁
+ AppendLogLineRichStyled(_T("鍑嗗灏辩华..."), LOG_COLOR_SUCCESS);
+
+ return TRUE; // 闄ら潪灏嗙劍鐐硅缃埌鎺т欢锛屽惁鍒欒繑鍥� TRUE
+}
+
+void CSGMeasurementDlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+ if ((nID & 0xFFF0) == IDM_ABOUTBOX)
+ {
+ CAboutDlg dlgAbout;
+ dlgAbout.DoModal();
+ }
+ else
+ {
+ CDialogEx::OnSysCommand(nID, lParam);
+ }
+}
+
+void CSGMeasurementDlg::OnPaint()
+{
+ if (IsIconic()) {
+ CPaintDC dc(this);
+
+ SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
+
+ // 浣垮浘鏍囧湪宸ヤ綔鍖虹煩褰腑灞呬腑
+ int cxIcon = GetSystemMetrics(SM_CXICON);
+ int cyIcon = GetSystemMetrics(SM_CYICON);
+ CRect rect;
+ GetClientRect(&rect);
+ int x = (rect.Width() - cxIcon + 1) / 2;
+ int y = (rect.Height() - cyIcon + 1) / 2;
+
+ // 缁樺埗鍥炬爣
+ dc.DrawIcon(x, y, m_hIcon);
+ }
+ else {
+ CDialogEx::OnPaint();
+ }
+}
+
+//褰撶敤鎴锋嫋鍔ㄦ渶灏忓寲绐楀彛鏃剁郴缁熻皟鐢ㄦ鍑芥暟鍙栧緱鍏夋爣鏄剧ず銆�
+HCURSOR CSGMeasurementDlg::OnQueryDragIcon()
+{
+ return static_cast<HCURSOR>(m_hIcon);
+}
+
+void CSGMeasurementDlg::OnTimer(UINT_PTR nIDEvent)
+{
+ // TODO: 鍦ㄦ娣诲姞娑堟伅澶勭悊绋嬪簭浠g爜鍜�/鎴栬皟鐢ㄩ粯璁ゅ��
+ if (nIDEvent == TIMER_ID_OUTPUT_UPDATE) {
+ SGIF_FLOATVALUE_OUT value[4] = { 0 };
+ RC nRet = SGIF_GetCalcDataALL(DeviceID, value);
+ if (nRet == RC_OK) {
+ for (int i = 0; i < 4; ++i) {
+ m_dOutValues[i] = value[i].Value;
+ }
+
+ // 鏇存柊缁戝畾鎺т欢
+ UpdateData(FALSE);
+ }
+ else {
+ CString strError;
+ strError.Format(_T("鑾峰彇娴嬮噺鍊煎け璐ワ紝閿欒鐮侊細%#X"), nRet);
+ AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
+
+ // 鏂紑杩炴帴
+ if (m_bConnected) {
+ DisconnectFromDevice();
+ }
+ }
+ }
+
+ CDialogEx::OnTimer(nIDEvent);
+}
+
+void CSGMeasurementDlg::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
+{
+ if (lpMeasureItemStruct->CtlType == ODT_MENU) {
+ lpMeasureItemStruct->itemHeight = 24;
+ lpMeasureItemStruct->itemWidth = 140;
+ }
+}
+
+void CSGMeasurementDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
+{
+ if (lpDrawItemStruct->CtlType != ODT_MENU) {
+ return;
+ }
+
+ CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
+ CRect rc = lpDrawItemStruct->rcItem;
+ UINT id = lpDrawItemStruct->itemID;
+
+ // 鑳屾櫙
+ COLORREF bgColor = (lpDrawItemStruct->itemState & ODS_SELECTED) ? RGB(200, 220, 255) : RGB(255, 255, 255);
+ pDC->FillSolidRect(rc, bgColor);
+
+ // 鍥炬爣
+ HICON hIcon = nullptr;
+ if (id == ID_TRAY_RESTORE) {
+ hIcon = AfxGetApp()->LoadIcon(IDI_ICON_RESTORE);
+ }
+
+ if (id == ID_TRAY_EXIT) {
+ hIcon = AfxGetApp()->LoadIcon(IDI_ICON_EXIT);
+ }
+
+ if (hIcon) {
+ DrawIconEx(pDC->GetSafeHdc(), rc.left + 4, rc.top + 4, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+ }
+
+ // 鏂囨湰
+ CString str;
+ if (id == ID_TRAY_RESTORE) {
+ str = _T("鎭㈠鐣岄潰");
+ }
+
+ if (id == ID_TRAY_EXIT) {
+ str = _T("閫�鍑虹▼搴�");
+ }
+
+ pDC->SetBkMode(TRANSPARENT);
+ pDC->SetTextColor(RGB(0, 0, 0));
+ pDC->DrawText(str, CRect(rc.left + 28, rc.top, rc.right, rc.bottom), DT_SINGLELINE | DT_VCENTER | DT_LEFT);
+}
+
+void CSGMeasurementDlg::OnClose()
+{
+ // TODO: 鍦ㄦ娣诲姞娑堟伅澶勭悊绋嬪簭浠g爜鍜�/鎴栬皟鐢ㄩ粯璁ゅ��
+ if (m_bExitingFromTray) {
+ // 浠庢墭鐩橀��鍑烘祦绋�
+ ExitApplication();
+ }
+ else {
+ // 姝e父鍏抽棴鎸夐挳
+ int nResult = AfxMessageBox(_T("鏄惁鏈�灏忓寲鍒版墭鐩橈紵"), MB_YESNO | MB_ICONQUESTION);
+ if (nResult == IDYES) {
+ ShowWindow(SW_HIDE);
+ }
+ else {
+ ExitApplication();
+ }
+ }
+}
+
+LRESULT CSGMeasurementDlg::OnTrayIconClick(WPARAM wParam, LPARAM lParam) {
+ if (wParam == m_nTrayIconID) {
+ if (LOWORD(lParam) == WM_LBUTTONUP) {
+ // 宸﹂敭鐐瑰嚮鎭㈠绐楀彛
+ ShowWindow(SW_SHOW);
+ SetForegroundWindow();
+ }
+ else if (LOWORD(lParam) == WM_RBUTTONUP) {
+ // 鍙抽敭鐐瑰嚮寮瑰嚭鑿滃崟
+ CMenu menu;
+ menu.CreatePopupMenu();
+ 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_RESTORE, &mii);
+
+ // 閫�鍑鸿彍鍗曢」鍥炬爣
+ mii.hbmpItem = HBMMENU_CALLBACK;
+ menu.SetMenuItemInfo(ID_TRAY_EXIT, &mii);
+
+ // 鑾峰彇榧犳爣褰撳墠浣嶇疆锛屽苟鏄剧ず鑿滃崟
+ POINT pt;
+ GetCursorPos(&pt);
+ SetForegroundWindow();
+ menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);
+ }
+ }
+ return 0;
+}
+
+void CSGMeasurementDlg::OnTrayRestore()
+{
+ ShowWindow(SW_SHOW); // 鎭㈠绐楀彛
+ SetForegroundWindow(); // 灏嗙獥鍙g疆浜庡墠绔�
+}
+
+void CSGMeasurementDlg::OnTrayExit()
+{
+ // 浠庢墭鐩樺浘鏍囪彍鍗曢�夋嫨鈥滈��鍑虹▼搴忊��
+ if (AfxMessageBox(_T("纭畾瑕侀��鍑虹▼搴忓悧锛�"), MB_YESNO | MB_ICONQUESTION) == IDYES) {
+ m_bExitingFromTray = TRUE;
+ PostMessage(WM_CLOSE);
+ }
+}
+
+void CSGMeasurementDlg::OnBnClickedButtonConnect()
+{
+ // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+ ConnectToDevice();
+}
+
+void CSGMeasurementDlg::OnBnClickedButtonDisconnect()
+{
+ // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+ DisconnectFromDevice();
+}
+
+void CSGMeasurementDlg::OnBnClickedButtonReceiveFromCtrl()
+{
+ // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+ if (!m_bConnected) {
+ AppendLogLineRichStyled(_T("璁惧鏈繛鎺ワ紝璇峰厛杩炴帴璁惧銆�"), LOG_COLOR_WARNING);
+ return;
+ }
+}
+
+void CSGMeasurementDlg::OnBnClickedButtonSendToCtrl()
+{
+ // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+ if (!m_bConnected) {
+ AppendLogLineRichStyled(_T("璁惧鏈繛鎺ワ紝璇峰厛杩炴帴璁惧銆�"), LOG_COLOR_WARNING);
+ return;
+ }
+}
+
+void CSGMeasurementDlg::OnBnClickedButtonClearStore()
+{
+ // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+ InitDataStorage();
+}
+
+void CSGMeasurementDlg::OnBnClickedButtonStartStore()
+{
+ // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+ StartDataStorage();
+ UpdateControlStatus(m_bConnected, m_bSaving);
+}
+
+void CSGMeasurementDlg::OnBnClickedButtonStopStore()
+{
+ // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+ StopDataStorage();
+ UpdateControlStatus(m_bConnected, m_bSaving);
+
+ int nSel = m_comboOutputPort.GetCurSel();
+ if (CB_ERR == nSel) {
+ AppendLogLineRichStyled(_T("璇烽�夋嫨涓�涓湁鏁堢殑杈撳嚭绔彛銆�"), LOG_COLOR_WARNING);
+ return;
+ }
+
+ int nOutNo = nSel + 1;
+ AnalyzeStoredData(nOutNo);
+}
+
+void CSGMeasurementDlg::OnBnClickedButtonClearLog()
+{
+ // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+ if (::IsWindow(m_editLog.GetSafeHwnd())) {
+ m_editLog.SetWindowText(_T(""));
+ }
+}
\ No newline at end of file
--
Gitblit v1.9.3