LAPTOP-SNT8I5JK\Boounion
2025-01-02 d362ec98ec0db2039944da31729ad8efcd72834a
1.20250102合并;
已添加12个文件
已修改29个文件
3019 ■■■■ 文件已修改
Document/Bond软件开发进度表.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/AlarmPopupDlg.cpp 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/AlarmPopupDlg.h 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondEq.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondEq.vcxproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondEq.vcxproj.filters 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondEq.vcxproj.user 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondEqDlg.cpp 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CBaseDlg.cpp 341 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CBaseDlg.h 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CBonder.cpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CBonder.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CComponentPLCDlg.cpp 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CPageAlarm.cpp 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CPageAlarm.h 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CPanelProject.cpp 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CPanelProject.h 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CProjectPageMain.cpp 320 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CProjectPageMain.h 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Common.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp 106 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/FileManager/RecipeManager.h 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/ToolUnits.cpp 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/ToolUnits.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/AxisDetailSettingsDlg.cpp 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/AxisDetailSettingsDlg.h 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/AxisSettingsDlg.h 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/RecipeListDlg.cpp 464 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/RecipeListDlg.h 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/SystemLogManagerDlg.cpp 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/SystemLogManagerDlg.h 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/UserManagerDlg.cpp 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/UserManagerDlg.h 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/res_en.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/res_zh.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/resource1.h 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/resource2.h 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/stdafx.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Config/BondEq.db 补丁 | 查看 | 原始文档 | blame | 历史
Document/BondÈí¼þ¿ª·¢½ø¶È±í.xlsx
Binary files differ
SourceCode/Bond/BondEq/AlarmPopupDlg.cpp
@@ -16,6 +16,8 @@
CAlarmPopupDlg::CAlarmPopupDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_DIALOG_POPUP_ALARM, pParent)
{
    m_pPLC = nullptr;
    m_crBkgnd = RGB(225, 225, 225);
    m_hbrBkgnd = nullptr;
    m_pActiveAlarm = nullptr;
@@ -24,6 +26,13 @@
CAlarmPopupDlg::~CAlarmPopupDlg()
{
}
void CAlarmPopupDlg::SetPLC(CPLC* pPLC)
{
    ASSERT(pPLC);
    m_pPLC = pPLC;
}
void CAlarmPopupDlg::DoDataExchange(CDataExchange* pDX)
{
@@ -36,6 +45,8 @@
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_BN_CLICKED(IDC_BUTTON_CLOSE, &CAlarmPopupDlg::OnBnClickedButtonClose)
    ON_BN_CLICKED(IDC_BUTTON_SOUND_OFF, &CAlarmPopupDlg::OnBnClickedButtonSoundOff)
    ON_BN_CLICKED(IDC_BUTTON_ALARM_OFF, &CAlarmPopupDlg::OnBnClickedButtonAlarmOff)
END_MESSAGE_MAP()
@@ -115,14 +126,12 @@
    // é™éŸ³æŒ‰é’®
    bool bMute = theApp.m_model.getBonder().isMute();
    m_btnSoundOff.SubclassDlgItem(IDC_BUTTON_SOUND_OFF, this);
    m_btnSoundOff.SetFrameColor(BS_NORMAL, BTN_SOUND_OFF_FRAME_NORMAL);
    m_btnSoundOff.SetFrameColor(BS_HOVER, BTN_SOUND_OFF_FRAME_HOVER);
    m_btnSoundOff.SetFrameColor(BS_PRESS, BTN_SOUND_OFF_FRAME_PRESS);
    m_btnSoundOff.SetBkgndColor(BS_NORMAL, BTN_SOUND_OFF_BKGND_NORMAL);
    m_btnSoundOff.SetBkgndColor(BS_HOVER, BTN_SOUND_OFF_BKGND_HOVER);
    m_btnSoundOff.SetBkgndColor(BS_PRESS, BTN_SOUND_OFF_BKGND_PRESS);
    SetButtonBackgroundColors(bMute);
    // æ¨ªçº¿1
    CHorizontalLine* pLine = CHorizontalLine::Hook(GetDlgItem(IDC_LINE1)->m_hWnd);
@@ -215,3 +224,71 @@
        ShowWindow(SW_HIDE);
    }
}
void CAlarmPopupDlg::SetButtonBackgroundColors(bool bMute)
{
    if (!bMute) {
        m_btnSoundOff.SetBkgndColor(BS_NORMAL, BTN_SOUND_OFF_BKGND_NORMAL);
        m_btnSoundOff.SetBkgndColor(BS_HOVER, BTN_SOUND_OFF_BKGND_HOVER);
        m_btnSoundOff.SetBkgndColor(BS_PRESS, BTN_SOUND_OFF_BKGND_PRESS);
    }
    else {
        m_btnSoundOff.SetBkgndColor(BS_NORMAL, BTN_SOUND_ON_BKGND_NORMAL);
        m_btnSoundOff.SetBkgndColor(BS_HOVER, BTN_SOUND_ON_BKGND_HOVER);
        m_btnSoundOff.SetBkgndColor(BS_PRESS, BTN_SOUND_ON_BKGND_PRESS);
    }
}
void CAlarmPopupDlg::OnBnClickedButtonSoundOff()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    if (m_pPLC == nullptr || !m_pPLC->isConnected()) {
        return;
    }
    // å‘ PLC å†™å…¥ä¿¡å·
    bool bMute = theApp.m_model.getBonder().isMute();
    char szWrite[4] = { 0x1, 0x0, 0x0, 0x0 };
    szWrite[0] = !bMute;
    m_pPLC->writeData(MC::M, 1003, szWrite, 2, [](IMcChannel* pChannel, int nAddr, DWORD nValue, int nFlag) {
        if (nFlag == 0) {
            TRACE("操作成功:地址=1003\n",  nAddr);
        }
        else {
            TRACE("操作失败:地址=1003,错误码=%d\n", nFlag);
        }
    });
    SetButtonBackgroundColors(!bMute);
}
void CAlarmPopupDlg::OnBnClickedButtonAlarmOff()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    if (m_pPLC == nullptr || !m_pPLC->isConnected()) {
        return;
    }
    // å‘ PLC å†™å…¥ä¿¡å·
    char szWrite[4] = { 0x1, 0x0, 0x0, 0x0 };
    m_pPLC->writeData(MC::M, 1009, szWrite, 2, [](IMcChannel* pChannel, int nAddr, DWORD nValue, int nFlag) {
        if (nFlag == 0) {
            TRACE("操作成功:地址=1009\n", nAddr);
        }
        else {
            TRACE("操作失败:地址=1009,错误码=%d\n", nFlag);
        }
    });
    Sleep(500);
    szWrite[0] = 0x0;
    m_pPLC->writeData(MC::M, 1009, szWrite, 2, [](IMcChannel* pChannel, int nAddr, DWORD nValue, int nFlag) {
        if (nFlag == 0) {
            TRACE("操作成功:地址=1009\n", nAddr);
        }
        else {
            TRACE("操作失败:地址=1009,错误码=%d\n", nFlag);
        }
    });
}
SourceCode/Bond/BondEq/AlarmPopupDlg.h
@@ -13,6 +13,8 @@
    CAlarmPopupDlg(CWnd* pParent = NULL);   // æ ‡å‡†æž„造函数
    virtual ~CAlarmPopupDlg();
public:
    void SetPLC(CPLC* pPLC);
public:
    void AlarmOn();
@@ -20,6 +22,7 @@
private:
    void ShowFirstAlarm();
    void SetButtonBackgroundColors(bool bMute);
private:
    COLORREF m_crBkgnd;
@@ -30,6 +33,7 @@
    CFont m_fontDescription;
private:
    CPLC* m_pPLC;
    CAlarm* m_pActiveAlarm;
    CBlButton m_btnClose;
    CBlButton m_btnSoundOff;
@@ -50,4 +54,6 @@
    afx_msg void OnDestroy();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnBnClickedButtonClose();
    afx_msg void OnBnClickedButtonSoundOff();
    afx_msg void OnBnClickedButtonAlarmOff();
};
SourceCode/Bond/BondEq/BondEq.rc
Binary files differ
SourceCode/Bond/BondEq/BondEq.vcxproj
@@ -192,6 +192,7 @@
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AlarmPopupDlg.h" />
    <ClInclude Include="CBaseDlg.h" />
    <ClInclude Include="CComponentDlg.h" />
    <ClInclude Include="CComponentPLCDlg.h" />
    <ClInclude Include="CPLC.h" />
@@ -211,6 +212,7 @@
    <ClInclude Include="CPanel.h" />
    <ClInclude Include="CParam.h" />
    <ClInclude Include="CProjectPageComponents.h" />
    <ClInclude Include="CProjectPageMain.h" />
    <ClInclude Include="CRemoteEqUnitView.h" />
    <ClInclude Include="CRemoteEqView.h" />
    <ClInclude Include="CHomeDialog.h" />
@@ -263,11 +265,13 @@
    <ClInclude Include="View\ChangePasswordDlg.h" />
    <ClInclude Include="View\IOMonitoringDlg.h" />
    <ClInclude Include="View\LoginDlg.h" />
    <ClInclude Include="View\RecipeListDlg.h" />
    <ClInclude Include="View\SystemLogManagerDlg.h" />
    <ClInclude Include="View\UserManagerDlg.h" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="AlarmPopupDlg.cpp" />
    <ClCompile Include="CBaseDlg.cpp" />
    <ClCompile Include="CComponentDlg.cpp" />
    <ClCompile Include="CComponentPLCDlg.cpp" />
    <ClCompile Include="CPLC.cpp" />
@@ -287,6 +291,7 @@
    <ClCompile Include="CPanel.cpp" />
    <ClCompile Include="CParam.cpp" />
    <ClCompile Include="CProjectPageComponents.cpp" />
    <ClCompile Include="CProjectPageMain.cpp" />
    <ClCompile Include="CRemoteEqUnitView.cpp" />
    <ClCompile Include="CRemoteEqView.cpp" />
    <ClCompile Include="CHomeDialog.cpp" />
@@ -343,6 +348,7 @@
    <ClCompile Include="View\ChangePasswordDlg.cpp" />
    <ClCompile Include="View\IOMonitoringDlg.cpp" />
    <ClCompile Include="View\LoginDlg.cpp" />
    <ClCompile Include="View\RecipeListDlg.cpp" />
    <ClCompile Include="View\SystemLogManagerDlg.cpp" />
    <ClCompile Include="View\UserManagerDlg.cpp" />
  </ItemGroup>
SourceCode/Bond/BondEq/BondEq.vcxproj.filters
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,244 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Manifest Include="res\application.exe.manifest" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="CPLC.cpp" />
    <ClCompile Include="AccordionWnd.cpp" />
    <ClCompile Include="Alarm.cpp" />
    <ClCompile Include="AlarmMonitor.cpp" />
    <ClCompile Include="ApredTreeCtrl.cpp" />
    <ClCompile Include="BaseSetPage.cpp" />
    <ClCompile Include="BlButton.cpp" />
    <ClCompile Include="BondEq.cpp" />
    <ClCompile Include="BondEqDlg.cpp" />
    <ClCompile Include="CBaseView.cpp" />
    <ClCompile Include="CBonder.cpp" />
    <ClCompile Include="CDataMonitor1.cpp" />
    <ClCompile Include="Component.cpp" />
    <ClCompile Include="Context.cpp" />
    <ClCompile Include="CPanel.cpp" />
    <ClCompile Include="CParam.cpp" />
    <ClCompile Include="CRemoteEqUnitView.cpp" />
    <ClCompile Include="CRemoteEqView.cpp" />
    <ClCompile Include="CHomeDialog.cpp" />
    <ClCompile Include="CMainContainer.cpp" />
    <ClCompile Include="CPageLogcat.cpp" />
    <ClCompile Include="CProjectPageRemoteEqs.cpp" />
    <ClCompile Include="Configuration.cpp" />
    <ClCompile Include="CPanelProject.cpp" />
    <ClCompile Include="EQState.cpp" />
    <ClCompile Include="EQStateMonitor.cpp" />
    <ClCompile Include="HmTab.cpp" />
    <ClCompile Include="HmVerticalTab.cpp" />
    <ClCompile Include="HorizontalLine.cpp" />
    <ClCompile Include="InputDialog.cpp" />
    <ClCompile Include="Intent.cpp" />
    <ClCompile Include="LoadMonitor.cpp" />
    <ClCompile Include="Log.cpp" />
    <ClCompile Include="LogEdit.cpp" />
    <ClCompile Include="McBool.cpp" />
    <ClCompile Include="McInt.cpp" />
    <ClCompile Include="McItem.cpp" />
    <ClCompile Include="McString.cpp" />
    <ClCompile Include="Model.cpp" />
    <ClCompile Include="CPageAlarm.cpp" />
    <ClCompile Include="Recipe.cpp" />
    <ClCompile Include="SetPage1.cpp" />
    <ClCompile Include="SetPage2.cpp" />
    <ClCompile Include="SettingsDlg.cpp" />
    <ClCompile Include="stdafx.cpp" />
    <ClCompile Include="ToolUnits.cpp" />
    <ClCompile Include="TopToolbar.cpp" />
    <ClCompile Include="VerticalLine.cpp" />
    <ClCompile Include="DBManager\UserManager.cpp">
      <Filter>DBManager</Filter>
    </ClCompile>
    <ClCompile Include="DBManager\SystemLogManager.cpp">
      <Filter>DBManager</Filter>
    </ClCompile>
    <ClCompile Include="View\ChangePasswordDlg.cpp">
      <Filter>View</Filter>
    </ClCompile>
    <ClCompile Include="View\LoginDlg.cpp">
      <Filter>View</Filter>
    </ClCompile>
    <ClCompile Include="View\SystemLogManagerDlg.cpp">
      <Filter>View</Filter>
    </ClCompile>
    <ClCompile Include="View\UserManagerDlg.cpp">
      <Filter>View</Filter>
    </ClCompile>
    <ClCompile Include="CProjectPageComponents.cpp" />
    <ClCompile Include="GB2860SQLite.cpp" />
    <ClCompile Include="sqlite3.c" />
    <ClCompile Include="DBManager\AxisManager.cpp">
      <Filter>DBManager</Filter>
    </ClCompile>
    <ClCompile Include="FileManager\RecipeManager.cpp">
      <Filter>FileManager</Filter>
    </ClCompile>
    <ClCompile Include="FileManager\pugixml.cpp">
      <Filter>FileManager</Filter>
    </ClCompile>
    <ClCompile Include="FileManager\IOManager.cpp">
      <Filter>FileManager</Filter>
    </ClCompile>
    <ClCompile Include="View\IOMonitoringDlg.cpp">
      <Filter>View</Filter>
    </ClCompile>
    <ClCompile Include="CComponentDlg.cpp" />
    <ClCompile Include="CComponentPLCDlg.cpp" />
    <ClCompile Include="View\AxisSettingsDlg.cpp">
      <Filter>View</Filter>
    </ClCompile>
    <ClCompile Include="View\AxisDetailSettingsDlg.cpp">
      <Filter>View</Filter>
    </ClCompile>
    <ClCompile Include="RegexEdit.cpp" />
    <ClCompile Include="AlarmPopupDlg.cpp" />
    <ClCompile Include="DBManager\AlarmManager.cpp">
      <Filter>DBManager</Filter>
    </ClCompile>
    <ClCompile Include="View\RecipeListDlg.cpp">
      <Filter>View</Filter>
    </ClCompile>
    <ClCompile Include="CBaseDlg.cpp" />
    <ClCompile Include="CProjectPageMain.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="CPLC.h" />
    <ClInclude Include="AccordionWnd.h" />
    <ClInclude Include="Alarm.h" />
    <ClInclude Include="AlarmMonitor.h" />
    <ClInclude Include="ApredTreeCtrl.h" />
    <ClInclude Include="BaseSetPage.h" />
    <ClInclude Include="BlButton.h" />
    <ClInclude Include="BondEq.h" />
    <ClInclude Include="BondEqDlg.h" />
    <ClInclude Include="CBaseView.h" />
    <ClInclude Include="CBonder.h" />
    <ClInclude Include="CDataMonitor1.h" />
    <ClInclude Include="Component.h" />
    <ClInclude Include="Context.h" />
    <ClInclude Include="CPanel.h" />
    <ClInclude Include="CParam.h" />
    <ClInclude Include="CRemoteEqUnitView.h" />
    <ClInclude Include="CRemoteEqView.h" />
    <ClInclude Include="CHomeDialog.h" />
    <ClInclude Include="CMainContainer.h" />
    <ClInclude Include="CPageLogcat.h" />
    <ClInclude Include="CProjectPageRemoteEqs.h" />
    <ClInclude Include="Common.h" />
    <ClInclude Include="Configuration.h" />
    <ClInclude Include="CPanelProject.h" />
    <ClInclude Include="EQState.h" />
    <ClInclude Include="EQStateMonitor.h" />
    <ClInclude Include="HmTab.h" />
    <ClInclude Include="HmVerticalTab.h" />
    <ClInclude Include="HorizontalLine.h" />
    <ClInclude Include="InputDialog.h" />
    <ClInclude Include="Intent.h" />
    <ClInclude Include="LoadMonitor.h" />
    <ClInclude Include="Log.h" />
    <ClInclude Include="LogEdit.h" />
    <ClInclude Include="McBool.h" />
    <ClInclude Include="McInt.h" />
    <ClInclude Include="McItem.h" />
    <ClInclude Include="McString.h" />
    <ClInclude Include="Model.h" />
    <ClInclude Include="CPageAlarm.h" />
    <ClInclude Include="Recipe.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="SetPage1.h" />
    <ClInclude Include="SetPage2.h" />
    <ClInclude Include="SettingsDlg.h" />
    <ClInclude Include="stdafx.h" />
    <ClInclude Include="targetver.h" />
    <ClInclude Include="ToolUnits.h" />
    <ClInclude Include="TopToolbar.h" />
    <ClInclude Include="VerticalLine.h" />
    <ClInclude Include="DBManager\UserManager.h">
      <Filter>DBManager</Filter>
    </ClInclude>
    <ClInclude Include="DBManager\SystemLogManager.h">
      <Filter>DBManager</Filter>
    </ClInclude>
    <ClInclude Include="View\ChangePasswordDlg.h">
      <Filter>View</Filter>
    </ClInclude>
    <ClInclude Include="View\LoginDlg.h">
      <Filter>View</Filter>
    </ClInclude>
    <ClInclude Include="View\SystemLogManagerDlg.h">
      <Filter>View</Filter>
    </ClInclude>
    <ClInclude Include="View\UserManagerDlg.h">
      <Filter>View</Filter>
    </ClInclude>
    <ClInclude Include="CProjectPageComponents.h" />
    <ClInclude Include="GB2860SQLite.h" />
    <ClInclude Include="sqlite3.h" />
    <ClInclude Include="sqlite3ext.h" />
    <ClInclude Include="DBManager\AxisManager.h">
      <Filter>DBManager</Filter>
    </ClInclude>
    <ClInclude Include="FileManager\RecipeManager.h">
      <Filter>FileManager</Filter>
    </ClInclude>
    <ClInclude Include="FileManager\pugiconfig.hpp">
      <Filter>FileManager</Filter>
    </ClInclude>
    <ClInclude Include="FileManager\pugixml.hpp">
      <Filter>FileManager</Filter>
    </ClInclude>
    <ClInclude Include="FileManager\IOManager.h">
      <Filter>FileManager</Filter>
    </ClInclude>
    <ClInclude Include="View\IOMonitoringDlg.h">
      <Filter>View</Filter>
    </ClInclude>
    <ClInclude Include="CComponentDlg.h" />
    <ClInclude Include="CComponentPLCDlg.h" />
    <ClInclude Include="View\AxisSettingsDlg.h">
      <Filter>View</Filter>
    </ClInclude>
    <ClInclude Include="View\AxisDetailSettingsDlg.h">
      <Filter>View</Filter>
    </ClInclude>
    <ClInclude Include="RegexEdit.h" />
    <ClInclude Include="AlarmPopupDlg.h" />
    <ClInclude Include="DBManager\AlarmManager.h">
      <Filter>DBManager</Filter>
    </ClInclude>
    <ClInclude Include="View\RecipeListDlg.h">
      <Filter>View</Filter>
    </ClInclude>
    <ClInclude Include="CBaseDlg.h" />
    <ClInclude Include="CProjectPageMain.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="BondEq.rc" />
  </ItemGroup>
  <ItemGroup>
    <Image Include="res\BondEq.ico" />
  </ItemGroup>
  <ItemGroup>
    <None Include="res\BondEq.rc2" />
  </ItemGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <Filter Include="DBManager">
      <UniqueIdentifier>{6b00bde2-91aa-41eb-9727-72d846b65036}</UniqueIdentifier>
    </Filter>
    <Filter Include="View">
      <UniqueIdentifier>{d11aa86e-1ee5-4307-89d0-84a9abb7ab1f}</UniqueIdentifier>
    </Filter>
    <Filter Include="FileManager">
      <UniqueIdentifier>{852d5282-c39d-45a3-b4a4-e6dd2a0c52a5}</UniqueIdentifier>
    </Filter>
  </ItemGroup>
