From 5a8bbd2426aeacdbbb2fdb1a7f7a1adce0cac7f9 Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期五, 01 八月 2025 16:23:29 +0800
Subject: [PATCH] 1. 新增以下功能函数并集成:    - InitStorage():初始化存储区域    - StartStorage():开始数据存储    - StopStorage():停止存储并自动提取、分析数据    - AnalyzeStoredData():分析指定端口数据,返回偏移量

---
 SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp |  993 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 993 insertions(+), 0 deletions(-)

diff --git a/SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp b/SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp
new file mode 100644
index 0000000..b946b61
--- /dev/null
+++ b/SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp
@@ -0,0 +1,993 @@
+锘�
+// SGMeasurementDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "pch.h"
+#include "framework.h"
+#include "SGMeasurement.h"
+#include "SGMeasurementDlg.h"
+#include "afxdialogex.h"
+#include "SGIF.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
+
+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(1.0f)
+	, 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& content, 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);
+
+	// 鎻掑叆鏃ュ織姝f枃锛堜紶鍏ラ鑹诧級
+	CHARFORMAT2 cfMsg = {};
+	cfMsg.cbSize = sizeof(cfMsg);
+	cfMsg.dwMask = CFM_COLOR;
+	cfMsg.crTextColor = color;
+	m_editLog.SetSelectionCharFormat(cfMsg);
+	m_editLog.ReplaceSel(content + _T("\r\n"));
+
+	// 闄愬埗鏈�澶ц鏁�
+	TrimRichEditLineLimit(100);
+}
+
+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;
+	}
+
+	RC nRet = SGIF_CloseDevice(DeviceID);
+	if (nRet == RC_OK) {
+		if (m_bSaving) {
+			m_bSaving = FALSE;
+			nRet = SGIF_DataStorageStop(DeviceID);
+			if (nRet == RC_OK) {
+				AppendLogLineRichStyled(_T("鏁版嵁瀛樺偍宸插仠姝€��"), LOG_COLOR_SUCCESS);
+			}
+			else {
+				CString strError;
+				strError.Format(_T("鍋滄鏁版嵁瀛樺偍澶辫触锛岄敊璇爜锛�%#X"), nRet);
+				AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
+			}
+		}
+
+		AppendLogLineRichStyled(_T("鏂紑杩炴帴鎴愬姛锛�"), LOG_COLOR_SUCCESS);
+
+		m_bConnected = FALSE;
+		UpdateControlStatus(FALSE, FALSE);
+		KillTimer(TIMER_ID_OUTPUT_UPDATE);
+		return true;
+	}
+	else {
+		CString strError;
+		strError.Format(_T("鏂紑杩炴帴澶辫触锛岄敊璇爜锛�%#X"), nRet);
+		AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
+
+		UpdateControlStatus(m_bConnected, m_bSaving);
+		return false;
+	}
+}
+
+void CSGMeasurementDlg::CleanInvalidValuesInPlace(int nOutNo, std::vector<float>& vecData, float fInvalid/* = -999.0f*/)
+{
+	// 鎵惧埌绗竴涓湁鏁堝��
+	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();
+	}
+}
+
+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 nMinGlass1Count /*= 10*/)
+{
+	const int n = static_cast<int>(vecData.size());
+	if (n < 2 * nWindow + 1 + nMinGlass1Count) {
+		CString strError;
+		strError.Format(_T("OUT%d: 鏁版嵁閲忎笉瓒筹紝鑷冲皯闇�瑕� %d 涓偣鎵嶈兘杩涜鍒囧壊銆�"), nOutNo, 2 * nWindow + 1 + nMinGlass1Count);
+		AppendLogLineRichStyled(strError, LOG_COLOR_WARNING);
+		return false;
+	}
+
+	int nValleyIdx = -1;
+	for (int i = nWindow; i < n - nWindow - nMinGlass1Count; ++i) {
+		float fDelta = std::fabs(vecData[i + nWindow] - vecData[i - nWindow]);
+		if (fDelta > fJumpThreshold) {
+			// 鎵� valley 鐐癸紙绋嶅井寰�鍚庤烦鍑犳浠ラ伩寮�杈圭紭鎶栧姩锛�
+			int nSearchStart = i + nWindow + 2;
+			int nSearchEnd = min(nSearchStart + 10, n);
+
+			auto itValley = std::min_element(vecData.begin() + nSearchStart, vecData.begin() + nSearchEnd,
+				[](float a, float b) {
+					return (a > -900.0f && b > -900.0f) ? a < b : false;
+				});
+
+			if (itValley != vecData.begin() + nSearchEnd) {
+				nValleyIdx = static_cast<int>(std::distance(vecData.begin(), itValley));
+				break;
+			}
+		}
+	}
+
+	if (nValleyIdx < 0 || nValleyIdx < nMinGlass1Count) {
+		AppendLogLineRichStyled(_T("鏈壘鍒板悎閫� valley 鐐癸紝鎴� valley 澶潬鍓嶃��"), LOG_COLOR_WARNING);
+		return false;
+	}
+
+	// 浠� valley 澶勫紑濮嬪垏鍓诧紝鎴栬�呭線鍚庡亸绉�
+	int nCutStart = min(nValleyIdx + nValleyMargin, n);
+	vecGlass1.assign(vecData.begin(), vecData.begin() + nCutStart);
+	vecGlass2.assign(vecData.begin() + nCutStart, vecData.end());
+
+	int nGlass1Count = static_cast<int>(vecGlass1.size());
+	int nGlass2Count = static_cast<int>(vecGlass2.size());
+
+	// 鏃ュ織杈撳嚭
+	CString strLog;
+	strLog.Format(_T("OUT%d: 鍒囧壊鎴愬姛锛岀涓�鐗囩幓鐠冩暟鎹噺 %d锛岀浜岀墖鐜荤拑鏁版嵁閲� %d銆�"), nOutNo, nGlass1Count, nGlass2Count);
+	AppendLogLineRichStyled(strLog, LOG_COLOR_SUCCESS);
+
+	if (nGlass1Count < nMinGlass1Count) {
+		strLog.Format(_T("OUT%d: 绗竴鐗囩幓鐠冩暟鎹噺杩囧皯锛屽彲鑳藉奖鍝嶅悗缁鐞嗐��"), nOutNo);
+		AppendLogLineRichStyled(strLog, LOG_COLOR_WARNING);
+	}
+	if (nGlass2Count < nMinGlass1Count) {
+		strLog.Format(_T("OUT%d: 绗簩鐗囩幓鐠冩暟鎹噺杩囧皯锛屽彲鑳藉奖鍝嶅悗缁鐞嗐��"), nOutNo);
+		AppendLogLineRichStyled(strLog, LOG_COLOR_WARNING);
+	}
+
+	AppendLogLineRichStyled(_T("绗竴鐗囩幓鐠冩暟鎹細"), LOG_COLOR_NORMAL);
+	PrintSampleData(nOutNo, vecGlass1);
+
+	AppendLogLineRichStyled(_T("绗簩鐗囩幓鐠冩暟鎹細"), LOG_COLOR_NORMAL);
+	PrintSampleData(nOutNo, vecGlass2);
+
+	return !vecGlass1.empty() && !vecGlass2.empty();
+}
+
+bool CSGMeasurementDlg::ExtractStableRegionFixed(int nOutNo, const std::vector<float>& vecIn, std::vector<float>& vecOut, int nFixedCount/* = 5*/, float fMaxDelta/* = 0.04f*/)
+{
+	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);
+
+	return true;
+}
+
+bool CSGMeasurementDlg::CalcGlassOffset(const std::vector<float>& vecGlass1, const std::vector<float>& vecGlass2, float& fAvg1, float& fAvg2, float& fOffset)
+{
+	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);
+
+	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)
+{
+	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> 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);
+	}
+
+	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);
+		}
+	}
+
+	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