From f71f467b68ce6c8dc6c983a2963ec9b131515441 Mon Sep 17 00:00:00 2001
From: chenluhua1980 <Chenluhua@qq.com>
Date: 星期三, 10 十二月 2025 17:55:02 +0800
Subject: [PATCH] 1.实现删除变量的功能;

---
 SourceCode/Bond/Servo/CHMPropertyPage.h   |    5 +
 SourceCode/Bond/Servo/CHMPropertyDlg.cpp  |   24 +++++
 SourceCode/Bond/Servo/CPageVarialbles.cpp |   43 ++++++++++
 SourceCode/Bond/Servo/HsmsPassive.h       |    4 +
 SourceCode/Bond/Servo/CHMPropertyDlg.h    |    1 
 SourceCode/Bond/Servo/CPageVarialbles.h   |    4 +
 SourceCode/Bond/Servo/HsmsPassive.cpp     |  102 +++++++++++++++++++++++++
 SourceCode/Bond/Servo/CHMPropertyPage.cpp |   10 ++
 8 files changed, 191 insertions(+), 2 deletions(-)

diff --git a/SourceCode/Bond/Servo/CHMPropertyDlg.cpp b/SourceCode/Bond/Servo/CHMPropertyDlg.cpp
index e6bba3e..59cce8a 100644
--- a/SourceCode/Bond/Servo/CHMPropertyDlg.cpp
+++ b/SourceCode/Bond/Servo/CHMPropertyDlg.cpp
@@ -5,6 +5,7 @@
 #include "Servo.h"
 #include "CHMPropertyDlg.h"
 #include "afxdialogex.h"
+#include <algorithm>
 
 
 // CEquipmentDlg 瀵硅瘽妗�
@@ -159,11 +160,11 @@
 	pItem->GetWindowRect(&rcItem);
 	pItem->MoveWindow(x2 - rcItem.Width(), y2 - rcItem.Height(),
 		rcItem.Width(), rcItem.Height());
-	y2 -= rcItem.Height() + 12;
 
 	// 褰撳墠瀛愰〉鎸夐挳锛堝鏋滄湁锛�
-	int btnY = y2 - rcItem.Height(); // 淇濇寔涓庡簲鐢ㄦ寜閽悓楂�
+	int btnY = y2 - rcItem.Height();
 	int btnX = 12;
+	y2 -= rcItem.Height() + 12;
 	int curIndex = (m_pTab != nullptr) ? m_pTab->GetCurSel() : 0;
 	if (curIndex >= 0 && curIndex < (int)m_pages.size()) {
 		auto& btnMap = m_pages[curIndex]->getBtns();
@@ -284,3 +285,22 @@
 		}
 	}
 }
+
+BOOL CHMPropertyDlg::OnCommand(WPARAM wParam, LPARAM lParam)
+{
+	UINT code = HIWORD(wParam);
+	HWND hCtrl = (HWND)lParam;
+
+	if (code == BN_CLICKED && hCtrl != nullptr) {
+		for (auto page : m_pages) {
+			for (auto& kv : page->getBtns()) {
+				if (kv.second != nullptr && kv.second->GetSafeHwnd() == hCtrl) {
+					page->HandleBtnClick(hCtrl);
+					return TRUE;
+				}
+			}
+		}
+	}
+
+	return CDialogEx::OnCommand(wParam, lParam);
+}
diff --git a/SourceCode/Bond/Servo/CHMPropertyDlg.h b/SourceCode/Bond/Servo/CHMPropertyDlg.h
index 243680b..43b8f25 100644
--- a/SourceCode/Bond/Servo/CHMPropertyDlg.h
+++ b/SourceCode/Bond/Servo/CHMPropertyDlg.h
@@ -51,4 +51,5 @@
 	afx_msg void OnTabSelChanged(NMHDR* nmhdr, LRESULT* result);
 	afx_msg void OnBnClickedOk();
 	afx_msg void OnBnClickedButtonApply();