</Project>
SourceCode/Bond/BondEq/BondEq.vcxproj.user
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <RESOURCE_FILE>BondEq.rc</RESOURCE_FILE>
  </PropertyGroup>
</Project>
SourceCode/Bond/BondEq/BondEqDlg.cpp
@@ -16,6 +16,8 @@
#include "UserManagerDlg.h"
#include "SystemLogManagerDlg.h"
// æµ‹è¯•
#include "RecipeListDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -251,10 +253,12 @@
    // è®¾ç½®é…æ–¹æ–‡ä»¶å¤¹è·¯å¾„
    RecipeManager& recipeManager = RecipeManager::getInstance();
    std::string strRecipePath =  CToolUnits::getCurrentExePath() + _T("\\Recipe");
    std::string strRecipePath =  CToolUnits::getRecipePath();
    CToolUnits::createDir(strRecipePath.c_str());
    recipeManager.setRecipeFolder(strRecipePath);
    if (!recipeManager.loadRecipe("Default")) {
        AfxMessageBox("Default é…æ–¹åŠ è½½å¤±è´¥ï¼");
    }
    // èœå•
    CMenu menu;
@@ -538,8 +542,11 @@
void CBondEqDlg::OnMenuFileSettings()
{
    CSettingsDlg dlg;
    CRecipeListDlg dlg;
    dlg.DoModal();
    //CSettingsDlg dlg;
    //dlg.DoModal();
}
void CBondEqDlg::OnUpdateMenuFileSettings(CCmdUI* pCmdUI)
@@ -825,6 +832,7 @@
{
    if (m_pAlarmWnd == nullptr) {
        m_pAlarmWnd = new CAlarmPopupDlg();
        m_pAlarmWnd->SetPLC(theApp.m_model.getBonder().getPLC("PLC(1)"));
        m_pAlarmWnd->Create(IDD_DIALOG_POPUP_ALARM, this);
        m_pAlarmWnd->CenterWindow();
    }
@@ -835,6 +843,7 @@
{
    if (m_pAlarmWnd == nullptr) {
        m_pAlarmWnd = new CAlarmPopupDlg();
        m_pAlarmWnd->SetPLC(theApp.m_model.getBonder().getPLC("PLC(1)"));
        m_pAlarmWnd->Create(IDD_DIALOG_POPUP_ALARM, this);
        m_pAlarmWnd->CenterWindow();
    }
SourceCode/Bond/BondEq/CBaseDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,341 @@
#include "stdafx.h"
#include "CBaseDlg.h"
#include "GridCtrl.h"
// å…¨å±€ä¸»é¢˜å¯¹è±¡
Theme g_lightTheme = { RGB(255, 255, 255), RGB(0, 0, 0), RGB(240, 240, 240), RGB(200, 200, 200) };
Theme g_darkTheme = { RGB(40, 40, 40), RGB(255, 255, 255), RGB(60, 60, 60), RGB(80, 80, 80) };
CFont g_defaultFont;
Theme* g_currentTheme = &g_lightTheme;
// å…¨å±€èµ„源句柄
HINSTANCE g_hCurrentResource = NULL;
IMPLEMENT_DYNAMIC(CBaseDlg, CDialogEx)
CBaseDlg::CBaseDlg(UINT nID, CWnd* pPage) : CDialogEx(nID, pPage), m_bResizing(false)
{
    m_nID = nID;
    m_pParent = pPage;
    m_nInitialWidth = 0;
    m_nInitialHeight = 0;
}
CBaseDlg::~CBaseDlg()
{
    // shared_ptr会自动清理内存,不需要手动删除
    m_mapFonts.clear();
    m_mapCtrlLayouts.clear();
    m_mapControls.clear();
}
void CBaseDlg::SwitchTheme(ThemeType enThemeType)
{
    // ä½¿ç”¨ map æ¥æ ¹æ® themeType æŸ¥æ‰¾ä¸»é¢˜
    static const std::unordered_map<ThemeType, Theme*> themeMap = {
        { ThemeType::Light, &g_lightTheme },
        { ThemeType::Dark, &g_darkTheme }
    };
    // è®¾ç½®å½“前主题
    auto it = themeMap.find(enThemeType);
    if (it != themeMap.end()) {
        g_currentTheme = it->second;
    }
    else {
        g_currentTheme = &g_lightTheme;
    }
    // æ›´æ–°æŽ§ä»¶çš„外观
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        pWnd->Invalidate();
        pWnd = pWnd->GetNextWindow();
    }
    // æ›´æ–°å¯¹è¯æ¡†èƒŒæ™¯é¢œè‰²
    SetBackgroundColor(g_currentTheme->backgroundColor);
}
void CBaseDlg::LoadResourceLibrary(const CString& strLanguage)
{
    // å¸è½½ä¹‹å‰åŠ è½½çš„èµ„æºåº“
    UnloadResourceLibrary();
    // åŠ è½½æ–°çš„èµ„æºåº“
    g_hCurrentResource = AfxLoadLibrary(strLanguage);
    // è®¾ç½®æ–°çš„资源句柄
    if (g_hCurrentResource != NULL) {
        AfxSetResourceHandle(g_hCurrentResource);
    }
}
void CBaseDlg::UnloadResourceLibrary()
{
    // å¸è½½ä¹‹å‰åŠ è½½çš„èµ„æºåº“
    if (g_hCurrentResource != NULL) {
        FreeLibrary(g_hCurrentResource);    // é‡Šæ”¾å½“前资源库
        g_hCurrentResource = NULL;            // æ¸…空资源句柄
    }
}
CFont* CBaseDlg::GetOrCreateFont(int nFontSize)
{
    auto it = m_mapFonts.find(nFontSize);
    if (it != m_mapFonts.end()) {
        return it->second.get();
    }
    // ä½¿ç”¨ shared_ptr æ¥ç®¡ç†å­—体对象
    auto font = std::make_shared<CFont>();
    LOGFONT logFont = { 0 };
    _tcscpy_s(logFont.lfFaceName, _T("Segoe UI"));
    logFont.lfHeight = -nFontSize;
    logFont.lfQuality = CLEARTYPE_QUALITY;
    font->CreateFontIndirect(&logFont);
    m_mapFonts[nFontSize] = font;
    return font.get();
}
void CBaseDlg::SetDefaultFont()
{
    CFont* defaultFont = GetOrCreateFont(12);
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        TCHAR szClassName[256];
        GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
        if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
            pWnd = pWnd->GetNextWindow();
            continue;
        }
        pWnd->SetFont(defaultFont, TRUE);
        pWnd = pWnd->GetNextWindow();
    }
}
BOOL CBaseDlg::AddControl(UINT nCtrlID, CWnd* pControl)
{
    // ç¡®ä¿æŽ§ä»¶ä¸é‡å¤æ·»åŠ 
    if (m_mapControls.find(nCtrlID) != m_mapControls.end()) {
        return FALSE;  // æŽ§ä»¶å·²ç»å­˜åœ¨
    }
    m_mapControls[nCtrlID] = std::unique_ptr<CWnd>(pControl);
    return TRUE;
}
BOOL CBaseDlg::RemoveControl(UINT nCtrlID)
{
    auto it = m_mapControls.find(nCtrlID);
    if (it != m_mapControls.end()) {
        m_mapControls.erase(it);
        return TRUE;
    }
    return FALSE;
}
BOOL CBaseDlg::UpdateControlText(UINT nCtrlID, const CString& strText)
{
    auto it = m_mapControls.find(nCtrlID);
    if (it != m_mapControls.end()) {
        CWnd* pWnd = it->second.get();
        if (pWnd->GetSafeHwnd() != nullptr)
        {
            pWnd->SetWindowText(strText);
            return TRUE;
        }
    }
    return FALSE;
}
CWnd* CBaseDlg::GetControl(UINT nCtrlID)
{
    auto it = m_mapControls.find(nCtrlID);
    if (it != m_mapControls.end()) {
        return it->second.get();
    }
    return nullptr;
}
void CBaseDlg::AdjustControls(float dScaleX, float dScaleY)
{
    if (m_bResizing) return; // é˜²æ­¢åœ¨è°ƒæ•´è¿‡ç¨‹ä¸­é‡å¤è°ƒæ•´
    m_bResizing = true;
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        int nCtrlID = pWnd->GetDlgCtrlID();
        if (nCtrlID != -1 && m_mapCtrlLayouts.find(nCtrlID) != m_mapCtrlLayouts.end()) {
            CRect originalRect = m_mapCtrlLayouts[nCtrlID];
            CRect newRect(
                static_cast<int>(originalRect.left * dScaleX),
                static_cast<int>(originalRect.top * dScaleY),
                static_cast<int>(originalRect.right * dScaleX),
                static_cast<int>(originalRect.bottom * dScaleY));
            TCHAR szClassName[256];
            GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
            if (_tcsicmp(szClassName, _T("ComboBox")) == 0) {
                CComboBox* pComboBox = (CComboBox*)pWnd;
                pComboBox->SetItemHeight(-1, newRect.Height());  // -1 è¡¨ç¤ºæ‰€æœ‰é¡¹çš„高度
            }
            if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
                CGridCtrl* pGridCtrl = (CGridCtrl*)pWnd;
                pGridCtrl->SetDefCellHeight(newRect.Height() / 21);
                pGridCtrl->ExpandColumnsToFit(TRUE);
                pGridCtrl->ExpandLastColumn();
                pGridCtrl->Invalidate();
                pGridCtrl->UpdateWindow();
            }
            pWnd->MoveWindow(&newRect);
            AdjustControlFont(pWnd, newRect.Width(), newRect.Height());
        }
        pWnd = pWnd->GetNextWindow();
    }
    m_bResizing = false;
}
void CBaseDlg::AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight)
{
    TCHAR szClassName[256];
    GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
    if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
        return;
    }
    int fontSize = nHeight / 2;
    if (fontSize < 8) fontSize = 8;
    if (fontSize > 32) fontSize = 32;
    CFont* pFont = GetOrCreateFont(fontSize);
    pWnd->SetFont(pFont);
    pWnd->Invalidate(); // åˆ·æ–°æŽ§ä»¶æ˜¾ç¤º
}
BEGIN_MESSAGE_MAP(CBaseDlg, CDialogEx)
    ON_WM_SIZE()
    ON_WM_GETMINMAXINFO()
    ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
BOOL CBaseDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // èŽ·å–å½“å‰è¯­è¨€
    LANGID langId = GetUserDefaultLangID();
    if (langId == LANG_CHINESE) {
        // åŠ è½½ä¸­æ–‡èµ„æº
    }
    else {
        // åŠ è½½è‹±æ–‡èµ„æº
    }
    // èŽ·å–å¯¹è¯æ¡†çš„å·¥ä½œåŒºï¼ˆå±å¹•å¯ç”¨åŒºåŸŸï¼‰
    CRect screenRect, dlgRect, clientRect;
    SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0);
    GetClientRect(&clientRect);
    m_nInitialWidth = clientRect.Width();
    m_nInitialHeight = clientRect.Height();
    // è®¾ç½®é»˜è®¤å­—体
    CFont* pDefaultFont = GetOrCreateFont(12);
    // éåŽ†å­çª—å£ï¼ˆæŽ§ä»¶ï¼‰
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        int nCtrlID = pWnd->GetDlgCtrlID();
        if (nCtrlID != -1) {
            // ä¿å­˜æŽ§ä»¶çš„初始布局
            CRect ctrlRect;
            pWnd->GetWindowRect(&ctrlRect);
            ScreenToClient(&ctrlRect);
            m_mapCtrlLayouts[nCtrlID] = ctrlRect;
            // æŽ’除不需要操作的控件(如自定义控件 GridCtrl)
            TCHAR szClassName[256];
            GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
            if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
                pWnd = pWnd->GetNextWindow();
                continue;
            }
            // è®¾ç½®æŽ§ä»¶çš„默认字体
            pWnd->SetFont(pDefaultFont);
        }
        pWnd = pWnd->GetNextWindow();
    }
    // å°†å¯¹è¯æ¡†å±…中
    GetWindowRect(&dlgRect);
    int dlgWidth = dlgRect.Width() * 2;
    int dlgHeight = dlgRect.Height() * 2;
    if (dlgWidth > screenRect.Width()) {
        dlgWidth = screenRect.Width();
    }
    if (dlgHeight > screenRect.Height()) {
        dlgHeight = screenRect.Height();
    }
    int centerX = screenRect.left + (screenRect.Width() - dlgWidth) / 2;
    int centerY = screenRect.top + (screenRect.Height() - dlgHeight) / 2;
    MoveWindow(centerX, centerY, dlgWidth, dlgHeight);
    return TRUE;
}
void CBaseDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (nType == SIZE_MINIMIZED || m_mapCtrlLayouts.empty()) {
        return;
    }
    // æ£€æŸ¥å°ºå¯¸å˜åŒ–是否足够大,避免频繁调整
    //static int lastWidth = 0, lastHeight = 0;
    //if (abs(cx - lastWidth) < 10 && abs(cy - lastHeight) < 10) {
    //    return;
    //}
    //lastWidth = cx;
    //lastHeight = cy;
    // è®¡ç®—比例并调整布局
    float dScaleX = static_cast<float>(cx) / m_nInitialWidth;
    float dScaleY = static_cast<float>(cy) / m_nInitialHeight;
    AdjustControls(dScaleX, dScaleY);
}
void CBaseDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
    lpMMI->ptMinTrackSize.x = 400;
    lpMMI->ptMinTrackSize.y = 300;
    CDialogEx::OnGetMinMaxInfo(lpMMI);
}
HBRUSH CBaseDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    if (g_currentTheme) {
        pDC->SetBkColor(g_currentTheme->backgroundColor);
        pDC->SetTextColor(g_currentTheme->textColor);
        // è¿”回背景画刷
        return CreateSolidBrush(g_currentTheme->backgroundColor);
    }
    return CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
}
SourceCode/Bond/BondEq/CBaseDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,62 @@
#pragma once
#include <memory>
#include <unordered_map>
enum class ThemeType {
    Light,  // æµ…色主题
    Dark    // æ·±è‰²ä¸»é¢˜
};
struct Theme {
    COLORREF backgroundColor;
    COLORREF textColor;
    COLORREF buttonColor;
    COLORREF borderColor;
};
class CBaseDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CBaseDlg)
public:
    CBaseDlg(UINT nID, CWnd* pPage);            // æ ‡å‡†æž„造函数
    virtual ~CBaseDlg();                        // æžæž„函数
    // ä¸»é¢˜ç®¡ç†
    void SwitchTheme(ThemeType enThemeType);            // åˆ‡æ¢ä¸»é¢˜
    // èµ„源管理
    void LoadResourceLibrary(const CString& strLanguage);            // åŠ è½½èµ„æºåº“
    void UnloadResourceLibrary();                                    // å¸è½½èµ„源库
    // å­—体管理
    CFont* GetOrCreateFont(int nFontSize);            // èŽ·å–æˆ–åˆ›å»ºå­—ä½“
    void SetDefaultFont();                            // è®¾ç½®é»˜è®¤å­—体
    // åŠ¨æ€æŽ§ä»¶ç®¡ç†
    BOOL AddControl(UINT nCtrlID, CWnd* pControl);                    // æ·»åŠ æŽ§ä»¶
    BOOL RemoveControl(UINT nCtrlID);                                // ç§»é™¤æŽ§ä»¶
    BOOL UpdateControlText(UINT nCtrlID, const CString& strText);   // æ›´æ–°æŽ§ä»¶æ–‡æœ¬
    CWnd* GetControl(UINT nCtrlID);                                    // èŽ·å–æŽ§ä»¶
private:
    void AdjustControls(float dScaleX, float dScaleY);                // è°ƒæ•´æŽ§ä»¶å¤§å°
    void AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight);    // è°ƒæ•´æŽ§ä»¶å­—体
private:
    UINT m_nID;                                                    // å¯¹è¯æ¡†ID
    CWnd* m_pParent;                                            // çˆ¶çª—口
    bool m_bResizing;                                            // æŽ§ä»¶æ˜¯å¦æ­£åœ¨è°ƒæ•´å¤§å°
    int m_nInitialWidth;                                        // å¯¹è¯æ¡†åˆå§‹å®½åº¦
    int m_nInitialHeight;                                        // å¯¹è¯æ¡†åˆå§‹é«˜åº¦
    std::unordered_map<int, CRect> m_mapCtrlLayouts;            // æŽ§ä»¶å¸ƒå±€
    std::map<UINT, std::unique_ptr<CWnd>> m_mapControls;        // æŽ§ä»¶é›†åˆ
    std::unordered_map<int, std::shared_ptr<CFont>> m_mapFonts;    // æŽ§ä»¶å­—体
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};
SourceCode/Bond/BondEq/CBonder.cpp
@@ -133,6 +133,7 @@
    AddComponent(pEQStateMonitor1);
    pEQStateMonitor1->init();
    m_bMute = false;
    // åˆå§‹åŒ–各种组件
    // è¯»PLC1配置
