| | |
| | | #include "Servo.h" |
| | | #include "CHMPropertyDlg.h" |
| | | #include "afxdialogex.h" |
| | | #include <algorithm> |
| | | |
| | | |
| | | // CEquipmentDlg 对话框 |
| | |
| | | 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(); |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | 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); |
| | | } |
| | |
| | | afx_msg void OnTabSelChanged(NMHDR* nmhdr, LRESULT* result); |
| | | afx_msg void OnBnClickedOk(); |
| | | afx_msg void OnBnClickedButtonApply(); |
| | | virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); |
| | | }; |
| | |
| | | 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() |
| | |
| | | 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); |
| | |
| | | ON_WM_CTLCOLOR() |
| | | ON_WM_DESTROY() |
| | | ON_WM_SIZE() |
| | | ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, &CPageVarialbles::OnLvnItemchangedList1) |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | |
| | | 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: 编辑逻辑 |
| | | } |
| | | } |
| | |
| | | private: |
| | | CListCtrlEx m_listCtrl; |
| | | |
| | | protected: |
| | | virtual void OnClickedBtn(const char* btnName) override; |
| | | |
| | | |
| | | // 对话框数据 |
| | | #ifdef AFX_DESIGN_TIME |
| | |
| | | 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); |
| | | }; |
| | |
| | | |
| | | 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)) { |
| | |
| | | // 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 |
| | |
| | | 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; |
| | | }; |
| | | |
| | |
| | | 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; |
| | | |
| | | // 写回文件,保持原编码(UTF-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); |
| | |
| | | // 取得指定Variable |
| | | SERVO::CVariable* getVariable(int variableId); |
| | | SERVO::CVariable* getVariable(const char* pszName); |
| | | int deleteVariable(int variableId); |
| | | |
| | | // 设置变量值 |
| | | void setVariableValue(const char* pszName, __int64 value); |
| | |
| | | |
| | | 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; |