+	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
 };
diff --git a/SourceCode/Bond/Servo/CHMPropertyPage.cpp b/SourceCode/Bond/Servo/CHMPropertyPage.cpp
index d692eb8..f5626b6 100644
--- a/SourceCode/Bond/Servo/CHMPropertyPage.cpp
+++ b/SourceCode/Bond/Servo/CHMPropertyPage.cpp
@@ -58,6 +58,16 @@
 	return m_btns;
 }
 
+void CHMPropertyPage::HandleBtnClick(HWND hBtn)
+{
+	for (auto& kv : m_btns) {
+		if (kv.second != nullptr && kv.second->GetSafeHwnd() == hBtn) {
+			OnClickedBtn(kv.first.c_str());
+			break;
+		}
+	}
+}
+
 BEGIN_MESSAGE_MAP(CHMPropertyPage, CDialogEx)
 	ON_WM_DESTROY()
 END_MESSAGE_MAP()
diff --git a/SourceCode/Bond/Servo/CHMPropertyPage.h b/SourceCode/Bond/Servo/CHMPropertyPage.h
index 446215d..33e53b4 100644
--- a/SourceCode/Bond/Servo/CHMPropertyPage.h
+++ b/SourceCode/Bond/Servo/CHMPropertyPage.h
@@ -14,6 +14,11 @@
 	afx_msg void OnDestroy();
 	std::map<std::string, CButton*>& getBtns();
 	CButton* GetBtnByName(const char* name);
+	void HandleBtnClick(HWND hBtn);
+
+protected:
+	// 瀛愮被鍙噸鍐欙細鏂板/鍒犻櫎/缂栬緫鎸夐挳鐐瑰嚮澶勭悊
+	virtual void OnClickedBtn(const char* btnName) {};
 
 protected:
 	CButton* CreateBtn(const char* name, int w, int h, const UINT id);
diff --git a/SourceCode/Bond/Servo/CPageVarialbles.cpp b/SourceCode/Bond/Servo/CPageVarialbles.cpp
index 7a6b34f..b379c18 100644
--- a/SourceCode/Bond/Servo/CPageVarialbles.cpp
+++ b/SourceCode/Bond/Servo/CPageVarialbles.cpp
@@ -32,6 +32,7 @@
 	ON_WM_CTLCOLOR()
 	ON_WM_DESTROY()
 	ON_WM_SIZE()
+	ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, &CPageVarialbles::OnLvnItemchangedList1)
 END_MESSAGE_MAP()
 
 
@@ -139,3 +140,45 @@
 	CreateBtn(_T("鍒犻櫎"), BTN_W, BTN_H, 1002)->EnableWindow(FALSE);
 	CreateBtn(_T("缂栬緫"), BTN_W, BTN_H, 1003)->EnableWindow(FALSE);
 }