@@ -971,4 +972,12 @@
    return iter->second;
}
bool CBonder::isMute()
{
    return m_bMute;
}
void CBonder::setMute(bool bMute)
{
    m_bMute = bMute;
}
SourceCode/Bond/BondEq/CBonder.h
@@ -69,6 +69,8 @@
    int loadReady(BEQ::IUnit* pUnit, const char* pszMaterielId, const char* pszRecipeId);
    int loadComplete(BEQ::IUnit* pUnit, int layer);
    int unloadComplete(BEQ::IUnit* pUnit, int layer);
    bool isMute();
    void setMute(bool bMute);
public:
    int writeInt(int unitId, int addr, int value);
@@ -115,5 +117,6 @@
    BEQ::IEquipment* m_pEquipment;
    std::map<int, CRecipe*> m_recipes;
    std::string m_strCurRecipeName;
    bool m_bMute;
};
SourceCode/Bond/BondEq/CComponentPLCDlg.cpp
@@ -152,9 +152,14 @@
void CComponentPLCDlg::OnBnClickedButtonAxisSetting()
{
    std::string strName = RecipeManager::getInstance().getCurrentRecipeName();
    if (strName.empty()) {
        AfxMessageBox("未选择配方!", MB_ICONERROR);
    }
    CAxisSettingsDlg axisDlg;
    axisDlg.SetPLC((CPLC*)m_pContext);
    axisDlg.SetRecipeName(_T("Default"));
    axisDlg.SetRecipeName(strName.c_str());
    axisDlg.DoModal();
}
SourceCode/Bond/BondEq/CPageAlarm.cpp
@@ -8,6 +8,7 @@
#include "Common.h"
#include "ToolUnits.h"
#define PAGE_SIZE        20
// CPageAlarm å¯¹è¯æ¡†
@@ -19,6 +20,16 @@
    m_crBkgnd = PAGE_BACKGROUND_COLOR;
    m_hbrBkgnd = nullptr;
    m_pObserver = nullptr;
    m_strKeyword = "";
    m_nCurPage = 0;
    m_nTotalPages = 0;
    m_nDateTimeFlag = 0;
    memset(m_szTimeStart, 0, sizeof(m_szTimeStart));
    memset(m_szTimeEnd, 0, sizeof(m_szTimeEnd));
    m_szTimeStart[0] = '\0';
    m_szTimeEnd[0] = '\0';
}
CPageAlarm::~CPageAlarm()
@@ -27,6 +38,8 @@
void CPageAlarm::DoDataExchange(CDataExchange* pDX)
{
    DDX_Control(pDX, IDC_DATETIMEPICKER_START, m_dateTimeStart);
    DDX_Control(pDX, IDC_DATETIMEPICKER_END, m_dateTimeEnd);
    CDialogEx::DoDataExchange(pDX);
}
@@ -35,6 +48,11 @@
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_CBN_SELCHANGE(IDC_COMBO_DATETIME, &CPageAlarm::OnCbnSelchangeComboDatetime)
    ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CPageAlarm::OnBnClickedButtonSearch)
    ON_BN_CLICKED(IDC_BUTTON_EXPORT, &CPageAlarm::OnBnClickedButtonExport)
    ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CPageAlarm::OnBnClickedButtonPrevPage)
    ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CPageAlarm::OnBnClickedButtonNextPage)
END_MESSAGE_MAP()
@@ -82,6 +100,19 @@
    CDialogEx::OnInitDialog();
    InitRxWindow();
    // ä¸‹æ‹‰æ¡†æŽ§ä»¶
    CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
    pComboBox->AddString(_T("不限"));
    pComboBox->AddString(_T("今天"));
    pComboBox->AddString(_T("七天内"));
    pComboBox->AddString(_T("本月"));
    pComboBox->AddString(_T("今年"));
    pComboBox->AddString(_T("自定义"));
    pComboBox->SetCurSel(0);
    // æ—¥æœŸæŽ§ä»¶
    m_dateTimeStart.EnableWindow(FALSE);
    m_dateTimeEnd.EnableWindow(FALSE);
    // æŠ¥è¡¨æŽ§ä»¶
    CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM);
@@ -98,6 +129,10 @@
    pListCtrl->InsertColumn(4, _T("发生时间"), LVCFMT_LEFT, 180);
    pListCtrl->InsertColumn(5, _T("解除时间"), LVCFMT_LEFT, 180);
    // è®¡ç®—总页数
    int totalRecords = AlarmManager::getInstance().getTotalAlarmCount(m_strKeyword, m_szTimeStart, m_szTimeEnd);
    m_nTotalPages = (totalRecords + PAGE_SIZE - 1) / PAGE_SIZE;
    m_nCurPage = 1;
    Resize();
    LoadAlarms();
@@ -150,13 +185,12 @@
    GetClientRect(&rcClient);
    pItem = GetDlgItem(IDC_LIST_ALARM);
    pItem->MoveWindow(12, 12, rcClient.Width() - 24, rcClient.Height() - 24);
    pItem->MoveWindow(12, 52, rcClient.Width() - 24, rcClient.Height() - 64);
}
void CPageAlarm::LoadAlarms()
{
    CAlarmMonitor* pMonitor = (CAlarmMonitor*)theApp.m_model.getBonder().GetComponent(ALARM_MONITOR);
    // å½“前正在发生的报警
    pMonitor->Lock();
@@ -166,19 +200,9 @@
    }
    pMonitor->Unlock();
    // èŽ·å–åŽ†å²æŠ¥è­¦æ•°æ®
    auto vecData = AlarmManager::getInstance().getAllAlarms();
    // å¡«å……数据
    CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM);
    for (auto item : vecData) {
        pListCtrl->InsertItem(0, _T(""));
        pListCtrl->SetItemText(0, 1, item[0].c_str());
        pListCtrl->SetItemText(0, 2, item[1].c_str());
        pListCtrl->SetItemText(0, 3, item[2].c_str());
        pListCtrl->SetItemText(0, 4, item[3].c_str());
    }
    // åˆ·æ–°åŽ†å²æŠ¥è­¦æ•°æ®
    m_nCurPage = 1;
    UpdatePageData();
}
void CPageAlarm::AddAlarm(CAlarmMonitor* pMonitor, CAlarm* pAlarm)
@@ -213,6 +237,52 @@
    }
}
void CPageAlarm::UpdatePageData()
{
    // æ ¹æ®è¿‡æ»¤æ¡ä»¶åŠ è½½æ•°æ®
    auto vecData = AlarmManager::getInstance().getFilteredAlarms(m_strKeyword, m_szTimeStart, m_szTimeEnd, m_nCurPage, PAGE_SIZE);
    // å¡«å……数据到控件
    CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM);
    FillDataToListCtrl(pListCtrl, vecData);
    // æ›´æ–°åˆ†é¡µæŽ§ä»¶ï¼ˆé¡µæ•°å’ŒæŒ‰é’®ï¼‰
    UpdatePageControls();
}
void CPageAlarm::UpdatePageControls()
{
    // æ›´æ–°åˆ†é¡µä¿¡æ¯
    CString strPage;
    strPage.Format(_T("第 %d é¡µ"), m_nCurPage);
    SetDlgItemText(IDC_LABEL_PAGE_NUMBER, strPage);
    // å¯ç”¨/禁用翻页按钮
    GetDlgItem(IDC_BUTTON_PREV_PAGE)->EnableWindow(m_nCurPage > 1);
    GetDlgItem(IDC_BUTTON_NEXT_PAGE)->EnableWindow(m_nCurPage < m_nTotalPages);
}
void CPageAlarm::FillDataToListCtrl(CListCtrl* pListCtrl, const std::vector<std::vector<std::string>>& vecData)
{
    // æ¸…空当前CListCtrl中的所有项
    for (int i = 0; i < pListCtrl->GetItemCount(); i++) {
        CAlarm* pAlarm = (CAlarm*)pListCtrl->GetItemData(i);
        if (pAlarm != nullptr) {
            pAlarm->release();
        }
    }
    pListCtrl->DeleteAllItems();
    // éåŽ†æ•°æ®å¹¶æ’å…¥åˆ°CListCtrl中
    for (const auto& item : vecData) {
        int nItem = pListCtrl->InsertItem(pListCtrl->GetItemCount(), _T(""));    // æ’入新行
        pListCtrl->SetItemText(nItem, 1, item[0].c_str());                        // è®¾ç½®ç¬¬ä¸€åˆ—的文本
        pListCtrl->SetItemText(nItem, 2, item[1].c_str());                        // è®¾ç½®ç¬¬äºŒåˆ—的文本
        pListCtrl->SetItemText(nItem, 3, item[2].c_str());                        // è®¾ç½®ç¬¬ä¸‰åˆ—的文本
        pListCtrl->SetItemText(nItem, 4, item[3].c_str());                        // è®¾ç½®ç¬¬å››åˆ—的文本
    }
}
BOOL CPageAlarm::DestroyWindow()
{
    CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM);
@@ -225,3 +295,146 @@
    return CDialogEx::DestroyWindow();
}
void CPageAlarm::OnCbnSelchangeComboDatetime()
{
    CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
    int nIndex = pComboBox->GetCurSel();
    int nCount = pComboBox->GetCount();
    m_dateTimeStart.EnableWindow(nIndex == nCount - 1);
    m_dateTimeEnd.EnableWindow(nIndex == nCount - 1);
}
void CPageAlarm::OnBnClickedButtonSearch()
{
    // èŽ·å–å…³é”®å­—
    CString cstrKeyword;
    GetDlgItemText(IDC_EDIT_KEYWORD, cstrKeyword);
    m_strKeyword = CT2A(cstrKeyword);
    // èŽ·å–æ—¥æœŸ
    CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
    m_nDateTimeFlag = pComboBox->GetCurSel();
    if (m_nDateTimeFlag == 0) {
        memset(m_szTimeStart, 0, sizeof(m_szTimeStart));
        memset(m_szTimeEnd, 0, sizeof(m_szTimeEnd));
        m_szTimeStart[0] = '\0';
        m_szTimeEnd[0] = '\0';
    }
    else {
        CTime time = CTime::GetCurrentTime();
        if (m_nDateTimeFlag == 1) {
            // ä»Šå¤©
            sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", time.GetYear(), time.GetMonth(), time.GetDay());
            sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
        }
        else if (m_nDateTimeFlag == 2) {
            // 7天内
            CTime time2 = time - CTimeSpan(7, 0, 0, 0);
            sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", time2.GetYear(), time2.GetMonth(), time2.GetDay());
            sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
        }
        else if (m_nDateTimeFlag == 3) {
            // æœ¬æœˆ
            sprintf_s(m_szTimeStart, 64, "%d-%02d-01 00:00:00", time.GetYear(), time.GetMonth());
            sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
        }
        else if (m_nDateTimeFlag == 4) {
            // ä»Šå¹´
            sprintf_s(m_szTimeStart, 64, "%d-01-01 00:00:00", time.GetYear());
            sprintf_s(m_szTimeEnd, 64, "%d-12-31 23:59:59", time.GetYear());
        }
        else if (m_nDateTimeFlag == 5) {
            // è‡ªå®šä¹‰
            SYSTEMTIME t1, t2;
            m_dateTimeStart.GetTime(&t1);
            m_dateTimeEnd.GetTime(&t2);
            sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d %02d:%02d:%02d",
                t1.wYear, t1.wMonth, t1.wDay, t1.wHour, t1.wMinute, t1.wSecond);
            sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d %02d:%02d:%02d",
                t2.wYear, t2.wMonth, t2.wDay, t2.wHour, t2.wMinute, t2.wSecond);
        }
    }
    // è®¡ç®—总页数
    int totalRecords = AlarmManager::getInstance().getTotalAlarmCount(m_strKeyword, m_szTimeStart, m_szTimeEnd);
    m_nTotalPages = (totalRecords + PAGE_SIZE - 1) / PAGE_SIZE;
    m_nCurPage = 1;
    UpdatePageData();  // è°ƒç”¨åˆ†é¡µæ›´æ–°å‡½æ•°
}
void CPageAlarm::OnBnClickedButtonExport()
{
    CFileDialog fileDialog(FALSE, "csv", "", OFN_HIDEREADONLY, "csv.files(*.csv)|*.csv||");
    if (fileDialog.DoModal() != IDOK) {
        return;
    }
    CStdioFile file;
    if (!file.Open(fileDialog.GetPathName(), CFile::modeCreate | CFile::modeWrite)) {
        AfxMessageBox("创建文件失败!");
    }
    int nSubItemCount = 0;
    CString strSubItem, strHeader, strRow;
    char szItem[256];
    HDITEM hdItem[35];
    for (int i = 0; i < 35; i++) {
        hdItem[i].pszText = szItem;
        hdItem[i].cchTextMax = 256;
        hdItem[i].mask = HDI_TEXT | HDI_WIDTH;
    }
    // å…ˆè¯»è¡¨å¤´
    CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM);
    CHeaderCtrl* pHeader = pListCtrl->GetHeaderCtrl();
    nSubItemCount = pHeader->GetItemCount();
    ASSERT(nSubItemCount <= 35);
    for (int i = 0; i < pHeader->GetItemCount(); i++) {
        pHeader->GetItem(i, &hdItem[i]);
        if (hdItem[i].cxy > 0) {
            if (!strHeader.IsEmpty()) {
                strHeader.Append(",");
            }
            strHeader.Append(CString(hdItem[i].pszText));
        }
    }
    strHeader.Append("\n");
    file.WriteString(strHeader);
    // å†™è¡¨æ ¼å†…容
    int count = pListCtrl->GetItemCount();
    for (int i = 0; i < count; i++) {
        strRow.Empty();
        for (int j = 0; j < nSubItemCount; j++) {
            if (hdItem[j].cxy > 0) {
                if (!strRow.IsEmpty()) {
                    strRow.Append(",");
                }
                CString strTemp = pListCtrl->GetItemText(i, j);
                strTemp.Replace("* ", "");
                strRow.Append(strTemp);
            }
        }
        strRow.Append("\n");
        file.WriteString(strRow);
    }
    file.Close();
}
void CPageAlarm::OnBnClickedButtonPrevPage()
{
    // ç‚¹å‡»ä¸Šä¸€é¡µ
    m_nCurPage--;
    UpdatePageData();  // è°ƒç”¨åˆ†é¡µæ›´æ–°å‡½æ•°
}
void CPageAlarm::OnBnClickedButtonNextPage()
{
    // ç‚¹å‡»ä¸‹ä¸€é¡µ
    m_nCurPage++;
    UpdatePageData();  // è°ƒç”¨åˆ†é¡µæ›´æ–°å‡½æ•°
}
SourceCode/Bond/BondEq/CPageAlarm.h
@@ -18,11 +18,30 @@
    void LoadAlarms();
    void AddAlarm(CAlarmMonitor* pMonitor, CAlarm* pAlarm);
    void UpdateAlarm(CAlarmMonitor* pMonitor, CAlarm* pAlarm);
    void UpdatePageData();
    void UpdatePageControls();
    void FillDataToListCtrl(CListCtrl* pListCtrl, const std::vector<std::vector<std::string>>& vecData);
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    IObserver* m_pObserver;
    // å…³é”®å­—
    std::string m_strKeyword;
    // é¡µç 
    int m_nCurPage;
    int m_nTotalPages;
    // æ—¥æœŸ
    int m_nDateTimeFlag;
    char m_szTimeStart[64];
    char m_szTimeEnd[64];
    // æŽ§ä»¶
    CDateTimeCtrl m_dateTimeStart;
    CDateTimeCtrl m_dateTimeEnd;
// å¯¹è¯æ¡†æ•°æ®
@@ -40,4 +59,9 @@
    afx_msg void OnDestroy();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    virtual BOOL DestroyWindow();
    afx_msg void OnCbnSelchangeComboDatetime();
    afx_msg void OnBnClickedButtonSearch();
    afx_msg void OnBnClickedButtonExport();
    afx_msg void OnBnClickedButtonPrevPage();
    afx_msg void OnBnClickedButtonNextPage();
};
SourceCode/Bond/BondEq/CPanelProject.cpp
@@ -18,7 +18,8 @@
    m_hbrBkgnd = nullptr;
    m_nPanelWidth = int((double)GetSystemMetrics(SM_CXSCREEN) * 0.25);
    m_pAccordionWnd = nullptr;
    m_pPageRemoteEqs = nullptr;
    //m_pPageRemoteEqs = nullptr;
    m_pPageMain = nullptr;
    m_pPageComponents = nullptr;
}
@@ -71,10 +72,16 @@
    m_pAccordionWnd->Setpadding(PADDING_BOTTOM, 2);
    m_pAccordionWnd->LoadExpandIcon(strExpandIcon, strCloseIcon);
    
    m_pPageRemoteEqs = new CProjectPageRemoteEqs();
    m_pPageRemoteEqs->Create(IDD_PROJECT_PAGE_REMOTEEQS, GetDlgItem(IDC_ACCORDION_WND1));
    m_pPageRemoteEqs->ShowWindow(SW_SHOW);
    m_pAccordionWnd->AddItem("远程设备", m_pPageRemoteEqs, 0, TRUE, TRUE);
    //m_pPageRemoteEqs = new CProjectPageRemoteEqs();
    //m_pPageRemoteEqs->Create(IDD_PROJECT_PAGE_REMOTEEQS, GetDlgItem(IDC_ACCORDION_WND1));
    //m_pPageRemoteEqs->ShowWindow(SW_SHOW);
    //m_pAccordionWnd->AddItem("远程设备", m_pPageRemoteEqs, 0, TRUE, TRUE);
    m_pPageMain = new CProjectPageMain();
    m_pPageMain->SetPLC(theApp.m_model.getBonder().getPLC("PLC(1)"));
    m_pPageMain->Create(IDD_PROJECT_PAGE_MAIN, GetDlgItem(IDC_ACCORDION_WND1));
    m_pPageMain->ShowWindow(SW_SHOW);
    m_pAccordionWnd->AddItem("主页面", m_pPageMain, 0, TRUE, TRUE);
    
    m_pPageComponents = new CProjectPageComponents();
    m_pPageComponents->Create(IDD_PROJECT_PAGE_COMPONENTS, GetDlgItem(IDC_ACCORDION_WND1));
@@ -121,10 +128,16 @@
        m_pPageComponents = nullptr;
    }
    if (m_pPageRemoteEqs != nullptr) {
        m_pPageRemoteEqs->DestroyWindow();
        delete m_pPageRemoteEqs;
        m_pPageRemoteEqs = nullptr;
    //if (m_pPageRemoteEqs != nullptr) {
    //    m_pPageRemoteEqs->DestroyWindow();
    //    delete m_pPageRemoteEqs;
    //    m_pPageRemoteEqs = nullptr;
    //}
    if (m_pPageMain != nullptr) {
        m_pPageMain->DestroyWindow();
        delete m_pPageMain;
        m_pPageMain = nullptr;
    }
}
SourceCode/Bond/BondEq/CPanelProject.h
@@ -1,6 +1,7 @@
#pragma once
#include "VerticalLine.h"
#include "CProjectPageRemoteEqs.h"
//#include "CProjectPageRemoteEqs.h"
#include "CProjectPageMain.h"
#include "CProjectPageComponents.h"
#include "AccordionWnd.h"
@@ -29,7 +30,8 @@
    HBRUSH m_hbrBkgnd;
    int m_nPanelWidth;
    CAccordionWnd* m_pAccordionWnd;
    CProjectPageRemoteEqs* m_pPageRemoteEqs;
    //CProjectPageRemoteEqs* m_pPageRemoteEqs;
    CProjectPageMain* m_pPageMain;
    CProjectPageComponents* m_pPageComponents;
