Merge branch 'liuyang' into clh
# Conflicts:
# SourceCode/Bond/Servo/Servo.vcxproj.filters
# SourceCode/Bond/Servo/ServoDlg.cpp
# SourceCode/Bond/Servo/ServoDlg.h
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // AddPLCInfo.cpp: å®ç°æä»¶ |
| | | // |
| | | |
| | | #include "stdafx.h" |
| | | #include "BoounionPLC.h" |
| | | #include "afxdialogex.h" |
| | | #include "AddPLCInfo.h" |
| | | |
| | | |
| | | // CAddPLCInfo å¯¹è¯æ¡ |
| | | |
| | | IMPLEMENT_DYNAMIC(CAddPLCInfo, CDialogEx) |
| | | |
| | | CAddPLCInfo::CAddPLCInfo(CWnd* pParent /*=nullptr*/) |
| | | : CDialogEx(IDD_DIALOG_ADD_PLC_INFO, pParent) |
| | | { |
| | | |
| | | } |
| | | |
| | | CAddPLCInfo::~CAddPLCInfo() |
| | | { |
| | | } |
| | | |
| | | CString CAddPLCInfo::GetPLCName() { return m_strPLCName; } |
| | | |
| | | CString CAddPLCInfo::GetIP() { return m_strIP; } |
| | | |
| | | CString CAddPLCInfo::GetPort() { return m_strPort; } |
| | | |
| | | bool CAddPLCInfo::IsValidPort(const CString& strPort) |
| | | { |
| | | // 夿æ¯å¦ä¸ºæ°å |
| | | for (int i = 0; i < strPort.GetLength(); ++i) { |
| | | if (!_istdigit(strPort[i])) { |
| | | return false; // éæ°å |
| | | } |
| | | } |
| | | |
| | | // 转æ¢ä¸ºæ´æ°å¹¶å¤æèå´ |
| | | int nPort = _ttoi(strPort); |
| | | return nPort >= 1 && nPort <= 65535; |
| | | } |
| | | |
| | | bool CAddPLCInfo::IsValidIPAddress(const CString& strIP1, const CString& strIP2, const CString& strIP3, const CString& strIP4) |
| | | { |
| | | // æ ¡éªæ¯ä¸æ®µæ¯å¦æ¯æ°åå¹¶å¨èå´å
|
| | | return IsValidIPSegment(strIP1) && |
| | | IsValidIPSegment(strIP2) && |
| | | IsValidIPSegment(strIP3) && |
| | | IsValidIPSegment(strIP4); |
| | | } |
| | | |
| | | bool CAddPLCInfo::IsValidIPSegment(const CString& strSegment) |
| | | { |
| | | // 夿æ¯å¦ä¸ºæ°å |
| | | for (int i = 0; i < strSegment.GetLength(); ++i) { |
| | | if (!_istdigit(strSegment[i])) { |
| | | return false; // éæ°å |
| | | } |
| | | } |
| | | |
| | | // 转æ¢ä¸ºæ´æ°å¹¶å¤æèå´ |
| | | int nSegment = _ttoi(strSegment); |
| | | return nSegment >= 0 && nSegment <= 255; |
| | | } |
| | | |
| | | void CAddPLCInfo::DoDataExchange(CDataExchange* pDX) |
| | | { |
| | | CDialogEx::DoDataExchange(pDX); |
| | | DDX_Control(pDX, IDC_EDIT_PLC_NAME, m_editPLCName); |
| | | DDX_Control(pDX, IDC_EDIT_PORT, m_editPort); |
| | | } |
| | | |
| | | |
| | | BEGIN_MESSAGE_MAP(CAddPLCInfo, CDialogEx) |
| | | ON_BN_CLICKED(IDOK, &CAddPLCInfo::OnBnClickedOk) |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | | // CAddPLCInfo æ¶æ¯å¤çç¨åº |
| | | |
| | | |
| | | void CAddPLCInfo::OnBnClickedOk() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | CString strIPAddr1; |
| | | CString strIPAddr2; |
| | | CString strIPAddr3; |
| | | CString strIPAddr4; |
| | | |
| | | m_editPLCName.GetWindowText(m_strPLCName); |
| | | if (m_strPLCName.IsEmpty()) { |
| | | AfxMessageBox(_T("PLC åç§°ä¸è½ä¸ºç©ºï¼")); |
| | | return; |
| | | } |
| | | |
| | | // æ ¡éªç«¯å£å· |
| | | m_editPort.GetWindowText(m_strPort); |
| | | if (!IsValidPort(m_strPort)) { |
| | | AfxMessageBox(_T("端å£å·ä¸åæ³ï¼è¯·è¾å
¥ 1 å° 65535 ä¹é´çæ°åã")); |
| | | return; |
| | | } |
| | | |
| | | // æ ¡éªIPå°å |
| | | GetDlgItem(IDC_EDIT_IP_ADDR1)->GetWindowText(strIPAddr1); |
| | | GetDlgItem(IDC_EDIT_IP_ADDR2)->GetWindowText(strIPAddr2); |
| | | GetDlgItem(IDC_EDIT_IP_ADDR3)->GetWindowText(strIPAddr3); |
| | | GetDlgItem(IDC_EDIT_IP_ADDR4)->GetWindowText(strIPAddr4); |
| | | |
| | | if (strIPAddr1.IsEmpty() || strIPAddr2.IsEmpty() || strIPAddr3.IsEmpty() || strIPAddr4.IsEmpty()) { |
| | | AfxMessageBox(_T("IP å°åä¸åæ³ï¼æ¯æ®µä¸è½ä¸ºç©ºã")); |
| | | return; |
| | | } |
| | | |
| | | if (!IsValidIPAddress(strIPAddr1, strIPAddr2, strIPAddr3, strIPAddr4)) { |
| | | AfxMessageBox(_T("IP å°åä¸åæ³ï¼æ¯æ®µå¿
é¡»æ¯ 0 å° 255 çæ°åã")); |
| | | return; |
| | | } |
| | | |
| | | // æ¼æ¥IPå°å |
| | | m_strIP.Format(_T("%s.%s.%s.%s"), strIPAddr1, strIPAddr2, strIPAddr3, strIPAddr4); |
| | | |
| | | CDialogEx::OnOK(); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include "afxdialogex.h" |
| | | |
| | | |
| | | // CAddPLCInfo å¯¹è¯æ¡ |
| | | |
| | | class CAddPLCInfo : public CDialogEx |
| | | { |
| | | DECLARE_DYNAMIC(CAddPLCInfo) |
| | | |
| | | public: |
| | | CAddPLCInfo(CWnd* pParent = nullptr); // æ åæé 彿° |
| | | virtual ~CAddPLCInfo(); |
| | | |
| | | // è·åplcåç§°\ip\ç«¯å£ |
| | | CString GetPLCName(); |
| | | CString GetIP(); |
| | | CString GetPort(); |
| | | |
| | | // å¯¹è¯æ¡æ°æ® |
| | | #ifdef AFX_DESIGN_TIME |
| | | enum { IDD = IDD_DIALOG_ADD_PLC_INFO }; |
| | | #endif |
| | | |
| | | protected: |
| | | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV æ¯æ |
| | | afx_msg void OnBnClickedOk(); |
| | | DECLARE_MESSAGE_MAP() |
| | | |
| | | private: |
| | | bool IsValidPort(const CString& strPort); |
| | | bool IsValidIPAddress(const CString& strIP1, const CString& strIP2, const CString& strIP3, const CString& strIP4); |
| | | bool IsValidIPSegment(const CString& strSegment); |
| | | |
| | | // æ°æ® |
| | | CString m_strPLCName; |
| | | CString m_strIP; |
| | | CString m_strPort; |
| | | |
| | | // æ§ä»¶ |
| | | CEdit m_editPLCName; |
| | | CEdit m_editPort; |
| | | }; |
| | |
| | | strTitle.Format(_T("è½´ç»é¨è®¾å®(PLC: %s)"), m_pPLC->getName().c_str()); |
| | | SetWindowText(strTitle); |
| | | |
| | | // ä¸å¯ç¼è¾ |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_POS_MIN)->EnableWindow(FALSE); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED_MIN)->EnableWindow(FALSE); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME_MIN)->EnableWindow(FALSE); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME_MAX)->EnableWindow(FALSE); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME_MIN)->EnableWindow(FALSE); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME_MAX)->EnableWindow(FALSE); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM_MIN)->EnableWindow(FALSE); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM_MAX)->EnableWindow(FALSE); |
| | | |
| | | // è·åè½´æ°æ® |
| | | auto axisDetails = m_pAxisManager->GetAxis(m_nAxisNO); |
| | | if (axisDetails.id == -1) { |
| | |
| | | #include "AxisDetailSettingsDlg.h" |
| | | #include "ToolUnits.h" |
| | | #include <cctype> |
| | | #include <regex> |
| | | |
| | | |
| | | #define COLOR_GREEN_ON RGB(0, 255, 0) // æ£å¸¸ç¶æç»¿è² |
| | |
| | | m_pBlBtns[i] = new CBlButton(); |
| | | } |
| | | |
| | | for (int i = 0; i < EDIT_MAX; i++) { |
| | | m_pRegexEdit[i] = new CRegexEdit(); |
| | | } |
| | | |
| | | for (int i = 0; i < LABEL_MAX; i++) { |
| | | m_pBlLabels[i] = new CBLLabel(); |
| | | } |
| | |
| | | { |
| | | for (int i = 0; i < BTN_MAX; i++) { |
| | | delete m_pBlBtns[i]; |
| | | } |
| | | |
| | | for (int i = 0; i < EDIT_MAX; i++) { |
| | | delete m_pRegexEdit[i]; |
| | | } |
| | | |
| | | for (int i = 0; i < LABEL_MAX; i++) { |
| | |
| | | SetLabelColorBasedOnState(*m_pBlLabels[LABEL_ERR], m_bErr, COLOR_RED, COLOR_GREEN_OFF); |
| | | } |
| | | |
| | | void CAxisSettingsDlg::UpdateRegexEdit(CRegexEdit* pRegexEdit, const ValueRange& range, const CString& title) |
| | | { |
| | | auto formatDouble = [](double value) -> CString { |
| | | CString str; |
| | | str.Format(_T("%.3f"), value); |
| | | return str; |
| | | }; |
| | | |
| | | pRegexEdit->SetWindowText(formatDouble(range.currentValue)); |
| | | pRegexEdit->SetRegexType(RegexType::Decimal); |
| | | pRegexEdit->SetValueRange(range.minValue, range.maxValue); |
| | | pRegexEdit->SetInvalidInputCallback([title, range]() { |
| | | CString strError; |
| | | strError.Format(_T("%sçå¼å¿
é¡»å¨ %.3f å %.3f ä¹é´ï¼"), title, range.minValue, range.maxValue); |
| | | AfxMessageBox(strError); |
| | | }); |
| | | } |
| | | |
| | | void CAxisSettingsDlg::UpdatePageButtonStates() |
| | | { |
| | | for (int i = 0; i < AXIS_PAGE_SIZE; ++i) { |
| | |
| | | m_staticAxisDescription.SetWindowText(CString(axisDetails.description.c_str())); // è½´æè¿° |
| | | m_staticStartAddress.SetWindowText(CString(axisDetails.startAddress.c_str())); // èµ·å§å°å |
| | | |
| | | UpdateRegexEdit(m_pRegexEdit[EDIT_MICROMENTUM], axisDetails.jogDistance, _T("å¾®å¨é")); |
| | | UpdateRegexEdit(m_pRegexEdit[EDIT_MANUAL_SPEED], axisDetails.manualSpeed, _T("æå¨é度")); |
| | | UpdateRegexEdit(m_pRegexEdit[EDIT_AUTO_SPEED], axisDetails.autoSpeed, _T("èªå¨é度")); |
| | | UpdateRegexEdit(m_pRegexEdit[EDIT_ACCE_TIME], axisDetails.accelerationTime, _T("å éæ¶é´")); |
| | | UpdateRegexEdit(m_pRegexEdit[EDIT_DECE_TIME], axisDetails.decelerationTime, _T("åéæ¶é´")); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_MANUAL_SPEED)->SetWindowText(formatDouble(axisDetails.manualSpeed.currentValue)); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED)->SetWindowText(formatDouble(axisDetails.autoSpeed.currentValue)); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME)->SetWindowText(formatDouble(axisDetails.accelerationTime.currentValue)); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME)->SetWindowText(formatDouble(axisDetails.decelerationTime.currentValue)); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM)->SetWindowText(formatDouble(axisDetails.jogDistance.currentValue)); |
| | | } |
| | | |
| | | void CAxisSettingsDlg::RefreshPositionDetails(int nAxisId, int pageNumber) |
| | |
| | | CString value; |
| | | value.Format(_T("%.3f"), position.range.currentValue); |
| | | if (pPositionCtrl) { |
| | | pPositionCtrl->SetWindowText(value); |
| | | pPositionCtrl->EnableWindow(position.isEnable); |
| | | |
| | | if (position.isEnable) { |
| | | if (!IsFloatInRange((LPTSTR)(LPCTSTR)value, position.range.minValue, position.range.maxValue)) { |
| | | CString strError; |
| | | strError.Format(_T("å®ä½ç¹%d"), i + 1); |
| | | UpdateRegexEdit((CRegexEdit*)pPositionCtrl, position.range, strError); |
| | | strError.Format(_T("å®ä½ç¹%då¼å¿
é¡»å¨ %.3f å %.3f ä¹é´ï¼"), i + 1, position.range.minValue, position.range.maxValue); |
| | | ShowTipText(strError, 5); |
| | | } |
| | | else { |
| | | pPositionCtrl->SetWindowText(value); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | // 夿è¾å
¥ç弿¯å¦å¨åæ³èå´å
|
| | | if (enteredValue < minValue || enteredValue > maxValue) { |
| | | CString strError; |
| | | strError.Format(_T("å®ä½ç¹çå¼å¿
é¡»å¨ %f å %f ä¹é´ï¼"), minValue, maxValue); |
| | | pDescriptionCtrl->SetWindowText(strError); |
| | | strError.Format(_T("å®ä½ç¹%dçå¼å¿
é¡»å¨ %f å %f ä¹é´ï¼"), currentIndex + 1, minValue, maxValue); |
| | | ShowTipText(strError, 5); |
| | | } |
| | | else { |
| | | position.range.currentValue = enteredValue; |
| | |
| | | |
| | | // è·åçé¢ä¸çä¿®æ¹åæ° |
| | | CString text; |
| | | m_pRegexEdit[EDIT_MANUAL_SPEED]->GetWindowText(text); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_MANUAL_SPEED)->GetWindowText(text); |
| | | axisData.manualSpeed.currentValue = _ttof(text); |
| | | |
| | | m_pRegexEdit[EDIT_AUTO_SPEED]->GetWindowText(text); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED)->GetWindowText(text); |
| | | axisData.autoSpeed.currentValue = _ttof(text); |
| | | |
| | | m_pRegexEdit[EDIT_ACCE_TIME]->GetWindowText(text); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME)->GetWindowText(text); |
| | | axisData.accelerationTime.currentValue = _ttof(text); |
| | | |
| | | m_pRegexEdit[EDIT_DECE_TIME]->GetWindowText(text); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME)->GetWindowText(text); |
| | | axisData.decelerationTime.currentValue = _ttof(text); |
| | | |
| | | m_pRegexEdit[EDIT_MICROMENTUM]->GetWindowText(text); |
| | | GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM)->GetWindowText(text); |
| | | axisData.jogDistance.currentValue = _ttof(text); |
| | | |
| | | // æ´æ°å®ä½ç¹æ°æ® |
| | |
| | | ON_BN_CLICKED(IDC_BUTTON_AXIS_UPDATE_UI, &CAxisSettingsDlg::OnBnClickedButtonAxisUpdateUi) |
| | | ON_BN_CLICKED(IDC_BUTTON_AXIS_DETAIL_SETTINGS, &CAxisSettingsDlg::OnBnClickedButtonAxisDetailSettings) |
| | | ON_MESSAGE(ID_MSG_UPDATA_DATA_TO_UI, &CAxisSettingsDlg::OnUpdateDataToUI) |
| | | ON_EN_KILLFOCUS(IDC_EDIT_AXIS_MODITFY_MANUAL_SPEED, &CAxisSettingsDlg::OnKillfocusEditAxisModitfyManualSpeed) |
| | | ON_EN_KILLFOCUS(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED, &CAxisSettingsDlg::OnKillfocusEditAxisModitfyAutoSpeed) |
| | | ON_EN_KILLFOCUS(IDC_EDIT_AXIS_MODITFY_DECE_TIME, &CAxisSettingsDlg::OnKillfocusEditAxisModitfyDeceTime) |
| | | ON_EN_KILLFOCUS(IDC_EDIT_AXIS_MODITFY_ACCE_TIME, &CAxisSettingsDlg::OnKillfocusEditAxisModitfyAcceTime) |
| | | ON_EN_KILLFOCUS(IDC_EDIT_AXIS_MODITFY_MICROMENTUM, &CAxisSettingsDlg::OnEnKillfocusEditAxisModitfyMicromentum) |
| | | ON_WM_SIZE() |
| | | ON_WM_TIMER() |
| | | ON_WM_CLOSE() |
| | | ON_WM_CTLCOLOR() |
| | | ON_EN_KILLFOCUS(IDC_EDIT_AXIS_MODITFY_MICROMENTUM, &CAxisSettingsDlg::OnEnKillfocusEditAxisModitfyMicromentum) |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | |
| | | |
| | | AdjustLabelFont(*pLabel); |
| | | } |
| | | |
| | | // åå§åç¼è¾æ¡ |
| | | m_pRegexEdit[EDIT_MANUAL_SPEED]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_MANUAL_SPEED, this); |
| | | m_pRegexEdit[EDIT_AUTO_SPEED]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED, this); |
| | | m_pRegexEdit[EDIT_ACCE_TIME]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME, this); |
| | | m_pRegexEdit[EDIT_DECE_TIME]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME, this); |
| | | m_pRegexEdit[EDIT_MICROMENTUM]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM, this); |
| | | m_pRegexEdit[EDIT_ANCHOR_POINT1]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT1, this); |
| | | m_pRegexEdit[EDIT_ANCHOR_POINT2]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT2, this); |
| | | m_pRegexEdit[EDIT_ANCHOR_POINT3]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT3, this); |
| | | m_pRegexEdit[EDIT_ANCHOR_POINT4]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT4, this); |
| | | m_pRegexEdit[EDIT_ANCHOR_POINT5]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT5, this); |
| | | |
| | | // æé®åå§å |
| | | m_pBlBtns[BTN_PAGE1]->SubclassDlgItem(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP1, this); |
| | |
| | | return 0; |
| | | } |
| | | |
| | | void CAxisSettingsDlg::OnKillfocusEditAxisModitfyManualSpeed() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | int nAxisId = GetCurrentSelectedAxisID(); |
| | | if (nAxisId == -1) { |
| | | AfxMessageBox(_T("è¯·éæ©ä¸ä¸ªææçè½´ç¼å·ï¼")); |
| | | return; |
| | | } |
| | | auto axisDetails = m_pAxisManager->GetAxis(nAxisId); |
| | | auto dMinValue = axisDetails.manualSpeed.minValue; |
| | | auto dMaxValue = axisDetails.manualSpeed.maxValue; |
| | | |
| | | CString strText; |
| | | GetDlgItemText(IDC_EDIT_AXIS_MODITFY_MANUAL_SPEED, strText); |
| | | if (!IsFloatInRange((LPTSTR)(LPCTSTR)strText, dMinValue, dMaxValue)) { |
| | | CString strError; |
| | | strError.Format(_T("æå¨é度å¼å¿
é¡»å¨ %.3f å %.3f ä¹é´ï¼"), dMinValue, dMaxValue); |
| | | ShowTipText(strError, 5); |
| | | } |
| | | } |
| | | |
| | | void CAxisSettingsDlg::OnKillfocusEditAxisModitfyAutoSpeed() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | int nAxisId = GetCurrentSelectedAxisID(); |
| | | if (nAxisId == -1) { |
| | | AfxMessageBox(_T("è¯·éæ©ä¸ä¸ªææçè½´ç¼å·ï¼")); |
| | | return; |
| | | } |
| | | auto axisDetails = m_pAxisManager->GetAxis(nAxisId); |
| | | auto dMinValue = axisDetails.autoSpeed.minValue; |
| | | auto dMaxValue = axisDetails.autoSpeed.maxValue; |
| | | |
| | | CString strText; |
| | | GetDlgItemText(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED, strText); |
| | | if (!IsFloatInRange((LPTSTR)(LPCTSTR)strText, dMinValue, dMaxValue)) { |
| | | CString strError; |
| | | strError.Format(_T("èªå¨é度å¼å¿
é¡»å¨ %.3f å %.3f ä¹é´ï¼"), dMinValue, dMaxValue); |
| | | ShowTipText(strError, 5); |
| | | } |
| | | } |
| | | |
| | | void CAxisSettingsDlg::OnKillfocusEditAxisModitfyAcceTime() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | int nAxisId = GetCurrentSelectedAxisID(); |
| | | if (nAxisId == -1) { |
| | | AfxMessageBox(_T("è¯·éæ©ä¸ä¸ªææçè½´ç¼å·ï¼")); |
| | | return; |
| | | } |
| | | auto axisDetails = m_pAxisManager->GetAxis(nAxisId); |
| | | auto dMinValue = axisDetails.accelerationTime.minValue; |
| | | auto dMaxValue = axisDetails.accelerationTime.maxValue; |
| | | |
| | | CString strText; |
| | | GetDlgItemText(IDC_EDIT_AXIS_MODITFY_ACCE_TIME, strText); |
| | | if (!IsFloatInRange((LPTSTR)(LPCTSTR)strText, dMinValue, dMaxValue)) { |
| | | CString strError; |
| | | strError.Format(_T("å éæ¶é´å¼å¿
é¡»å¨ %.3f å %.3f ä¹é´ï¼"), dMinValue, dMaxValue); |
| | | ShowTipText(strError, 5); |
| | | } |
| | | } |
| | | |
| | | void CAxisSettingsDlg::OnKillfocusEditAxisModitfyDeceTime() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | int nAxisId = GetCurrentSelectedAxisID(); |
| | | if (nAxisId == -1) { |
| | | AfxMessageBox(_T("è¯·éæ©ä¸ä¸ªææçè½´ç¼å·ï¼")); |
| | | return; |
| | | } |
| | | auto axisDetails = m_pAxisManager->GetAxis(nAxisId); |
| | | auto dMinValue = axisDetails.decelerationTime.minValue; |
| | | auto dMaxValue = axisDetails.decelerationTime.maxValue; |
| | | |
| | | CString strText; |
| | | GetDlgItemText(IDC_EDIT_AXIS_MODITFY_DECE_TIME, strText); |
| | | if (!IsFloatInRange((LPTSTR)(LPCTSTR)strText, dMinValue, dMaxValue)) { |
| | | CString strError; |
| | | strError.Format(_T("åéæ¶é´å¼å¿
é¡»å¨ %.3f å %.3f ä¹é´ï¼"), dMinValue, dMaxValue); |
| | | ShowTipText(strError, 5); |
| | | } |
| | | } |
| | | |
| | | void CAxisSettingsDlg::OnEnKillfocusEditAxisModitfyMicromentum() |
| | | { |
| | | int nAxisId = GetCurrentSelectedAxisID(); |
| | | if (nAxisId == -1) { |
| | | AfxMessageBox(_T("è¯·éæ©ä¸ä¸ªææçè½´ç¼å·ï¼")); |
| | | return; |
| | | } |
| | | auto axisDetails = m_pAxisManager->GetAxis(nAxisId); |
| | | auto dMinValue = axisDetails.jogDistance.minValue; |
| | | auto dMaxValue = axisDetails.jogDistance.maxValue; |
| | | |
| | | CString strText; |
| | | GetDlgItemText(IDC_EDIT_AXIS_MODITFY_MICROMENTUM, strText); |
| | | if (!IsFloatInRange((LPTSTR)(LPCTSTR)strText, dMinValue, dMaxValue)) { |
| | | CString strError; |
| | | strError.Format(_T("å¾®å¨éå¼å¿
é¡»å¨ %.3f å %.3f ä¹é´ï¼"), dMinValue, dMaxValue); |
| | | ShowTipText(strError, 5); |
| | | } |
| | | } |
| | | |
| | | void CAxisSettingsDlg::OnTimer(UINT_PTR nIDEvent) |
| | | { |
| | | if (TIMER_READ_PLC_DATA == nIDEvent) { |
| | |
| | | GetDlgItem(IDC_LABEL_TIP)->ShowWindow(SW_HIDE); |
| | | } |
| | | |
| | | void CAxisSettingsDlg::OnEnKillfocusEditAxisModitfyMicromentum() |
| | | bool CAxisSettingsDlg::IsFloatInRange(const std::string& strInput, double fLowerBound, double fUpperBound) |
| | | { |
| | | CString strText; |
| | | GetDlgItemText(IDC_EDIT_AXIS_MODITFY_MICROMENTUM, strText); |
| | | double value = atof(strText); |
| | | if (value < 0.0 || value > 0.1) { |
| | | ShowTipText("å¾®å¨éå¼å¿
é¡»å¨0.0 ~ 0.1ä¹é´", 5); |
| | | // æ¯å¦ä¸ºåæ³æµ®ç¹æ° |
| | | std::regex floatRegex(R"([-+]?\d*\.?\d+([eE][-+]?\d+)?)"); |
| | | if (!std::regex_match(strInput, floatRegex)) { |
| | | return false; |
| | | } |
| | | |
| | | try { |
| | | double value = std::stod(strInput); |
| | | return value >= fLowerBound && value <= fUpperBound; |
| | | } |
| | | catch (const std::exception&) { |
| | | return false; |
| | | } |
| | | } |
| | |
| | | #pragma once |
| | | #include "BlButton.h" |
| | | #include "BLLabel.h" |
| | | #include "RegexEdit.h" |
| | | #include "CBaseDlg.h" |
| | | #include "PLC.h" |
| | | #include "AxisManager.h" |
| | |
| | | #define LABEL_READY 3 |
| | | #define LABEL_BUSY 4 |
| | | #define LABEL_ERR 5 |
| | | |
| | | // RegexEditæ§ä»¶ |
| | | #define EDIT_MAX 10 |
| | | #define EDIT_MANUAL_SPEED 0 |
| | | #define EDIT_AUTO_SPEED 1 |
| | | #define EDIT_ACCE_TIME 2 |
| | | #define EDIT_DECE_TIME 3 |
| | | #define EDIT_MICROMENTUM 4 |
| | | #define EDIT_ANCHOR_POINT1 5 |
| | | #define EDIT_ANCHOR_POINT2 6 |
| | | #define EDIT_ANCHOR_POINT3 7 |
| | | #define EDIT_ANCHOR_POINT4 8 |
| | | #define EDIT_ANCHOR_POINT5 9 |
| | | |
| | | // BUTTONæ§ä»¶ |
| | | #define BTN_MAX 15 |
| | |
| | | void SetLabelColor(CBLLabel& label, COLORREF color); |
| | | void SetLabelColorBasedOnState(CBLLabel& label, BOOL bState, COLORREF colorTrue, COLORREF colorFalse); |
| | | void UpdateLabels(); |
| | | void UpdateRegexEdit(CRegexEdit* pRegexEdit, const ValueRange& range, const CString& title); |
| | | void UpdatePageButtonStates(); |
| | | void HideEditCursor(int nCtrlID); |
| | | int GetCurrentSelectedAxisID(); |
| | |
| | | void ReadPLCDataToUI(int nAxisId); |
| | | void ShowTipText(const char* pszText, float sec); |
| | | void HideTip(); |
| | | bool IsFloatInRange(const std::string& strInput, double fLowerBound, double fUpperBound); |
| | | |
| | | private: |
| | | CPLC* m_pPLC; |
| | |
| | | // æ§ä»¶ |
| | | CBlButton* m_pBlBtns[BTN_MAX]; |
| | | CBLLabel* m_pBlLabels[LABEL_MAX]; |
| | | CRegexEdit* m_pRegexEdit[EDIT_MAX]; |
| | | CComboBox m_comboAxisNO; |
| | | CStatic m_staticAxisNO, m_staticAxisDescription, m_staticStartAddress; |
| | | |
| | |
| | | afx_msg void OnBnClickedButtonAxisUpdateUi(); |
| | | afx_msg void OnBnClickedButtonAxisDetailSettings(); |
| | | afx_msg LRESULT OnUpdateDataToUI(WPARAM wParam, LPARAM lParam); |
| | | afx_msg void OnKillfocusEditAxisModitfyManualSpeed(); |
| | | afx_msg void OnKillfocusEditAxisModitfyAutoSpeed(); |
| | | afx_msg void OnKillfocusEditAxisModitfyDeceTime(); |
| | | afx_msg void OnKillfocusEditAxisModitfyAcceTime(); |
| | | afx_msg void OnEnKillfocusEditAxisModitfyMicromentum(); |
| | | afx_msg void OnTimer(UINT_PTR nIDEvent); |
| | | afx_msg void OnClose(); |
| | | DECLARE_MESSAGE_MAP() |
| | | public: |
| | | afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); |
| | | afx_msg void OnEnKillfocusEditAxisModitfyMicromentum(); |
| | | DECLARE_MESSAGE_MAP() |
| | | }; |
| | |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="..\BondEq\HorizontalLine.h" /> |
| | | <ClInclude Include="AddPLCInfo.h" /> |
| | | <ClInclude Include="Alarm.h" /> |
| | | <ClInclude Include="AlarmMonitor.h" /> |
| | | <ClInclude Include="AlarmPopupDlg.h" /> |
| | |
| | | <ClInclude Include="PagePlcList.h" /> |
| | | <ClInclude Include="PLC.h" /> |
| | | <ClInclude Include="PlcView.h" /> |
| | | <ClInclude Include="RegexEdit.h" /> |
| | | <ClInclude Include="Resource.h" /> |
| | | <ClInclude Include="stdafx.h" /> |
| | | <ClInclude Include="targetver.h" /> |
| | |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClCompile Include="..\BondEq\HorizontalLine.cpp" /> |
| | | <ClCompile Include="AddPLCInfo.cpp" /> |
| | | <ClCompile Include="Alarm.cpp" /> |
| | | <ClCompile Include="AlarmMonitor.cpp" /> |
| | | <ClCompile Include="AlarmPopupDlg.cpp" /> |
| | |
| | | <ClCompile Include="PagePlcList.cpp" /> |
| | | <ClCompile Include="PLC.cpp" /> |
| | | <ClCompile Include="PlcView.cpp" /> |
| | | <ClCompile Include="RegexEdit.cpp" /> |
| | | <ClCompile Include="stdafx.cpp"> |
| | | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> |
| | | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> |
| | |
| | | <ClInclude Include="CBaseDlg.h"> |
| | | <Filter>头æä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="RegexEdit.h"> |
| | | <ClInclude Include="AddPLCInfo.h"> |
| | | <Filter>头æä»¶</Filter> |
| | | </ClInclude> |
| | | </ItemGroup> |
| | |
| | | <ClCompile Include="CBaseDlg.cpp"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | <ClCompile Include="RegexEdit.cpp"> |
| | | <ClCompile Include="AddPLCInfo.cpp"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | </ItemGroup> |
| | |
| | | #include "PlcView.h" |
| | | #include "Log.h" |
| | | #include "InputDialog.h" |
| | | #include "AddPLCInfo.h" |
| | | #include "AxisManager.h" |
| | | #include "IOManager.h" |
| | | |
| | |
| | | { |
| | | int id = (int)lParam; |
| | | if (id == IDC_BUTTON_ADD) { |
| | | CInputDialog inputDialog(_T("æ°å»ºè®¾å¤"), _T("请è¾å
¥è®¾å¤åç§°ï¼")); |
| | | if (inputDialog.DoModal() != IDOK) { |
| | | AfxMessageBox(_T("åæ¶éªè¯ï¼")); |
| | | CAddPLCInfo dlgAddPLCInfo; |
| | | if (dlgAddPLCInfo.DoModal() != IDOK) { |
| | | return 0; |
| | | } |
| | | |
| | | CString strName; |
| | | strName = inputDialog.GetInputText(); |
| | | if (!strName.IsEmpty()) { |
| | | theApp.m_model.addPlc((LPTSTR)(LPCTSTR)strName, "192.168.1.188", 1001); |
| | | CString strPLCName = dlgAddPLCInfo.GetPLCName(); |
| | | CString strIP = dlgAddPLCInfo.GetIP(); |
| | | CString strPort = dlgAddPLCInfo.GetPort(); |
| | | |
| | | if (!strPLCName.IsEmpty() && !strIP.IsEmpty() && !strPort.IsEmpty()) { |
| | | theApp.m_model.addPlc((LPTSTR)(LPCTSTR)strPLCName, (LPTSTR)(LPCTSTR)strIP, std::stoi((LPTSTR)(LPCTSTR)strPort)); |
| | | |
| | | // æ°å»ºè½´æä»¶ |
| | | AxisManager axisManager; |
| | | axisManager.SaveAxis((LPTSTR)(LPCTSTR)strName); |
| | | axisManager.SaveAxis((LPTSTR)(LPCTSTR)strPLCName); |
| | | |
| | | // æ°å»ºIOæä»¶ |
| | | IOManager ioManager; |
| | | ioManager.SaveToFile((LPTSTR)(LPCTSTR)strName); |
| | | ioManager.SaveToFile((LPTSTR)(LPCTSTR)strPLCName); |
| | | } |
| | | } |
| | | else if (id == IDC_BUTTON_DELETE) { |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "AlarmManager.h" |
| | | #include <sstream> |
| | | #include <iostream> |
| | | #include <stdexcept> |
| | | #include <ctime> |
| | | |
| | | // 常é |
| | | const std::string DATABASE_FILE = R"(AlarmManager.db)"; |
| | | |
| | | // éææååå§å |
| | | std::mutex AlarmManager::m_mutex; |
| | | |
| | | // è·ååä¾å®ä¾ |
| | | AlarmManager& AlarmManager::getInstance() { |
| | | static AlarmManager instance; |
| | | return instance; |
| | | } |
| | | |
| | | // æé 彿° |
| | | AlarmManager::AlarmManager() { |
| | | m_pDB = new BL::SQLiteDatabase(); |
| | | } |
| | | |
| | | // ææå½æ° |
| | | AlarmManager::~AlarmManager() { |
| | | if (m_pDB != nullptr) { |
| | | delete m_pDB; |
| | | m_pDB = nullptr; |
| | | } |
| | | } |
| | | |
| | | // è®¾ç½®æ°æ®åºè¿æ¥ |
| | | void AlarmManager::setDatabase(BL::Database* db) { |
| | | std::lock_guard<std::mutex> lock(m_mutex); |
| | | m_pDB = db; |
| | | } |
| | | |
| | | // åå§åæ¥è¦è¡¨ |
| | | bool AlarmManager::initAlarmTable() { |
| | | char path[MAX_PATH]; |
| | | GetModuleFileName(NULL, path, MAX_PATH); |
| | | std::string exePath(path); |
| | | std::string dbFileDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB"; |
| | | if (!CreateDirectory(dbFileDir.c_str(), NULL) && ERROR_ALREADY_EXISTS != GetLastError()) { |
| | | throw std::runtime_error("Failed to create database directory."); |
| | | } |
| | | |
| | | std::string dbFilePath = dbFileDir + "\\" + DATABASE_FILE; |
| | | if (!m_pDB->connect(dbFilePath, true)) { |
| | | throw std::runtime_error("Failed to connect to database."); |
| | | } |
| | | |
| | | const std::string createTableQuery = R"( |
| | | CREATE TABLE IF NOT EXISTS alarms ( |
| | | id TEXT NOT NULL, |
| | | device_name TEXT NOT NULL, |
| | | description TEXT NOT NULL, |
| | | start_time DATETIME NOT NULL, |
| | | end_time DATETIME NOT NULL |
| | | ) |
| | | )"; |
| | | |
| | | return m_pDB->executeQuery(createTableQuery); |
| | | } |
| | | |
| | | // 鿝æ¥è¦è¡¨ |
| | | void AlarmManager::termAlarmTable() { |
| | | if (m_pDB != nullptr) { |
| | | m_pDB->disconnect(); |
| | | } |
| | | } |
| | | |
| | | // 鿝æ¥è¦è¡¨ |
| | | bool AlarmManager::destroyAlarmTable() { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | const std::string dropTableQuery = "DROP TABLE IF EXISTS alarms"; |
| | | return m_pDB->executeQuery(dropTableQuery); |
| | | } |
| | | |
| | | // æ·»å æ¥è¦ |
| | | bool AlarmManager::addAlarm(const std::string& id, const std::string& deviceName, const std::string& description, const std::string& startTime, const std::string& endTime) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "INSERT INTO alarms (id, device_name, description, start_time, end_time) VALUES (" |
| | | << "'" << id << "', " |
| | | << "'" << deviceName << "', " |
| | | << "'" << description << "', " |
| | | << "'" << startTime << "', " |
| | | << "'" << endTime << "')"; |
| | | |
| | | std::lock_guard<std::mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(query.str()); |
| | | } |
| | | |
| | | // æ¥è¯¢æææ¥è¦æ°æ® |
| | | std::vector<std::vector<std::string>> AlarmManager::getAllAlarms() { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | const std::string query = "SELECT id, device_name, description, start_time, end_time FROM alarms"; |
| | | return m_pDB->fetchResults(query); |
| | | } |
| | | |
| | | // æ ¹æ®æ¥è¦IDæ¥è¯¢æ¥è¦ |
| | | std::vector<std::vector<std::string>> AlarmManager::getAlarmsById(const std::string& id) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT id, device_name, description, start_time, end_time FROM alarms WHERE id = '" << id << "'"; |
| | | return m_pDB->fetchResults(query.str()); |
| | | } |
| | | |
| | | // æ ¹æ®æè¿°æ¥è¯¢æ¥è¦ |
| | | std::vector<std::vector<std::string>> AlarmManager::getAlarmsByDescription(const std::string& description) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT id, device_name, description, start_time, end_time FROM alarms WHERE description LIKE '%" << description << "%'"; |
| | | return m_pDB->fetchResults(query.str()); |
| | | } |
| | | |
| | | // æ ¹æ®æ¶é´èå´æ¥è¯¢æ¥è¦ |
| | | std::vector<std::vector<std::string>> AlarmManager::getAlarmsByTimeRange( |
| | | const std::string& startTime, const std::string& endTime) { |
| | | |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT id, device_name, description, start_time, end_time FROM alarms WHERE 1=1"; |
| | | |
| | | if (!startTime.empty()) { |
| | | query << " AND start_time >= '" << startTime << "'"; |
| | | } |
| | | if (!endTime.empty()) { |
| | | query << " AND end_time <= '" << endTime << "'"; |
| | | } |
| | | |
| | | return m_pDB->fetchResults(query.str()); |
| | | } |
| | | |
| | | // æ ¹æ®IDãå¼å§æ¶é´åç»ææ¶é´æ¥è¯¢æ¥è¦ |
| | | std::vector<std::vector<std::string>> AlarmManager::getAlarmsByIdAndTimeRange( |
| | | const std::string& id, const std::string& startTime, const std::string& endTime) { |
| | | |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT id, device_name, description, start_time, end_time FROM alarms WHERE id = '" << id << "'"; |
| | | |
| | | if (!startTime.empty()) { |
| | | query << " AND start_time >= '" << startTime << "'"; |
| | | } |
| | | if (!endTime.empty()) { |
| | | query << " AND end_time <= '" << endTime << "'"; |
| | | } |
| | | |
| | | return m_pDB->fetchResults(query.str()); |
| | | } |
| | | |
| | | // å页æ¥è¯¢æ¥è¦æ°æ® |
| | | std::vector<std::vector<std::string>> AlarmManager::getAlarms(int startPosition, int count) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT id, device_name, description, start_time, end_time FROM alarms LIMIT " << count << " OFFSET " << startPosition; |
| | | return m_pDB->fetchResults(query.str()); |
| | | } |
| | | |
| | | // çéæ¥è¦æ°æ® |
| | | std::vector<std::vector<std::string>> AlarmManager::getFilteredAlarms( |
| | | const std::string& id, |
| | | const std::string& deviceName, |
| | | const std::string& description, |
| | | const std::string& startTime, |
| | | const std::string& endTime, |
| | | int pageNumber, |
| | | int pageSize) { |
| | | |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT id, device_name, description, start_time, end_time FROM alarms WHERE 1=1"; |
| | | |
| | | if (!id.empty()) { |
| | | query << " AND id = '" << id << "'"; |
| | | } |
| | | if (!deviceName.empty()) { |
| | | query << " AND device_name LIKE '%" << deviceName << "%'"; |
| | | } |
| | | if (!description.empty()) { |
| | | query << " AND description LIKE '%" << description << "%'"; |
| | | } |
| | | if (!startTime.empty()) { |
| | | query << " AND start_time >= '" << startTime << "'"; |
| | | } |
| | | if (!endTime.empty()) { |
| | | query << " AND end_time <= '" << endTime << "'"; |
| | | } |
| | | |
| | | int offset = (pageNumber - 1) * pageSize; |
| | | query << " ORDER BY start_time DESC LIMIT " << pageSize << " OFFSET " << offset; |
| | | |
| | | return m_pDB->fetchResults(query.str()); |
| | | } |
| | | |
| | | // è·åç¬¦åæ¡ä»¶çæ¥è¦æ»æ° |
| | | int AlarmManager::getTotalAlarmCount( |
| | | const std::string& id, |
| | | const std::string& deviceName, |
| | | const std::string& description, |
| | | const std::string& startTime, |
| | | const std::string& endTime) { |
| | | |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT COUNT(*) FROM alarms WHERE 1=1"; |
| | | |
| | | if (!id.empty()) { |
| | | query << " AND id = '" << id << "'"; |
| | | } |
| | | if (!deviceName.empty()) { |
| | | query << " AND device_name LIKE '%" << deviceName << "%'"; |
| | | } |
| | | if (!description.empty()) { |
| | | query << " AND description LIKE '%" << description << "%'"; |
| | | } |
| | | if (!startTime.empty()) { |
| | | query << " AND start_time >= '" << startTime << "'"; |
| | | } |
| | | if (!endTime.empty()) { |
| | | query << " AND end_time <= '" << endTime << "'"; |
| | | } |
| | | |
| | | auto results = m_pDB->fetchResults(query.str()); |
| | | return (!results.empty() && !results[0].empty()) ? std::stoi(results[0][0]) : 0; |
| | | } |
| | | |
| | | // æ´æ°æ¥è¦çç»ææ¶é´ |
| | | bool AlarmManager::updateAlarmEndTime(const std::string& id, const std::string& deviceName, const std::string& description, const std::string& startTime, const std::string& newEndTime) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "UPDATE alarms SET end_time = '" << newEndTime << "'" |
| | | << " WHERE id = '" << id << "'" |
| | | << " AND device_name = '" << deviceName << "'" |
| | | << " AND description = '" << description << "'" |
| | | << " AND start_time = '" << startTime << "'"; |
| | | |
| | | return m_pDB->executeQuery(query.str()); |
| | | } |
| | | |
| | | // æ¸
çæ§æ¥è¦æ°æ® |
| | | void AlarmManager::cleanOldAlarms(int daysToKeep, const std::string& deviceName) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "DELETE FROM alarms WHERE end_time < datetime('now', '-" << daysToKeep << " days')"; |
| | | |
| | | if (!deviceName.empty()) { |
| | | query << " AND device_name = '" << deviceName << "'"; |
| | | } |
| | | m_pDB->executeQuery(query.str()); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #ifndef ALARM_MANAGER_H |
| | | #define ALARM_MANAGER_H |
| | | |
| | | #include <string> |
| | | #include <vector> |
| | | #include <mutex> |
| | | #include "Database.h" |
| | | |
| | | class AlarmManager { |
| | | public: |
| | | /** |
| | | * è·ååä¾å®ä¾ |
| | | * @return AlarmManagerå®ä¾çå¼ç¨ |
| | | */ |
| | | static AlarmManager& getInstance(); |
| | | |
| | | /** |
| | | * è®¾ç½®æ°æ®åºè¿æ¥ |
| | | * @param db æ°æ®åºè¿æ¥çæé |
| | | */ |
| | | void setDatabase(BL::Database* db); |
| | | |
| | | /** |
| | | * åå§åæ¥è¦è¡¨ |
| | | * @return æåè¿åtrueï¼å¤±è´¥è¿åfalse |
| | | */ |
| | | bool initAlarmTable(); |
| | | |
| | | /** |
| | | * 鿝æ¥è¦è¡¨ |
| | | */ |
| | | void termAlarmTable(); |
| | | |
| | | /** |
| | | * 鿝æ¥è¦è¡¨ |
| | | * @return æåè¿åtrueï¼å¤±è´¥è¿åfalse |
| | | */ |
| | | bool destroyAlarmTable(); |
| | | |
| | | /** |
| | | * æ·»å æ¥è¦ |
| | | * @param id æ¥è¦ID |
| | | * @param deviceName 设å¤åç§° |
| | | * @param description æ¥è¦æè¿° |
| | | * @param startTime æ¥è¦å¼å§æ¶é´ |
| | | * @param endTime æ¥è¦ç»ææ¶é´ |
| | | * @return æåè¿åtrueï¼å¤±è´¥è¿åfalse |
| | | */ |
| | | bool addAlarm(const std::string& id, const std::string& deviceName, const std::string& description, const std::string& startTime, const std::string& endTime); |
| | | |
| | | /** |
| | | * æ¥è¯¢æææ¥è¦æ°æ® |
| | | * @return å
å«æææ¥è¦æ°æ®çäºç»´å符串åé |
| | | */ |
| | | std::vector<std::vector<std::string>> getAllAlarms(); |
| | | |
| | | /** |
| | | * æ ¹æ®æ¥è¦IDæ¥è¯¢æ¥è¦ |
| | | * @param id æ¥è¦ID |
| | | * @return å
å«çéåæ¥è¦æ°æ®çäºç»´å符串åé |
| | | */ |
| | | std::vector<std::vector<std::string>> getAlarmsById(const std::string& id); |
| | | |
| | | /** |
| | | * æ ¹æ®æè¿°æ¥è¯¢æ¥è¦ |
| | | * @param description æ¥è¦æè¿°çç鿡件 |
| | | * @return å
å«çéåæ¥è¦æ°æ®çäºç»´å符串åé |
| | | */ |
| | | std::vector<std::vector<std::string>> getAlarmsByDescription(const std::string& description); |
| | | |
| | | /** |
| | | * æ ¹æ®æ¶é´èå´æ¥è¯¢æ¥è¦ |
| | | * @param startTime èµ·å§æ¶é´ |
| | | * @param endTime ç»ææ¶é´ |
| | | * @return å
嫿¥è¯¢ç»æçäºç»´å符串åé |
| | | */ |
| | | std::vector<std::vector<std::string>> getAlarmsByTimeRange( |
| | | const std::string& startTime, const std::string& endTime); |
| | | |
| | | /** |
| | | * æ ¹æ®IDåæ¶é´èå´æ¥è¯¢æ¥è¦ |
| | | * @param id æ¥è¦ID |
| | | * @param startTime èµ·å§æ¶é´ |
| | | * @param endTime ç»ææ¶é´ |
| | | * @return å
嫿¥è¯¢ç»æçäºç»´å符串åé |
| | | */ |
| | | std::vector<std::vector<std::string>> getAlarmsByIdAndTimeRange( |
| | | const std::string& id, const std::string& startTime, const std::string& endTime); |
| | | |
| | | /** |
| | | * è·åæ¥è¦æ°æ® |
| | | * @param startPosition èµ·å§ä½ç½® |
| | | * @param count è·åçè®°å½æ°é |
| | | * @return å
嫿¥è¦æ°æ®çäºç»´å符串åé |
| | | */ |
| | | std::vector<std::vector<std::string>> getAlarms(int startPosition, int count); |
| | | |
| | | /** |
| | | * è·åçéåçæ¥è¦æ°æ® |
| | | * @param id æ¥è¦IDçç鿡件 |
| | | * @param deviceName 设å¤åç§°çç鿡件 |
| | | * @param description æ¥è¦æè¿°çç鿡件 |
| | | * @param startTime èµ·å§æ¶é´ç鿡件 |
| | | * @param endTime ç»ææ¶é´ç鿡件 |
| | | * @param pageNumber 页ç |
| | | * @param pageSize æ¯é¡µçè®°å½æ° |
| | | * @return å
å«çéåæ¥è¦æ°æ®çäºç»´å符串åé |
| | | */ |
| | | std::vector<std::vector<std::string>> getFilteredAlarms( |
| | | const std::string& id, |
| | | const std::string& deviceName, |
| | | const std::string& description, |
| | | const std::string& startTime, |
| | | const std::string& endTime, |
| | | int pageNumber, |
| | | int pageSize); |
| | | |
| | | /** |
| | | * è·åç¬¦åæ¡ä»¶çæ¥è¦æ»æ° |
| | | * @param id æ¥è¦IDçç鿡件 |
| | | * @param deviceName 设å¤åç§°çç鿡件 |
| | | * @param description æ¥è¦æè¿°çç鿡件 |
| | | * @param startTime èµ·å§æ¶é´ç鿡件 |
| | | * @param endTime ç»ææ¶é´ç鿡件 |
| | | * @return ç¬¦åæ¡ä»¶çæ¥è¦æ»æ° |
| | | */ |
| | | int getTotalAlarmCount( |
| | | const std::string& id, |
| | | const std::string& deviceName, |
| | | const std::string& description, |
| | | const std::string& startTime, |
| | | const std::string& endTime); |
| | | |
| | | /** |
| | | * æ´æ°æ¥è¦ç»ææ¶é´ |
| | | * @param id æ¥è¦ID |
| | | * @param description æ¥è¦æè¿° |
| | | * @param startTime æ¥è¦å¼å§æ¶é´ |
| | | * @param newEndTime æ°çæ¥è¦ç»ææ¶é´ |
| | | * @return æåè¿åtrueï¼å¤±è´¥è¿åfalse |
| | | */ |
| | | bool updateAlarmEndTime(const std::string& id, const std::string& deviceName, const std::string& description, const std::string& startTime, const std::string& newEndTime); |
| | | |
| | | /** |
| | | * æ¸
çæ§æ¥è¦ |
| | | * @param daysToKeep ä¿ççå¤©æ° |
| | | * @param deviceName 设å¤åç§° |
| | | */ |
| | | void cleanOldAlarms(int daysToKeep = 30, const std::string& deviceName = ""); |
| | | |
| | | private: |
| | | AlarmManager(); |
| | | ~AlarmManager(); |
| | | |
| | | // ç¦æ¢æ·è´åèµå¼ |
| | | AlarmManager(const AlarmManager&) = delete; |
| | | AlarmManager& operator=(const AlarmManager&) = delete; |
| | | |
| | | BL::Database* m_pDB; |
| | | static std::mutex m_mutex; |
| | | }; |
| | | |
| | | #endif // ALARM_MANAGER_H |
| | |
| | | #include "Servo.h" |
| | | #include "ServoDlg.h" |
| | | #include "ServoGraph.h" |
| | | #include "AlarmManager.h" |
| | | |
| | | // 声æå
¨å±åéï¼ç¨äºç®¡ç GDI+ åå§å |
| | | ULONG_PTR g_diplusToken; |
| | | GdiplusStartupInput g_diplusStartupInput; |
| | | |
| | | #ifdef _DEBUG |
| | | #define new DEBUG_NEW |
| | |
| | | HSMS_Initialize(); |
| | | |
| | | |
| | | // åå§å GDI+ |
| | | InitGDIPlus(); |
| | | |
| | | |
| | | // åå§åæ¥è¦ç®¡çå¨ |
| | | try { |
| | | if (!AlarmManager::getInstance().initAlarmTable()) { |
| | | AfxMessageBox("åå§åæ¥è¦ç®¡çå¨å¤±è´¥ï¼"); |
| | | return FALSE; |
| | | } |
| | | } |
| | | catch (const std::exception& ex) { |
| | | CString errorMsg; |
| | | errorMsg.Format(_T("åå§åæ¥è¦ç®¡çå¨å¤±è´¥ï¼%s"), CString(ex.what())); |
| | | AfxMessageBox(errorMsg, MB_ICONERROR); |
| | | return FALSE; |
| | | } |
| | | |
| | | |
| | | CServoDlg dlg; |
| | | m_pMainWnd = &dlg; |
| | | INT_PTR nResponse = dlg.DoModal(); |
| | |
| | | HSMS_Term(); |
| | | RX_Term(); |
| | | |
| | | // æ¸
ç GDI+ |
| | | TermGDIPlus(); |
| | | |
| | | // 鿝æ¥è¦è¡¨ |
| | | AlarmManager::getInstance().termAlarmTable(); |
| | | |
| | | return CWinApp::ExitInstance(); |
| | | } |
| | | |
| | | // åå§å GDI+ |
| | | void CServoApp::InitGDIPlus() |
| | | { |
| | | // åå§å GDI+ å¾å½¢åº |
| | | GdiplusStartup(&g_diplusToken, &g_diplusStartupInput, NULL); |
| | | } |
| | | |
| | | // æ¸
ç GDI+ |
| | | void CServoApp::TermGDIPlus() |
| | | { |
| | | // æ¸
ç GDI+ å¾å½¢åº |
| | | GdiplusShutdown(g_diplusToken); |
| | | } |
| | |
| | | { |
| | | public: |
| | | CServoApp(); |
| | | void InitGDIPlus(); |
| | | void TermGDIPlus(); |
| | | |
| | | |
| | | public: |
| | |
| | | <Optimization>Disabled</Optimization> |
| | | <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| | | <SDLCheck>true</SDLCheck> |
| | | <AdditionalIncludeDirectories>.;..;..\DatabaseSDK\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| | | </ClCompile> |
| | | <Link> |
| | | <SubSystem>Windows</SubSystem> |
| | |
| | | <IntrinsicFunctions>true</IntrinsicFunctions> |
| | | <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| | | <SDLCheck>true</SDLCheck> |
| | | <AdditionalIncludeDirectories>.;..;..\DatabaseSDK\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| | | </ClCompile> |
| | | <Link> |
| | | <SubSystem>Windows</SubSystem> |
| | |
| | | <Text Include="ReadMe.txt" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="AlarmManager.h" /> |
| | | <ClInclude Include="BlButton.h" /> |
| | | <ClInclude Include="Common.h" /> |
| | | <ClInclude Include="Configuration.h" /> |
| | |
| | | <ClInclude Include="TerminalDisplayDlg.h" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClCompile Include="AlarmManager.cpp" /> |
| | | <ClCompile Include="BlButton.cpp" /> |
| | | <ClCompile Include="Configuration.cpp" /> |
| | | <ClCompile Include="Context.cpp" /> |
| | |
| | | <Filter>头æä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="TerminalDisplayDlg.h"> |
| | | <ClInclude Include="AlarmManager.h"> |
| | | <Filter>头æä»¶</Filter> |
| | | </ClInclude> |
| | | </ItemGroup> |
| | |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | <ClCompile Include="TerminalDisplayDlg.cpp"> |
| | | <ClCompile Include="AlarmManager.cpp"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | </ItemGroup> |
| | |
| | | #include "Common.h" |
| | | #include "Log.h" |
| | | #include "SecsTestDlg.h" |
| | | #include "AlarmManager.h" |
| | | #include <chrono> |
| | | #include <thread> |
| | | #include <cmath> |
| | | |
| | | |
| | | #ifdef _DEBUG |
| | | #define new DEBUG_NEW |
| | | #endif |
| | | |
| | | // Image |
| | | #define IMAGE_ROBOT 2 |
| | | |
| | | #define INDICATE_BONDER1 1 |
| | | #define INDICATE_BONDER2 2 |
| | |
| | | m_crBkgnd = APPDLG_BACKGROUND_COLOR; |
| | | m_hbrBkgnd = nullptr; |
| | | m_bShowLogWnd = FALSE; |
| | | m_bIsRobotMoving = FALSE; |
| | | m_pLogDlg = nullptr; |
| | | m_pTerminalDisplayDlg = nullptr; |
| | | m_pObserver = nullptr; |
| | |
| | | ON_COMMAND(ID_MENU_HELP_ABOUT, &CServoDlg::OnMenuHelpAbout) |
| | | ON_WM_INITMENUPOPUP() |
| | | ON_WM_TIMER() |
| | | ON_WM_ERASEBKGND() |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | |
| | | strPath.Format(_T("%s\\res\\Servo001.bmp"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir); |
| | | m_pGraph->AddImage(1, (LPTSTR)(LPCTSTR)strPath, 0, 0); |
| | | |
| | | strPath.Format(_T("%s\\res\\Robot001.bmp"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir); |
| | | m_pGraph->AddImage(IMAGE_ROBOT, (LPTSTR)(LPCTSTR)strPath, 170, 270); |
| | | |
| | | // æ·»å æç¤ºå¨ |
| | | // Bonder |
| | |
| | | |
| | | |
| | | // Robot |
| | | m_pGraph->AddIndicateBox(INDICATE_ROBOT_ARM1, 620, 294, 48, RGB(22, 22, 22), |
| | | m_pGraph->AddIndicateBox(INDICATE_ROBOT_ARM1, 190, 294, 48, RGB(22, 22, 22), |
| | | RGB(255, 127, 39), RGB(0, 176, 80)); |
| | | m_pGraph->SetBoxText(INDICATE_ROBOT_ARM1, "5", "Robot"); |
| | | m_pGraph->AddIndicateBox(INDICATE_ROBOT_ARM2, 673, 294, 48, RGB(22, 22, 22), |
| | | m_pGraph->AddIndicateBox(INDICATE_ROBOT_ARM2, 243, 294, 48, RGB(22, 22, 22), |
| | | RGB(255, 127, 39), RGB(0, 176, 80)); |
| | | m_pGraph->SetBoxText(INDICATE_ROBOT_ARM2, "6", "Robot"); |
| | | |
| | |
| | | m_btnLog.Invalidate(); |
| | | } |
| | | |
| | | void CServoDlg::UpdateRobotPosition(float percentage) |
| | | { |
| | | // éå¶ç¾åæ¯èå´å¨ [0, 1] ä¹é´ |
| | | if (percentage < 0.0f) percentage = 0.0f; |
| | | if (percentage > 1.0f) percentage = 1.0f; |
| | | |
| | | // æ ¹æ®ç¾åæ¯è®¡ç®ç®æ X åæ |
| | | int startX = m_pGraph->GetImage(IMAGE_ROBOT)->x; |
| | | int endX = static_cast<int>(170 + percentage * (700 - 170)); |
| | | |
| | | int arm1Offset = 20; // ä»å¾çå°ARM1çåç§» |
| | | int arm2Offset = 73; // ä»å¾çå°ARM2çåç§» |
| | | |
| | | // 计ç®ç§»å¨æéçæ¶é´ |
| | | int distance = abs(endX - startX); |
| | | int duration = static_cast<int>((distance / 100.0) * 1000); |
| | | |
| | | auto startTime = std::chrono::steady_clock::now(); |
| | | auto endTime = startTime + std::chrono::milliseconds(duration); |
| | | |
| | | // å¼å§ç§»å¨ï¼è®¾ç½®æ è®° |
| | | m_bIsRobotMoving = TRUE; |
| | | |
| | | // å¼å§å¹³æ»ç§»å¨ |
| | | while (std::chrono::steady_clock::now() < endTime) { |
| | | auto currentTime = std::chrono::steady_clock::now(); |
| | | float progress = std::chrono::duration<float, std::milli>(currentTime - startTime).count() / duration; |
| | | progress = min(progress, 1.0f); |
| | | |
| | | // æ ¹æ®è¿åº¦è®¡ç®å½åä½ç½® |
| | | int currentX = static_cast<int>(startX + progress * (endX - startX)); |
| | | m_pGraph->UpdateImageCoordinates(IMAGE_ROBOT, currentX, 270); |
| | | m_pGraph->UpdateIndicateBoxCoordinates(INDICATE_ROBOT_ARM1, currentX + arm1Offset, 294); |
| | | m_pGraph->UpdateIndicateBoxCoordinates(INDICATE_ROBOT_ARM2, currentX + arm2Offset, 294); |
| | | |
| | | // å·æ°çé¢ |
| | | Invalidate(); |
| | | UpdateWindow(); |
| | | |
| | | // æ§å¶å¸§ç约为 60 FPS |
| | | std::this_thread::sleep_for(std::chrono::milliseconds(16)); |
| | | } |
| | | |
| | | // ç¡®ä¿æåä½ç½®ç²¾ç¡®å°ç®æ ä½ç½® |
| | | m_pGraph->UpdateImageCoordinates(IMAGE_ROBOT, endX, 270); |
| | | m_pGraph->UpdateIndicateBoxCoordinates(INDICATE_ROBOT_ARM1, endX + arm1Offset, 294); |
| | | m_pGraph->UpdateIndicateBoxCoordinates(INDICATE_ROBOT_ARM2, endX + arm2Offset, 294); |
| | | |
| | | // çé¢éç» |
| | | Invalidate(); |
| | | |
| | | // å¨ç»ç»æï¼è®¾ç½®æ è®° |
| | | m_bIsRobotMoving = FALSE; |
| | | } |
| | | |
| | | void CServoDlg::RotateRobot(float angleInDegrees) |
| | | { |
| | | // å°è§åº¦è½¬æ¢ä¸ºå¼§åº¦ |
| | | float angleInRadians = static_cast<float>(std::acos(-1)) / 180.0f * angleInDegrees; |
| | | |
| | | // è·åæºå¨äººå¾ççå½ååæ åä¸å¿ |
| | | auto* pImage = m_pGraph->GetImage(IMAGE_ROBOT); |
| | | if (!pImage) return; |
| | | |
| | | // æ´æ° Rotate å¾ççè§åº¦ï¼ç¡®ä¿è§åº¦ä¿æå¨ [0, 360) èå´å
|
| | | m_pGraph->UpdateImageAngle(IMAGE_ROBOT, static_cast<float>(fmod(pImage->angle + angleInDegrees + 360, 360))); |
| | | |
| | | int cx = pImage->x + pImage->bmWidth / 2; // å¾çä¸å¿ X |
| | | int cy = pImage->y + pImage->bmHeight / 2; // å¾çä¸å¿ Y |
| | | |
| | | // æè½¬æç¤ºæ¡çåæ |
| | | auto* pRobot1 = m_pGraph->GetIndicateBox(INDICATE_ROBOT_ARM1); |
| | | auto* pRobot2 = m_pGraph->GetIndicateBox(INDICATE_ROBOT_ARM2); |
| | | |
| | | if (pRobot1 && pRobot2) { |
| | | int newArmX1 = pImage->x + 20; |
| | | int newArmY1 = 294; |
| | | |
| | | int newArmX2 = pImage->x + 73; |
| | | int newArmY2 = 294; |
| | | |
| | | if (angleInDegrees != 0.0f) { |
| | | // è®¡ç®æç¤ºæ¡1çæ°åæ |
| | | newArmX1 = static_cast<int>(cx + (pRobot1->x - cx) * cos(angleInRadians) - (pRobot1->y - cy) * sin(angleInRadians)); |
| | | newArmY1 = static_cast<int>(cy + (pRobot1->x - cx) * sin(angleInRadians) + (pRobot1->y - cy) * cos(angleInRadians)); |
| | | |
| | | // è®¡ç®æç¤ºæ¡2çæ°åæ |
| | | newArmX2 = static_cast<int>(cx + (pRobot2->x - cx) * cos(angleInRadians) - (pRobot2->y - cy) * sin(angleInRadians)); |
| | | newArmY2 = static_cast<int>(cy + (pRobot2->x - cx) * sin(angleInRadians) + (pRobot2->y - cy) * cos(angleInRadians)); |
| | | } |
| | | |
| | | // æ´æ°æç¤ºæ¡çä½ç½® |
| | | m_pGraph->UpdateIndicateBoxCoordinates(INDICATE_ROBOT_ARM1, newArmX1, newArmY1); |
| | | m_pGraph->UpdateIndicateBoxCoordinates(INDICATE_ROBOT_ARM2, newArmX2, newArmY2); |
| | | } |
| | | |
| | | // 强å¶éç»çé¢ |
| | | Invalidate(); |
| | | } |
| | | |
| | | void CServoDlg::OnSize(UINT nType, int cx, int cy) |
| | | { |
| | | CDialogEx::OnSize(nType, cx, cy); |
| | |
| | | |
| | | CDialogEx::OnTimer(nIDEvent); |
| | | } |
| | | |
| | | |
| | | BOOL CServoDlg::OnEraseBkgnd(CDC* pDC) |
| | | { |
| | | // TODO: 卿¤æ·»å æ¶æ¯å¤çç¨åºä»£ç å/æè°ç¨é»è®¤å¼ |
| | | if (m_bIsRobotMoving) { |
| | | // ç¦æ¢å·æ°èæ¯ï¼é¿å
éªç |
| | | return TRUE; |
| | | } |
| | | |
| | | return CDialogEx::OnEraseBkgnd(pDC); |
| | | } |
| | |
| | | void InitRxWindows(); |
| | | void Resize(); |
| | | void UpdateLogBtn(); |
| | | void UpdateRobotPosition(float percentage); |
| | | void RotateRobot(float angleInDegrees); |
| | | |
| | | |
| | | private: |
| | |
| | | protected: |
| | | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV æ¯æ |
| | | |
| | | |
| | | private: |
| | | BOOL m_bIsRobotMoving; |
| | | BOOL m_bShowLogWnd; |
| | | CLogDlg* m_pLogDlg; |
| | | |
| | | // å®ç° |
| | | protected: |
| | |
| | | afx_msg void OnUpdateMenuFileExit(CCmdUI* pCmdUI); |
| | | afx_msg void OnMenuHelpAbout(); |
| | | afx_msg void OnTimer(UINT_PTR nIDEvent); |
| | | afx_msg BOOL OnEraseBkgnd(CDC* pDC); |
| | | }; |
| | |
| | | |
| | | |
| | | // ç»IMAGE |
| | | HDC hDCTemp = ::CreateCompatibleDC(hMemDC); |
| | | for (auto& item : m_images) { |
| | | // è½½å
¥BMP |
| | | if (item.hBitmap == nullptr) { |
| | | item.hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(), |
| | | item.szPath, IMAGE_BITMAP, 0, 0, |
| | | LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE); |
| | | if (item.hBitmap != nullptr) { |
| | | BITMAP bitmap; |
| | | ::GetObject(item.hBitmap, sizeof(BITMAP), &bitmap); |
| | | item.bmWidth = bitmap.bmWidth; |
| | | item.bmHeight = bitmap.bmHeight; |
| | | DrawImage(hMemDC, item); |
| | | } |
| | | |
| | | } |
| | | |
| | | if (item.hBitmap != nullptr) { |
| | | ::SelectObject(hDCTemp, item.hBitmap); |
| | | ::BitBlt(hMemDC, item.x, item.y, item.bmWidth, item.bmHeight, |
| | | hDCTemp, 0, 0, SRCCOPY); |
| | | } |
| | | } |
| | | ::DeleteDC(hDCTemp); |
| | | |
| | | |
| | | // ç»èæ¯æç¤º |
| | |
| | | } |
| | | |
| | | // text |
| | | ::DrawText(hMemDC, item.szText, strlen(item.szText), |
| | | ::DrawText(hMemDC, item.szText, static_cast<int>(strlen(item.szText)), |
| | | &rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); |
| | | } |
| | | |
| | |
| | | SendMessage(m_hWndTooltip, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&tti); |
| | | } |
| | | } |
| | | |
| | | void CServoGraph::UpdateImageCoordinates(int id, int newX, int newY) |
| | | { |
| | | IMAGE* pImage = GetImage(id); |
| | | if (pImage != nullptr) { |
| | | pImage->x = newX; |
| | | pImage->y = newY; |
| | | } |
| | | } |
| | | |
| | | void CServoGraph::UpdateIndicateBoxCoordinates(int id, int newX, int newY) |
| | | { |
| | | INDICATEBOX* pIndicateBox = GetIndicateBox(id); |
| | | if (pIndicateBox != nullptr) { |
| | | pIndicateBox->x = newX; |
| | | pIndicateBox->y = newY; |
| | | } |
| | | } |
| | | |
| | | void CServoGraph::UpdateImageAngle(int id, float angle) |
| | | { |
| | | IMAGE* pImage = GetImage(id); |
| | | if (pImage != nullptr) { |
| | | pImage->angle = angle; |
| | | } |
| | | } |
| | | |
| | | void CServoGraph::DrawImage(HDC hMemDC, IMAGE& item) |
| | | { |
| | | // è½½å
¥BMP |
| | | if (item.hBitmap == nullptr) { |
| | | item.hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(), |
| | | item.szPath, IMAGE_BITMAP, 0, 0, |
| | | LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE); |
| | | if (item.hBitmap != nullptr) { |
| | | BITMAP bitmap; |
| | | ::GetObject(item.hBitmap, sizeof(BITMAP), &bitmap); |
| | | item.bmWidth = bitmap.bmWidth; |
| | | item.bmHeight = bitmap.bmHeight; |
| | | } |
| | | } |
| | | |
| | | if (item.hBitmap != nullptr) { |
| | | // ä½¿ç¨ GDI+ å è½½ä½å¾ï¼å¹¶å建GDI+ Graphics 对象 |
| | | Bitmap bitmap(item.hBitmap, nullptr); |
| | | Graphics graphics(hMemDC); |
| | | |
| | | // 妿å¾åéè¦æè½¬ |
| | | if (item.angle != 0.0f) { |
| | | // è§åº¦è½¬æ¢ä¸ºå¼§åº¦ |
| | | float angleInRadians = item.angle; |
| | | |
| | | // è·åå¾åä¸å¿ |
| | | REAL cx = static_cast<REAL>(item.x + item.bmWidth / 2); // å°ä¸å¿X转æ¢ä¸ºREALç±»å |
| | | REAL cy = static_cast<REAL>(item.y + item.bmHeight / 2); // å°ä¸å¿Y转æ¢ä¸ºREALç±»å |
| | | |
| | | // å建æè½¬ç©éµ |
| | | Matrix rotateMatrix; |
| | | rotateMatrix.RotateAt(angleInRadians, PointF(cx, cy)); |
| | | |
| | | // åºç¨æè½¬ç©éµå°å¾å½¢ |
| | | graphics.SetTransform(&rotateMatrix); |
| | | } |
| | | |
| | | graphics.DrawImage(&bitmap, item.x, item.y); |
| | | graphics.ResetTransform(); |
| | | } |
| | | } |
| | |
| | | HBITMAP hBitmap; |
| | | int bmWidth; |
| | | int bmHeight; |
| | | float angle; |
| | | } IMAGE; |
| | | |
| | | |
| | |
| | | BOOL GetIndicateBoxRect(int id, LPRECT lprcBox); |
| | | void SetBoxText(int id, const char* pszText, const char* pszTooltip); |
| | | HWND GetSafeWnd(); |
| | | void UpdateImageCoordinates(int id, int newX, int newY); |
| | | void UpdateIndicateBoxCoordinates(int id, int newX, int newY); |
| | | void UpdateImageAngle(int id, float angle); |
| | | |
| | | private: |
| | | void DrawImage(HDC hMemDC, IMAGE& item); |
| | | |
| | | private: |
| | | HWND m_hWnd; |
| | |
| | | #include <afxcontrolbars.h> // åè½åºåæ§ä»¶æ¡ç MFC æ¯æ |
| | | |
| | | |
| | | // GDI+ |
| | | #include <gdiplus.h> |
| | | using namespace Gdiplus; |
| | | |
| | | |
| | | // æ°æ®åºæ¨¡å |
| | | #include "..\DatabaseSDK\include\Database.h" |
| | | #include "..\DatabaseSDK\include\MySQLDatabase.h" |
| | | #include "..\DatabaseSDK\include\SQLiteDatabase.h" |
| | | |
| | | #if defined(_WIN64) |
| | | #if defined(_DEBUG) |
| | | #pragma comment(lib, "..\\DatabaseSDK\\lib\\x64\\Debug\\DatabaseEx.lib") |
| | | #else |
| | | #pragma comment(lib, "..\\DatabaseSDK\\lib\\x64\\Release\\DatabaseEx.lib") |
| | | #endif |
| | | #else |
| | | #if defined(_DEBUG) |
| | | #pragma comment(lib, "..\\DatabaseSDK\\lib\\Win32\\Debug\\DatabaseEx.lib") |
| | | #else |
| | | #pragma comment(lib, "..\\DatabaseSDK\\lib\\Win32\\Release\\DatabaseEx.lib") |
| | | #endif |
| | | #endif |
| | | |
| | | |
| | | #include "..\RxWindows1.0\include\RxWindowsLib.h" |
| | | #include "..\HSMSSDK\Include\HSMSSDK.h" |