+
+void CPageVarialbles::OnLvnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult)
+{
+	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
+	int nSelCount = m_listCtrl.GetSelectedCount();
+
+	// 鏍规嵁閫変腑鐘舵�佸惎鐢�/绂佺敤鎸夐挳
+	if (CButton* pDel = GetBtnByName("鍒犻櫎")) {
+		pDel->EnableWindow(nSelCount > 0);
+	}
+	if (CButton* pEdit = GetBtnByName("缂栬緫")) {
+		pEdit->EnableWindow(nSelCount > 0);
+	}
+
+	*pResult = 0;
+}
+
+void CPageVarialbles::OnClickedBtn(const char* btnName)
+{
+	ASSERT(btnName);
+	if (_strcmpi(btnName, "鏂板") == 0) {
+		// TODO: 鏂板閫昏緫
+	}
+	else if (_strcmpi(btnName, "鍒犻櫎") == 0) {
+		POSITION pos = m_listCtrl.GetFirstSelectedItemPosition();
+		if (pos == nullptr) return;
+		int nItem = m_listCtrl.GetNextSelectedItem(pos);
+		auto pVar = reinterpret_cast<SERVO::CVariable*>(m_listCtrl.GetItemData(nItem));
+		if (pVar == nullptr) return;
+
+		int ret = theApp.m_model.m_hsmsPassive.deleteVariable(pVar->getVarialbleId());
+		if (ret == 0) {
+			m_listCtrl.DeleteAllItems();
+			loadVariables();
+			if (CButton* pDel = GetBtnByName("鍒犻櫎")) pDel->EnableWindow(FALSE);
+			if (CButton* pEdit = GetBtnByName("缂栬緫")) pEdit->EnableWindow(FALSE);
+		}
+	}
+	else if (_strcmpi(btnName, "缂栬緫") == 0) {
+		// TODO: 缂栬緫閫昏緫
+	}
+}
diff --git a/SourceCode/Bond/Servo/CPageVarialbles.h b/SourceCode/Bond/Servo/CPageVarialbles.h
index 6055dc6..3898e68 100644
--- a/SourceCode/Bond/Servo/CPageVarialbles.h
+++ b/SourceCode/Bond/Servo/CPageVarialbles.h
@@ -19,6 +19,9 @@
 private:
 	CListCtrlEx m_listCtrl;
 
+protected:
+	virtual void OnClickedBtn(const char* btnName) override;
+
 
 // 瀵硅瘽妗嗘暟鎹�
 #ifdef AFX_DESIGN_TIME
@@ -34,4 +37,5 @@
 	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
 	afx_msg void OnDestroy();
 	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg void OnLvnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult);
 };
diff --git a/SourceCode/Bond/Servo/HsmsPassive.cpp b/SourceCode/Bond/Servo/HsmsPassive.cpp
index e73919d..3315b32 100644
--- a/SourceCode/Bond/Servo/HsmsPassive.cpp
+++ b/SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -228,6 +228,9 @@
 
 int CHsmsPassive::loadVarialbles(const char* pszFilepath)
 {
+	m_strVariableFilepath = pszFilepath;
+	m_bVariableUtf8 = false;
+	m_bVariableUtf8Bom = false;
 	// 鍏堣鍘熷瀛楄妭锛屽悗缁啀鎸� UTF-8/BOM 鎴栨湰鍦扮紪鐮佽浆鎹�
 	CFile file;
 	if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
@@ -251,6 +254,8 @@
 	// UTF-8 BOM
 	if (nLen >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
 		offset = 3;
+		m_bVariableUtf8 = true;
+		m_bVariableUtf8Bom = true;
 	}
 
 	// UTF-16 LE BOM
@@ -281,6 +286,7 @@
 			MultiByteToWideChar(CP_UTF8, 0, buffer.data() + off,
 				static_cast<int>(buffer.size() - off), temp.data(), need);
 			content = temp.c_str();
+			m_bVariableUtf8 = true;
 			return true;
 		};
 
@@ -397,6 +403,102 @@
 	m_variabels.clear();
 }
 