SourceCode/Bond/BondEq/CProjectPageMain.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,320 @@
// CProjectPageMain.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondEq.h"
#include "afxdialogex.h"
#include "CProjectPageMain.h"
#include "ToolUnits.h"
#define TIMER_INIT                    1
#define TIMER_READ_PLC_DATA            2
#define ID_MSG_UPDATA_DATA_TO_UI    WM_USER + 101
// CProjectPageMain å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CProjectPageMain, CDialogEx)
CProjectPageMain::CProjectPageMain(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_PROJECT_PAGE_MAIN, pParent)
{
    m_crBkgnd = PROPAGE_BACKGROUND_COLOR;
    m_hbrBkgnd = nullptr;
    m_pObserver = nullptr;
    nVelocityRatio = 0.0;
    dTactTime = 0.0;
    nDayShiftCapacity = 0;
    nNightShiftCapacity = 0;
}
CProjectPageMain::~CProjectPageMain()
{
}
void CProjectPageMain::SetPLC(CPLC* pPLC)
{
    ASSERT(pPLC);
    m_pPLC = pPLC;
}
void CProjectPageMain::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
void CProjectPageMain::HandleOperation(OperationType eOpType)
{
    WriteOperationDataToPLC(eOpType, true);
    Sleep(200);
    WriteOperationDataToPLC(eOpType, false);
}
void CProjectPageMain::WriteOperationDataToPLC(OperationType eOpType, bool bPressed)
{
    if (m_pPLC == nullptr || !m_pPLC->isConnected()) {
        return;
    }
    MC::SOFT_COMPONENT enComponent = MC::M;
    int nStartAddress = 1000;
    // æ ¹æ®æ“ä½œç±»åž‹è®¡ç®—目标地址
    char szWrite[4] = { 0x0, 0x0, 0x0, 0x0 };
    switch (eOpType) {
    case OperationType::RUN:
        nStartAddress = 1002;  // RUN   ä¿¡å·åœ°å€ M1002,闪动信息 M1103
        szWrite[0] = bPressed ? 0x01 : 0;
        break;
    case OperationType::AUTO:
        nStartAddress = 1000; // AUTO   ä¿¡å·åœ°å€ M1000,闪动信息 M1100
        szWrite[0] = bPressed ? 0x01 : 0;
        break;
    case OperationType::PUASE:
        nStartAddress = 1004; // PUASE  ä¿¡å·åœ°å€ M1004,闪动信息 M1104
        szWrite[0] = bPressed ? 0x01 : 0;
        break;
    case OperationType::MANUAL:
        nStartAddress = 1001; // MANUAL ä¿¡å·åœ°å€ M1001,闪动信息 M1100
        szWrite[0] = bPressed ? 0x01 : 0;
        break;
    case OperationType::MUTE:
        nStartAddress = 1003; // MUTE   ä¿¡å·åœ°å€ M1003,闪动信息 M1003
        szWrite[0] = bPressed ? 0x01 : 0;
        break;
    case OperationType::OPR:
        nStartAddress = 1050; // OPR    ä¿¡å·åœ°å€ M1050,闪动信息 M1150
        szWrite[0] = bPressed ? 0x01 : 0;
        break;
    case OperationType::STOP:
        nStartAddress = 1114; // STOP   ä¿¡å·åœ°å€ M1114,闪动信息 M1114
        szWrite[0] = bPressed ? 0x01 : 0;
        break;
    default:
        AfxMessageBox(_T("未知操作类型!"));
        return;
    }
    // å‘ PLC å†™å…¥ä¿¡å·
    m_pPLC->writeData(enComponent, nStartAddress, szWrite, 2, [eOpType, nStartAddress, bPressed](IMcChannel* pChannel, int nAddr, DWORD nValue, int nFlag) {
        if (nFlag == 0) {
            TRACE("操作成功:类型=%d,地址=%d,值=%d\n", static_cast<int>(eOpType), nAddr, bPressed);
        }
        else {
            TRACE("操作失败:类型=%d,地址=%d,错误码=%d\n", static_cast<int>(eOpType), nAddr, nFlag);
        }
    });
}
void CProjectPageMain::ReadPLCDataToUI()
{
    ASSERT(m_pPLC->isConnected());
    // æ€»ä»»åŠ¡æ•°
    int nPendingTasks = 5;
    auto createReadTask = [this, &nPendingTasks](MC::SOFT_COMPONENT type, int nAddr, auto onProcessData) {
        return [this, &nPendingTasks, onProcessData](IMcChannel* pChannel, int nAddr, char* pData, unsigned int nDataSize, int nFlag) {
            if (nDataSize == 2 && nFlag == 0 && ::IsWindow(m_hWnd)) {
                onProcessData(CToolUnits::toInt16(&pData[0]));
            }
            // ä»»åŠ¡å®Œæˆï¼Œå‡å°‘è®¡æ•°
            if (--nPendingTasks == 0) {
                PostMessage(ID_MSG_UPDATA_DATA_TO_UI);
            }
        };
    };
    m_pPLC->readData(MC::M, 1003, 2, createReadTask(MC::M, 1003, [this](int nValue) {
        theApp.m_model.getBonder().setMute(nValue != 0);
    }));
    m_pPLC->readData(MC::D, 530, 2, createReadTask(MC::D, 530, [this](int nValue) {
        nVelocityRatio = static_cast<unsigned int>(nValue);
    }));
    m_pPLC->readData(MC::ZR, 1500, 2, createReadTask(MC::ZR, 1500, [this](int nValue) {
        dTactTime = nValue;
    }));
    m_pPLC->readData(MC::ZR, 2012, 2, createReadTask(MC::ZR, 2012, [this](int nValue) {
        nDayShiftCapacity = nValue;
    }));
    m_pPLC->readData(MC::ZR, 2027, 2, createReadTask(MC::ZR, 2027, [this](int nValue) {
        nNightShiftCapacity = nValue;
    }));
}
BEGIN_MESSAGE_MAP(CProjectPageMain, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_WM_TIMER()
    ON_WM_CLOSE()
    ON_BN_CLICKED(IDC_BUTTON_ACTIVATE, &CProjectPageMain::OnBnClickedButtonActivate)
    ON_BN_CLICKED(IDC_BUTTON_AUTO, &CProjectPageMain::OnBnClickedButtonAuto)
    ON_BN_CLICKED(IDC_BUTTON_PUASE, &CProjectPageMain::OnBnClickedButtonPuase)
    ON_BN_CLICKED(IDC_BUTTON_MANUAL_OPERATION, &CProjectPageMain::OnBnClickedButtonManualOperation)
    ON_BN_CLICKED(IDC_BUTTON_SOUND_OFF, &CProjectPageMain::OnBnClickedButtonSoundOff)
    ON_BN_CLICKED(IDC_BUTTON_RESETTING, &CProjectPageMain::OnBnClickedButtonResetting)
    ON_BN_CLICKED(IDC_BUTTON_STOP, &CProjectPageMain::OnBnClickedButtonStop)
    ON_MESSAGE(ID_MSG_UPDATA_DATA_TO_UI, &CProjectPageMain::OnUpdateDataToUI)
END_MESSAGE_MAP()
// CProjectPageMain æ¶ˆæ¯å¤„理程序
void CProjectPageMain::InitRxWindows()
{
    /* code */
    // è®¢é˜…数据
    IRxWindows* pRxWindows = RX_GetRxWindows();
    pRxWindows->enableLog(5);
    if (m_pObserver == NULL) {
        m_pObserver = pRxWindows->allocObserver([&](IAny* pAny) -> void {
            // onNext
            pAny->addRef();
            int code = pAny->getCode();
            //if (true) {
            //}
            pAny->release();
        }, [&]() -> void {
            // onComplete
        }, [&](IThrowable* pThrowable) -> void {
            // onErrorm
            pThrowable->printf();
        });
        theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
            ->subscribe(m_pObserver);
    }
}
BOOL CProjectPageMain::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    InitRxWindows();
    SetTimer(TIMER_READ_PLC_DATA, 500, nullptr);
    return TRUE;  // return TRUE unless you set the focus to a control
    // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CProjectPageMain::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    if (nCtlColor == CTLCOLOR_STATIC) {
        pDC->SetBkColor(m_crBkgnd);
    }
    if (m_hbrBkgnd == nullptr) {
        m_hbrBkgnd = CreateSolidBrush(m_crBkgnd);
    }
    return m_hbrBkgnd;
}
void CProjectPageMain::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
    ASSERT(m_pObserver != NULL);
    m_pObserver->unsubscribe();
    m_pObserver = NULL;
}
void CProjectPageMain::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    CRect rcClient;
    GetClientRect(&rcClient);
}
void CProjectPageMain::OnTimer(UINT_PTR nIDEvent)
{
    if (TIMER_READ_PLC_DATA == nIDEvent) {
        ASSERT(m_pPLC);
        if (m_pPLC != nullptr && m_pPLC->isConnected()) {
            ReadPLCDataToUI();
        }
    }
    CDialogEx::OnTimer(nIDEvent);
}
void CProjectPageMain::OnClose()
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    KillTimer(TIMER_READ_PLC_DATA);
    CDialogEx::OnClose();
}
void CProjectPageMain::OnBnClickedButtonActivate()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleOperation(OperationType::RUN);
}
void CProjectPageMain::OnBnClickedButtonAuto()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleOperation(OperationType::AUTO);
}
void CProjectPageMain::OnBnClickedButtonPuase()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleOperation(OperationType::PUASE);
}
void CProjectPageMain::OnBnClickedButtonManualOperation()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleOperation(OperationType::MANUAL);
}
void CProjectPageMain::OnBnClickedButtonSoundOff()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    bool bMute = theApp.m_model.getBonder().isMute();
    WriteOperationDataToPLC(OperationType::MUTE, !bMute);
}
void CProjectPageMain::OnBnClickedButtonResetting()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleOperation(OperationType::OPR);
}
void CProjectPageMain::OnBnClickedButtonStop()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleOperation(OperationType::STOP);
}
LRESULT CProjectPageMain::OnUpdateDataToUI(WPARAM wParam, LPARAM lParam)
{
    CString strText;
    strText.Format(_T("%d %s"), nVelocityRatio, _T("%"));
    GetDlgItem(IDC_EDIT_VELOCITY_RATIO)->SetWindowText(strText);
    strText.Format(_T("%.2f"), dTactTime);
    GetDlgItem(IDC_EDIT_TACT_TIME)->SetWindowText(strText);
    SetDlgItemInt(IDC_EDIT_DAY_SHIFT_CAPACITY, nDayShiftCapacity);
    SetDlgItemInt(IDC_EDIT_NIGHT_SHIFT_CAPACITY, nNightShiftCapacity);
    return 0;
}
SourceCode/Bond/BondEq/CProjectPageMain.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
#pragma once
#include "afxdialogex.h"
// CProjectPageMain å¯¹è¯æ¡†
enum class OperationType {
    RUN = 0,            // å¯åЍ
    AUTO,                // è‡ªåЍ
    PUASE,                // æš‚停
    MANUAL,                // æ‰‹åЍ
    MUTE,                // é™éŸ³
    OPR,                // å¤ä½
    STOP                // åœæ­¢
};
class CProjectPageMain : public CDialogEx
{
    DECLARE_DYNAMIC(CProjectPageMain)
public:
    CProjectPageMain(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CProjectPageMain();
public:
    void SetPLC(CPLC* pPLC);
private:
    void InitRxWindows();
    void HandleOperation(OperationType eOpType);
    void WriteOperationDataToPLC(OperationType eOpType, bool bPressed);
    void ReadPLCDataToUI();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    IObserver* m_pObserver;
    CPLC* m_pPLC;
    int nVelocityRatio;            // é€Ÿåº¦æ¯”
    double dTactTime;            // å‘¨æœŸæ—¶é—´
    int nDayShiftCapacity;
    int nNightShiftCapacity;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_PROJECT_PAGE_MAIN };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    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 OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnClose();
    afx_msg void OnBnClickedButtonActivate();
    afx_msg void OnBnClickedButtonAuto();
    afx_msg void OnBnClickedButtonPuase();
    afx_msg void OnBnClickedButtonManualOperation();
    afx_msg void OnBnClickedButtonSoundOff();
    afx_msg void OnBnClickedButtonResetting();
    afx_msg void OnBnClickedButtonStop();
    afx_msg LRESULT OnUpdateDataToUI(WPARAM wParam, LPARAM lParam);
};
SourceCode/Bond/BondEq/Common.h
@@ -161,6 +161,9 @@
#define BTN_SOUND_OFF_BKGND_NORMAL        RGB(255, 127, 39)
#define BTN_SOUND_OFF_BKGND_HOVER        RGB(255, 157, 59)
#define BTN_SOUND_OFF_BKGND_PRESS        RGB(255, 100, 29)
#define BTN_SOUND_ON_BKGND_NORMAL        RGB(100, 200, 100)
#define BTN_SOUND_ON_BKGND_HOVER        RGB(150, 250, 150)
#define BTN_SOUND_ON_BKGND_PRESS        RGB(50, 150, 50)
/* æŒ‰é’®id */
SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp
@@ -10,35 +10,17 @@
}
// æž„造函数
RecipeManager::RecipeManager() : m_recipeFolder("Recipe") {}
RecipeManager::RecipeManager() : m_recipeFolder("Recipe"), m_currentRecipeName("") {}
// è®¾ç½®é…æ–¹æ–‡ä»¶å¤¹
void RecipeManager::setRecipeFolder(const std::string& folderPath) {
    m_recipeFolder = folderPath;
}
// åŠ è½½é…æ–¹ï¼ˆå¦‚æžœæ–‡ä»¶ä¸å­˜åœ¨ï¼ŒåŠ è½½é»˜è®¤æ•°æ®ï¼‰
bool RecipeManager::loadRecipe(const std::string& recipeName) {
    std::string filePath = m_recipeFolder + "/" + recipeName + ".xml";
    pugi::xml_document doc;
    if (!doc.load_file(filePath.c_str())) {
        std::cerr << "Recipe file not found: " << filePath << ". Loading default recipe." << std::endl;
        generateDefaultRecipe();
        return false; // æ–‡ä»¶ä¸å­˜åœ¨ï¼Œä½†åŠ è½½äº†é»˜è®¤æ•°æ®
    }
// åŠ è½½è½´ä¿¡æ¯
bool RecipeManager::loadAxes(pugi::xml_node axesNode) {
    m_axes.clear();
    auto recipe = doc.child("Recipe");
    for (auto axisNode : recipe.child("Axes").children("Axis")) {
    for (auto axisNode : axesNode.children("Axis")) {
        AxisInfo axisInfo;
        axisInfo.id = axisNode.attribute("id").as_int();
        axisInfo.number = axisNode.attribute("number").value();
        axisInfo.description = axisNode.attribute("description").value();
        axisInfo.startAddress = axisNode.attribute("start_address").value();
        //axisInfo.maxPositioningSpeed = axisNode.attribute("maxPositioningSpeed").as_double();
        //axisInfo.maxManualSpeed = axisNode.attribute("maxManualSpeed").as_double();
        // åŠ è½½ ValueRange å€¼
        axisInfo.jogDistance = ValueRange(
@@ -68,9 +50,9 @@
        );
        // åŠ è½½ PositionRange å€¼
        axisInfo.positioningPointCount = axisNode.child("Positions").attribute("positioningPointCount").as_int();
        axisInfo.positioningPointCount = axisNode.child("Positions").attribute("positioningPointCount").as_int();
        for (auto positionNode : axisNode.child("Positions").children("Position")) {
            bool isEnable = positionNode.attribute("isEnable").as_bool();
            bool isEnable = positionNode.attribute("isEnable").as_bool();
            std::string description = positionNode.attribute("description").value();
            ValueRange positionRange(
                positionNode.attribute("min").as_double(),
@@ -87,26 +69,8 @@
    return true;
}
// ä¿å­˜é…æ–¹
bool RecipeManager::saveRecipe(const std::string& recipeName) {
    // ç”Ÿæˆæ–‡ä»¶è·¯å¾„
    std::string filePath = m_recipeFolder + "/" + recipeName + ".xml";
    // åˆ›å»º XML æ–‡æ¡£å¯¹è±¡
    pugi::xml_document doc;
    // å¦‚果轴数据为空,生成默认配方
    if (m_axes.empty()) {
        generateDefaultRecipe();
    }
    // æ·»åŠ é…æ–¹æ ¹èŠ‚ç‚¹
    auto recipe = doc.append_child("Recipe");
    // æ·»åŠ è½´åˆ—è¡¨èŠ‚ç‚¹
    auto axesNode = recipe.append_child("Axes");
    // éåŽ†æ‰€æœ‰è½´æ•°æ®å¹¶å†™å…¥ XML
// ä¿å­˜è½´ä¿¡æ¯
void RecipeManager::saveAxes(pugi::xml_node& axesNode) {
    for (const auto& axisEntry : m_axes) {
        const AxisInfo& axisInfo = axisEntry.second;
@@ -115,8 +79,6 @@
        axisNode.append_attribute("number") = axisInfo.number.c_str();
        axisNode.append_attribute("description") = axisInfo.description.c_str();
        axisNode.append_attribute("start_address") = axisInfo.startAddress.c_str();
        //axisNode.append_attribute("maxPositioningSpeed") = axisInfo.maxPositioningSpeed;
        //axisNode.append_attribute("maxManualSpeed") = axisInfo.maxManualSpeed;
        // ä¿å­˜ ValueRange å€¼
        auto jog_distance = axisNode.append_child("jog_distance");
@@ -156,6 +118,55 @@
            positionNode.append_attribute("current") = position.range.currentValue;
        }
    }
}
// è®¾ç½®é…æ–¹æ–‡ä»¶å¤¹
void RecipeManager::setRecipeFolder(const std::string& folderPath) {
    m_recipeFolder = folderPath;
}
// èŽ·å–å½“å‰é…æ–¹åç§°
std::string RecipeManager::getCurrentRecipeName() const {
    return m_currentRecipeName;
}
// åŠ è½½é…æ–¹ï¼ˆå¦‚æžœæ–‡ä»¶ä¸å­˜åœ¨ï¼ŒåŠ è½½é»˜è®¤æ•°æ®ï¼‰
bool RecipeManager::loadRecipe(const std::string& recipeName) {
    std::string filePath = m_recipeFolder + "/" + recipeName + ".xml";
    pugi::xml_document doc;
    if (!doc.load_file(filePath.c_str())) {
        std::cerr << "Recipe file not found: " << filePath << ". Loading default recipe." << std::endl;
        return false; // æ–‡ä»¶ä¸å­˜åœ¨
    }
    m_currentRecipeName = recipeName;
    auto recipeNode = doc.child("Recipe");
    auto axesNode = recipeNode.child("Axes");
    loadAxes(axesNode);  // åŠ è½½è½´ä¿¡æ¯
    return true;
}
// ä¿å­˜é…æ–¹
bool RecipeManager::saveRecipe(const std::string& recipeName) {
    // ç”Ÿæˆæ–‡ä»¶è·¯å¾„
    std::string filePath = m_recipeFolder + "/" + recipeName + ".xml";
    // åˆ›å»º XML æ–‡æ¡£å¯¹è±¡
    pugi::xml_document doc;
    // å¦‚果轴数据为空,生成默认配方
    if (m_axes.empty()) {
        generateDefaultRecipe();
    }
    // æ·»åŠ é…æ–¹æ ¹èŠ‚ç‚¹
    auto recipeNode = doc.append_child("Recipe");
    // æ·»åŠ è½´ä¿¡æ¯
    auto axesNode = recipeNode.append_child("Axes");
    saveAxes(axesNode);
    // ä¿å­˜ XML æ–‡ä»¶
    return doc.save_file(filePath.c_str());
@@ -164,13 +175,12 @@
// ç”Ÿæˆé»˜è®¤é…æ–¹
void RecipeManager::generateDefaultRecipe() {
    m_axes.clear();
    m_currentRecipeName = "Default";
    for (int axisId = 1; axisId <= 12; ++axisId) {
        AxisInfo axisInfo;
        axisInfo.id = axisId;
        axisInfo.positioningPointCount = 25;
        //axisInfo.maxPositioningSpeed = 100.0;
        //axisInfo.maxManualSpeed = 100.0;
        axisInfo.number = "M100-M" + std::to_string(axisId);
        axisInfo.description = "Default_Axis" + std::to_string(axisId);
        axisInfo.startAddress = "ZR" + std::to_string(10000 + (axisId - 1) * 300);
SourceCode/Bond/BondEq/FileManager/RecipeManager.h
@@ -52,6 +52,9 @@
    // è®¾ç½®é…æ–¹æ–‡ä»¶å¤¹è·¯å¾„
    void setRecipeFolder(const std::string& folderPath);
    // èŽ·å–å½“å‰é…æ–¹åç§°
    std::string getCurrentRecipeName() const;
    // åŠ è½½é…æ–¹ï¼ˆæ–‡ä»¶ä¸å­˜åœ¨æ—¶åŠ è½½é»˜è®¤æ•°æ®ï¼‰
    bool loadRecipe(const std::string& recipeName);
@@ -88,7 +91,12 @@
private:
    RecipeManager();
    // è½´åŠ è½½å’Œä¿å­˜å‡½æ•°
    bool loadAxes(pugi::xml_node axesNode);
    void saveAxes(pugi::xml_node& axesNode);
private:
    std::string m_currentRecipeName; // å½“前配方名称
    std::string m_recipeFolder;      // é…æ–¹æ–‡ä»¶å¤¹è·¯å¾„
    std::map<int, AxisInfo> m_axes;  // è½´ä¿¡æ¯ç¼“å­˜
};
SourceCode/Bond/BondEq/Resource.h
Binary files differ
SourceCode/Bond/BondEq/ToolUnits.cpp
@@ -152,7 +152,7 @@
int CToolUnits::toInt32(const char* pBuffer)
{
    return (pBuffer[0] & 0xff) | (pBuffer[1] & 0xff) << 8 | (pBuffer[2] & 0xff) << 16 | (pBuffer[3] & 0xff) << 24;
    return (pBuffer[0] & 0xff) | ((pBuffer[1] & 0xff) << 8) | ((pBuffer[2] & 0xff) << 16) | ((pBuffer[3] & 0xff) << 24);
}
int CToolUnits::toInt16(const char* pBuffer)
@@ -247,3 +247,57 @@
    strText.Format(_T("%.03f"), value);
    pWnd->SetDlgItemText(nCtrlId, strText);
}
std::vector<CString> CToolUnits::GetFileNamesInDirectory(const CString& strFolderPath, const CString& strExtension)
{
    std::vector<CString> fileNames;
    // ç¡®ä¿ç›®å½•路径最后有反斜杠
    CString strSearchPath = strFolderPath;
    if (strSearchPath[strSearchPath.GetLength() - 1] != '\\') {
        strSearchPath += '\\';
    }
    CString finalExtension = strExtension;
    if (finalExtension.Find('.') == -1) {
        finalExtension = '.' + finalExtension;
    }
    strSearchPath += "*" + finalExtension;
    std::unique_ptr<CFileFind> finder = std::make_unique<CFileFind>();
    BOOL bWorking = finder->FindFile(strSearchPath);
    // éåŽ†æ–‡ä»¶å¤¹
    while (bWorking) {
        bWorking = finder->FindNextFile();
        if (!finder->IsDirectory()) {
            CString fileName = finder->GetFileName();
            int dotPos = fileName.ReverseFind('.');
            if (dotPos != -1) {
                fileName = fileName.Left(dotPos);
            }
            fileNames.push_back(fileName);
        }
    }
    return fileNames;
}
std::string CToolUnits::getRecipePath()
{
    return getCurrentExePath() + "\\Recipe";
}
std::string CToolUnits::getCurrentTimeString()
{
    struct tm ltm;
    time_t now = time(0);
    localtime_s(&ltm, &now);  // ä½¿ç”¨å®‰å…¨çš„ localtime_s å‡½æ•°
    char buffer[256];
    sprintf_s(buffer, sizeof(buffer), "%04d-%02d-%02d %02d:%02d:%02d",
        ltm.tm_year + 1900, ltm.tm_mon + 1, ltm.tm_mday,
        ltm.tm_hour, ltm.tm_min, ltm.tm_sec);
    return std::string(buffer);
}
SourceCode/Bond/BondEq/ToolUnits.h
@@ -25,5 +25,8 @@
    static BOOL getBit(const char c, int index);
    static void setBit(char* p, int index);
    static void setDlgItemDouble(CWnd* pWnd, int nCtrlId, double value);
    static std::vector<CString> GetFileNamesInDirectory(const CString& strFolderPath, const CString& strExtension);
    static std::string getRecipePath();
    static std::string getCurrentTimeString();
};
SourceCode/Bond/BondEq/View/AxisDetailSettingsDlg.cpp
@@ -11,17 +11,15 @@
// CAxisDetailSettingsDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CAxisDetailSettingsDlg, CDialogEx)
IMPLEMENT_DYNAMIC(CAxisDetailSettingsDlg, CBaseDlg)
CAxisDetailSettingsDlg::CAxisDetailSettingsDlg(const CString& strRecipeName, int nAxisNO, CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_AXIS_DETAIL_SETTINGS, pParent)
    : CBaseDlg(IDD_DIALOG_AXIS_DETAIL_SETTINGS, pParent)
{
    m_strRecipeName = strRecipeName;
    m_nAxisNO = nAxisNO;
    m_pPLC = nullptr;
    m_nInitialWidth = 0;
    m_nInitialHeight = 0;
}
CAxisDetailSettingsDlg::~CAxisDetailSettingsDlg()
@@ -206,9 +204,153 @@
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME_MAX)->SetWindowText(formatDouble(axisDetails.decelerationTime.maxValue));
}
bool CAxisDetailSettingsDlg::ParsePLCAddress(const CString& address, MC::SOFT_COMPONENT& component, int& addr)
{
    if (address.GetLength() < 2) {
        return false;
    }
    // æå–组件类型(第一个字符)
    TCHAR componentChar = address[0];
    if (address.Left(2) == _T("ZR")) {
        component = MC::SOFT_COMPONENT::ZR;
        // æå–数字部分(去除ZR前缀)
        CString numericAddress = address.Mid(2);
        addr = _ttoi(numericAddress);
        return addr != 0 || numericAddress.CompareNoCase(_T("0")) == 0;  // å¦‚果是 "0",也认为有效
    }
    // å¯¹äºŽå…¶ä»–组件,按照常规规则处理
    CString hexAddress = address.Mid(1);
    switch (componentChar) {
    case 'D':
        component = MC::SOFT_COMPONENT::D;
        addr = _ttoi(hexAddress);
        break;
    case 'M':
        component = MC::SOFT_COMPONENT::M;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'X':
        component = MC::SOFT_COMPONENT::X;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'Y':
        component = MC::SOFT_COMPONENT::Y;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'W':
        component = MC::SOFT_COMPONENT::W;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'L':
        component = MC::SOFT_COMPONENT::L;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'S':
        component = MC::SOFT_COMPONENT::S;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'B':
        component = MC::SOFT_COMPONENT::B;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'F':
        component = MC::SOFT_COMPONENT::F;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    default:
        return false;
    }
    // æ£€æŸ¥åœ°å€æ˜¯å¦æœ‰æ•ˆ
    if (addr == 0 && hexAddress.CompareNoCase(_T("0")) != 0) {
        return false;
    }
    return true;
}
void CAxisDetailSettingsDlg::writeAxisDataToPLC(int nAxisId)
{
    // èŽ·å–è½´æ•°æ®
    RecipeManager& recipeManager = RecipeManager::getInstance();
    AxisInfo axisData = recipeManager.getAxis(nAxisId);
    MC::SOFT_COMPONENT enComponent;
    int nStartAddress, nEndAddress, nSize;
    if (!ParsePLCAddress(CString(axisData.startAddress.c_str()), enComponent, nStartAddress)) {
        AfxMessageBox(_T("无效的起始地址!"));
    }
    nEndAddress = nStartAddress + 300;
    nSize = (nEndAddress - nStartAddress + 1) * 2;
    char szWrite[300] = { 0 };
    auto writeIntToBuffer = [&](int value, int nWriteIndex) {
        if (nWriteIndex + 4 <= sizeof(szWrite)) {
            // å°ç«¯
            szWrite[nWriteIndex] = static_cast<char>(value & 0xFF);             // ä½Žå­—节
            szWrite[nWriteIndex + 1] = static_cast<char>((value >> 8) & 0xFF);  // æ¬¡ä½Žå­—节
            szWrite[nWriteIndex + 2] = static_cast<char>((value >> 16) & 0xFF); // æ¬¡é«˜å­—节
            szWrite[nWriteIndex + 3] = static_cast<char>((value >> 24) & 0xFF); // é«˜å­—节
            // å¤§ç«¯
            //szWrite[nWriteIndex + 3] = static_cast<char>(value & 0xFF);         // é«˜å­—节
            //szWrite[nWriteIndex + 2] = static_cast<char>((value >> 8) & 0xFF);  // æ¬¡é«˜å­—节
            //szWrite[nWriteIndex + 1] = static_cast<char>((value >> 16) & 0xFF); // æ¬¡ä½Žå­—节
            //szWrite[nWriteIndex] = static_cast<char>((value >> 24) & 0xFF);     // ä½Žå­—节
        }
    };
    // å†™å…¥æ‰‹åŠ¨é€Ÿåº¦
    // writeIntToBuffer(static_cast<int>(axisData.manualSpeed.minValue * 1000), 0);
    writeIntToBuffer(static_cast<int>(axisData.manualSpeed.currentValue * 1000), 82);
    // writeIntToBuffer(static_cast<int>(axisData.manualSpeed.maxValue * 1000), 0);
    // å†™å…¥è‡ªåŠ¨é€Ÿåº¦
    // writeIntToBuffer(static_cast<int>(axisData.autoSpeed.minValue * 1000), 0);
    writeIntToBuffer(static_cast<int>(axisData.autoSpeed.currentValue * 1000), 84);
    // writeIntToBuffer(static_cast<int>(axisData.autoSpeed.maxValue * 1000), 0);
    // å†™å…¥åŠ é€Ÿæ—¶é—´
    // writeIntToBuffer(static_cast<int>(axisData.accelerationTime.minValue * 1000), 0);
    writeIntToBuffer(static_cast<int>(axisData.accelerationTime.currentValue * 1000), 62);
    // writeIntToBuffer(static_cast<int>(axisData.accelerationTime.maxValue * 1000), 0);
    // å†™å…¥å‡é€Ÿæ—¶é—´
    // writeIntToBuffer(static_cast<int>(axisData.decelerationTime.minValue * 1000), 0);
    writeIntToBuffer(static_cast<int>(axisData.decelerationTime.currentValue * 1000), 64);
    // writeIntToBuffer(static_cast<int>(axisData.decelerationTime.maxValue * 1000), 0);
    // å†™å…¥å¾®åŠ¨é‡
    // writeIntToBuffer(static_cast<int>(axisData.jogDistance.minValue * 1000), 0);
    writeIntToBuffer(static_cast<int>(axisData.jogDistance.currentValue * 1000), 81);
    // writeIntToBuffer(static_cast<int>(axisData.jogDistance.maxValue * 1000), 0);
    // å®šä½ç‚¹æ•°æ®
    int nIndex = 100;
    for (int i = 0; i < axisData.positions.size(); ++i) {
        const auto& position = axisData.positions[i];
        // writeIntToBuffer(static_cast<int>(position.range.minValue * 1000), 0);
        writeIntToBuffer(static_cast<int>(position.range.currentValue * 1000), nIndex + (i * 2));
        // writeIntToBuffer(static_cast<int>(position.range.maxValue * 1000), 0);
    }
    // å‘ PLC å†™å…¥ä¿¡å·
    m_pPLC->writeData(enComponent, nStartAddress, szWrite, nSize, [nStartAddress, &szWrite](IMcChannel* pChannel, int nAddr, DWORD nValue, int nFlag) {
        if (nFlag == 0) {
            TRACE("操作成功:地址=%d,值=%s\n", nStartAddress, szWrite);
        }
        else {
            TRACE("操作失败:地址=%d,错误码=%d\n", nStartAddress, nFlag);
        }
    });
}
void CAxisDetailSettingsDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    CBaseDlg::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_STATIC_AXIS_NUMBER, m_staticAxisNO);
    DDX_Control(pDX, IDC_STATIC_AXIS_DESCRIP, m_staticAxisDescription);
    DDX_Control(pDX, IDC_STATIC_START_ADDRESS, m_staticStartAddress);
@@ -216,7 +358,7 @@
}
BEGIN_MESSAGE_MAP(CAxisDetailSettingsDlg, CDialogEx)
BEGIN_MESSAGE_MAP(CAxisDetailSettingsDlg, CBaseDlg)
    ON_NOTIFY(NM_CLICK, IDC_CUSTOM_AXIS_ANCHOR_POINT, &CAxisDetailSettingsDlg::OnGridItemChanged)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_DETAIL_SETTINGS_SAVE, &CAxisDetailSettingsDlg::OnBnClickedButtonAxisDetailSettingsSave)
    ON_BN_CLICKED(IDC_BUTTON_SET_AXIS_POSITIONING_POINTS, &CAxisDetailSettingsDlg::OnBnClickedButtonSetAxisPositioningPoints)
@@ -228,7 +370,7 @@
BOOL CAxisDetailSettingsDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    CBaseDlg::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    CString strTitle;
@@ -387,6 +529,7 @@
    // ä¿å­˜è½´æ•°æ®åˆ°æ–‡ä»¶
    CString cstrMessage;
    if (RecipeManager::getInstance().saveRecipe(std::string(CT2A(m_strRecipeName)))) {
        writeAxisDataToPLC(m_nAxisNO);
        cstrMessage.Format(_T("保存轴 [%d] ç»†éƒ¨å‚数成功!"), m_nAxisNO);
        SystemLogManager::getInstance().log(SystemLogManager::LogType::Operation, std::string(CT2A(cstrMessage)));
    }
SourceCode/Bond/BondEq/View/AxisDetailSettingsDlg.h
@@ -1,11 +1,12 @@
#pragma once
#include "afxdialogex.h"
#include "GridCtrl.h"
#include "CBaseDlg.h"
// CAxisDetailSettingsDlg å¯¹è¯æ¡†
class CAxisDetailSettingsDlg : public CDialogEx
class CAxisDetailSettingsDlg : public CBaseDlg
{
    DECLARE_DYNAMIC(CAxisDetailSettingsDlg)
@@ -25,12 +26,11 @@
    void InitAnchorPontManager();
    void FillAnchorPontManager();
    void UpdateAxisDetailSettings();
    bool ParsePLCAddress(const CString& address, MC::SOFT_COMPONENT& component, int& addr);
    void writeAxisDataToPLC(int nAxisId);
private:
    CPLC* m_pPLC;
    int m_nInitialWidth;
    int m_nInitialHeight;
    // æ•°æ®
    int m_nAxisNO;
SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp
@@ -21,13 +21,11 @@
// CAxisSettingsDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CAxisSettingsDlg, CDialogEx)
IMPLEMENT_DYNAMIC(CAxisSettingsDlg, CBaseDlg)
CAxisSettingsDlg::CAxisSettingsDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_AXIS_SETTINGS, pParent)
    : CBaseDlg(IDD_DIALOG_AXIS_SETTINGS, pParent)
{
    m_nInitialWidth = 0;
    m_nInitialHeight = 0;
    m_pPLC = nullptr;
    m_bSEV = FALSE;
@@ -63,14 +61,6 @@
CAxisSettingsDlg::~CAxisSettingsDlg()
{
    for (auto& pair : m_mapFonts) {
        if (pair.second) {
            pair.second->DeleteObject();
            delete pair.second;
        }
    }
    m_mapFonts.clear();
    for (int i = 0; i < BTN_MAX; i++) {
        delete m_pBlBtns[i];
    }
@@ -97,7 +87,7 @@
void CAxisSettingsDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    CBaseDlg::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_COMBO_AXIS_NAME, m_comboAxisNO);
    DDX_Control(pDX, IDC_STATIC_AXIS_NUMBER, m_staticAxisNO);
    DDX_Control(pDX, IDC_STATIC_AXIS_DESCRIP, m_staticAxisDescription);
@@ -130,81 +120,12 @@
    return 0;
}
CFont* CAxisSettingsDlg::GetOrCreateFont(int nFontSize)
{
    auto it = m_mapFonts.find(nFontSize);
    if (it != m_mapFonts.end()) {
        return it->second;
    }
    CFont* font = new CFont();
    LOGFONT logFont = { 0 };
    _tcscpy_s(logFont.lfFaceName, _T("Segoe UI"));
    logFont.lfHeight = -nFontSize;
    logFont.lfQuality = CLEARTYPE_QUALITY;
    font->CreateFontIndirect(&logFont);
    m_mapFonts[nFontSize] = font;
    return font;
}
void CAxisSettingsDlg::SetDefaultFont()
{
    CFont* defaultFont = GetOrCreateFont(12);
    // éåŽ†æ‰€æœ‰æŽ§ä»¶ï¼Œåº”ç”¨é»˜è®¤å­—ä½“
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        pWnd->SetFont(defaultFont, TRUE);
        pWnd = pWnd->GetNextWindow();
    }
}
void CAxisSettingsDlg::AdjustControls(float dScaleX, float dScaleY)
{
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        int nCtrlID = pWnd->GetDlgCtrlID();
        if (nCtrlID != -1 && m_mapCtrlLayouts.find(nCtrlID) != m_mapCtrlLayouts.end())
        {
            CRect originalRect = m_mapCtrlLayouts[nCtrlID];
            CRect newRect(
                static_cast<int>(originalRect.left * dScaleX),
                static_cast<int>(originalRect.top * dScaleY),
                static_cast<int>(originalRect.right * dScaleX),
                static_cast<int>(originalRect.bottom * dScaleY));
            TCHAR szClassName[256];
            GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
            if (_tcsicmp(szClassName, _T("ComboBox")) == 0) {
                CComboBox* pComboBox = (CComboBox*)pWnd;
                pComboBox->SetItemHeight(-1, newRect.Height());  // -1 è¡¨ç¤ºæ‰€æœ‰é¡¹çš„高度
            }
            pWnd->MoveWindow(&newRect);
            AdjustControlFont(pWnd, newRect.Width(), newRect.Height());
        }
        pWnd = pWnd->GetNextWindow();
    }
}
void CAxisSettingsDlg::AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight)
{
    // æ ¹æ®æŽ§ä»¶é«˜åº¦åŠ¨æ€è°ƒæ•´å­—ä½“å¤§å°
    int fontSize = nHeight / 2;
    if (fontSize < 8) fontSize = 8;
    if (fontSize > 24) fontSize = 24;  // æœ€å¤§å­—体大小
    // èŽ·å–æˆ–åˆ›å»ºå­—ä½“
    CFont* pFont = GetOrCreateFont(fontSize);
    pWnd->SetFont(pFont);
    pWnd->Invalidate(); // åˆ·æ–°æŽ§ä»¶æ˜¾ç¤º
}
void CAxisSettingsDlg::AdjustLabelFont(CBLLabel& label)
{
    if (label.m_hWnd == nullptr) {
        return;
    }
    // èŽ·å–æŽ§ä»¶çš„çŸ©å½¢åŒºåŸŸ
    CRect rect;
    label.GetClientRect(&rect);
@@ -212,7 +133,7 @@
    // åŠ¨æ€è®¡ç®—å­—ä½“å¤§å°ï¼ŒåŸºäºŽæŽ§ä»¶çš„é«˜åº¦
    int fontSize = rect.Height() / 2; // æŽ§ä»¶é«˜åº¦çš„一半作为字体大小
    if (fontSize < 8) fontSize = 8;   // æœ€å°å­—体大小
    if (fontSize > 30) fontSize = 30; // æœ€å¤§å­—体大小
    if (fontSize > 20) fontSize = 20; // æœ€å¤§å­—体大小
    // è®¾ç½®å­—体大小
    label.SetFontSize(fontSize);
@@ -299,7 +220,6 @@
    RecipeManager& recipeManager = RecipeManager::getInstance();
    if (m_strRecipeName.IsEmpty() || !recipeManager.loadRecipe(std::string(CT2A(m_strRecipeName)))) {
        AfxMessageBox(_T("加载配方失败!"));
        recipeManager.saveRecipe(std::string(CT2A(m_strRecipeName)));
        return;
    }
@@ -829,7 +749,7 @@
}
BEGIN_MESSAGE_MAP(CAxisSettingsDlg, CDialogEx)
BEGIN_MESSAGE_MAP(CAxisSettingsDlg, CBaseDlg)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_LAST, &CAxisSettingsDlg::OnBnClickedButtonAxisLast)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_NEXT, &CAxisSettingsDlg::OnBnClickedButtonAxisNext)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP1, &CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup1)
@@ -851,8 +771,6 @@
    ON_BN_CLICKED(IDC_BUTTON_AXIS_DETAIL_SETTINGS, &CAxisSettingsDlg::OnBnClickedButtonAxisDetailSettings)
    ON_MESSAGE(ID_MSG_UPDATA_DATA_TO_UI, &CAxisSettingsDlg::OnUpdateDataToUI)
    ON_WM_SIZE()
    ON_WM_CTLCOLOR()
    ON_WM_SIZING()
    ON_WM_TIMER()
    ON_WM_CLOSE()