+CStringA WideToUtf8(const CStringW& ws)
+{
+	int need = WideCharToMultiByte(CP_UTF8, 0, ws, -1, nullptr, 0, nullptr, nullptr);
+	if (need <= 0) return "";
+	CStringA out;
+	LPSTR buf = out.GetBufferSetLength(need - 1);
+	WideCharToMultiByte(CP_UTF8, 0, ws, -1, buf, need, nullptr, nullptr);
+	out.ReleaseBuffer();
+	return out;
+}
+
+CStringA WideToAnsi(const CStringW& ws)
+{
+	int need = WideCharToMultiByte(CP_ACP, 0, ws, -1, nullptr, 0, nullptr, nullptr);
+	if (need <= 0) return "";
+	CStringA out;
+	LPSTR buf = out.GetBufferSetLength(need - 1);
+	WideCharToMultiByte(CP_ACP, 0, ws, -1, buf, need, nullptr, nullptr);
+	out.ReleaseBuffer();
+	return out;
+}
+
+static CStringA AnsiToUtf8(const std::string& s)
+{
+	int wlen = MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, nullptr, 0);
+	if (wlen <= 0) return "";
+	CStringW ws;
+	LPWSTR wbuf = ws.GetBufferSetLength(wlen - 1);
+	MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, wbuf, wlen);
+	ws.ReleaseBuffer();
+	return WideToUtf8(ws);
+}
+
+int CHsmsPassive::deleteVariable(int variableId)
+{
+	Lock();
+	auto it = std::find_if(m_variabels.begin(), m_variabels.end(), [=](SERVO::CVariable* v) {
+		return v != nullptr && v->getVarialbleId() == variableId;
+		});
+	if (it == m_variabels.end()) {
+		Unlock();
+		return -1;
+	}
+	delete *it;
+	m_variabels.erase(it);
+	auto filepath = m_strVariableFilepath;
+	Unlock();
+
+	if (filepath.empty()) return -2;
+
+	// 鍐欏洖鏂囦欢锛屼繚鎸佸師缂栫爜锛圲TF-8 鎴栨湰鍦扮紪鐮侊級
+	CFile file;
+	if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone)) {
+		return -3;
+	}
+
+	// header
+	const std::string headerAnsi = "SVID,SV Name,SV Format,SV Remark\r\n";
+	if (m_bVariableUtf8) {
+		if (m_bVariableUtf8Bom) {
+			const BYTE bom[3] = { 0xEF, 0xBB, 0xBF };
+			file.Write(bom, 3);
+		}
+		CStringA header = AnsiToUtf8(headerAnsi);
+		file.Write(header.GetString(), header.GetLength());
+	}
+	else {
+		file.Write(headerAnsi.data(), (UINT)headerAnsi.size());
+	}
+
+	for (auto v : m_variabels) {
+		if (v == nullptr) continue;
+		std::string lineAnsi;
+		lineAnsi.reserve(256);
+		lineAnsi += std::to_string(v->getVarialbleId());
+		lineAnsi.push_back(',');
+		lineAnsi += v->getName();
+		lineAnsi.push_back(',');
+		lineAnsi += SERVO::CVariable::formatToString(v->getFormat());
+		lineAnsi.push_back(',');
+		lineAnsi += v->getRemark();
+		lineAnsi.append("\r\n");
+
+		if (m_bVariableUtf8) {
+			CStringA outLine = AnsiToUtf8(lineAnsi);
+			file.Write(outLine.GetString(), outLine.GetLength());
+		}
+		else {
+			file.Write(lineAnsi.data(), (UINT)lineAnsi.size());
+		}
+	}
+	file.Close();
+
+	return 0;
+}
+
 void CHsmsPassive::setVariableValue(const char* pszName, __int64 value)
 {
 	auto v = getVariable(pszName);
diff --git a/SourceCode/Bond/Servo/HsmsPassive.h b/SourceCode/Bond/Servo/HsmsPassive.h
index de60213..737f6c4 100644
--- a/SourceCode/Bond/Servo/HsmsPassive.h
+++ b/SourceCode/Bond/Servo/HsmsPassive.h
@@ -146,6 +146,7 @@
 	// 鍙栧緱鎸囧畾Variable
 	SERVO::CVariable* getVariable(int variableId);
 	SERVO::CVariable* getVariable(const char* pszName);
+	int deleteVariable(int variableId);
 
 	// 璁剧疆鍙橀噺鍊�
 	void setVariableValue(const char* pszName, __int64 value);
@@ -251,6 +252,9 @@
 
 private:
 	SECSListener m_listener;
+	std::string m_strVariableFilepath;
+	bool m_bVariableUtf8{ false };
+	bool m_bVariableUtf8Bom{ false };
 	BOOL m_bCimWorking;
 	HANDLE m_hCimWorkEvent;
 	HANDLE m_hCimWorkThreadHandle;

--
Gitblit v1.9.3