END_MESSAGE_MAP()
@@ -863,7 +781,7 @@
BOOL CAxisSettingsDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    CBaseDlg::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    CString strTitle;
@@ -893,6 +811,8 @@
        pLabel->SetTextColor(RGB(255, 255, 255));
        pLabel->SetAlignment(AlignCenter);
        pLabel->SetDynamicFont(TRUE);
        AdjustLabelFont(*pLabel);
    }
    
    // åˆå§‹åŒ–编辑框
@@ -967,47 +887,6 @@
    initializeAxisIDCombo();
    refreshAxisDetails(1);
    refreshPositionDetails(1, m_currentPage);
    CRect screenRect, dlgRect, clientRect;
    GetClientRect(&clientRect);
    m_nInitialWidth = clientRect.Width();
    m_nInitialHeight = clientRect.Height();
    // åˆå§‹åŒ–默认字体
    CFont* pDefaultFont = GetOrCreateFont(12);
    // éåŽ†æ‰€æœ‰å­æŽ§ä»¶ï¼Œè®°å½•åˆå§‹ä½ç½®å¹¶è®¾ç½®é»˜è®¤å­—ä½“
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        int nCtrlID = pWnd->GetDlgCtrlID();
        if (nCtrlID != -1) {
            // è®°å½•控件初始布局
            CRect ctrlRect;
            pWnd->GetWindowRect(&ctrlRect);
            ScreenToClient(&ctrlRect);
            m_mapCtrlLayouts[nCtrlID] = ctrlRect;
            // è®¾ç½®é»˜è®¤å­—体
            pWnd->SetFont(pDefaultFont);
        }
        pWnd = pWnd->GetNextWindow();
    }
    GetWindowRect(&dlgRect);
    int dlgWidth = dlgRect.Width() * 2;
    int dlgHeight = dlgRect.Height() * 2;
    SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0);
    if (dlgWidth > screenRect.Width()) {
        dlgWidth = screenRect.Width();
    }
    if (dlgHeight > screenRect.Height()) {
        dlgHeight = screenRect.Height();
    }
    int centerX = screenRect.left + (screenRect.Width() - dlgWidth) / 2;
    int centerY = screenRect.top + (screenRect.Height() - dlgHeight) / 2;
    MoveWindow(centerX, centerY, dlgWidth, dlgHeight);
    
    SetTimer(TIMER_READ_PLC_DATA, 500, nullptr);
@@ -1053,7 +932,7 @@
            }
            if (currentIndex == -1) {
                return CDialogEx::PreTranslateMessage(pMsg);
                return CBaseDlg::PreTranslateMessage(pMsg);
            }
            CString descriptionCtrlName, positionCtrlName;
@@ -1067,7 +946,7 @@
            CWnd* pPositionCtrl = GetDlgItem(positionCtrlId);
            if (pDescriptionCtrl == nullptr || pPositionCtrl == nullptr) {
                return CDialogEx::PreTranslateMessage(pMsg);
                return CBaseDlg::PreTranslateMessage(pMsg);
            }
            PositionRange& position = recipeManager.getPositionByIndex(getCurrentSelectedAxisID(), m_currentPage, AXIS_PAGE_SIZE, currentIndex);
@@ -1079,7 +958,7 @@
                CString strText;
                GetDlgItem(IDC_EDIT_AXIS_CURR_POS)->GetWindowText(strText);
                if (strText.IsEmpty()) {
                    return CDialogEx::PreTranslateMessage(pMsg);;
                    return CBaseDlg::PreTranslateMessage(pMsg);;
                }
                double enteredValue = _ttof(strText);
@@ -1135,24 +1014,14 @@
        }
    }
    return CDialogEx::PreTranslateMessage(pMsg);
    return CBaseDlg::PreTranslateMessage(pMsg);
}
void CAxisSettingsDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    CBaseDlg::OnSize(nType, cx, cy);
    // TODO: åœ¨æ­¤å¤„添加消息处理程序代码
    if (nType == SIZE_MINIMIZED || m_mapCtrlLayouts.empty()) {
        return;
    }
    float dScaleX = static_cast<float>(cx) / m_nInitialWidth;
    float dScaleY = static_cast<float>(cy) / m_nInitialHeight;
    // éåŽ†å¯¹è¯æ¡†ä¸­çš„æ‰€æœ‰æŽ§ä»¶
    AdjustControls(dScaleX, dScaleY);
    // åŠ¨æ€è°ƒæ•´å„ä¸ª CBLLabel çš„字体大小
    for (auto pLabel : m_pBlLabels) {
        AdjustLabelFont(*pLabel);
@@ -1179,30 +1048,6 @@
        pComboBox->MoveWindow(&rectComboBox);
        pComboBox->SetItemHeight(-1, rectButton.Height() - 6);
    }
}
void CAxisSettingsDlg::OnSizing(UINT fwSide, LPRECT pRect)
{
    if (fwSide == WMSZ_BOTTOMRIGHT) {
        if (pRect->right - pRect->left < 200) {
            pRect->right = pRect->left + 200;
        }
        if (pRect->bottom - pRect->top < 150) {
            pRect->bottom = pRect->top + 150;
        }
    }
    CDialogEx::OnSizing(fwSide, pRect);
}
HBRUSH CAxisSettingsDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    // TODO:  åœ¨æ­¤æ›´æ”¹ DC çš„任何特性
    // TODO:  å¦‚果默认的不是所需画笔,则返回另一个画笔
    return hbr;
}
void CAxisSettingsDlg::OnBnClickedButtonAxisLast()
@@ -1513,7 +1358,7 @@
        readPLCDataToUI(nAxisId);
    }    
    CDialogEx::OnTimer(nIDEvent);
    CBaseDlg::OnTimer(nIDEvent);
}
void CAxisSettingsDlg::OnClose()
@@ -1521,5 +1366,5 @@
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    KillTimer(TIMER_READ_PLC_DATA);
    CDialogEx::OnClose();
    CBaseDlg::OnClose();
}
SourceCode/Bond/BondEq/View/AxisSettingsDlg.h
@@ -4,6 +4,7 @@
#include "BLLabel.h"
#include "RegexEdit.h"
#include "CPLC.h"
#include "CBaseDlg.h"
// æ¯é¡µå®šä½ç‚¹æ˜¾ç¤ºä¸ªæ•°
#define AXIS_PAGE_SIZE    5
@@ -63,7 +64,7 @@
    POSITION_5  // å®šä½ç‚¹5
};
class CAxisSettingsDlg : public CDialogEx
class CAxisSettingsDlg : public CBaseDlg
{
    DECLARE_DYNAMIC(CAxisSettingsDlg)
@@ -82,10 +83,6 @@
private:
    UINT FindIDByName(const CString& strControlID);
    CFont* GetOrCreateFont(int nFontSize);
    void SetDefaultFont();
    void AdjustControls(float dScaleX, float dScaleY);
    void AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight);
    void AdjustLabelFont(CBLLabel& label);
    void SetLabelColor(CBLLabel& label, COLORREF color);
    void SetLabelColorBasedOnState(CBLLabel& label, BOOL bState, COLORREF colorTrue, COLORREF colorFalse);
@@ -108,8 +105,6 @@
private:
    CPLC* m_pPLC;
    int m_nInitialWidth;
    int m_nInitialHeight;
    // å½“前选中的定位页面索引
    int m_currentPage;
@@ -123,10 +118,6 @@
    CRegexEdit* m_pRegexEdit[EDIT_MAX];
    CComboBox m_comboAxisNO;
    CStatic m_staticAxisNO, m_staticAxisDescription, m_staticStartAddress;
    //CEdit m_editManualSpeed, m_editAutoSpeed, m_editAccelerationTime, m_editDecelerationTime, m_editJogDistance;
    std::map<int, CRect> m_mapCtrlLayouts;
    std::map<int, CFont*> m_mapFonts;
    // è¯»åˆ°çš„æ•°æ®
    BOOL m_bSEV;
@@ -151,8 +142,6 @@
    virtual BOOL OnInitDialog();
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnSizing(UINT fwSide, LPRECT pRect);
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnBnClickedButtonAxisLast();
    afx_msg void OnBnClickedButtonAxisNext();
    afx_msg void OnBnClickedButtonAxisAnchorPointGroup1();
SourceCode/Bond/BondEq/View/RecipeListDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,464 @@
// RecipeLiseDlg.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondEq.h"
#include "afxdialogex.h"
#include "RecipeListDlg.h"
#include "InputDialog.h"
#include "ToolUnits.h"
#include <fstream>
#include <sstream>
#include <map>
// CRecipeListDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CRecipeListDlg, CBaseDlg)
CRecipeListDlg::CRecipeListDlg(CWnd* pParent /*=nullptr*/)
    : CBaseDlg(IDD_DIALOG_RECIPE_LIST, pParent)
{
    m_staticCurrRecipe = new CBLLabel();
}
CRecipeListDlg::~CRecipeListDlg()
{
    if (m_staticCurrRecipe != nullptr) {
        delete m_staticCurrRecipe;
        m_staticCurrRecipe = nullptr;
    }
}
void CRecipeListDlg::AdjustLabelFont(CBLLabel& label)
{
    if (label.m_hWnd == nullptr) {
        return;
    }
    // èŽ·å–æŽ§ä»¶çš„çŸ©å½¢åŒºåŸŸ
    CRect rect;
    label.GetClientRect(&rect);
    // åŠ¨æ€è®¡ç®—å­—ä½“å¤§å°ï¼ŒåŸºäºŽæŽ§ä»¶çš„é«˜åº¦
    int fontSize = rect.Height() / 2; // æŽ§ä»¶é«˜åº¦çš„一半作为字体大小
    if (fontSize < 8) fontSize = 8;   // æœ€å°å­—体大小
    if (fontSize > 30) fontSize = 30; // æœ€å¤§å­—体大小
    // è®¾ç½®å­—体大小
    label.SetFontSize(fontSize);
    // åˆ·æ–°æŽ§ä»¶æ˜¾ç¤º
    label.Invalidate();
    label.UpdateWindow();
}
void CRecipeListDlg::InitRecipeLise()
{
    if (m_grid.GetSafeHwnd() == NULL)
        return;
    int nRows = 1;
    int nCols = 4;
    int nFixRows = 1;
    int nFixCols = 0;
    int nRowIdx = 0;
    int nColIdx = 0;
    m_grid.DeleteAllItems();
    m_grid.SetVirtualMode(FALSE);
    m_grid.GetDefaultCell(TRUE, FALSE)->SetBackClr(g_nGridFixCellColor); // è®¾ç½®å›ºå®šè¡ŒèƒŒæ™¯è‰²
    m_grid.GetDefaultCell(FALSE, TRUE)->SetBackClr(g_nGridFixCellColor); // è®¾ç½®å›ºå®šåˆ—背景色
    m_grid.GetDefaultCell(FALSE, FALSE)->SetBackClr(g_nGridCellColor);     // è®¾ç½®å•元格背景色
    m_grid.SetFixedTextColor(g_nGridFixFontColor);                         // è®¾ç½®å›ºå®šè¡Œåˆ—字体颜色
    m_grid.SetRowCount(nRows);
    m_grid.SetColumnCount(nCols);
    m_grid.SetFixedRowCount(nFixRows);
    m_grid.SetFixedColumnCount(nFixCols);
    // Col
    m_grid.SetColumnWidth(nColIdx, 10);
    m_grid.SetItemText(nRowIdx, nColIdx++, _T("No."));
    m_grid.SetColumnWidth(nColIdx, 10);
    m_grid.SetItemText(nRowIdx, nColIdx++, _T("名称"));
    m_grid.SetColumnWidth(nColIdx, 120);
    m_grid.SetItemText(nRowIdx, nColIdx++, _T("描述"));
    m_grid.SetColumnWidth(nColIdx, 30);
    m_grid.SetItemText(nRowIdx, nColIdx++, _T("创建时间"));
    m_grid.SetFixedRowSelection(FALSE);     // è®¾ç½®å›ºå®šè¡Œä¸å¯é€‰ä¸­
    m_grid.SetFixedColumnSelection(FALSE);  // è®¾ç½®å›ºå®šåˆ—不可选中
    m_grid.SetEditable(FALSE);                // è®¾ç½®å•元格可编辑
    m_grid.SetRowResize(FALSE);                // è®¾ç½®è¡Œä¸å¯è°ƒæ•´å¤§å°
    m_grid.SetColumnResize(TRUE);            // è®¾ç½®åˆ—可调整大小
    m_grid.ExpandColumnsToFit(TRUE);        // è‡ªåŠ¨è°ƒæ•´åˆ—å®½
    m_grid.SetListMode(TRUE);                // å¯ç”¨åˆ—表模式
    m_grid.EnableSelection(TRUE);            // å¯ç”¨é€‰æ‹©
    m_grid.SetSingleRowSelection(TRUE);        // è‡ªåŠ¨æ•´è¡Œé«˜äº®ï¼ˆé™åˆ¶ä¸ºå•è¡Œé€‰æ‹©ï¼‰
    m_grid.ExpandLastColumn();                // æœ€åŽä¸€åˆ—填充网格
    FillRecipeLise();
}
void CRecipeListDlg::FillRecipeLise()
{
    // æ¸…除数据行,保留表头
    for (int i = m_grid.GetRowCount() - 1; i > 0; --i) {
        m_grid.DeleteRow(i);
    }
    // 1. éåŽ†æ–‡ä»¶å¤¹ä¸‹æ‰€æœ‰XML文件
    std::string strRecipePath = CToolUnits::getRecipePath();
    std::vector<CString> vecFile = CToolUnits::GetFileNamesInDirectory(strRecipePath.c_str(), _T(".xml"));
    // 2. è¯»å– RecipeList.txt æ–‡ä»¶
    std::map<CString, std::pair<CString, CString>> recipeData; // {配方名, {描述, åˆ›å»ºæ—¶é—´}}
    std::ifstream inFile(strRecipePath + "\\RecipeList.txt");
    if (inFile.is_open()) {
        std::string line;
        while (std::getline(inFile, line)) {
            if (line.empty()) continue; // è·³è¿‡ç©ºè¡Œ
            std::istringstream ss(line);
            std::string name, description, createTime;
            // CSV格式解析(逗号分隔)
            if (std::getline(ss, name, ',') &&
                std::getline(ss, description, ',') &&
                std::getline(ss, createTime)) {
                recipeData[CString(name.c_str())] = std::make_pair(CString(description.c_str()), CString(createTime.c_str()));
            }
        }
        inFile.close();
    }
    // 3. æ›´æ–°è¡¨æ ¼æ•°æ®
    int rowIdx = 1;
    m_grid.SetRowCount(static_cast<int>(vecFile.size()) + 1);
    for (const auto& fileName : vecFile) {
        // ä»Ž RecipeList.txt æ•°æ®ä¸­æŸ¥æ‰¾å¯¹åº”的描述和创建时间
        CString description = _T("");
        CString createTime = _T("");
        auto it = recipeData.find(fileName);
        if (it != recipeData.end()) {
            description = it->second.first;  // é…æ–¹æè¿°
            createTime = it->second.second;  // åˆ›å»ºæ—¶é—´
        }
        // å¡«å……表格数据
        m_grid.SetItemText(rowIdx, 0, CString(std::to_string(rowIdx).c_str())); // No.
        m_grid.SetItemText(rowIdx, 1, fileName);                                // é…æ–¹åç§°
        m_grid.SetItemText(rowIdx, 2, description);                                // é…æ–¹æè¿°
        m_grid.SetItemText(rowIdx, 3, createTime);                                // åˆ›å»ºæ—¶é—´
        ++rowIdx;
    }
    m_grid.ExpandColumnsToFit(FALSE);   // è‡ªåŠ¨è°ƒæ•´åˆ—å®½
    m_grid.ExpandLastColumn();            // æœ€åŽä¸€åˆ—填充网格
    // åˆ·æ–°ç½‘格控件
    m_grid.Invalidate();
    m_grid.UpdateWindow();
}
void CRecipeListDlg::UpdateDataFile(const CString& strRecipeName, const CString& strNewDescription)
{
    CStdioFile file;
    CFileException fe;
    // æ‰“开文件以读取和写入
    CString strFilePath;
    strFilePath.Format(_T("%s\\RecipeList.txt"), CToolUnits::getRecipePath().c_str());
    if (file.Open(strFilePath, CFile::modeReadWrite | CFile::shareDenyNone, &fe)) {
        CString strLine;
        CStringArray arrLines;
        BOOL bFound = FALSE;
        // è¯»å–文件内容到内存
        while (file.ReadString(strLine)) {
            // å°†è¿™ä¸€è¡ŒæŒ‰é€—号分割
            CStringArray arrColumns;
            int nPos = 0;
            while ((nPos = strLine.Find(_T(','))) != -1) {
                arrColumns.Add(strLine.Left(nPos));
                strLine = strLine.Mid(nPos + 1);
            }
            arrColumns.Add(strLine); // æœ€åŽä¸€åˆ—
            // å¦‚果第一列(配方名称)匹配,修改第二列(配方描述)
            if (arrColumns.GetSize() > 0 && arrColumns[0] == strRecipeName) {
                arrColumns[1] = strNewDescription; // ä¿®æ”¹é…æ–¹æè¿°åˆ—
                bFound = TRUE;
            }
            // å°†ä¿®æ”¹åŽçš„行保存回内存
            CString strUpdatedLine;
            for (int i = 0; i < arrColumns.GetSize(); ++i) {
                if (i > 0) strUpdatedLine += _T(",");
                strUpdatedLine += arrColumns[i];
            }
            arrLines.Add(strUpdatedLine);
        }
        if (bFound) {
            // å¦‚果找到了配方名称,保存修改后的内容回文件
            file.SeekToBegin();
            file.SetLength(0);  // æ¸…空文件内容
            for (int i = 0; i < arrLines.GetSize(); ++i) {
                file.WriteString(arrLines[i] + _T("\n"));
            }
        }
        else {
            // å¦‚果没有找到配方名称,则追加新配方
            CString strNewLine;
            strNewLine.Format(_T("%s,%s,%s"), strRecipeName, strNewDescription, CToolUnits::getCurrentTimeString().c_str());
            file.SeekToEnd();
            file.WriteString(strNewLine + _T("\n"));
        }
        file.Close();
    }
    else {
        AfxMessageBox(_T("无法打开文件"));
    }
}
void CRecipeListDlg::DoDataExchange(CDataExchange* pDX)
{
    CBaseDlg::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_CUSTOM_RECIPE_LIST, m_grid);
}
BEGIN_MESSAGE_MAP(CRecipeListDlg, CBaseDlg)
    ON_BN_CLICKED(IDC_BUTTON_CREATE_RECIPE, &CRecipeListDlg::OnBnClickedButtonCreateRecipe)
    ON_BN_CLICKED(IDC_BUTTON_DELETE_RECIPE, &CRecipeListDlg::OnBnClickedButtonDeleteRecipe)
    ON_BN_CLICKED(IDC_BUTTON_SELECT_RECIPE, &CRecipeListDlg::OnBnClickedButtonSelectRecipe)
    ON_NOTIFY(NM_DBLCLK, IDC_CUSTOM_RECIPE_LIST, &CRecipeListDlg::OnGridCellEditFinished)
    ON_WM_SIZE()
END_MESSAGE_MAP()
// CRecipeListDlg æ¶ˆæ¯å¤„理程序
BOOL CRecipeListDlg::OnInitDialog()
{
    CBaseDlg::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    m_staticCurrRecipe->SubclassDlgItem(IDC_STATIC_CURR_RECIPE, this);
    m_staticCurrRecipe->SetBkColor(RGB(0, 110, 110));
    m_staticCurrRecipe->ModifyStyle(0, SS_NOTIFY);
    m_staticCurrRecipe->SetTextColor(RGB(255, 255, 255));
    m_staticCurrRecipe->SetAlignment(AlignCenter);
    m_staticCurrRecipe->SetDynamicFont(TRUE);
    m_staticCurrRecipe->SetWindowText(RecipeManager::getInstance().getCurrentRecipeName().c_str());
    AdjustLabelFont(*m_staticCurrRecipe);
    InitRecipeLise();
    return TRUE;  // return TRUE unless you set the focus to a control
    // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
void CRecipeListDlg::OnSize(UINT nType, int cx, int cy)
{
    CBaseDlg::OnSize(nType, cx, cy);
    // TODO: åœ¨æ­¤å¤„添加消息处理程序代码
    AdjustLabelFont(*m_staticCurrRecipe);
}
void CRecipeListDlg::OnBnClickedButtonCreateRecipe()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    CInputDialog inputDialog(_T("配方名称"), _T("请输入配方名称:"));
    if (inputDialog.DoModal() != IDOK) {
        return;
    }
    CString newRecipeName = inputDialog.GetInputText();
    // éªŒè¯åç§°ä¸é‡å¤
    std::string recipePath = CToolUnits::getRecipePath();
    std::string recipeListPath = recipePath + "\\RecipeList.txt";
    std::vector<CString> existingFiles = CToolUnits::GetFileNamesInDirectory(recipePath.c_str(), ".xml");
    for (const auto& fileName : existingFiles) {
        if (newRecipeName.Compare(fileName) == 0) {
            AfxMessageBox(_T("配方名称已存在,请输入其他名称!"));
            return;
        }
    }
    // æ£€æŸ¥æ˜¯å¦è¦å¤åˆ¶é€‰ä¸­é…æ–¹
    CString strCopyRecipe = _T("");
    for (int i = 1; i < m_grid.GetRowCount(); i++) {
        if (m_grid.IsCellSelected(i, 1)) {
            strCopyRecipe = m_grid.GetItemText(i, 1);
            CString strMessage;
            strMessage.Format(_T("Copy [%s] -> [%s]?"), strCopyRecipe, newRecipeName);
            if (AfxMessageBox(strMessage, MB_YESNO | MB_ICONQUESTION) != IDYES) {
                strCopyRecipe = _T("");
            }
            break;
        }
    }
    // åˆ›å»ºæ–°çš„XML文件
    CString newRecipeFile = CString(recipePath.c_str()) + "\\" + newRecipeName + ".xml";
    if (!strCopyRecipe.IsEmpty()) {
        CString sourceFile = CString(recipePath.c_str()) + "\\" + strCopyRecipe + ".xml";
        CopyFile(sourceFile, newRecipeFile, FALSE);
    }
    else {
        // ç”Ÿæˆé»˜è®¤XML文件
        RecipeManager& recipeManager = RecipeManager::getInstance();
        recipeManager.generateDefaultRecipe();
        if (!recipeManager.saveRecipe(std::string(CT2A(newRecipeName)))) {
            AfxMessageBox(_T("创建配方失败!"));
            return;
        }
    }
    // æ›´æ–° RecipeList.txt
    std::ofstream outFile(recipeListPath, std::ios::app); // è¿½åŠ æ¨¡å¼
    if (outFile.is_open()) {
        SYSTEMTIME sysTime;
        GetLocalTime(&sysTime);
        char buffer[64];
        sprintf_s(buffer, "%04d-%02d-%02d %02d:%02d:%02d",
            sysTime.wYear, sysTime.wMonth, sysTime.wDay,
            sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
        outFile << CT2A(newRecipeName) << ",默认描述," << buffer << std::endl;
        outFile.close();
    }
    // åˆ·æ–°ç½‘格控件
    FillRecipeLise();
}
void CRecipeListDlg::OnBnClickedButtonDeleteRecipe()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    int nSelect = -1;
    for (int i = 1; i < m_grid.GetRowCount(); i++) {
        if (m_grid.IsCellSelected(i, 1)) {
            nSelect = i;
            break;
        }
    }
    if (nSelect < 0) {
        AfxMessageBox(_T("请选择要删除的配方!"));
        return;
    }
    CString selectedRecipe = m_grid.GetItemText(nSelect, 1);
    if (selectedRecipe.IsEmpty()) {
        AfxMessageBox(_T("配方名称无效!"));
        return;
    }
    CString message = _T("确定要删除配方 \"") + selectedRecipe + _T("\" å—?");
    if (AfxMessageBox(message, MB_YESNO | MB_ICONQUESTION) != IDYES) {
        return;
    }
    // åˆ é™¤XML文件
    std::string recipePath = CToolUnits::getRecipePath();
    CString xmlFilePath = CString(recipePath.c_str()) + "\\" + selectedRecipe + ".xml";
    if (!DeleteFile(xmlFilePath)) {
        AfxMessageBox(_T("删除XML文件失败!"));
        return;
    }
    // æ›´æ–°RecipeList.txt文件
    std::string recipeListPath = recipePath + "\\RecipeList.txt";
    std::ifstream inFile(recipeListPath);
    std::ofstream outFile(recipeListPath + ".tmp"); // åˆ›å»ºä¸´æ—¶æ–‡ä»¶
    if (inFile.is_open() && outFile.is_open()) {
        std::string line;
        while (std::getline(inFile, line)) {
            std::istringstream ss(line);
            std::string name;
            if (std::getline(ss, name, ',')) {
                if (selectedRecipe != CString(name.c_str())) {
                    outFile << line << std::endl; // ä¿ç•™ä¸åŒ¹é…çš„行
                }
            }
        }
        inFile.close();
        outFile.close();
        // æ›¿æ¢æ–‡ä»¶
        DeleteFile(CString(recipeListPath.c_str()));
        MoveFile(CString((recipeListPath + ".tmp").c_str()), CString(recipeListPath.c_str()));
    }
    // åˆ·æ–°ç½‘格控件
    FillRecipeLise();
}
void CRecipeListDlg::OnBnClickedButtonSelectRecipe()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    int nSelect = -1;
    for (int i = 1; i < m_grid.GetRowCount(); i++) {
        if (m_grid.IsCellSelected(i, 1)) {
            nSelect = i;
            break;
        }
    }
    if (nSelect < 0) {
        AfxMessageBox(_T("请选择配方!"));
        return;
    }
    CString strSelectedRecipe = m_grid.GetItemText(nSelect, 1);
    if (RecipeManager::getInstance().loadRecipe(std::string(CT2A(strSelectedRecipe)))) {
        m_staticCurrRecipe->SetWindowText(strSelectedRecipe);
        m_staticCurrRecipe->SetBkColor(RGB(0, 110, 110));
    }
    else {
        AfxMessageBox(_T("加载配方失败!"));
    }
}
void CRecipeListDlg::OnGridCellEditFinished(NMHDR* pNotifyStruct, LRESULT* pResult)
{
    // èŽ·å–ä¿®æ”¹çš„è¡Œåˆ—ä¿¡æ¯
    NM_GRIDVIEW* pItem = (NM_GRIDVIEW*)pNotifyStruct;
    int nRow = pItem->iRow;
    int nCol = pItem->iColumn;
    // åªå¤„理“配方描述”列的修改
    if (nCol == 2) {
        CString strRecipeName = m_grid.GetItemText(nRow, 1);
        CInputDialog inputDialog(_T("配方描述"), _T("请输入配方描述:"));
        if (inputDialog.DoModal() != IDOK) {
            *pResult = 0;
            return;
        }
        CString strText = inputDialog.GetInputText();
        m_grid.SetItemText(nRow, nCol, strText);
        UpdateDataFile(strRecipeName, strText);
        m_grid.ExpandColumnsToFit(FALSE);   // è‡ªåŠ¨è°ƒæ•´åˆ—å®½
        m_grid.ExpandLastColumn();            // æœ€åŽä¸€åˆ—填充网格
        // åˆ·æ–°ç½‘格控件
        m_grid.Invalidate();
        m_grid.UpdateWindow();
    }
    *pResult = 0;
}
SourceCode/Bond/BondEq/View/RecipeListDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
#pragma once
#include "afxdialogex.h"
#include "GridCtrl.h"
#include "CBaseDlg.h"
#include "BLLabel.h"
// CRecipeListDlg å¯¹è¯æ¡†
class CRecipeListDlg : public CBaseDlg
{
    DECLARE_DYNAMIC(CRecipeListDlg)
public:
    CRecipeListDlg(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CRecipeListDlg();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_RECIPE_LIST };
#endif
private:
    //CFont* GetOrCreateFont(int nFontSize);
    //void AdjustControls(float dScaleX, float dScaleY);
    //void AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight);
    void AdjustLabelFont(CBLLabel& label);
    void InitRecipeLise();
    void FillRecipeLise();
    void UpdateDataFile(const CString& strRecipeName, const CString& strNewDescription);
private:
    //int m_nInitialWidth;
    //int m_nInitialHeight;
    //std::map<int, CFont*> m_mapFonts;        // å­—体映射
    //std::map<int, CRect> m_mapCtrlLayouts;    // æŽ§ä»¶å¸ƒå±€æ˜ å°„
    // æŽ§ä»¶
    CBLLabel* m_staticCurrRecipe;
    CGridCtrl m_grid;
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    virtual BOOL OnInitDialog();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnBnClickedButtonCreateRecipe();
    afx_msg void OnBnClickedButtonDeleteRecipe();
    afx_msg void OnBnClickedButtonSelectRecipe();
    afx_msg void OnGridCellEditFinished(NMHDR* pNotifyStruct, LRESULT* pResult);
    DECLARE_MESSAGE_MAP()
};
SourceCode/Bond/BondEq/View/SystemLogManagerDlg.cpp
@@ -9,29 +9,20 @@
// CSystemLogManagerDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CSystemLogManagerDlg, CDialogEx)
IMPLEMENT_DYNAMIC(CSystemLogManagerDlg, CBaseDlg)
CSystemLogManagerDlg::CSystemLogManagerDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_SYSTEM_LOG_MANAGER, pParent)
    : CBaseDlg(IDD_DIALOG_SYSTEM_LOG_MANAGER, pParent)
{
    m_nInitialWidth = 0;
    m_nInitialHeight = 0;
}
CSystemLogManagerDlg::~CSystemLogManagerDlg()
{
    for (auto& pair : m_mapFonts) {
        if (pair.second) {
            pair.second->DeleteObject();
            delete pair.second;
        }
    }
    m_mapFonts.clear();
}
void CSystemLogManagerDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    CBaseDlg::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_COMBO_TYPE, m_comboType);
    DDX_Control(pDX, IDC_COMBO_USER, m_comboUser);
    DDX_Control(pDX, IDC_DATETIMEPICKER_START, m_dateTimeStart);
@@ -161,24 +152,6 @@
    UpdatePageInfo();
}
CFont* CSystemLogManagerDlg::GetOrCreateFont(int nFontSize)
{
    auto it = m_mapFonts.find(nFontSize);
    if (it != m_mapFonts.end()) {
        return it->second;
    }
    CFont* font = new CFont();
    LOGFONT logFont = { 0 };
    _tcscpy_s(logFont.lfFaceName, _T("Segoe UI"));
    logFont.lfHeight = -nFontSize;
    logFont.lfQuality = CLEARTYPE_QUALITY;
    font->CreateFontIndirect(&logFont);
    m_mapFonts[nFontSize] = font;
    return font;
}
void CSystemLogManagerDlg::UpdatePageInfo()
{
    // æ ¼å¼åŒ–页码信息为 "当前页/总页数"
@@ -187,112 +160,13 @@
    m_staticPageNum.SetWindowText(pageInfo);
}
void CSystemLogManagerDlg::SetDefaultFont()
{
    CFont* defaultFont = GetOrCreateFont(12);
    // éåŽ†æ‰€æœ‰æŽ§ä»¶ï¼Œåº”ç”¨é»˜è®¤å­—ä½“
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        // è·³è¿‡ç‰¹æ®ŠæŽ§ä»¶ï¼ˆå¦‚ MFCGridCtrl)
        TCHAR szClassName[256];
        GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
        if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
            pWnd = pWnd->GetNextWindow();
            continue;
        }
        pWnd->SetFont(defaultFont, TRUE);
        pWnd = pWnd->GetNextWindow();
    }
}
void CSystemLogManagerDlg::AdjustControls(float dScaleX, float dScaleY)
{
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        int nCtrlID = pWnd->GetDlgCtrlID();
        if (nCtrlID != -1 && m_mapCtrlLayouts.find(nCtrlID) != m_mapCtrlLayouts.end())
        {
            CRect originalRect = m_mapCtrlLayouts[nCtrlID];
            CRect newRect(
                static_cast<int>(originalRect.left * dScaleX),
                static_cast<int>(originalRect.top * dScaleY),
                static_cast<int>(originalRect.right * dScaleX),
                static_cast<int>(originalRect.bottom * dScaleY));
            TCHAR szClassName[256];
            GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
            if (_tcsicmp(szClassName, _T("ComboBox")) == 0) {
                CComboBox* pComboBox = (CComboBox*)pWnd;
                pComboBox->SetItemHeight(-1, newRect.Height());  // -1 è¡¨ç¤ºæ‰€æœ‰é¡¹çš„高度
            }
            if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
                CGridCtrl* pGridCtrl = (CGridCtrl*)pWnd;
                pGridCtrl->SetDefCellHeight(newRect.Height() / 21);
                pGridCtrl->ExpandColumnsToFit(TRUE);
                pGridCtrl->ExpandLastColumn();
                pGridCtrl->Invalidate();
                pGridCtrl->UpdateWindow();
            }
            pWnd->MoveWindow(&newRect);
            AdjustControlFont(pWnd, newRect.Width(), newRect.Height());
        }
        pWnd = pWnd->GetNextWindow();
    }
}
void CSystemLogManagerDlg::AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight)
{
    TCHAR szClassName[256];
    GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
    // è·³è¿‡ç‰¹æ®ŠæŽ§ä»¶ï¼ˆå¦‚ MFCGridCtrl)
    if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
        return;
    }
    // æ ¹æ®æŽ§ä»¶é«˜åº¦åŠ¨æ€è°ƒæ•´å­—ä½“å¤§å°
    int fontSize = nHeight / 2;
    if (fontSize < 8) fontSize = 8;
    // èŽ·å–æˆ–åˆ›å»ºå­—ä½“
    CFont* pFont = GetOrCreateFont(fontSize);
    pWnd->SetFont(pFont);
    pWnd->Invalidate(); // åˆ·æ–°æŽ§ä»¶æ˜¾ç¤º
}
void CSystemLogManagerDlg::AdjustComboBoxStyle(CComboBox& comboBox)
{
    DWORD dwStyle = comboBox.GetStyle();
    comboBox.ModifyStyle(0, CBS_DROPDOWNLIST | CBS_HASSTRINGS | CBS_OWNERDRAWFIXED);
    comboBox.Invalidate();
    comboBox.UpdateWindow();
}
void CSystemLogManagerDlg::AdjustDateTimeCtrlStyle(CDateTimeCtrl& dateTimeCtrl)
{
    dateTimeCtrl.ModifyStyle(0, DTS_RIGHTALIGN);
    dateTimeCtrl.Invalidate();
    dateTimeCtrl.UpdateWindow();
}
BEGIN_MESSAGE_MAP(CSystemLogManagerDlg, CDialogEx)
BEGIN_MESSAGE_MAP(CSystemLogManagerDlg, CBaseDlg)
    ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CSystemLogManagerDlg::OnBnClickedButtonSearch)
    ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CSystemLogManagerDlg::OnBnClickedButtonPrevPage)
    ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CSystemLogManagerDlg::OnBnClickedButtonNextPage)
    ON_CBN_SELCHANGE(IDC_COMBO_TYPE, &CSystemLogManagerDlg::OnSelchangeComboType)
    ON_CBN_SELCHANGE(IDC_COMBO_USER, &CSystemLogManagerDlg::OnSelchangeComboUser)
    ON_WM_SIZE()
    ON_WM_GETMINMAXINFO()
END_MESSAGE_MAP()
@@ -301,7 +175,7 @@
BOOL CSystemLogManagerDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    CBaseDlg::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    SetWindowText(_T("系统运行日志"));
@@ -330,88 +204,11 @@
    COleDateTime defaultStartTime = currentTime - COleDateTimeSpan(30, 0, 0, 0);
    m_dateTimeStart.SetTime(defaultStartTime);
    CRect screenRect, dlgRect, clientRect;
    GetClientRect(&clientRect);
    m_nInitialWidth = clientRect.Width();
    m_nInitialHeight = clientRect.Height();
    // åˆå§‹åŒ–默认字体
    CFont* pDefaultFont = GetOrCreateFont(12);
    // éåŽ†æ‰€æœ‰å­æŽ§ä»¶ï¼Œè®°å½•åˆå§‹ä½ç½®å¹¶è®¾ç½®é»˜è®¤å­—ä½“
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        int nCtrlID = pWnd->GetDlgCtrlID();
        if (nCtrlID != -1) {
            // è®°å½•控件初始布局
            CRect ctrlRect;
            pWnd->GetWindowRect(&ctrlRect);
            ScreenToClient(&ctrlRect);
            m_mapCtrlLayouts[nCtrlID] = ctrlRect;
            // è·³è¿‡ç‰¹æ®ŠæŽ§ä»¶ï¼ˆå¦‚ MFCGridCtrl)
            TCHAR szClassName[256];
            GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
            if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
                pWnd = pWnd->GetNextWindow();
                continue;
            }
            // è®¾ç½®é»˜è®¤å­—体
            pWnd->SetFont(pDefaultFont);
        }
        pWnd = pWnd->GetNextWindow();
    }
    GetWindowRect(&dlgRect);
    int dlgWidth = dlgRect.Width() * 2;
    int dlgHeight = dlgRect.Height() * 2;
    SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0);
    if (dlgWidth > screenRect.Width()) {
        dlgWidth = screenRect.Width();
    }
    if (dlgHeight > screenRect.Height()) {
        dlgHeight = screenRect.Height();
    }
    int centerX = screenRect.left + (screenRect.Width() - dlgWidth) / 2;
    int centerY = screenRect.top + (screenRect.Height() - dlgHeight) / 2;
    MoveWindow(centerX, centerY, dlgWidth, dlgHeight);
    InitSystemLogManager();
    return TRUE;  // return TRUE unless you set the focus to a control
    // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
void CSystemLogManagerDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    // TODO: åœ¨æ­¤å¤„添加消息处理程序代码
    if (nType == SIZE_MINIMIZED || m_mapCtrlLayouts.empty()) {
        return;
    }
    float dScaleX = static_cast<float>(cx) / m_nInitialWidth;
    float dScaleY = static_cast<float>(cy) / m_nInitialHeight;
    // éåŽ†å¯¹è¯æ¡†ä¸­çš„æ‰€æœ‰æŽ§ä»¶
    AdjustControls(dScaleX, dScaleY);
}
void CSystemLogManagerDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    lpMMI->ptMinTrackSize.x = 400; // æœ€å°å®½åº¦
    lpMMI->ptMinTrackSize.y = 300; // æœ€å°é«˜åº¦
    CDialogEx::OnGetMinMaxInfo(lpMMI);
}
void CSystemLogManagerDlg::OnBnClickedButtonSearch()
{
@@ -426,7 +223,6 @@
        AfxMessageBox(errorMsg, MB_ICONERROR);
    }
}
void CSystemLogManagerDlg::OnBnClickedButtonPrevPage()
{
@@ -447,7 +243,6 @@
    }
}
void CSystemLogManagerDlg::OnBnClickedButtonNextPage()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
@@ -467,7 +262,6 @@
    }
}
void CSystemLogManagerDlg::OnSelchangeComboType()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
@@ -481,7 +275,6 @@
        AfxMessageBox(errorMsg, MB_ICONERROR);
    }
}
void CSystemLogManagerDlg::OnSelchangeComboUser()
{
SourceCode/Bond/BondEq/View/SystemLogManagerDlg.h
@@ -1,10 +1,11 @@
#pragma once
#include "afxdialogex.h"
#include "GridCtrl.h"
#include "CBaseDlg.h"
// CSystemLogManagerDlg å¯¹è¯æ¡†
class CSystemLogManagerDlg : public CDialogEx
class CSystemLogManagerDlg : public CBaseDlg
{
    DECLARE_DYNAMIC(CSystemLogManagerDlg)
@@ -20,21 +21,11 @@
private:
    void InitSystemLogManager();
    void FillSystemLogManager();
    CFont* GetOrCreateFont(int nFontSize);
    void UpdatePageInfo();
    void SetDefaultFont();
    void AdjustControls(float dScaleX, float dScaleY);
    void AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight);
    void AdjustComboBoxStyle(CComboBox& comboBox);
    void AdjustDateTimeCtrlStyle(CDateTimeCtrl& dateTimeCtrl);
private:
    int m_nInitialWidth;   // åˆå§‹å®½åº¦
    int m_nInitialHeight;  // åˆå§‹é«˜åº¦
    int m_nCurrentPage;    // å½“前页码
    int m_nTotalPages;     // æ€»é¡µæ•°
    std::map<int, CRect> m_mapCtrlLayouts;    // å­˜å‚¨æŽ§ä»¶çš„初始布局信息
    std::map<int, CFont*> m_mapFonts;        // ç®¡ç†å­—体的容器,键为字体大小
private:
    CComboBox m_comboType;
@@ -47,15 +38,11 @@
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
    afx_msg void OnBnClickedButtonSearch();
    afx_msg void OnBnClickedButtonPrevPage();
    afx_msg void OnBnClickedButtonNextPage();
    afx_msg void OnSelchangeComboType();
    afx_msg void OnSelchangeComboUser();
    DECLARE_MESSAGE_MAP()
};
SourceCode/Bond/BondEq/View/UserManagerDlg.cpp
@@ -8,37 +8,27 @@
#include "InputDialog.h"
#include "NewCellTypes/GridCellCombo.h"
#include "NewCellTypes/GridCellNumeric.h"
#include <set>
const COLORREF CURR_USER_BK_COLOR = RGB(0, 255, 0);
// CUserManagerDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CUserManagerDlg, CDialogEx)
IMPLEMENT_DYNAMIC(CUserManagerDlg, CBaseDlg)
CUserManagerDlg::CUserManagerDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_USER_MANAGER, pParent)
    : CBaseDlg(IDD_DIALOG_USER_MANAGER, pParent)
{
    m_nInitialWidth = 0;
    m_nInitialHeight = 0;
}
CUserManagerDlg::~CUserManagerDlg()
{
    for (auto& pair : m_mapFonts) {
        if (pair.second) {
            pair.second->DeleteObject();
            delete pair.second;
        }
    }
    m_mapFonts.clear();
}
void CUserManagerDlg::DoDataExchange(CDataExchange* pDX)
{
    DDX_Control(pDX, IDC_CUSTOM_USER, m_gridUserManager);
    CDialogEx::DoDataExchange(pDX);
    CBaseDlg::DoDataExchange(pDX);
}
void CUserManagerDlg::InitUserManager()
@@ -350,111 +340,12 @@
    return false;
}
CFont* CUserManagerDlg::GetOrCreateFont(int nFontSize)
{
    auto it = m_mapFonts.find(nFontSize);
    if (it != m_mapFonts.end()) {
        return it->second;
    }
    CFont* font = new CFont();
    LOGFONT logFont = { 0 };
    _tcscpy_s(logFont.lfFaceName, _T("Segoe UI"));
    logFont.lfHeight = -nFontSize;
    logFont.lfQuality = CLEARTYPE_QUALITY;
    font->CreateFontIndirect(&logFont);
    m_mapFonts[nFontSize] = font;
    return font;
}
void CUserManagerDlg::SetDefaultFont()
{
    CFont* defaultFont = GetOrCreateFont(12);
    // éåŽ†æ‰€æœ‰æŽ§ä»¶ï¼Œåº”ç”¨é»˜è®¤å­—ä½“
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        // è·³è¿‡ç‰¹æ®ŠæŽ§ä»¶ï¼ˆå¦‚ MFCGridCtrl)
        TCHAR szClassName[256];
        GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
        if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
            pWnd = pWnd->GetNextWindow();
            continue;
        }
        pWnd->SetFont(defaultFont, TRUE);
        pWnd = pWnd->GetNextWindow();
    }
}
void CUserManagerDlg::AdjustControls(float dScaleX, float dScaleY)
{
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        int nCtrlID = pWnd->GetDlgCtrlID();
        if (nCtrlID != -1 && m_mapCtrlLayouts.find(nCtrlID) != m_mapCtrlLayouts.end())
        {
            CRect originalRect = m_mapCtrlLayouts[nCtrlID];
            CRect newRect(
                static_cast<int>(originalRect.left * dScaleX),
                static_cast<int>(originalRect.top * dScaleY),
                static_cast<int>(originalRect.right * dScaleX),
                static_cast<int>(originalRect.bottom * dScaleY));
            TCHAR szClassName[256];
            GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
            if (_tcsicmp(szClassName, _T("ComboBox")) == 0) {
                CComboBox* pComboBox = (CComboBox*)pWnd;
                pComboBox->SetItemHeight(-1, newRect.Height());  // -1 è¡¨ç¤ºæ‰€æœ‰é¡¹çš„高度
            }
            if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
                CGridCtrl* pGridCtrl = (CGridCtrl*)pWnd;
                pGridCtrl->SetDefCellHeight(newRect.Height() / 21);
                pGridCtrl->ExpandColumnsToFit(TRUE);
                pGridCtrl->ExpandLastColumn();
                pGridCtrl->Invalidate();
                pGridCtrl->UpdateWindow();
            }
            pWnd->MoveWindow(&newRect);
            AdjustControlFont(pWnd, newRect.Width(), newRect.Height());
        }
        pWnd = pWnd->GetNextWindow();
    }
}
void CUserManagerDlg::AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight)
{
    TCHAR szClassName[256];
    GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
    // è·³è¿‡ç‰¹æ®ŠæŽ§ä»¶ï¼ˆå¦‚ MFCGridCtrl)
    if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
        return;
    }
    // æ ¹æ®æŽ§ä»¶é«˜åº¦åŠ¨æ€è°ƒæ•´å­—ä½“å¤§å°
    int fontSize = nHeight / 2;
    if (fontSize < 8) fontSize = 8;
    // èŽ·å–æˆ–åˆ›å»ºå­—ä½“
    CFont* pFont = GetOrCreateFont(fontSize);
    pWnd->SetFont(pFont);
    pWnd->Invalidate(); // åˆ·æ–°æŽ§ä»¶æ˜¾ç¤º
}
BEGIN_MESSAGE_MAP(CUserManagerDlg, CDialogEx)
    ON_WM_SIZE()
BEGIN_MESSAGE_MAP(CUserManagerDlg, CBaseDlg)
    ON_NOTIFY(GVN_COMBOSELCHANGE, IDC_CUSTOM_USER, &CUserManagerDlg::OnGridComboSelChange)
    ON_BN_CLICKED(IDC_BUTTON_ADD, &CUserManagerDlg::OnBnClickedButtonAdd)
    ON_BN_CLICKED(IDC_BUTTON_DEL, &CUserManagerDlg::OnBnClickedButtonDel)
    ON_BN_CLICKED(IDOK, &CUserManagerDlg::OnBnClickedOk)
    ON_BN_CLICKED(IDC_BUTTON_INSERT, &CUserManagerDlg::OnBnClickedButtonInsert)
    ON_WM_GETMINMAXINFO()
END_MESSAGE_MAP()
@@ -463,59 +354,10 @@
BOOL CUserManagerDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    CBaseDlg::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    CRect screenRect, dlgRect, clientRect;
    SetWindowText(_T("用户管理"));
    SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0);
    GetClientRect(&clientRect);
    m_nInitialWidth = clientRect.Width();
    m_nInitialHeight = clientRect.Height();
    // åˆå§‹åŒ–默认字体
    CFont* pDefaultFont = GetOrCreateFont(12);
    // éåŽ†æ‰€æœ‰å­æŽ§ä»¶ï¼Œè®°å½•åˆå§‹ä½ç½®å¹¶è®¾ç½®é»˜è®¤å­—ä½“
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        int nCtrlID = pWnd->GetDlgCtrlID();
        if (nCtrlID != -1) {
            // è®°å½•控件初始布局
            CRect ctrlRect;
            pWnd->GetWindowRect(&ctrlRect);
            ScreenToClient(&ctrlRect);
            m_mapCtrlLayouts[nCtrlID] = ctrlRect;
            // è·³è¿‡ç‰¹æ®ŠæŽ§ä»¶ï¼ˆå¦‚ MFCGridCtrl)
            TCHAR szClassName[256];
            GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
            if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
                pWnd = pWnd->GetNextWindow();
                continue;
            }
            // è®¾ç½®é»˜è®¤å­—体
            pWnd->SetFont(pDefaultFont);
        }
        pWnd = pWnd->GetNextWindow();
    }
    GetWindowRect(&dlgRect);
    int dlgWidth = dlgRect.Width() * 3;
    int dlgHeight = dlgRect.Height() * 3;
    if (dlgWidth > screenRect.Width()) {
        dlgWidth = screenRect.Width();
    }
    if (dlgHeight > screenRect.Height()) {
        dlgHeight = screenRect.Height();
    }
    int centerX = screenRect.left + (screenRect.Width() - dlgWidth) / 2;
    int centerY = screenRect.top + (screenRect.Height() - dlgHeight) / 2;
    MoveWindow(centerX, centerY, dlgWidth, dlgHeight);
    // åˆå§‹åŒ–用户管理表格
    InitUserManager();
@@ -523,34 +365,6 @@
    return TRUE;  // return TRUE unless you set the focus to a control
    // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
void CUserManagerDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    // TODO: åœ¨æ­¤å¤„添加消息处理程序代码
    if (nType == SIZE_MINIMIZED || m_mapCtrlLayouts.empty()) {
        return;
    }
    float dScaleX = static_cast<float>(cx) / m_nInitialWidth;
    float dScaleY = static_cast<float>(cy) / m_nInitialHeight;
    // éåŽ†å¯¹è¯æ¡†ä¸­çš„æ‰€æœ‰æŽ§ä»¶
    AdjustControls(dScaleX, dScaleY);
}
void CUserManagerDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    lpMMI->ptMinTrackSize.x = 400; // æœ€å°å®½åº¦
    lpMMI->ptMinTrackSize.y = 300; // æœ€å°é«˜åº¦
    CDialogEx::OnGetMinMaxInfo(lpMMI);
}
void CUserManagerDlg::OnGridComboSelChange(NMHDR* pNMHDR, LRESULT* pResult)
{
@@ -726,5 +540,5 @@
    }
    userManager.setUsers(vecData);
    CDialogEx::OnOK();
    CBaseDlg::OnOK();
}
SourceCode/Bond/BondEq/View/UserManagerDlg.h
@@ -1,10 +1,11 @@
#pragma once
#include "afxdialogex.h"
#include "GridCtrl.h"
#include "CBaseDlg.h"
// CUserManagerDlg å¯¹è¯æ¡†
class CUserManagerDlg : public CDialogEx
class CUserManagerDlg : public CBaseDlg
{
    DECLARE_DYNAMIC(CUserManagerDlg)
@@ -23,19 +24,11 @@
    void AddRow(CGridCtrl* pGridCtrl);
    void DeleteSelectedRow(CGridCtrl* pGridCtrl);
    bool IsUsernameDuplicate(const CString& username);
    CFont* GetOrCreateFont(int nFontSize);
    void SetDefaultFont();
    void AdjustControls(float dScaleX, float dScaleY);
    void AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight);
private:
    int m_nInitialWidth;
    int m_nInitialHeight;
    std::map<int, CRect> m_mapCtrlLayouts;
    std::map<int, CFont*> m_mapFonts;
    std::map<CString, CString> m_mapRoleDescriptions;
private:
    // æŽ§ä»¶
    CGridCtrl m_gridUserManager;
protected:
@@ -44,8 +37,6 @@
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
    afx_msg void OnGridComboSelChange(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnBnClickedButtonAdd();
    afx_msg void OnBnClickedButtonInsert();
SourceCode/Bond/BondEq/res_en.rc
Binary files differ
SourceCode/Bond/BondEq/res_zh.rc
Binary files differ
SourceCode/Bond/BondEq/resource1.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by res_en.rc
// æ–°å¯¹è±¡çš„下一组默认值
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        101
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
SourceCode/Bond/BondEq/resource2.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by res_zh.rc
// æ–°å¯¹è±¡çš„下一组默认值
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        101
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
SourceCode/Bond/BondEq/stdafx.h
@@ -56,7 +56,7 @@
// æŽ§ä»¶æ ·å¼
static UINT g_nGridFixCellColor = RGB(144, 200, 246);
static UINT g_nGridFixFontColor = RGB(0, 0, 0);
static UINT g_nGridCellColor = RGB(255, 255, 255);
static UINT g_nGridCellColor = RGB(255, 255, 224);
static UINT g_nGridCellColor_NonSelect = RGB(150, 150, 150);
static UINT g_nGridCellReadyColor = RGB(255, 255, 0);
static UINT g_nGridCellOnColor = RGB(255, 69, 0);
SourceCode/Bond/x64/Debug/Config/BondEq.db
Binary files differ