LAPTOP-SNT8I5JK\Boounion
2024-11-13 5471abe440f1b449293a3c93b3a638396682617a
1.初始导入;
已添加225个文件
已修改1个文件
21955 ■■■■■ 文件已修改
.gitignore 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/BEQDemo.cpp 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/BEQDemo.h 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/BEQDemo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/BEQDemo.vcxproj 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/BEQDemo.vcxproj.filters 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/BEQDemo.vcxproj.user 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/BEQDemoDlg.cpp 481 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/BEQDemoDlg.h 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/ColorStatic.cpp 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/ColorStatic.h 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/ReadMe.txt 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/res/BEQDemo.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/res/BEQDemo.rc2 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/res/application.exe.manifest 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/stdafx.cpp 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/stdafx.h 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQDemo/targetver.h 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/AcceptClient.cpp 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/AcceptClient.h 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/Action.cpp 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/Action.h 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/BEQCommon.h 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/BEQLib.h 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/BEQLibrary.cpp 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/BEQLibrary.def 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/BEQLibrary.h 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/BEQLibrary.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/BEQLibrary.vcxproj 265 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/BEQLibrary.vcxproj.filters 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/BEQLibrary.vcxproj.user 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/BEQMain.cpp 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/Data.cpp 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/Data.h 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/Equipment.cpp 935 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/Equipment.h 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/IEquipment.h 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/IRemoteEquipment.h 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/IServo.h 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/IUnit.h 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/ReadMe.txt 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/RemoteEquipment.cpp 1061 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/RemoteEquipment.h 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/Resource.h 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/Servo.cpp 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/Servo.h 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/SocketClient.cpp 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/SocketClient.h 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/SocketServer.cpp 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/SocketServer.h 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/Unit.cpp 425 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/Unit.h 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/res/BEQLibrary.rc2 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/stdafx.cpp 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/stdafx.h 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrary/targetver.h 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrarySDK/Include/BEQLib.h 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrarySDK/Include/IEquipment.h 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrarySDK/Include/IRemoteEquipment.h 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrarySDK/Include/IServo.h 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BEQLibrarySDK/Include/IUnit.h 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/BLButton.h 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/BLFolderScheduling.h 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/BLJogBtn2Parent.h 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/BLJogButton.h 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/BLLabel.h 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/BLListBoxLog.h 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/BLListCtrlExt.h 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/CellCtrl.h 304 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/ColorButton.h 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/DefectMap.h 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/FontStatic.h 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/GradientStatic.h 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/HeadCtrl.h 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/InPlaceComboBox.h 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/InPlaceEdit.h 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/LogCtrl.h 213 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/SortClass.h 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/StaticMap.h 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/WKButton.h 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BLControlsSDK/include/XTabCtrl.h 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/AccordionWnd.cpp 777 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/AccordionWnd.h 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/ApredTreeCtrl.cpp 466 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/ApredTreeCtrl.h 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BaseSetPage.cpp 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BaseSetPage.h 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BlButton.cpp 448 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BlButton.h 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondEq.vcxproj 290 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondSEq.vcxproj.filters 255 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondServo.cpp 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondServo.h 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondServo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondServoDlg.cpp 627 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondServoDlg.h 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CBaseView.cpp 415 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CBaseView.h 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CHomeDialog.cpp 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CHomeDialog.h 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CMainContainer.cpp 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CMainContainer.h 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CPageAlarm.cpp 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CPageAlarm.h 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CPageLogcat.cpp 300 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CPageLogcat.h 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CPanelProject.cpp 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CPanelProject.h 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CProjectPageRemoteEqs.cpp 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CProjectPageRemoteEqs.h 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CRemoteEqUnitView.cpp 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CRemoteEqUnitView.h 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CRemoteEqView.cpp 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/CRemoteEqView.h 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Common.h 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Configuration.cpp 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Configuration.h 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/DBManager/UserManager.cpp 484 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/DBManager/UserManager.h 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/HmTab.cpp 529 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/HmTab.h 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/HmVerticalTab.cpp 576 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/HmVerticalTab.h 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/HorizontalLine.cpp 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/HorizontalLine.h 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Log.cpp 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Log.h 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/LogEdit.cpp 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/LogEdit.h 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Model.cpp 357 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Model.h 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/ReadMe.txt 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Servo.cpp 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Servo.h 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/SetPage1.cpp 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/SetPage1.h 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/SetPage2.cpp 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/SetPage2.h 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/SettingsDlg.cpp 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/SettingsDlg.h 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/ToolUnits.cpp 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/ToolUnits.h 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/TopToolbar.cpp 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/TopToolbar.h 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/VerticalLine.cpp 310 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/VerticalLine.h 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/ChangePasswordDlg.cpp 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/ChangePasswordDlg.h 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/LoginDlg.cpp 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/LoginDlg.h 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/res/BondServo.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/res/BondServo.rc2 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/res/application.exe.manifest 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/stdafx.cpp 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/stdafx.h 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/targetver.h 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/DatabaseSDK/include/Database.h 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/DatabaseSDK/include/MySQLDatabase.h 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/DatabaseSDK/include/SQLiteDatabase.h 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860.sln 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.cpp 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.h 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.vcxproj 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.vcxproj.filters 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.vcxproj.user 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/GangBond2860EmulatorDlg.cpp 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/GangBond2860EmulatorDlg.h 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/HmTab.cpp 529 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/HmTab.h 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/Model.cpp 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/Model.h 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/PageEquipment.cpp 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/PageEquipment.h 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/PageUnit.cpp 406 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/PageUnit.h 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/ReadMe.txt 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/Resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/res/GangBond2860Emulator.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/res/GangBond2860Emulator.rc2 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/res/application.exe.manifest 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/stdafx.cpp 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/stdafx.h 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860Emulator/targetver.h 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/RxWindows1.0/include/IAny.h 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/RxWindows1.0/include/IObservable.h 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/RxWindows1.0/include/IObservableEmitter.h 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/RxWindows1.0/include/IObserver.h 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/RxWindows1.0/include/IRxObject.h 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/RxWindows1.0/include/IRxWindows.h 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/RxWindows1.0/include/IThrowable.h 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/RxWindows1.0/include/RxWindowsLib.h 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/AlarmList.txt 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Config/BondServo.db 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/Operator_Gray_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/Operator_High_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/Run_Gray_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/Run_High_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/Settings_Gray_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/Settings_High_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/Stop_Gray_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/Stop_High_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/arrow_down.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/arrow_right.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/indicator_check_24.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/indicator_check_28.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/indicator_check_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/indicator_check_32_dark.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/indicator_check_32_dark2.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/logcat_include.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/remote_eq_dark_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/remote_eq_light_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/small_close0.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/small_close1.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/small_close2.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/small_close3.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Release/AlarmList.txt 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Release/Res/arrow_down.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Release/Res/arrow_right.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Release/Res/small_close0.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Release/Res/small_close1.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Release/Res/small_close2.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Release/Res/small_close3.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Release/configuration.ini 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -19,3 +19,21 @@
*.exe
*.out
*.app
*.opensdf
*.sdf
SourceCode/Bond/.vs/GangBond2860/v14/.suo
*.aps
SourceCode/Bond/BEQDemo/x64/
SourceCode/Bond/BEQLibrary/x64/
*.pdb
SourceCode/Bond/BondEq/x64/
SourceCode/Bond/GangBond2860Emulator/x64/
*.ipch
*.log
*.ipdb
SourceCode/Bond/x64/Debug/configuration.ini
*.ilk
SourceCode/Bond/x64/Debug/BEQ.exp
SourceCode/Bond/x64/Debug/Bonder.dat
SourceCode/Bond/x64/Release/BEQ.exp
SourceCode/Bond/x64/Release/Bonder.dat
SourceCode/Bond/BEQDemo/BEQDemo.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
// BEQDemo.cpp : å®šä¹‰åº”用程序的类行为。
//
#include "stdafx.h"
#include "BEQDemo.h"
#include "BEQDemoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CBEQDemoApp
BEGIN_MESSAGE_MAP(CBEQDemoApp, CWinApp)
    ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// CBEQDemoApp æž„造
CBEQDemoApp::CBEQDemoApp()
{
    // æ”¯æŒé‡æ–°å¯åŠ¨ç®¡ç†å™¨
    m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
    // TODO: åœ¨æ­¤å¤„添加构造代码,
    // å°†æ‰€æœ‰é‡è¦çš„初始化放置在 InitInstance ä¸­
}
// å”¯ä¸€çš„一个 CBEQDemoApp å¯¹è±¡
CBEQDemoApp theApp;
// CBEQDemoApp åˆå§‹åŒ–
BOOL CBEQDemoApp::InitInstance()
{
    // å¦‚果一个运行在 Windows XP ä¸Šçš„应用程序清单指定要
    // ä½¿ç”¨ ComCtl32.dll ç‰ˆæœ¬ 6 æˆ–更高版本来启用可视化方式,
    //则需要 InitCommonControlsEx()。  å¦åˆ™ï¼Œå°†æ— æ³•创建窗口。
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    // å°†å®ƒè®¾ç½®ä¸ºåŒ…括所有要在应用程序中使用的
    // å…¬å…±æŽ§ä»¶ç±»ã€‚
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);
    CWinApp::InitInstance();
    AfxEnableControlContainer();
    // åˆ›å»º shell ç®¡ç†å™¨ï¼Œä»¥é˜²å¯¹è¯æ¡†åŒ…含
    // ä»»ä½• shell æ ‘视图控件或 shell åˆ—表视图控件。
    CShellManager *pShellManager = new CShellManager;
    // æ¿€æ´»â€œWindows Native”视觉管理器,以便在 MFC æŽ§ä»¶ä¸­å¯ç”¨ä¸»é¢˜
    CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
    // æ ‡å‡†åˆå§‹åŒ–
    // å¦‚果未使用这些功能并希望减小
    // æœ€ç»ˆå¯æ‰§è¡Œæ–‡ä»¶çš„大小,则应移除下列
    // ä¸éœ€è¦çš„特定初始化例程
    // æ›´æ”¹ç”¨äºŽå­˜å‚¨è®¾ç½®çš„æ³¨å†Œè¡¨é¡¹
    // TODO: åº”适当修改该字符串,
    // ä¾‹å¦‚修改为公司或组织名
    SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
    // åˆå§‹åŒ–BEQ库
    BEQ_Initialize();
    CBEQDemoDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
        // TODO: åœ¨æ­¤æ”¾ç½®å¤„理何时用
        //  â€œç¡®å®šâ€æ¥å…³é—­å¯¹è¯æ¡†çš„代码
    }
    else if (nResponse == IDCANCEL)
    {
        // TODO: åœ¨æ­¤æ”¾ç½®å¤„理何时用
        //  â€œå–消”来关闭对话框的代码
    }
    else if (nResponse == -1)
    {
        TRACE(traceAppMsg, 0, "警告: å¯¹è¯æ¡†åˆ›å»ºå¤±è´¥ï¼Œåº”用程序将意外终止。\n");
        TRACE(traceAppMsg, 0, "警告: å¦‚果您在对话框上使用 MFC æŽ§ä»¶ï¼Œåˆ™æ— æ³• #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
    }
    // åˆ é™¤ä¸Šé¢åˆ›å»ºçš„ shell ç®¡ç†å™¨ã€‚
    if (pShellManager != NULL)
    {
        delete pShellManager;
    }
    // ç”±äºŽå¯¹è¯æ¡†å·²å…³é—­ï¼Œæ‰€ä»¥å°†è¿”回 FALSE ä»¥ä¾¿é€€å‡ºåº”用程序,
    //  è€Œä¸æ˜¯å¯åŠ¨åº”ç”¨ç¨‹åºçš„æ¶ˆæ¯æ³µã€‚
    return FALSE;
}
int CBEQDemoApp::ExitInstance()
{
    BEQ_Term();
    return CWinApp::ExitInstance();
}
SourceCode/Bond/BEQDemo/BEQDemo.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
// BEQDemo.h : PROJECT_NAME åº”用程序的主头文件
//
#pragma once
#ifndef __AFXWIN_H__
    #error "在包含此文件之前包含“stdafx.h”以生成 PCH æ–‡ä»¶"
#endif
#include "resource.h"        // ä¸»ç¬¦å·
// CBEQDemoApp:
// æœ‰å…³æ­¤ç±»çš„实现,请参阅 BEQDemo.cpp
//
class CBEQDemoApp : public CWinApp
{
public:
    CBEQDemoApp();
// é‡å†™
public:
    virtual BOOL InitInstance();
// å®žçް
    DECLARE_MESSAGE_MAP()
    virtual int ExitInstance();
};
extern CBEQDemoApp theApp;
SourceCode/Bond/BEQDemo/BEQDemo.rc
Binary files differ
SourceCode/Bond/BEQDemo/BEQDemo.vcxproj
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,230 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{E374F8A0-F864-49F4-AF5C-F751AAC5F133}</ProjectGuid>
    <RootNamespace>BEQDemo</RootNamespace>
    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
    <Keyword>MFCProj</Keyword>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>MultiByte</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>MultiByte</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="Shared">
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="BEQDemo.h" />
    <ClInclude Include="BEQDemoDlg.h" />
    <ClInclude Include="ColorStatic.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="stdafx.h" />
    <ClInclude Include="targetver.h" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="BEQDemo.cpp" />
    <ClCompile Include="BEQDemoDlg.cpp" />
    <ClCompile Include="ColorStatic.cpp" />
    <ClCompile Include="stdafx.cpp">
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="BEQDemo.rc" />
  </ItemGroup>
  <ItemGroup>
    <None Include="res\BEQDemo.rc2" />
  </ItemGroup>
  <ItemGroup>
    <Image Include="res\BEQDemo.ico" />
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="res\application.exe.manifest" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
  <ProjectExtensions>
    <VisualStudio>
      <UserProperties RESOURCE_FILE="BEQDemo.rc" />
    </VisualStudio>
  </ProjectExtensions>
</Project>
SourceCode/Bond/BEQDemo/BEQDemo.vcxproj.filters
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="源文件">
      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
    </Filter>
    <Filter Include="头文件">
      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
    </Filter>
    <Filter Include="资源文件">
      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="stdafx.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="targetver.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Resource.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="BEQDemo.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="BEQDemoDlg.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="ColorStatic.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="stdafx.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="BEQDemo.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="BEQDemoDlg.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="ColorStatic.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="BEQDemo.rc">
      <Filter>资源文件</Filter>
    </ResourceCompile>
  </ItemGroup>
  <ItemGroup>
    <None Include="res\BEQDemo.rc2">
      <Filter>资源文件</Filter>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Image Include="res\BEQDemo.ico">
      <Filter>资源文件</Filter>
    </Image>
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="res\application.exe.manifest" />
  </ItemGroup>
</Project>
SourceCode/Bond/BEQDemo/BEQDemo.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>BEQDemo.rc</RESOURCE_FILE>
  </PropertyGroup>
</Project>
SourceCode/Bond/BEQDemo/BEQDemoDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,481 @@
// BEQDemoDlg.cpp : å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BEQDemo.h"
#include "BEQDemoDlg.h"
#include "afxdialogex.h"
#include <map>
#include <chrono>
#include <sstream>
#include <iomanip>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// ç”¨äºŽåº”用程序“关于”菜单项的 CAboutDlg å¯¹è¯æ¡†
class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_ABOUTBOX };
#endif
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
// å®žçް
protected:
    DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CBEQDemoDlg å¯¹è¯æ¡†
CBEQDemoDlg::CBEQDemoDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_BEQDEMO_DIALOG, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CBEQDemoDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT_LOG, m_editLog);
    DDX_Control(pDX, IDC_STATIC_DOOR1, m_staticDoor1);
    DDX_Control(pDX, IDC_STATIC_DOOR2, m_staticDoor2);
    DDX_Control(pDX, IDC_STATIC_DOOR3, m_staticDoor3);
    DDX_Control(pDX, IDC_STATIC_DOOR4, m_staticDoor4);
    DDX_Control(pDX, IDC_STATIC_DOOR5, m_staticDoor5);
}
BEGIN_MESSAGE_MAP(CBEQDemoDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BUTTON_TEST1, &CBEQDemoDlg::OnBnClickedButtonTest1)
    ON_BN_CLICKED(IDC_BUTTON_TEST2, &CBEQDemoDlg::OnBnClickedButtonTest2)
    ON_BN_CLICKED(IDC_BUTTON_TEST3, &CBEQDemoDlg::OnBnClickedButtonTest3)
    ON_BN_CLICKED(IDC_BUTTON_SET_STATE, &CBEQDemoDlg::OnBnClickedButtonSetState)
    ON_BN_CLICKED(IDC_BUTTON_SET_STATE2, &CBEQDemoDlg::OnBnClickedButtonSetState2)
    ON_BN_CLICKED(IDC_BUTTON_SERVO_TEST1, &CBEQDemoDlg::OnBnClickedButtonServoTest1)
    ON_BN_CLICKED(IDC_BUTTON_SERVO_TEST2, &CBEQDemoDlg::OnBnClickedButtonServoTest2)
    ON_BN_CLICKED(IDC_BUTTON_SERVO_TEST3, &CBEQDemoDlg::OnBnClickedButtonServoTest3)
END_MESSAGE_MAP()
// CBEQDemoDlg æ¶ˆæ¯å¤„理程序
BOOL CBEQDemoDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // å°†â€œå…³äºŽ...”菜单项添加到系统菜单中。
    // IDM_ABOUTBOX å¿…须在系统命令范围内。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);
    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }
    // è®¾ç½®æ­¤å¯¹è¯æ¡†çš„图标。  å½“应用程序主窗口不是对话框时,框架将自动
    //  æ‰§è¡Œæ­¤æ“ä½œ
    SetIcon(m_hIcon, TRUE);            // è®¾ç½®å¤§å›¾æ ‡
    SetIcon(m_hIcon, FALSE);        // è®¾ç½®å°å›¾æ ‡
    // TODO: åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–ä»£ç 
    return TRUE;  // é™¤éžå°†ç„¦ç‚¹è®¾ç½®åˆ°æŽ§ä»¶ï¼Œå¦åˆ™è¿”回 TRUE
}
void CBEQDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}
// å¦‚果向对话框添加最小化按钮,则需要下面的代码
//  æ¥ç»˜åˆ¶è¯¥å›¾æ ‡ã€‚  å¯¹äºŽä½¿ç”¨æ–‡æ¡£/视图模型的 MFC åº”用程序,
//  è¿™å°†ç”±æ¡†æž¶è‡ªåŠ¨å®Œæˆã€‚
void CBEQDemoDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // ç”¨äºŽç»˜åˆ¶çš„设备上下文
        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
        // ä½¿å›¾æ ‡åœ¨å·¥ä½œåŒºçŸ©å½¢ä¸­å±…中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;
        // ç»˜åˆ¶å›¾æ ‡
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CBEQDemoDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}
void CBEQDemoDlg::OnBnClickedButtonTest1()
{
    BEQ::IEquipment* pEuqipment = nullptr;
    BEQ_CreateEquipment(pEuqipment, "BEQ001");
}
void CBEQDemoDlg::OnBnClickedButtonTest2()
{
    BEQ::IEquipment* pEuqipment = nullptr;
    BEQ_GetEquipment(pEuqipment, "BEQ001");
    if (pEuqipment != nullptr) {
        pEuqipment->setVersion("1.0.2");
        BEQ::IUnit* pUnit1 = pEuqipment->addUnit("U1", 5);
        pEuqipment->runOnServerMode(8080);
        char szName[256];
        pUnit1->getName(szName, 256);
        AfxMessageBox(szName);
        pUnit1->setState(BEQ::EQ_STATE::IDLE);
    }
}
void CBEQDemoDlg::OnBnClickedButtonTest3()
{
    BEQ::IEquipment* pEuqipment = nullptr;
    BEQ_GetEquipment(pEuqipment, "Test1");
    if (pEuqipment != nullptr) {
        BEQ_DestroyEquipment(pEuqipment);
    }
}
void CBEQDemoDlg::OnBnClickedButtonSetState()
{
    BEQ::IUnit* pUnit = nullptr;
    BEQ::IEquipment* pEuqipment = nullptr;
    BEQ_GetEquipment(pEuqipment, "BEQ001");
    if (pEuqipment != nullptr) {
        pUnit = pEuqipment->getUnit("U1");
    }
    if (pUnit != nullptr) {
        // pUnit->setState(BEQ::EQ_STATE::E_TIME);
        // pUnit->setDoorState(BEQ::DOOR_STATE::CLOSE);
        pUnit->setAlarm(0, 0, "");
    }
}
void CBEQDemoDlg::OnBnClickedButtonSetState2()
{
    BEQ::IUnit* pUnit = nullptr;
    BEQ::IEquipment* pEuqipment = nullptr;
    BEQ_GetEquipment(pEuqipment, "BEQ001");
    if (pEuqipment != nullptr) {
        pUnit = pEuqipment->getUnit("U1");
    }
    if (pUnit != nullptr) {
        // pUnit->setState(BEQ::EQ_STATE::RUN);
        // pUnit->setDoorState(BEQ::DOOR_STATE::OPEN);
        // pUnit->setAlarm(206, 1, "A单元-上腔体Zè½´1异常");
        /*
        static int i = 0;
        i++;
        if (i % 6 == 1) {
            pUnit->stepIdle();
        }
        if (i % 6 == 2) {
            pUnit->stepMaterialReceived("A12345");
        }
        if (i % 6 == 3) {
            pUnit->stepProcessingStarted("A12345");
        }
        if (i % 6 == 4) {
            pUnit->stepProcessing("A12345", 15, 1);
        }
        if (i % 6 == 5) {
            pUnit->stepMaterialRemoved("A12345");
        }
        if (i % 6 == 0) {
            pUnit->stepProcessingCompleted("A12345");
        }
        */
        /*
        auto now = std::chrono::system_clock::now();
        auto duration_in_milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
        uint64_t timestamp = duration_in_milliseconds.count();
        pUnit->setDataTimeAndResetData(timestamp);
        static int i = 0;
        i++;
        if (i < 6) {
            pUnit->addData("TMP", "1.1,2.1,3.2,4.3,5.4,6.6,7.7,8.8,9.9,10.1,11.1,12.1", false);
            pUnit->addData("AIR", "112.19", false);
            pUnit->addData("PRE", "151,152.3,153.4,154.5,155.6", true);
        }
        else {
            pUnit->addData("TMP", "81.1,2.1,3.2,4.3,5.4,6.6,7.7,8.8,9.9,10.1,11.1,12.1", false);
            pUnit->addData("AIR", "8112.19", false);
            pUnit->addData("PRE", "8151,152.3,153.4,154.5,155.6", true);
        }*/
        pUnit->addRecipe(1001, "RECIPE_1001", false);
        pUnit->addRecipe(1002, "RECIPE_1002", false);
        pUnit->addRecipe(1003, "RECIPE_1003", false);
        pUnit->addRecipe(1004, "RECIPE_1004", false);
        pUnit->addRecipe(1005, "RECIPE_1005", false);
        pUnit->addRecipe(1006, "RECIPE_1006", true);
    }
}
void CBEQDemoDlg::OnBnClickedButtonServoTest1()
{
    BEQ::IServo* pServo = nullptr;
    BEQ_CreateServo(pServo, "BLServo");
    ASSERT(pServo);
    BEQ::IRemoteEquipment* pRemoteEquipment = nullptr;
    pServo->createRemoteEquipment(pRemoteEquipment, "127.0.0.1", 8192);
    ASSERT(pRemoteEquipment);
    if (pRemoteEquipment != nullptr) {
        BEQ::IUnit* pUnitA = pRemoteEquipment->addUnit("UNITA", 5);
        BEQ::IUnit* pUnitB = pRemoteEquipment->addUnit("UNITB", 5);
    }
    char szAddr[64];
    pRemoteEquipment->getAddr(szAddr, 64);
    CString s; s.Format("%s:%d", szAddr, pRemoteEquipment->getPort());
    AfxMessageBox(s);
    BEQ::ServoListener listener;
    listener.onRemoteEqConnecting = [&](void* pServo, void* pRemoteEiuipment) -> void {
        TRACE("<ServoListener>onRemoteEqConnecting...\n");
    };
    listener.onRemoteEqConnected = [&](void* pServo, void* pRemoteEiuipment) -> void {
        TRACE("<ServoListener>onRemoteEqConnected...\n");
    };
    listener.onRemoteEqConnectFailed = [&](void* pServo, void* pRemoteEiuipment, int errorCode) -> void {
        TRACE("<ServoListener>onRemoteEqConnectFailed...\n");
    };
    listener.onRemoteEqDisconnecting = [&](void* pServo, void* pRemoteEiuipment) -> void {
        TRACE("<ServoListener>onRemoteEqDisconnecting...\n");
    };
    listener.onRemoteEqDisconnected = [&](void* pServo, void* pRemoteEiuipment) -> void {
        TRACE("<ServoListener>onRemoteEqDisconnected...\n");
    };
    listener.onRemoteEqReadRawdata = [&](void* pServo, void* pRemoteEiuipment, const char* pszData, int len) -> void {
        TRACE("<ServoListener>onRemoteEqReadRawdata...\n");
    };
    listener.onRemoteEqEventUpdate = [&](void* pServo, void* pRemoteEiuipment, void* pUnit, BEQ::REMOTE_EQ_EVENT eventCode) -> void {
        TRACE("<ServoListener>onRemoteEqEventUpdate...\n");
        HandleRemoteEqEventUpdate(eventCode, pUnit);
    };
    pServo->setListener(listener);
    pServo->connectRemoteEquipment(pRemoteEquipment);
}
void CBEQDemoDlg::OnBnClickedButtonServoTest2()
{
    BEQ::IServo* pServo = nullptr;
    BEQ_GetServo(pServo, "BLServo");
    ASSERT(pServo);
    char szName[256];
    pServo->getName(szName, 256);
    AfxMessageBox(szName);
}
void CBEQDemoDlg::OnBnClickedButtonServoTest3()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
}
void CBEQDemoDlg::AppendTextToLog(const CString& text)
{
    // è¿½åŠ æ–‡æœ¬ä¹‹å‰æ£€æŸ¥è¡Œæ•°
    CString existingText;
    m_editLog.GetWindowText(existingText);
    // è®¡ç®—当前行数
    int lineCount = 0;
    for (int i = 0; i < existingText.GetLength(); i++)
    {
        if (existingText[i] == '\n')
            lineCount++;
    }
    // å¦‚果行数超过 100,清空控件
    if (lineCount >= 100)
    {
        m_editLog.SetWindowText(_T("")); // æ¸…空控件
    }
    // è¿½åŠ æ–°æ–‡æœ¬
    m_editLog.SetSel(m_editLog.GetWindowTextLength(), m_editLog.GetWindowTextLength()); // è®¾ç½®å…‰æ ‡åˆ°æ–‡æœ¬æœ«å°¾
    m_editLog.ReplaceSel(text + _T("\r\n")); // è¿½åŠ æ–‡æœ¬å¹¶æ¢è¡Œ
}
const char* CBEQDemoDlg::ConverUint64ToTimeString(uint64_t time)
{
    static char buffer[32];
    auto timePoint = std::chrono::time_point<std::chrono::system_clock>(std::chrono::milliseconds(time));
    std::time_t t = std::chrono::system_clock::to_time_t(timePoint);
    std::tm tmPtr;
    if (localtime_s(&tmPtr, &t) == 0) {
        strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tmPtr);
    }
    else {
        snprintf(buffer, sizeof(buffer), "Invalid Time");
    }
    return buffer;
}
void CBEQDemoDlg::UpdateDoorStatus(CColorStatic& doorControl, bool isOpen)
{
    if (isOpen) {
        doorControl.SetWindowText(_T("open"));
        doorControl.SetBkColor(RGB(255, 0, 0)); // çº¢è‰²è¡¨ç¤ºæ‰“å¼€
    }
    else {
        doorControl.SetWindowText(_T("close"));
        doorControl.SetBkColor(RGB(0, 255, 0)); // ç»¿è‰²è¡¨ç¤ºå…³é—­
    }
    doorControl.Invalidate();
}
void CBEQDemoDlg::HandleRemoteEqEventUpdate(BEQ::REMOTE_EQ_EVENT eventCode, void* pUnit)
{
    BEQ::IUnit* pUnitEx = (BEQ::IUnit*)pUnit;
    char chUnitName[128] = {0};
    pUnitEx->getName(chUnitName, sizeof(chUnitName));
    switch (eventCode) {
    case BEQ::REMOTE_EQ_EVENT::DEVICE_STATUS_CHANGED: {
        // å¤„理设备状态
        CString strStatus;
        static char* eqState[] = { "IDLE", "RUN", "DOWN", "MAINTENANCE", "MCHG", "E_TIME" };
        strStatus.Format("DEVICE_STATUS_CHANGED@%s: %s", chUnitName, eqState[(int)pUnitEx->getState()]);
        AppendTextToLog(strStatus);
        break;
    }
    case BEQ::REMOTE_EQ_EVENT::DOOR_STATUS_CHANGED: {
        // å¤„理门状态
        UpdateDoorStatus(m_staticDoor1, (pUnitEx->getDoorState() >> 0) & 1);
        UpdateDoorStatus(m_staticDoor2, (pUnitEx->getDoorState() >> 1) & 1);
        UpdateDoorStatus(m_staticDoor3, (pUnitEx->getDoorState() >> 2) & 1);
        UpdateDoorStatus(m_staticDoor4, (pUnitEx->getDoorState() >> 3) & 1);
        UpdateDoorStatus(m_staticDoor5, (pUnitEx->getDoorState() >> 4) & 1);
        CString strDoorStatus;
        strDoorStatus.Format("DOOR_STATUS_CHANGED@%s: %d", chUnitName, pUnitEx->getDoorState());
        AppendTextToLog(strDoorStatus);
        break;
    }
    case BEQ::REMOTE_EQ_EVENT::ALARM_INFO_CHANGED: {
        // å¤„理报警信息
        CString strAlarmInfo;
        strAlarmInfo.Format("ALARM_INFO_CHANGED@%s: %d %d", chUnitName, pUnitEx->getAlarmCode(), pUnitEx->getAlarmLevel());
        AppendTextToLog(strAlarmInfo);
        break;
    }
    case BEQ::REMOTE_EQ_EVENT::REMOVE_ALARM_INFO: {
        // å¤„理解除告警
        CString strRemoveAlarmInfo;
        strRemoveAlarmInfo.Format("REMOVE_ALARM_INFO@%s: %d %d", chUnitName, pUnitEx->getAlarmCode(), pUnitEx->getAlarmLevel());
        AppendTextToLog(strRemoveAlarmInfo);
        break;
    }
    case BEQ::REMOTE_EQ_EVENT::PRODUCTION_PROCESS_CHANGED: {
        // å¤„理制作过程状态
        static char* stepState[] = { "IDLE", "MATERIAL_RECEIVED", "MATERIAL_REMOVED", "PROCESSING_STARTED", "PROCESSING", "PROCESSING_COMPLETED" };
        CString strProduction;
        strProduction.Format("PRODUCTION_PROCESS_CHANGED@%s: %s", chUnitName, stepState[(int)pUnitEx->getStepState()]);
        AppendTextToLog(strProduction);
        break;
    }
    case BEQ::REMOTE_EQ_EVENT::SERSOR_DATA_CHANGED: {
        // å¤„理最新数据,传感器(温度、压力等)
        CString strSersorData;
        strSersorData.Format("SERSOR_DATA_CHANGED@%s: %s", chUnitName, ConverUint64ToTimeString(pUnitEx->getDataTime()));
        AppendTextToLog(strSersorData);
        break;
    }
    case::BEQ::REMOTE_EQ_EVENT::RECIPE_LIST_CHANGED: {
        // å¤„理配方列表
        CString strRecipeList;
        strRecipeList.Format("RECIPE_LIST_CHANGED@%s: ", chUnitName);
        std::map<int, std::string> mapRec;// = pUnit->getRecipes();
        for (auto it = mapRec.begin(); it != mapRec.end(); it++)
        {
            TRACE("RecipeList[%d]: %s\n", it->first, it->second.c_str());
        }
        AppendTextToLog(strRecipeList);
        break;
    }
    case BEQ::REMOTE_EQ_EVENT::LOAD_EVENT_CHANGED: {
        // å¤„理上报事件
        break;
    }
    default:
        // å¤„理其他状态...
        TRACE("<ServoListener>Unknown status...\n");
        break;
    }
}
SourceCode/Bond/BEQDemo/BEQDemoDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
// BEQDemoDlg.h : å¤´æ–‡ä»¶
//
#pragma once
#include "ColorStatic.h"
// CBEQDemoDlg å¯¹è¯æ¡†
class CBEQDemoDlg : public CDialogEx
{
// æž„造
public:
    CBEQDemoDlg(CWnd* pParent = NULL);    // æ ‡å‡†æž„造函数
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_BEQDEMO_DIALOG };
#endif
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
// å®žçް
protected:
    HICON m_hIcon;
    CEdit m_editLog;
    CColorStatic m_staticDoor1;
    CColorStatic m_staticDoor2;
    CColorStatic m_staticDoor3;
    CColorStatic m_staticDoor4;
    CColorStatic m_staticDoor5;
private:
    void AppendTextToLog(const CString& text);
    const char* ConverUint64ToTimeString(uint64_t time);
    void UpdateDoorStatus(CColorStatic& doorControl, bool isOpen);
    void HandleRemoteEqEventUpdate(BEQ::REMOTE_EQ_EVENT eventCode, void* pUnit);
    // ç”Ÿæˆçš„æ¶ˆæ¯æ˜ å°„函数
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnBnClickedButtonTest1();
    afx_msg void OnBnClickedButtonTest2();
    afx_msg void OnBnClickedButtonTest3();
    afx_msg void OnBnClickedButtonSetState();
    afx_msg void OnBnClickedButtonSetState2();
    afx_msg void OnBnClickedButtonServoTest1();
    afx_msg void OnBnClickedButtonServoTest2();
    afx_msg void OnBnClickedButtonServoTest3();
};
SourceCode/Bond/BEQDemo/ColorStatic.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
#include "stdafx.h"
#include "ColorStatic.h"
BEGIN_MESSAGE_MAP(CColorStatic, CStatic)
    ON_WM_PAINT()
END_MESSAGE_MAP()
void CColorStatic::OnPaint()
{
    CPaintDC dc(this); // åˆ›å»ºç»˜å›¾ä¸Šä¸‹æ–‡
    // å¡«å……背景颜色
    CRect rect;
    GetClientRect(&rect);
    dc.FillSolidRect(rect, m_bkColor);
    // ç»˜åˆ¶æ–‡æœ¬
    CString text;
    GetWindowText(text);
    dc.SetTextColor(RGB(0, 0, 0)); // è®¾ç½®æ–‡æœ¬é¢œè‰²ä¸ºé»‘色
    dc.DrawText(text, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); // ç»˜åˆ¶æ–‡æœ¬
}
SourceCode/Bond/BEQDemo/ColorStatic.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
#pragma once
#include <afxwin.h>
class CColorStatic : public CStatic
{
public:
    void SetBkColor(COLORREF color) { m_bkColor = color; }
protected:
    afx_msg void OnPaint();
    DECLARE_MESSAGE_MAP()
private:
    COLORREF m_bkColor = RGB(255, 255, 255); // é»˜è®¤èƒŒæ™¯é¢œè‰²ä¸ºç™½è‰²
};
SourceCode/Bond/BEQDemo/ReadMe.txt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
================================================================================
    MICROSOFT åŸºç¡€ç±»åº“ : BEQDemo é¡¹ç›®æ¦‚è¿°
===============================================================================
应用程序向导已为您创建了此 BEQDemo åº”用程序。此应用程序不仅演示 Microsoft åŸºç¡€ç±»çš„基本使用方法,还可作为您编写应用程序的起点。
本文件概要介绍组成 BEQDemo åº”用程序的每个文件的内容。
BEQDemo.vcxproj
    è¿™æ˜¯ä½¿ç”¨åº”用程序向导生成的 VC++ é¡¹ç›®çš„主项目文件,其中包含生成该文件的 Visual C++ çš„版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
BEQDemo.vcxproj.filters
    è¿™æ˜¯ä½¿ç”¨â€œåº”用程序向导”生成的 VC++ é¡¹ç›®ç­›é€‰å™¨æ–‡ä»¶ã€‚它包含有关项目文件与筛选器之间的关联信息。在 IDE ä¸­ï¼Œé€šè¿‡è¿™ç§å…³è”,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
BEQDemo.h
    è¿™æ˜¯åº”用程序的主头文件。
    å…¶ä¸­åŒ…括其他项目特定的标头(包括 Resource.h),并声明 CBEQDemoApp åº”用程序类。
BEQDemo.cpp
    è¿™æ˜¯åŒ…含应用程序类 CBEQDemoApp çš„主应用程序源文件。
BEQDemo.rc
    è¿™æ˜¯ç¨‹åºä½¿ç”¨çš„æ‰€æœ‰ Microsoft Windows èµ„源的列表。它包括 RES å­ç›®å½•中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ ä¸­è¿›è¡Œç¼–辑。项目资源包含在 2052 ä¸­ã€‚
res\BEQDemo.ico
    è¿™æ˜¯ç”¨ä½œåº”用程序图标的图标文件。此图标包括在主资源文件 BEQDemo.rc ä¸­ã€‚
res\BEQDemo.rc2
    æ­¤æ–‡ä»¶åŒ…含不在 Microsoft Visual C++ ä¸­è¿›è¡Œç¼–辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。
/////////////////////////////////////////////////////////////////////////////
应用程序向导创建一个对话框类:
BEQDemoDlg.h、BEQDemoDlg.cpp - å¯¹è¯æ¡†
    è¿™äº›æ–‡ä»¶åŒ…含 CBEQDemoDlg ç±»ã€‚此类定义应用程序的主对话框的行为。对话框模板包含在 BEQDemo.rc ä¸­ï¼Œè¯¥æ–‡ä»¶å¯ä»¥åœ¨ Microsoft Visual C++ ä¸­ç¼–辑。
/////////////////////////////////////////////////////////////////////////////
其他功能:
ActiveX æŽ§ä»¶
    è¯¥åº”用程序包含对使用 ActiveX æŽ§ä»¶çš„æ”¯æŒã€‚
/////////////////////////////////////////////////////////////////////////////
其他标准文件:
StdAfx.h, StdAfx.cpp
    è¿™äº›æ–‡ä»¶ç”¨äºŽç”Ÿæˆåä¸º BEQDemo.pch çš„预编译头 (PCH) æ–‡ä»¶å’Œåä¸º StdAfx.obj çš„预编译类型文件。
Resource.h
    è¿™æ˜¯æ ‡å‡†å¤´æ–‡ä»¶ï¼Œå¯ç”¨äºŽå®šä¹‰æ–°çš„资源 ID。Microsoft Visual C++ å°†è¯»å–并更新此文件。
BEQDemo.manifest
    Windows XP ä½¿ç”¨åº”用程序清单文件来描述特定版本的并行程序集的应用程序依赖项。加载程序使用这些信息来从程序集缓存中加载相应的程序集,并保护其不被应用程序访问。应用程序清单可能会包含在内,以作为与应用程序可执行文件安装在同一文件夹中的外部 .manifest æ–‡ä»¶è¿›è¡Œé‡æ–°åˆ†å‘,它还可能以资源的形式包含在可执行文件中。
/////////////////////////////////////////////////////////////////////////////
其他注释:
应用程序向导使用“TODO:”来指示应添加或自定义的源代码部分。
如果应用程序使用共享 DLL ä¸­çš„ MFC,您将需要重新分发 MFC DLL。如果应用程序所使用的语言与操作系统的区域设置不同,则还需要重新分发相应的本地化资源 mfc110XXX.DLL。
有关上述话题的更多信息,请参见 MSDN æ–‡æ¡£ä¸­æœ‰å…³é‡æ–°åˆ†å‘ Visual C++ åº”用程序的部分。
/////////////////////////////////////////////////////////////////////////////
SourceCode/Bond/BEQDemo/res/BEQDemo.ico
SourceCode/Bond/BEQDemo/res/BEQDemo.rc2
Binary files differ
SourceCode/Bond/BEQDemo/res/application.exe.manifest
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity
         name="XP style manifest"
         processorArchitecture="amd64"
         version="1.0.0.0"
         type="win32"/>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity
                type="win32"
                name="Microsoft.Windows.Common-Controls"
                version="6.0.0.0"
                processorArchitecture="amd64"
                publicKeyToken="6595b64144ccf1df"
                language="*"
            />
        </dependentAssembly>
    </dependency>
</assembly>
SourceCode/Bond/BEQDemo/resource.h
Binary files differ
SourceCode/Bond/BEQDemo/stdafx.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
// stdafx.cpp : åªåŒ…括标准包含文件的源文件
// BEQDemo.pch å°†ä½œä¸ºé¢„编译头
// stdafx.obj å°†åŒ…含预编译类型信息
#include "stdafx.h"
SourceCode/Bond/BEQDemo/stdafx.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,54 @@
// stdafx.h : æ ‡å‡†ç³»ç»ŸåŒ…含文件的包含文件,
// æˆ–是经常使用但不常更改的
// ç‰¹å®šäºŽé¡¹ç›®çš„包含文件
#pragma once
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN            // ä»Ž Windows å¤´ä¸­æŽ’除极少使用的资料
#endif
#include "targetver.h"
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // æŸäº› CString æž„造函数将是显式的
// å…³é—­ MFC å¯¹æŸäº›å¸¸è§ä½†ç»å¸¸å¯æ”¾å¿ƒå¿½ç•¥çš„警告消息的隐藏
#define _AFX_ALL_WARNINGS
#include <afxwin.h>         // MFC æ ¸å¿ƒç»„件和标准组件
#include <afxext.h>         // MFC æ‰©å±•
#include <afxdisp.h>        // MFC è‡ªåŠ¨åŒ–ç±»
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxdtctl.h>           // MFC å¯¹ Internet Explorer 4 å…¬å…±æŽ§ä»¶çš„æ”¯æŒ
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>             // MFC å¯¹ Windows å…¬å…±æŽ§ä»¶çš„æ”¯æŒ
#endif // _AFX_NO_AFXCMN_SUPPORT
#include <afxcontrolbars.h>     // åŠŸèƒ½åŒºå’ŒæŽ§ä»¶æ¡çš„ MFC æ”¯æŒ
#include "..\BEQLibrarySDK\include\BEQLib.h"
#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif
SourceCode/Bond/BEQDemo/targetver.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
#pragma once
// åŒ…括 SDKDDKVer.h å°†å®šä¹‰å¯ç”¨çš„æœ€é«˜ç‰ˆæœ¬çš„ Windows å¹³å°ã€‚
// å¦‚果要为以前的 Windows å¹³å°ç”Ÿæˆåº”用程序,请包括 WinSDKVer.h,并将
// å°† _WIN32_WINNT å®è®¾ç½®ä¸ºè¦æ”¯æŒçš„平台,然后再包括 SDKDDKVer.h。
#include <SDKDDKVer.h>
SourceCode/Bond/BEQLibrary/AcceptClient.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
#include "stdafx.h"
#include "AcceptClient.h"
namespace BEQ {
    CAcceptClient::CAcceptClient()
    {
        m_listener.onRead = nullptr;
        m_listener.onClose = nullptr;
        m_pContext1 = nullptr;
        m_pContext2 = nullptr;
        m_pContext3 = nullptr;
        m_pContext4 = nullptr;
    }
    CAcceptClient::~CAcceptClient()
    {
    }
    void CAcceptClient::setListener(AcceptClientListener listener)
    {
        m_listener.onRead = listener.onRead;
        m_listener.onClose = listener.onClose;
    }
    void CAcceptClient::OnClose(int nErrorCode)
    {
        if (m_listener.onClose != nullptr) {
            m_listener.onClose(this);
        }
        __super::OnClose(nErrorCode);
    }
    void CAcceptClient::OnReceive(int nErrorCode)
    {
        char szBuffer[4096];
        int nRead = Receive(szBuffer, 4096);
        switch (nRead) {
        case 0:
            Close();
            break;
        case SOCKET_ERROR:
            if (GetLastError() != WSAEWOULDBLOCK) {
                Close();
            }
            break;
        default:
            if (m_listener.onRead != nullptr) {
                m_listener.onRead(this, szBuffer, nRead);
            }
        }
        __super::OnReceive(nErrorCode);
    }
}
SourceCode/Bond/BEQLibrary/AcceptClient.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
#pragma once
#include <afxSock.h>
#include <functional>
namespace BEQ {
    typedef std::function<int(void* pClient, const char* pData, int nLen)> ONREAD;
    typedef std::function<int(void* pClient)> ONCLOSE;
    typedef struct _AcceptClientListener
    {
        ONREAD            onRead;
        ONCLOSE            onClose;
    } AcceptClientListener;
    class CAcceptClient :
        public CAsyncSocket
    {
    public:
        CAcceptClient();
        ~CAcceptClient();
    public:
        void setListener(AcceptClientListener listener);
        virtual void OnClose(int nErrorCode);
        virtual void OnReceive(int nErrorCode);
    private:
        AcceptClientListener m_listener;
    public:
        void* m_pContext1;
        void* m_pContext2;
        void* m_pContext3;
        void* m_pContext4;
    };
}
SourceCode/Bond/BEQLibrary/Action.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,66 @@
#include "stdafx.h"
#include "Action.h"
namespace BEQ {
    static int g_nActionId = 0;
    CAction::CAction()
    {
        m_id = ++g_nActionId;
        m_nType = 0;
        m_nTime = 0;
        m_nValidLen = 0;
        m_nReplyCode = REPLY_NOERROR;
    }
    CAction::CAction(int type)
    {
        m_id = ++g_nActionId;
        m_nType = type;
        m_nTime = 0;
        m_nValidLen = 0;
        m_nReplyCode = REPLY_NOERROR;
    }
    CAction::~CAction()
    {
    }
    int CAction::getId()
    {
        return m_id;
    }
    int CAction::getType()
    {
        return m_nType;
    }
    int CAction::timeIncrease(int ms)
    {
        m_nTime += ms;
        return m_nTime;
    }
    void CAction::getRawData(char*& pRawData, int& size, int& validLen)
    {
        pRawData = m_szRawData;
        size = 1024;
        validLen = m_nValidLen;
    }
    int CAction::setRawString(const char* pszTxt)
    {
        int len = min(1023, strlen(pszTxt));
        memcpy(m_szRawData, pszTxt, len);
        m_szRawData[len] = '\0';
        m_nValidLen = len;
        return len;
    }
    void CAction::setReplyCode(int code)
    {
        m_nReplyCode = code;
    }
}
SourceCode/Bond/BEQLibrary/Action.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
#pragma once
#define REPLY_PACKET_NOT_END    1
#define REPLY_NOERROR            0
#define REPLY_MEMROY_ERROR        -1
#define REPLY_PACKET_ERROR        -2
namespace BEQ {
    class CAction
    {
    public:
        CAction();
        CAction(int type);
        ~CAction();
    public:
        int getId();
        int getType();
        int timeIncrease(int ms);
        int setRawString(const char* pszTxt);
        void getRawData(char*& pRawData, int& size, int& validLen);
        void setReplyCode(int code);
    private:
        int m_id;
        int m_nType;
        int m_nTime;
        char m_szRawData[1024];
        int m_nValidLen;
        int m_nReplyCode;
    };
}
SourceCode/Bond/BEQLibrary/BEQCommon.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
#pragma once
#define LERROR        4
#define LWARN        3
#define LINFO        2
#define LDEBUG        1
/* ERROR CODE*/
#define ERR_NOERR                    0        /* æ²¡æœ‰é”™è¯¯ */
#define ERR_MISMATCH                -1        /* æœºå™¨åä¸åŒ¹é… */
#define ERR_UNKNOWN_CMD                -2        /* æœªè¯†åˆ«çš„æŒ‡ä»¤ */
#define ERR_UNIT_ALREADY_EXIST        -3        /* å•元已存在 */
#define ERR_NO_UNIT                    -4        /* å•元不存在 */
#define ERR_PARAM_ERROE                -5        /* å‚数不正确 */
/* Command Request */
#define CMD_GET_EQID_REQ        _T("GET_EQID_REQ")
#define CMD_GET_VERSION_REQ        _T("GET_VERSION_REQ")
#define CMD_GET_STATE_REQ        _T("GET_STATE_REQ")
#define CMD_GET_DOOR_REQ        _T("GET_DOOR_REQ")
#define CMD_GET_ERROR_REQ        _T("GET_ERROR_REQ")
#define CMD_GET_STEP_REQ        _T("GET_STEP_REQ")
#define CMD_GET_DATA_REQ        _T("GET_DATA_REQ")
#define CMD_GET_RECIPE_LIST_REQ    _T("GET_RECIPE_LIST_REQ")
#define CMD_RUN_RECIPE_REQ        _T("RUN_RECIPE_REQ")
#define CMD_LOAD_READY_REQ        _T("LOAD_READY_REQ")
#define CMD_LOAD_COMPLETE_REQ    _T("LOAD_COMPLETE_REQ")
#define CMD_UNLOAD_COMPLETE_REQ    _T("UNLOAD_COMPLETE_REQ")
/* Command Reply*/
#define CMD_GET_EQID_REP        _T("GET_EQID_REP")
#define CMD_GET_VERSION_REP        _T("GET_VERSION_REP")
#define CMD_GET_STATE_REP        _T("GET_STATE_REP")
#define CMD_GET_DOOR_REP        _T("GET_DOOR_REP")
#define CMD_GET_ERROR_REP        _T("GET_ERROR_REP")
#define CMD_GET_STEP_REP        _T("GET_STEP_REP")
#define CMD_GET_DATA_REP        _T("GET_DATA_REP")
#define CMD_GET_RECIPE_LIST_REP    _T("GET_RECIPE_LIST_REP")
#define CMD_RUN_RECIPE_REP        _T("RUN_RECIPE_REP")
#define CMD_LOAD_READY_REP        _T("LOAD_READY_REP")
#define CMD_LOAD_COMPLETE_REP    _T("LOAD_COMPLETE_REP")
#define CMD_UNLOAD_COMPLETE_REP    _T("UNLOAD_COMPLETE_REP")
/* Auto send */
#define AS_MC_STATE_REP            _T("MC_STATE_REP")
#define AS_GET_DOOR_REP            _T("GET_DOOR_REP")
#define AS_SEND_ERROR_REP        _T("SEND_ERROR_REP")
#define AS_REMOVE_ERROR_REP        _T("REMOVE_ERROR_REP")
#define AS_MC_INFO_REP            _T("MC_INFO_REP")
#define AS_SEND_STEP_REP        _T("SEND_STEP_REP")
#define AS_SEND_EVENT_REP        _T("SEND_EVENT_REP")
/* Param */
#define PARAM_EQID                _T("EQID")
#define PARAM_VERSION            _T("VERSION")
#define PARAM_UNIT                _T("UNIT")
#define PARAM_STATE                _T("STATE")
#define PARAM_DOOR                _T("DOOR")
#define PARAM_CODE                _T("CODE")
#define PARAM_STEP                _T("STEP")
#define PARAM_PVTIME            _T("PVTIME")
#define PARAM_SVTIME            _T("SVTIME")
#define PARAM_MATERIAL_ID        _T("MATERIAL_ID")
#define PARAM_MATERIEL_ID        _T("MATERIEL_ID")
#define PARAM_RESULT            _T("RESULT")
#define PARAM_TEX                _T("TEX")
#define PARAM_TIME                _T("TIME")
#define PARAM_AIR                _T("AIR")
#define PARAM_PRE                _T("PRE")
#define PARAM_TMP                _T("TMP")
#define PARAM_RECIPE_LIST        _T("RECIPE_LIST")
#define PARAM_RECIPEID            _T("RECIPEID")
#define PARAM_RECIPENAME        _T("RECIPENAME")
#define PARAM_EVENT                _T("EVENT")
/* EVENT */
#define EVENT_LOAD                _T("LOAD")
#define EVENT_UNLOAD            _T("UNLOAD")
SourceCode/Bond/BEQLibrary/BEQLib.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
#pragma once
#include <vector>
#include "IServo.h"
#include "IUnit.h"
#include "IEquipment.h"
#include "IRemoteEquipment.h"
#ifdef _COMPILE_AS_LIB
    #warning "compiling as lib!"
#else
    #ifdef _DEBUG
        #ifndef _WIN64
            #pragma comment(lib, "../BEQibrarySDK/lib/Win32/Debug/BEQ.lib")
        #else
            #pragma comment(lib, "../BEQLibrarySDK/lib/x64/Debug/BEQ.lib")
        #endif
    #else
        #ifndef _WIN64
            #pragma comment(lib, "../BEQLibrarySDK/lib/Win32/Release/BEQ.lib")
        #else
            #pragma comment(lib, "../BEQLibrarySDK/lib/x64/Release/BEQ.lib")
        #endif
    #endif
#endif // !BUILD_AS_LIB
///////////////////////////////////////////////////////////////////////////////////
//// Define C linkage if using a C++ compiler
///////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
    ///////////////////////////////////////////////////////////////////////////////////
    //// Determine callling convention baesd on compiler
    ///////////////////////////////////////////////////////////////////////////////////
#ifdef __BORLANDC__
#ifdef __WIN32__
#define EXPORTED __declspec(dllexport) __stdcall
#else
#define EXPORTED FAR PASCAL __export
#endif // WIN32
#else // __BORLANDC__
#ifdef WIN32
#define EXPORTED __declspec(dllexport)
#else
#define EXPORTED FAR PASCAL __export
#endif // WIN32
#endif //__BORLANDC__
    /////////////////////////////////////////////////////////////////////////////////////
    //// å¯¼å‡ºå‡½æ•°
    ////////////////////////////////////////////////////////////////////////////////////
    int            EXPORTED    BEQ_Initialize();
    int            EXPORTED    BEQ_Term();
    int            EXPORTED    BEQ_CreateServo(BEQ::IServo*& pServo, const char* pszName);
    int            EXPORTED    BEQ_GetServo(BEQ::IServo*& pServo, const char* pszName);
    int            EXPORTED    BEQ_DestroyServo(BEQ::IServo* pServo);
    int            EXPORTED    BEQ_CreateEquipment(BEQ::IEquipment*& pEquipment, const char* pszName);
    int            EXPORTED    BEQ_GetEquipment(BEQ::IEquipment*& pEquipment, const char* pszName);
    int            EXPORTED    BEQ_DestroyEquipment(BEQ::IEquipment*& pEquipment);
#ifdef __cplusplus
};
#endif //__cplusplus
SourceCode/Bond/BEQLibrary/BEQLibrary.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
// BEQLibrary.cpp : å®šä¹‰ DLL çš„初始化例程。
//
#include "stdafx.h"
#include "BEQLibrary.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//
//TODO:  å¦‚果此 DLL ç›¸å¯¹äºŽ MFC DLL æ˜¯åŠ¨æ€é“¾æŽ¥çš„ï¼Œ
//        åˆ™ä»Žæ­¤ DLL å¯¼å‡ºçš„任何调入
//        MFC çš„函数必须将 AFX_MANAGE_STATE å®æ·»åŠ åˆ°
//        è¯¥å‡½æ•°çš„æœ€å‰é¢ã€‚
//
//        ä¾‹å¦‚:
//
//        extern "C" BOOL PASCAL EXPORT ExportedFunction()
//        {
//            AFX_MANAGE_STATE(AfxGetStaticModuleState());
//            // æ­¤å¤„为普通函数体
//        }
//
//        æ­¤å®å…ˆäºŽä»»ä½• MFC è°ƒç”¨
//        å‡ºçŽ°åœ¨æ¯ä¸ªå‡½æ•°ä¸­ååˆ†é‡è¦ã€‚  è¿™æ„å‘³ç€
//        å®ƒå¿…须作为函数中的第一个语句
//        å‡ºçŽ°ï¼Œç”šè‡³å…ˆäºŽæ‰€æœ‰å¯¹è±¡å˜é‡å£°æ˜Žï¼Œ
//        è¿™æ˜¯å› ä¸ºå®ƒä»¬çš„æž„造函数可能生成 MFC
//        DLL è°ƒç”¨ã€‚
//
//        æœ‰å…³å…¶ä»–详细信息,
//        è¯·å‚阅 MFC æŠ€æœ¯è¯´æ˜Ž 33 å’Œ 58。
//
// CBEQLibraryApp
BEGIN_MESSAGE_MAP(CBEQLibraryApp, CWinApp)
END_MESSAGE_MAP()
// CBEQLibraryApp æž„造
CBEQLibraryApp::CBEQLibraryApp()
{
    // TODO:  åœ¨æ­¤å¤„添加构造代码,
    // å°†æ‰€æœ‰é‡è¦çš„初始化放置在 InitInstance ä¸­
}
// å”¯ä¸€çš„一个 CBEQLibraryApp å¯¹è±¡
CBEQLibraryApp theApp;
// CBEQLibraryApp åˆå§‹åŒ–
BOOL CBEQLibraryApp::InitInstance()
{
    CWinApp::InitInstance();
    return TRUE;
}
SourceCode/Bond/BEQLibrary/BEQLibrary.def
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
; BEQLibrary.def : å£°æ˜Ž DLL çš„æ¨¡å—参数。
LIBRARY
EXPORTS
    ; æ­¤å¤„可以是显式导出
SourceCode/Bond/BEQLibrary/BEQLibrary.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
// BEQLibrary.h : BEQLibrary DLL çš„主头文件
//
#pragma once
#ifndef __AFXWIN_H__
    #error "在包含此文件之前包含“stdafx.h”以生成 PCH æ–‡ä»¶"
#endif
#include "resource.h"        // ä¸»ç¬¦å·
// CBEQLibraryApp
// æœ‰å…³æ­¤ç±»å®žçŽ°çš„ä¿¡æ¯ï¼Œè¯·å‚é˜… BEQLibrary.cpp
//
class CBEQLibraryApp : public CWinApp
{
public:
    CBEQLibraryApp();
// é‡å†™
public:
    virtual BOOL InitInstance();
    DECLARE_MESSAGE_MAP()
};
SourceCode/Bond/BEQLibrary/BEQLibrary.rc
Binary files differ
SourceCode/Bond/BEQLibrary/BEQLibrary.vcxproj
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,265 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{8421CE64-06F9-48F4-A3F3-ACFB683C94D4}</ProjectGuid>
    <RootNamespace>BEQLibrary</RootNamespace>
    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
    <Keyword>MFCDLLProj</Keyword>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>MultiByte</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>MultiByte</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="Shared">
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <LinkIncremental>true</LinkIncremental>
    <TargetName>BEQ</TargetName>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <LinkIncremental>false</LinkIncremental>
    <TargetName>BEQ</TargetName>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ModuleDefinitionFile>.\BEQLibrary.def</ModuleDefinitionFile>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>_WINDOWS;_DEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ModuleDefinitionFile>.\BEQLibrary.def</ModuleDefinitionFile>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
    <PostBuildEvent>
      <Command>copy "$(SolutionDir)$(ProjectName)\IEquipment.h" "$(SolutionDir)BEQLibrarySDK\Include\IEquipment.h"
copy "$(SolutionDir)$(ProjectName)\IRemoteEquipment.h" "$(SolutionDir)BEQLibrarySDK\Include\IRemoteEquipment.h"
copy "$(SolutionDir)$(ProjectName)\IUnit.h" "$(SolutionDir)BEQLibrarySDK\Include\IUnit.h"
copy "$(SolutionDir)$(ProjectName)\IServo.h" "$(SolutionDir)BEQLibrarySDK\Include\IServo.h"
copy "$(SolutionDir)$(ProjectName)\BEQLib.h" "$(SolutionDir)BEQLibrarySDK\Include\BEQLib.h"
copy "$(SolutionDir)$(Platform)\$(Configuration)\BEQ.dll" "$(SolutionDir)BEQLibrarySDK\lib\$(Platform)\$(Configuration)\BEQ.dll"
copy "$(SolutionDir)$(Platform)\$(Configuration)\BEQ.lib" "$(SolutionDir)BEQLibrarySDK\lib\$(Platform)\$(Configuration)\BEQ.lib"
copy "$(SolutionDir)$(Platform)\$(Configuration)\BEQ.pdb" "$(SolutionDir)BEQLibrarySDK\lib\$(Platform)\$(Configuration)\BEQ.pdb_"
</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <ModuleDefinitionFile>.\BEQLibrary.def</ModuleDefinitionFile>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>_WINDOWS;NDEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <ModuleDefinitionFile>.\BEQLibrary.def</ModuleDefinitionFile>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
    <PostBuildEvent>
      <Command>copy "$(SolutionDir)$(ProjectName)\IEquipment.h" "$(SolutionDir)BEQLibrarySDK\Include\IEquipment.h"
copy "$(SolutionDir)$(ProjectName)\IRemoteEquipment.h" "$(SolutionDir)BEQLibrarySDK\Include\IRemoteEquipment.h"
copy "$(SolutionDir)$(ProjectName)\IUnit.h" "$(SolutionDir)BEQLibrarySDK\Include\IUnit.h"
copy "$(SolutionDir)$(ProjectName)\IServo.h" "$(SolutionDir)BEQLibrarySDK\Include\IServo.h"
copy "$(SolutionDir)$(ProjectName)\BEQLib.h" "$(SolutionDir)BEQLibrarySDK\Include\BEQLib.h"
copy "$(SolutionDir)$(Platform)\$(Configuration)\BEQ.dll" "$(SolutionDir)BEQLibrarySDK\lib\$(Platform)\$(Configuration)\BEQ.dll"
copy "$(SolutionDir)$(Platform)\$(Configuration)\BEQ.lib" "$(SolutionDir)BEQLibrarySDK\lib\$(Platform)\$(Configuration)\BEQ.lib"
copy "$(SolutionDir)$(Platform)\$(Configuration)\BEQ.pdb" "$(SolutionDir)BEQLibrarySDK\lib\$(Platform)\$(Configuration)\BEQ.pdb_"
</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="AcceptClient.cpp" />
    <ClCompile Include="Action.cpp" />
    <ClCompile Include="BEQLibrary.cpp" />
    <ClCompile Include="BEQMain.cpp" />
    <ClCompile Include="Data.cpp" />
    <ClCompile Include="Equipment.cpp" />
    <ClCompile Include="RemoteEquipment.cpp" />
    <ClCompile Include="Servo.cpp" />
    <ClCompile Include="SocketClient.cpp" />
    <ClCompile Include="SocketServer.cpp" />
    <ClCompile Include="stdafx.cpp">
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
    </ClCompile>
    <ClCompile Include="Unit.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AcceptClient.h" />
    <ClInclude Include="Action.h" />
    <ClInclude Include="BEQCommon.h" />
    <ClInclude Include="BEQLib.h" />
    <ClInclude Include="BEQLibrary.h" />
    <ClInclude Include="Data.h" />
    <ClInclude Include="Equipment.h" />
    <ClInclude Include="IEquipment.h" />
    <ClInclude Include="IRemoteEquipment.h" />
    <ClInclude Include="IServo.h" />
    <ClInclude Include="IUnit.h" />
    <ClInclude Include="RemoteEquipment.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="Servo.h" />
    <ClInclude Include="SocketClient.h" />
    <ClInclude Include="SocketServer.h" />
    <ClInclude Include="stdafx.h" />
    <ClInclude Include="targetver.h" />
    <ClInclude Include="Unit.h" />
  </ItemGroup>
  <ItemGroup>
    <None Include="BEQLibrary.def" />
    <None Include="res\BEQLibrary.rc2" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="BEQLibrary.rc" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>
SourceCode/Bond/BEQLibrary/BEQLibrary.vcxproj.filters
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="源文件">
      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
    </Filter>
    <Filter Include="头文件">
      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
    </Filter>
    <Filter Include="资源文件">
      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="BEQLibrary.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="stdafx.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="BEQMain.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Servo.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="SocketClient.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="SocketServer.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="AcceptClient.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Equipment.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Data.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Unit.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="RemoteEquipment.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Action.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="stdafx.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="targetver.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Resource.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="IServo.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Servo.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="SocketClient.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="SocketServer.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="AcceptClient.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Equipment.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="IEquipment.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Data.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Unit.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="IUnit.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="BEQLibrary.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="BEQLib.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="BEQCommon.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="RemoteEquipment.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="IRemoteEquipment.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Action.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <None Include="BEQLibrary.def">
      <Filter>源文件</Filter>
    </None>
    <None Include="res\BEQLibrary.rc2">
      <Filter>资源文件</Filter>
    </None>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="BEQLibrary.rc">
      <Filter>资源文件</Filter>
    </ResourceCompile>
  </ItemGroup>
</Project>
SourceCode/Bond/BEQLibrary/BEQLibrary.vcxproj.user
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup />
</Project>
SourceCode/Bond/BEQLibrary/BEQMain.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,216 @@
// BEQMain.cpp : å®šä¹‰ DLL çš„初始化例程。
//
#include "stdafx.h"
#include "BEQCommon.h"
#include "Servo.h"
#include "Equipment.h"
#include <map>
#include <string>
CString            g_strLogDir;                // æ—¥å¿—目录
CStdioFile        g_logFile;                    // æ—¥å¿—文件
int                g_nActionTimeout = 5000;    // è¶…æ—¶æ—¶é—´
std::map<std::string, BEQ::CServo*>        g_mapServos;        // Servo映身表
std::map<std::string, BEQ::CEquipment*>    g_mapEquipments;    // Equipment映身表
CString& GetCurTime(CString& strTime)
{
    _SYSTEMTIME sysTime;
    GetLocalTime(&sysTime);
    strTime.Format(_T("%d/%02d/%02d %02d:%02d:%02d.%03d"), sysTime.wYear, sysTime.wMonth, sysTime.wDay,
        sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds);
    return strTime;
}
void log(int level, const char* pszMessage)
{
    if (g_logFile.m_hFile != CFile::hFileNull) {
        CTime time = CTime::GetCurrentTime();
        CString strTime, strText;
        strText.Format(_T("%s > %s\n"), GetCurTime(strTime), pszMessage);
        g_logFile.WriteString(strText);
        // æ–‡ä»¶è¶…过50M,重新创建
        if (g_logFile.GetLength() > 50 * 1024 * 1024) {
            g_logFile.Close();
            CString strFilepath;
            strFilepath.Format(_T("%s\\%d_%02d_%02d_%02d_%02d_%02d.log"), g_strLogDir,
                time.GetYear(), time.GetMonth(), time.GetDay(), time.GetHour(), time.GetMinute(), time.GetSecond());
            if (g_logFile.Open(strFilepath, CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::shareDenyWrite)) {
                g_logFile.SeekToEnd();
            }
        }
    }
}
//
// åˆå§‹åŒ–网络
//
extern "C" __declspec(dllexport)
int BEQ_Initialize()
{
    // åˆå§‹åŒ–网络
    WSADATA wsaData;
    WORD version = MAKEWORD(2, 2);
    int ret = WSAStartup(version, &wsaData);
    if (ret != 0) {
        log(LERROR, "初始化网络失败。");
        return -1;
    }
    log(LDEBUG, "初始化网络成功 ã€‚");
    // æœ¬ç¨‹åºæ–‡ä»¶ç›®å½•
    TCHAR sDrive[_MAX_DRIVE];
    TCHAR sDir[_MAX_DIR];
    TCHAR sFilename[_MAX_FNAME], sAppFilename[_MAX_FNAME];
    TCHAR sExt[_MAX_EXT];
    GetModuleFileName((HMODULE)&__ImageBase, sAppFilename, _MAX_FNAME);
    _tsplitpath_s(sAppFilename, sDrive, sDir, sFilename, sExt);
    g_strLogDir = CString(sDrive) + CString(sDir) + CString("\\BEQLog");
    ::CreateDirectory(g_strLogDir, NULL);
    CTime time = CTime::GetCurrentTime();
    CString strFilepath;
    strFilepath.Format(_T("%s\\%d_%02d_%02d_%02d_%02d_%02d.log"), g_strLogDir,
        time.GetYear(), time.GetMonth(), time.GetDay(), time.GetHour(), time.GetMinute(), time.GetSecond());
    if (!g_logFile.Open(strFilepath, CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::shareDenyWrite)) {
        return -2;
    }
    g_logFile.SeekToEnd();
    log(0, "BEQ_Initialize å®Œæˆ.");
    return 0;
}
//
// ç»ˆæ­¢å¹¶æ¸…理
//
extern "C" __declspec(dllexport)
int BEQ_Term()
{
    // å…³é—­å’Œé‡Šæ”¾æ‰€æœ‰Servo, Equipment
    for (auto itor : g_mapServos) {
        BEQ::CServo *pServo = (BEQ::CServo *)itor.second;
        pServo->close();
        delete pServo;
    }
    g_mapServos.clear();
    for (auto itor : g_mapEquipments) {
        BEQ::CEquipment *pEquipment = (BEQ::CEquipment *)itor.second;
        delete pEquipment;
    }
    g_mapEquipments.clear();
    // å…¶å®ƒæ¸…理工作
    WSACleanup();
    log(LDEBUG, "BEQ_Initialize.");
    if (g_logFile.m_hFile != CFile::hFileNull) {
        g_logFile.Close();
    }
    return 0;
}
extern "C" __declspec(dllexport)
int BEQ_CreateServo(BEQ::IServo*& pServo, const char* pszName)
{
    // æ£€æŸ¥æ˜¯å¦å·²ç»å­˜åœ¨
    auto iter = g_mapServos.find(pszName);
    if (iter != g_mapServos.end()) {
        return -1;
    }
    // ä¸å­˜åœ¨åˆ™åˆ›å»ºæ–°çš„
    BEQ::CServo* pTemp = new BEQ::CServo(pszName);
    pServo = pTemp;
    g_mapServos[pszName] = pTemp;
    return 0;
}
extern "C" __declspec(dllexport)
int BEQ_GetServo(BEQ::IServo*& pServo, const char* pszName)
{
    // æ£€æŸ¥æ˜¯å¦å·²ç»å­˜åœ¨
    auto iter = g_mapServos.find(pszName);
    if (iter == g_mapServos.end()) {
        return -1;
    }
    pServo = (BEQ::IServo*)iter->second;
    return 0;
}
extern "C" __declspec(dllexport)
int BEQ_DestroyServo(BEQ::IServo* pServo)
{
    // æ£€æŸ¥æ˜¯å¦å­˜åœ¨
    BOOL bFound = FALSE;
    for (auto iter = g_mapServos.begin(); iter != g_mapServos.end(); iter++) {
        if (iter->second == pServo) {
            delete iter->second;
            g_mapServos.erase(iter);
            bFound = TRUE;
            break;
        }
    }
    return bFound ? 0 : -1;
}
extern "C" __declspec(dllexport)
int BEQ_CreateEquipment(BEQ::IEquipment*& pEquipment, const char* pszName)
{
    // æ£€æŸ¥æ˜¯å¦å·²ç»å­˜åœ¨
    auto iter = g_mapEquipments.find(pszName);
    if (iter != g_mapEquipments.end()) {
        return -1;
    }
    // ä¸å­˜åœ¨åˆ™åˆ›å»ºæ–°çš„
    BEQ::CEquipment* pTemp = new BEQ::CEquipment(pszName);
    pEquipment = pTemp;
    g_mapEquipments[pszName] = pTemp;
    return 0;
}
extern "C" __declspec(dllexport)
int BEQ_GetEquipment(BEQ::IEquipment*& pEquipment, const char* pszName)
{
    // æ£€æŸ¥æ˜¯å¦å·²ç»å­˜åœ¨
    auto iter = g_mapEquipments.find(pszName);
    if (iter == g_mapEquipments.end()) {
        return -1;
    }
    pEquipment = (BEQ::IEquipment*)iter->second;
    return 0;
}
extern "C" __declspec(dllexport)
int BEQ_DestroyEquipment(BEQ::IEquipment*& pEquipment)
{
    // æ£€æŸ¥æ˜¯å¦å­˜åœ¨
    BOOL bFound = FALSE;
    for (auto iter = g_mapEquipments.begin(); iter != g_mapEquipments.end(); iter++) {
        if (iter->second == pEquipment) {
            delete iter->second;
            g_mapEquipments.erase(iter);
            bFound = TRUE;
            break;
        }
    }
    return bFound ? 0 : -1;
}
SourceCode/Bond/BEQLibrary/Data.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
#include "stdafx.h"
#include "Data.h"
namespace BEQ {
    CData::CData()
    {
        m_pBuffer = nullptr;
        m_nBufferSize = 0;
        m_nDataLen = 0;
    }
    CData::CData(int nInitSize)
    {
        m_pBuffer = new char[nInitSize];
        m_nBufferSize = nInitSize;
        m_nDataLen = 0;
    }
    CData::~CData()
    {
        if (m_pBuffer != nullptr) {
            delete[] m_pBuffer;
        }
    }
    void CData::init(int nInitSize)
    {
        m_pBuffer = new char[nInitSize];
        m_nBufferSize = nInitSize;
        m_nDataLen = 0;
    }
    int CData::append(const char* pData, int len)
    {
        if (m_nDataLen + len > m_nBufferSize) {
            return -1;
        }
        memcpy(&m_pBuffer[m_nDataLen], pData, len);
        m_nDataLen += len;
        return (int)m_nDataLen;
    }
    void CData::clear()
    {
        m_nDataLen = 0;
    }
}
SourceCode/Bond/BEQLibrary/Data.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
#pragma once
namespace BEQ {
    class CData
    {
    public:
        CData();
        CData(int nInitSize);
        ~CData();
    public:
        void init(int nInitSize);
        int append(const char* pData, int len);
        void clear();
    public:
        char* m_pBuffer;
        size_t m_nBufferSize;
        size_t m_nDataLen;
    };
}
SourceCode/Bond/BEQLibrary/Equipment.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,935 @@
#include "stdafx.h"
#include "Equipment.h"
#include "Data.h"
#include "BEQCommon.h"
#define DATA_INIT_LEN        1024 * 8
namespace BEQ {
    CEquipment::CEquipment()
    {
        m_pClientListener = nullptr;
        m_strVersion = _T("1.0.1");
        m_pActiveClient = nullptr;
        m_listener.onConnected = nullptr;
        m_listener.onDisconnected = nullptr;
        m_listener.onRunRecipe = nullptr;
        m_listener.onGetRecipeList = nullptr;
        m_listener.onLoadReady = nullptr;
        m_listener.onLoadComplete = nullptr;
        m_listener.onUnloadComplete = nullptr;
        m_pReqRecipeListClient = nullptr;
        m_pReqRecipeListUnit = nullptr;
    }
    CEquipment::CEquipment(const char* pszName)
    {
        m_strName = pszName;
        m_strVersion = _T("1.0.1");
        m_pClientListener = nullptr;
        m_pActiveClient = nullptr;
        m_listener.onConnected = nullptr;
        m_listener.onDisconnected = nullptr;
        m_listener.onRunRecipe = nullptr;
        m_listener.onGetRecipeList = nullptr;
        m_listener.onLoadReady = nullptr;
        m_listener.onLoadComplete = nullptr;
        m_listener.onUnloadComplete = nullptr;
        m_pReqRecipeListClient = nullptr;
        m_pReqRecipeListUnit = nullptr;
    }
    CEquipment::~CEquipment()
    {
        for (auto iter = m_recycleClients.begin(); iter != m_recycleClients.end(); iter++) {
            delete (CData*)((*iter)->m_pContext1);
            delete *iter;
        }
        m_recycleClients.clear();
        for (auto iter = m_clients.begin(); iter != m_clients.end(); iter++) {
            delete (CData*)((*iter)->m_pContext1);
            delete *iter;
        }
        for (auto iter = m_units.begin(); iter != m_units.end(); iter++) {
            delete iter->second;
        }
        m_units.clear();
        if (m_pClientListener != nullptr) {
            delete m_pClientListener;
            m_pClientListener = nullptr;
        }
        if (m_pServer != nullptr) {
            m_pServer->Close();
            delete m_pServer;
            m_pServer = nullptr;
        }
    }
    void CEquipment::setEquipmentListener(EquipmentListener listener)
    {
        m_listener.onConnected = listener.onConnected;
        m_listener.onDisconnected = listener.onDisconnected;
        m_listener.onRunRecipe = listener.onRunRecipe;
        m_listener.onGetRecipeList = listener.onGetRecipeList;
        m_listener.onLoadReady = listener.onLoadReady;
        m_listener.onLoadComplete = listener.onLoadComplete;
        m_listener.onUnloadComplete = listener.onUnloadComplete;
    }
    int CEquipment::getName(char* pszBuffer, int nMaxCount)
    {
        return strcpy_s(pszBuffer, nMaxCount, m_strName.c_str());
    }
    void CEquipment::setName(const char* pszName)
    {
        m_strName = pszName;
    }
    int CEquipment::getVersion(char* pszBuffer, int nMaxCount)
    {
        return strcpy_s(pszBuffer, nMaxCount, m_strName.c_str());
    }
    void CEquipment::setVersion(const char* pszVersion)
    {
        m_strVersion = pszVersion;
    }
    IUnit* CEquipment::addUnit(const char* pszName, int nDoorCount)
    {
        auto iter = m_units.find(pszName);
        if (iter != m_units.end()) {
            return (IUnit*)iter->second;
        }
        CUnit* pUnit = new CUnit(pszName);
        m_units[pszName] = pUnit;
        pUnit->setDoorCount(nDoorCount);
        UnitListener listener;
        listener.onStateChanged = [&](void* pUnit, EQ_STATE nStete) -> void {
            if (m_pActiveClient != nullptr) {
                repState(m_pActiveClient, (CUnit*)pUnit, AS_MC_STATE_REP);
            }
        };
        listener.onDoorStateChanged = [&](void* pUnit, int stete) -> void {
            if (m_pActiveClient != nullptr) {
                repDoorState(m_pActiveClient, (CUnit*)pUnit, AS_GET_DOOR_REP);
            }
        };
        listener.onAlarm = [&](void* pUnit, int code, int level, const char* pszText) -> void {
            if (m_pActiveClient != nullptr) {
                repAlarm(m_pActiveClient, (CUnit*)pUnit, AS_SEND_ERROR_REP);
            }
        };
        listener.onRemoveAlarm = [&](void* pUnit, int code, int level, const char* pszText) -> void {
            if (m_pActiveClient != nullptr) {
                repAlarm(m_pActiveClient, (CUnit*)pUnit, AS_REMOVE_ERROR_REP);
            }
        };
        listener.onStepChanged = [&](void* pUnit, STEP_STATE) -> void {
            if (m_pActiveClient != nullptr) {
                repStep(m_pActiveClient, (CUnit*)pUnit, AS_SEND_STEP_REP);
            }
        };
        listener.onDataChanged = [&](void* pUnit, unsigned long long time) -> void {
            if (m_pActiveClient != nullptr) {
                repData(m_pActiveClient, (CUnit*)pUnit, AS_MC_INFO_REP);
            }
        };
        listener.onReqLoad = [&](void* pUnit, int layer) -> void {
            if (m_pActiveClient != nullptr) {
                repLoad(m_pActiveClient, (CUnit*)pUnit, layer, AS_SEND_EVENT_REP);
            }
        };
        listener.onReqUnload = [&](void* pUnit, int layer) -> void {
            if (m_pActiveClient != nullptr) {
                repUnload(m_pActiveClient, (CUnit*)pUnit, layer, AS_SEND_EVENT_REP);
            }
        };
        pUnit->setListener(listener);
        return (IUnit*)pUnit;
    }
    IUnit* CEquipment::getUnit(const char* pszName)
    {
        auto iter = m_units.find(pszName);
        if (iter != m_units.end()) {
            return (IUnit*)iter->second;
        }
        return nullptr;
    }
    int CEquipment::runOnClientMode(const char* pAddr, int port)
    {
        return 0;
    }
    int CEquipment::runOnServerMode(int port)
    {
        m_pClientListener = new AcceptClientListener;
        m_pClientListener->onClose = [&](void* pClient) -> int {
            if (m_listener.onDisconnected != nullptr) {
                CAcceptClient* p = (CAcceptClient*)pClient;
                CString strIp;
                UINT port;
                m_pActiveClient->GetPeerName(strIp, port);
                m_listener.onDisconnected(this, (LPTSTR)(LPCTSTR)strIp, port);
            }
            removeClient((CAcceptClient*)pClient);
            m_pActiveClient = nullptr;
            return 0;
        };
        m_pClientListener->onRead = [&](void* pClient, const char* pData, int len) -> int {
            return decode((CAcceptClient*)pClient, pData, len);
        };
        ServerListener listener;
        listener.onAccept = [&](void* pServer, CAcceptClient* pClient) -> int {
            addClient(pClient);
            m_pActiveClient = pClient;
            for (auto item : m_units) {
                item.second->resetLoadState();
            }
            if (m_listener.onConnected != nullptr) {
                CString strIp;
                UINT port;
                m_pActiveClient->GetPeerName(strIp, port);
                m_listener.onConnected(this, (LPTSTR)(LPCTSTR)strIp, port);
            }
            return 0;
        };
        listener.onClose = [&](void* pServer) -> int {
            return 0;
        };
        m_pServer = new CSocketServer(port, listener);
        m_pServer->init();
        return 0;
    }
    void CEquipment::addClient(CAcceptClient* pClient)
    {
        pClient->m_pContext1 = new CData(DATA_INIT_LEN);
        m_clients.push_back(pClient);
        pClient->setListener(*m_pClientListener);
    }
    void CEquipment::removeClient(CAcceptClient* pClient)
    {
        for (auto iter = m_clients.begin(); iter != m_clients.end(); iter++) {
            if (*iter == pClient) {
                m_recycleClients.push_back(*iter);
                m_clients.erase(iter);
                break;
            }
        }
    }
    int CEquipment::decode(CAcceptClient* pClient, const char* pData, int len)
    {
        // å¢žåŠ æ•°æ®åˆ°å°¾éƒ¨
        BEQ::CData* pClsData = (BEQ::CData*) (pClient->m_pContext1);
        if (-1 == pClsData->append(pData, len)) {
            return -1;
        }
        // åœ¨æœªæ‰¾åˆ°@符之前,所有的字母必须是 'A' ~ 'Z' æˆ– '_'
        int nCmdEnd = -1;
        BOOL bInvalid = false;
        for (int i = 0; i < pClsData->m_nDataLen; i++) {
            if ((char)'@' == pClsData->m_pBuffer[i]) {
                nCmdEnd = i;
                break;
            }
            if ( !(((char)'A' <= pClsData->m_pBuffer[i] && pClsData->m_pBuffer[i] <= (char)'Z')
                || (char)'_' == pClsData->m_pBuffer[i]) ) {
                bInvalid = true;
                break;
            }
        }
        if (bInvalid) {
            pClsData->clear();
            return -1;
        }
        if (nCmdEnd <= 0) {
            return -2;
        }
        // æŸ¥æ‰¾ç»ˆæ­¢ç¬¦
        int nPacketEnd = -1;
        bInvalid = false;
        for (int i = nCmdEnd; i < pClsData->m_nDataLen; i++) {
            if ((char)'#' == pClsData->m_pBuffer[i]) {
                nPacketEnd = i;
                break;
            }
            if ( !((char)32 <= pClsData->m_pBuffer[i] && pClsData->m_pBuffer[i] <= (char)127) ) {
                bInvalid = true;
                break;
            }
        }
        if (bInvalid) {
            pClsData->clear();
            return -3;
        }
        if (nPacketEnd <= nCmdEnd) {
            return -4;
        }
        // å¾—到命令,消息体
        // æ¶ˆæ¯ä½“分解为参数列表
        CString strCmd = CString(pClsData->m_pBuffer, nCmdEnd);
        CString strBody = CString(&pClsData->m_pBuffer[nCmdEnd+1], nPacketEnd - nCmdEnd - 1);
        int iParam = 0;
        CString strParam;
        std::map<std::string, std::string> params;
        do {
            if (!AfxExtractSubString(strParam, (LPCTSTR)strBody, iParam, '/')) break;
            int n = strParam.Find("=");
            if (n > 0) {
                std::string strName = (LPTSTR)(LPCTSTR)strParam.Left(n);
                std::string strValue = (LPTSTR)(LPCTSTR)strParam.Right(strParam.GetLength() - n - 1);
                params[strName] = strValue;
            }
            iParam++;
        } while (true);
        // å¤„理消息后复位
        int nRet = executeCommand(pClient, strCmd, params);
        pClsData->clear();
        return nRet;
    }
    int CEquipment::executeCommand(CAcceptClient* pClient, CString& strCmd, std::map<std::string, std::string>& params)
    {
        // èŽ·å–æœºå™¨å
        CString strResponse;
        if (strCmd.Compare(CMD_GET_EQID_REQ) == 0) {
            makeResponse(CMD_GET_EQID_REP, PARAM_EQID, m_strName.c_str(), strResponse);
            pClient->Send((LPTSTR)(LPCTSTR)strResponse, strResponse.GetLength());
            return ERR_NOERR;
        }
        // ä»¥ä¸‹å‘½ä»¤éœ€è¦éªŒè¯æœºå™¨ID,不一致不回复
        auto iter = params.find(PARAM_EQID);
        if (iter == params.end()) return -101;
        if (iter->second.compare(m_strName) != 0) {
            return ERR_MISMATCH;
        }
        // èŽ·å–ç¨‹åºç‰ˆæœ¬
        if (strCmd.Compare(CMD_GET_VERSION_REQ) == 0) {
            makeResponseEx(CMD_GET_VERSION_REP, PARAM_VERSION, m_strVersion.c_str(), strResponse);
            pClient->Send((LPTSTR)(LPCTSTR)strResponse, strResponse.GetLength());
            return ERR_NOERR;
        }
        // å–出参数中的单元,默认为0
        CUnit* pUnit = nullptr;
        std::string strUnit = "1";
        auto iterUnit = params.find("UNIT");
        if (iterUnit != params.end()) {
            strUnit = iterUnit->second;
        }
        // èŽ·å–æœºå™¨çŠ¶æ€
        if (strCmd.Compare(CMD_GET_STATE_REQ) == 0) {
            pUnit = checkUnitAndReply(strUnit, pClient, CMD_GET_STATE_REP);
            if (pUnit == nullptr) {
                return ERR_NO_UNIT;
            }
            repState(m_pActiveClient, (CUnit*)pUnit, CMD_GET_STATE_REP);
            return ERR_NOERR;
        }
        // èŽ·å–å®‰å…¨é—¨çŠ¶æ€
        if (strCmd.Compare(CMD_GET_DOOR_REQ) == 0) {
            pUnit = checkUnitAndReply(strUnit, pClient, CMD_GET_DOOR_REP);
            if (pUnit == nullptr) {
                return ERR_NO_UNIT;
            }
            repDoorState(pClient, pUnit, CMD_GET_DOOR_REP);
            return ERR_NOERR;
        }
        // èŽ·å–å½“å‰å‘Šè­¦ä¿¡æ¯
        if (strCmd.Compare(CMD_GET_ERROR_REQ) == 0) {
            pUnit = checkUnitAndReply(strUnit, pClient, CMD_GET_ERROR_REP);
            if (pUnit == nullptr) {
                return ERR_NO_UNIT;
            }
            repAlarm(pClient, pUnit, CMD_GET_ERROR_REP);
            return ERR_NOERR;
        }
        // èŽ·å–å½“å‰åˆ¶ç¨‹
        if (strCmd.Compare(CMD_GET_STEP_REQ) == 0) {
            pUnit = checkUnitAndReply(strUnit, pClient, CMD_GET_STEP_REP);
            if (pUnit == nullptr) {
                return ERR_NO_UNIT;
            }
            repStep(pClient, pUnit, CMD_GET_STEP_REP);
            return ERR_NOERR;
        }
        // èŽ·å–æ•°æ®
        if (strCmd.Compare(CMD_GET_DATA_REQ) == 0) {
            pUnit = checkUnitAndReply(strUnit, pClient, CMD_GET_DATA_REP);
            if (pUnit == nullptr) {
                return ERR_NO_UNIT;
            }
            repData(pClient, pUnit, CMD_GET_DATA_REP);
            return ERR_NOERR;
        }
        // èŽ·å–é…æ–¹åˆ—è¡¨
        if (strCmd.Compare(CMD_GET_RECIPE_LIST_REQ) == 0) {
            pUnit = checkUnitAndReply(strUnit, pClient, CMD_GET_RECIPE_LIST_REP);
            if (pUnit == nullptr) {
                return ERR_NO_UNIT;
            }
            repRecipeList(pClient, pUnit, CMD_GET_RECIPE_LIST_REP);
            return ERR_NOERR;
        }
        // æ‰§è¡Œé…æ–¹
        if (strCmd.Compare(CMD_RUN_RECIPE_REQ) == 0) {
            pUnit = checkUnitAndReply(strUnit, pClient, CMD_RUN_RECIPE_REP);
            if (pUnit == nullptr) {
                return ERR_NO_UNIT;
            }
            auto iterId = params.find(PARAM_RECIPEID);
            auto iterName = params.find(PARAM_RECIPENAME);
            if (iterId == params.end() || iterName == params.end()) {
                makeFailResponse(CMD_RUN_RECIPE_REP, strUnit.c_str(),
                    "缺少参数", strResponse);
                pClient->Send((LPTSTR)(LPCTSTR)strResponse, strResponse.GetLength());
                return ERR_PARAM_ERROE;
            }
            repRunRecipe(pClient, pUnit, atoi(iterId->second.c_str()),
                iterName->second.c_str(), CMD_RUN_RECIPE_REP);
            return ERR_NOERR;
        }
        // ä¸Šæ–™å°±ç»ª
        if (strCmd.Compare(CMD_LOAD_READY_REQ) == 0) {
            int layer = 1;
            pUnit = checkUnitAndReplyEx(strUnit, layer, pClient, CMD_LOAD_READY_REP);
            if (pUnit == nullptr) {
                return ERR_NO_UNIT;
            }
            auto iterMeterialId = params.find(PARAM_MATERIAL_ID);
            if (iterMeterialId == params.end()) {
                iterMeterialId = params.find(PARAM_MATERIEL_ID);
            }
            if (iterMeterialId == params.end()) {
                makeFailResponse(CMD_LOAD_READY_REP, strUnit.c_str(),
                    "缺少参数\"MATERIAL_ID\"", strResponse);
                pClient->Send((LPTSTR)(LPCTSTR)strResponse, strResponse.GetLength());
                return ERR_PARAM_ERROE;
            }
            auto iterRecipeId = params.find(PARAM_RECIPEID);
            if (iterRecipeId == params.end()) {
                makeFailResponse(CMD_LOAD_READY_REP, strUnit.c_str(),
                    "缺少参数\"RECIPEID\"", strResponse);
                pClient->Send((LPTSTR)(LPCTSTR)strResponse, strResponse.GetLength());
                return ERR_PARAM_ERROE;
            }
            repLoadReady(pClient, pUnit, strUnit.c_str(), iterMeterialId->second.c_str(),
                iterRecipeId->second.c_str(), CMD_LOAD_READY_REP);
            return ERR_NOERR;
        }
        // ä¸Šæ–™å®Œæˆ
        if (strCmd.Compare(CMD_LOAD_COMPLETE_REQ) == 0) {
            int layer = 1;
            pUnit = checkUnitAndReplyEx(strUnit, layer, pClient, CMD_LOAD_COMPLETE_REP);
            if (pUnit == nullptr) {
                return ERR_NO_UNIT;
            }
            repLoadComplete(pClient, pUnit, strUnit.c_str(), layer, CMD_LOAD_COMPLETE_REP);
            return ERR_NOERR;
        }
        // ä¸‹æ–™å®Œæˆ
        if (strCmd.Compare(CMD_UNLOAD_COMPLETE_REQ) == 0) {
            int layer = 1;
            pUnit = checkUnitAndReplyEx(strUnit, layer, pClient, CMD_UNLOAD_COMPLETE_REP);
            if (pUnit == nullptr) {
                return ERR_NO_UNIT;
            }
            repUnloadComplete(pClient, pUnit, strUnit.c_str(), layer, CMD_UNLOAD_COMPLETE_REP);
            return ERR_NOERR;
        }
        return ERR_UNKNOWN_CMD;
    }
    const char* CEquipment::getReply(const char* pszReply)
    {
        if (strcmp(pszReply, CMD_GET_EQID_REQ) == 0) {
            return CMD_GET_EQID_REP;
        }
        if (strcmp(pszReply, CMD_GET_VERSION_REQ) == 0) {
            return CMD_GET_VERSION_REP;
        }
        if (strcmp(pszReply, CMD_GET_STATE_REQ) == 0) {
            return CMD_GET_STATE_REP;
        }
        return "";
    }
    CUnit* CEquipment::checkUnitAndReply(std::string& strUnit, CAcceptClient* pClient, const char* pszReply)
    {
        auto iter = m_units.find(strUnit);
        if (iter != m_units.end()) return iter->second;
        CString strResponse;
        makeFailResponse(pszReply, strUnit.c_str(),
            "单元不存在", strResponse);
        pClient->Send((LPTSTR)(LPCTSTR)strResponse, strResponse.GetLength());
        return nullptr;
    }
    CUnit* CEquipment::checkUnitAndReplyEx(std::string& strUnit, int& layer, CAcceptClient* pClient, const char* pszReply)
    {
        // æŸ¥æ‰¾åˆ°æ•°å­—,取出层
        std::string strUnit2, strLayer;
        BOOL bLeft = TRUE;
        for (int i = 0; i < strUnit.length(); i++) {
            char c = strUnit.at(i);
            if (0x30 <= c && c <= 0x39) {
                bLeft = FALSE;
            }
            if (bLeft) strUnit2.push_back(c);
            else strLayer.push_back(c);
        }
        layer = strLayer.empty() ? 1 : atoi(strLayer.c_str());
        auto iter = m_units.find(strUnit2);
        if (iter != m_units.end()) return iter->second;
        CString strResponse;
        makeFailResponse(pszReply, strUnit.c_str(),
            "单元不存在", strResponse);
        pClient->Send((LPTSTR)(LPCTSTR)strResponse, strResponse.GetLength());
        return nullptr;
    }
    void CEquipment::makeResponse(const char* pszReply, const char* pszParam, const char* pValue, CString& strResponse)
    {
        strResponse.Format(_T("%s@%s=%s#"), pszReply, pszParam, pValue);
    }
    void CEquipment::makeResponseEx(const char* pszReply, const char* pszParam, const char* pValue, CString& strResponse)
    {
        strResponse.Format(_T("%s@%s=%s/%s=%s#"), pszReply, PARAM_EQID, m_strName.c_str(), pszParam, pValue);
    }
    void CEquipment::makeResponseEx(const char* pszReply, const char* pszUnit, const char* pszParam, const char* pValue, CString& strResponse)
    {
        strResponse.Format(_T("%s@%s=%s/%s=%s/%s=%s#"), pszReply, PARAM_EQID, m_strName.c_str(),
            PARAM_UNIT, pszUnit, pszParam, pValue);
    }
    void CEquipment::makeFailResponse(const char* pszReply, const char* pszUnit, const char* pszText, CString& strResponse)
    {
        strResponse.Format(_T("%s@%s=%s/%s=%s/RESULT=FAIL/TEXT=%s#"), pszReply, PARAM_EQID, m_strName.c_str(),
            PARAM_UNIT, pszUnit, pszText);
    }
    void CEquipment::repState(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        CString strReply;
        strReply.Format(_T("%s@%s=%s/%s=%s/%s=%s#"), pszReply, PARAM_EQID, m_strName.c_str(),
            PARAM_UNIT, pUnit->getName().c_str(),
            PARAM_STATE, pUnit->getStateText());
        pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
    }
    void CEquipment::repDoorState(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        std::string strDoorState;
        CString strReply;
        strReply.Format(_T("%s@%s=%s/%s=%s/%s=%s#"), pszReply, PARAM_EQID, m_strName.c_str(),
            PARAM_UNIT, pUnit->getName().c_str(),
            PARAM_DOOR, pUnit->getDoorState(strDoorState).c_str());
        pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
    }
    void CEquipment::repAlarm(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        CString strReply;
        int code = pUnit->getAlarmCode();
        if (code == 0) {
            strReply.Format(_T("%s@%s=%s/%s=%s/%s=%d#"), pszReply, PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str(),
                PARAM_CODE, pUnit->getAlarmCode());
        }
        else {
            strReply.Format(_T("%s@%s=%s/%s=%s/%s=%d,%d,%s#"), pszReply, PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str(),
                PARAM_CODE, pUnit->getAlarmCode(), pUnit->getAlarmLevel(), pUnit->getAlarmText().c_str());
        }
        pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
    }
    void CEquipment::repStep(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        CString strReply;
        STEP_STATE stepState = pUnit->getStepState();
        if (stepState == STEP_STATE::IDLE) {
            // idle只有状态
            strReply.Format(_T("%s@%s=%s/%s=%s/%s=%s#"), pszReply,
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str(),
                PARAM_STEP, pUnit->getStepStateText());
        }
        else if (stepState == STEP_STATE::PROCESSING) {
            // step, id, svtime, pvtime
            strReply.Format(_T("%s@%s=%s/%s=%s/%s=%s/%s=%s/SVTIME=%d/PVTIME=%d#"), pszReply,
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str(),
                PARAM_STEP, pUnit->getStepStateText(),
                PARAM_MATERIAL_ID, pUnit->getStepMaterialId().c_str(),
                pUnit->getStepSvTime(), pUnit->getSetpPvTime());
        }
        else {
            // step, id
            strReply.Format(_T("%s@%s=%s/%s=%s/%s=%s/%s=%s#"), pszReply,
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str(),
                PARAM_STEP, pUnit->getStepStateText(),
                PARAM_MATERIAL_ID, pUnit->getStepMaterialId().c_str());
        }
        pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
    }
    void CEquipment::repData(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        CString strReply;
        unsigned long long time = pUnit->getDataTime();
        if (time == 0) {
            // æ²¡æœ‰æ•°æ®
            strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=FAIL/TEX=NO DATA#"), pszReply,
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str());
        }
        else {
            strReply.Format(_T("%s@%s=%s/%s=%s/%s=%s"), pszReply,
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str(),
                PARAM_TIME, timeToString(pUnit->getDataTime()).c_str());
            std::map<std::string, std::string>& datas = pUnit->getDatas();
            for (auto& item : datas) {
                strReply.AppendFormat("/%s=%s", item.first.c_str(),
                    item.second.c_str());
            }
            strReply.Append("#");
        }
        pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
    }
    void CEquipment::repRecipeList(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        CString strReply;
        if (m_listener.onGetRecipeList != nullptr) {
            int nRet = m_listener.onGetRecipeList(this, pUnit);
            if (nRet == 1) {
                // ä¿å­˜æ•°æ®ï¼Œç­‰å¾…上层完成
                m_pReqRecipeListClient = pClient;
                m_pReqRecipeListUnit = pUnit;
                m_strReqRecipeListReply = pszReply;
            }
            else {
                std::map<int, std::string>& recipes = pUnit->getRecipes();
                if (recipes.empty()) {
                    // æ²¡æœ‰é…æ–¹
                    strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=FAIL/TEX=NO RECIPE#"), pszReply,
                        PARAM_EQID, m_strName.c_str(),
                        PARAM_UNIT, pUnit->getName().c_str());
                }
                else {
                    strReply.Format(_T("%s@%s=%s/%s=%s/RECIPE_LIST="), pszReply,
                        PARAM_EQID, m_strName.c_str(),
                        PARAM_UNIT, pUnit->getName().c_str());
                    for (auto& item : recipes) {
                        strReply.AppendFormat("%d,%s,", item.first, item.second.c_str());
                    }
                    strReply.SetAt(strReply.GetLength() - 1, '#');
                }
                pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
            }
        }
    }
    int CEquipment::repRecipeListComplete()
    {
        if (m_pReqRecipeListClient == nullptr) return -1;
        if (m_pReqRecipeListUnit == nullptr) return -1;
        CString strReply;
        std::map<int, std::string>& recipes = m_pReqRecipeListUnit->getRecipes();
        if (recipes.empty()) {
            // æ²¡æœ‰é…æ–¹
            strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=FAIL/TEX=NO RECIPE#"), m_strReqRecipeListReply.c_str(),
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, m_pReqRecipeListUnit->getName().c_str());
        }
        else {
            strReply.Format(_T("%s@%s=%s/%s=%s/RECIPE_LIST="), m_strReqRecipeListReply.c_str(),
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, m_pReqRecipeListUnit->getName().c_str());
            for (auto& item : recipes) {
                strReply.AppendFormat("%d,%s,", item.first, item.second.c_str());
            }
            strReply.SetAt(strReply.GetLength() - 1, '#');
        }
        m_pReqRecipeListClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
        return 0;
    }
    void CEquipment::repRunRecipe(CAcceptClient* pClient, CUnit* pUnit, int id, const char* pszName, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        CString strReply;
        if (!pUnit->checkRecipe(id, pszName)) {
            // æ²¡æœ‰é…æ–¹
            strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=FAIL/TEX=RECIPE'S ID AND NAME DO NOT MATCH#"), pszReply,
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str());
        }
        else {
            // æ¨¡æ‹Ÿåˆ‡æ¢é…æ–¹
            if (m_listener.onRunRecipe != nullptr) {
                int ret = m_listener.onRunRecipe(this, pUnit, id);
                if (ret >= 0) {
                    strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=PASS#"), pszReply,
                        PARAM_EQID, m_strName.c_str(),
                        PARAM_UNIT, pUnit->getName().c_str());
                }
                else {
                    strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=FAIL/TEX=ERROR%d#"), pszReply,
                        PARAM_EQID, m_strName.c_str(),
                        PARAM_UNIT, pUnit->getName().c_str(), ret);
                }
            }
        }
        pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
    }
    void CEquipment::repLoadReady(CAcceptClient* pClient, CUnit* pUnit, const char* pszUnitName, const char* pszMaterielId, const char* pszRecipeId, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        CString strReply;
        if (m_listener.onRunRecipe != nullptr) {
            int ret = m_listener.onLoadReady(this, pUnit, pszMaterielId, pszRecipeId);
            if (ret == 1) {
                // ä¿å­˜æ•°æ®ï¼Œç­‰å¾…上层完成
                m_pRunRecipeClient = pClient;
                m_pRunRecipeUnit = pUnit;
                m_strRunRecipeReply = pszReply;
            }
            else if (ret >= 0) {
                strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=PASS#"), pszReply,
                    PARAM_EQID, m_strName.c_str(),
                    PARAM_UNIT, pszUnitName);
            }
            else {
                strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=FAIL/TEX=ERROR%d#"), pszReply,
                    PARAM_EQID, m_strName.c_str(),
                    PARAM_UNIT, pszUnitName, ret);
            }
        }
        pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
    }
    int CEquipment::repLoadReadyComplete(int errorCode)
    {
        if (m_pRunRecipeClient == nullptr) return -1;
        if (m_pRunRecipeUnit == nullptr) return -1;
        CString strReply;
        if (errorCode == 0) {
            strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=PASS#"), m_strRunRecipeReply.c_str(),
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, m_pRunRecipeUnit->getName().c_str());
        }
        else {
            strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=FAIL/TEX=ERROR%d#"), m_strRunRecipeReply.c_str(),
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, m_pRunRecipeUnit->getName().c_str(), errorCode);
        }
        m_pRunRecipeClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
        return 0;
    }
    void CEquipment::repLoad(CAcceptClient* pClient, CUnit* pUnit, int layer, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        CString strReply;
        if (pUnit->getLayerCount() == 1) {
            strReply.Format(_T("%s@%s=%s/%s=%s/%s=%s#"), pszReply,
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str(),
                PARAM_EVENT, EVENT_LOAD);
        }
        else {
            strReply.Format(_T("%s@%s=%s/%s=%s%d/%s=%s#"), pszReply,
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str(), layer,
                PARAM_EVENT, EVENT_LOAD);
        }
        pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
    }
    void CEquipment::repUnload(CAcceptClient* pClient, CUnit* pUnit, int layer, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        CString strReply;
        if (pUnit->getLayerCount() == 1) {
            strReply.Format(_T("%s@%s=%s/%s=%s/%s=%s#"), pszReply,
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str(),
                PARAM_EVENT, EVENT_UNLOAD);
        }
        else {
            strReply.Format(_T("%s@%s=%s/%s=%s%d/%s=%s#"), pszReply,
                PARAM_EQID, m_strName.c_str(),
                PARAM_UNIT, pUnit->getName().c_str(), layer,
                PARAM_EVENT, EVENT_UNLOAD);
        }
        pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
    }
    void CEquipment::repLoadComplete(CAcceptClient* pClient, CUnit* pUnit, const char* pszUnitName, int layer, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        CString strReply;
        if (m_listener.onLoadComplete != nullptr) {
            int ret = m_listener.onLoadComplete(this, pUnit, layer);
            if (ret >= 0) {
                strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=PASS#"), pszReply,
                    PARAM_EQID, m_strName.c_str(),
                    PARAM_UNIT, pszUnitName);
            }
            else {
                strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=FAIL/TEX=ERROR%d#"), pszReply,
                    PARAM_EQID, m_strName.c_str(),
                    PARAM_UNIT, pszUnitName, ret);
            }
        }
        pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
    }
    void CEquipment::repUnloadComplete(CAcceptClient* pClient, CUnit* pUnit, const char* pszUnitName, int layer, const char* pszReply)
    {
        ASSERT(pClient != nullptr);
        CString strReply;
        if (m_listener.onUnloadComplete != nullptr) {
            int ret = m_listener.onUnloadComplete(this, pUnit, layer);
            if (ret >= 0) {
                strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=PASS#"), pszReply,
                    PARAM_EQID, m_strName.c_str(),
                    PARAM_UNIT, pszUnitName);
            }
            else {
                strReply.Format(_T("%s@%s=%s/%s=%s/RESULT=FAIL/TEX=ERROR%d#"), pszReply,
                    PARAM_EQID, m_strName.c_str(),
                    PARAM_UNIT, pszUnitName, ret);
            }
        }
        pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
    }
    std::string CEquipment::timeToString(ULONGLONG time)
    {
        ULONGLONG time1;
        time1 = time / 1000;
        char buffer[256];
        struct tm timeinfo;
        time_t t = time_t(time1);
        localtime_s(&timeinfo, &t);
        strftime(buffer, 128, "%Y-%m-%d %H:%M:%S", &timeinfo);
        return std::string(buffer);
    }
}
SourceCode/Bond/BEQLibrary/Equipment.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,82 @@
#pragma once
#include "IEquipment.h"
#include <string>
#include "SocketServer.h"
#include <list>
#include <map>
#include "Unit.h"
namespace BEQ {
    class CEquipment :
        public IEquipment
    {
    public:
        CEquipment();
        CEquipment::CEquipment(const char* pszName);
        ~CEquipment();
    public:
        virtual void setEquipmentListener(EquipmentListener listener);
        virtual int getName(char* pszBuffer, int nMaxCount);
        virtual void setName(const char* pszName);
        virtual int getVersion(char* pszBuffer, int nMaxCount);
        virtual void setVersion(const char* pszVersion);
        virtual IUnit* addUnit(const char* pszName, int nDoorCount);
        virtual IUnit* getUnit(const char* pszName);
        virtual int runOnClientMode(const char* pAddr, int port);
        virtual int runOnServerMode(int port);
        virtual int repRecipeListComplete();
        virtual int repLoadReadyComplete(int errorCode);
    private:
        void addClient(CAcceptClient* pClient);
        void removeClient(CAcceptClient* pClient);
        int decode(CAcceptClient* pClient, const char* pData, int len);
        int executeCommand(CAcceptClient* pClient, CString& strCmd, std::map<std::string, std::string>& params);
        const char* getReply(const char* pszReply);
        CUnit* checkUnitAndReply(std::string& strUnit, CAcceptClient* pClient, const char* pszReply);
        CUnit* checkUnitAndReplyEx(std::string& strUnit, int& layer, CAcceptClient* pClient, const char* pszReply);
        void makeResponse(const char* pszReply, const char* pszParam, const char* pValue, CString& strResponse);
        void makeResponseEx(const char* pszReply, const char* pszParam, const char* pValue, CString& strResponse);
        void makeResponseEx(const char* pszReply, const char* pszUnit, const char* pszParam, const char* pValue, CString& strResponse);
        void makeFailResponse(const char* pszReply, const char* pszUnit, const char* pszText, CString& strResponse);
        void repState(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply);
        void repDoorState(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply);
        void repAlarm(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply);
        void repStep(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply);
        void repData(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply);
        void repRecipeList(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply);
        void repRunRecipe(CAcceptClient* pClient, CUnit* pUnit, int id, const char* pszName, const char* pszReply);
        void repLoadReady(CAcceptClient* pClient, CUnit* pUnit, const char* pszUnitName, const char* pszMaterielId, const char* pszRecipeId, const char* pszReply);
        void repLoad(CAcceptClient* pClient, CUnit* pUnit, int layer, const char* pszReply);
        void repUnload(CAcceptClient* pClient, CUnit* pUnit, int layer, const char* pszReply);
        void repLoadComplete(CAcceptClient* pClient, CUnit* pUnit, const char* pszUnitName, int layer, const char* pszReply);
        void repUnloadComplete(CAcceptClient* pClient, CUnit* pUnit, const char* pszUnitName, int layer, const char* pszReply);
    private:
        std::string timeToString(ULONGLONG time);
    private:
        std::string m_strName;
        std::string m_strVersion;
        CSocketServer* m_pServer;
        AcceptClientListener* m_pClientListener;
        std::list<CAcceptClient*> m_clients;
        std::list<CAcceptClient*> m_recycleClients;
        CAcceptClient* m_pActiveClient;
    private:
        std::map<std::string, BEQ::CUnit*> m_units;
        EquipmentListener m_listener;
    private:
        CAcceptClient* m_pReqRecipeListClient;
        CUnit* m_pReqRecipeListUnit;
        std::string m_strReqRecipeListReply;
        CAcceptClient* m_pRunRecipeClient;
        CUnit* m_pRunRecipeUnit;
        std::string m_strRunRecipeReply;
    };
}
SourceCode/Bond/BEQLibrary/IEquipment.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
#pragma once
#include "IUnit.h"
#include <functional>
namespace BEQ {
    typedef std::function<void(void* pEiuipment, const char* pszAddr, int port)> ONCONNECTED;
    typedef std::function<void(void* pEiuipment, const char* pszAddr, int port)> ONDISCONNECTED;
    typedef std::function<int(void* pEiuipment, void* pUnit, int id)> ONRUNRECIPE;
    typedef std::function<int(void* pEiuipment, void* pUnit)> ONGETRECIPELIST;
    typedef std::function<int(void* pEiuipment, void* pUnit, const char* pszMaterielId, const char* pszRecipeId)> ONLOADREADY;
    typedef std::function<int(void* pEiuipment, void* pUnit, int layer)> ONLOADCOMPLETE;
    typedef struct _EquipmentListener
    {
        ONCONNECTED            onConnected;
        ONDISCONNECTED        onDisconnected;
        ONRUNRECIPE            onRunRecipe;
        ONGETRECIPELIST        onGetRecipeList;
        ONLOADREADY            onLoadReady;
        ONLOADCOMPLETE        onLoadComplete;
        ONLOADCOMPLETE        onUnloadComplete;
    } EquipmentListener;
    class IEquipment
    {
    public:
        virtual void setEquipmentListener(EquipmentListener listener) = 0;
        virtual int getName(char* pszBuffer, int nMaxCount) = 0;
        virtual void setName(const char* pszName) = 0;
        virtual int getVersion(char* pszBuffer, int nMaxCount) = 0;
        virtual void setVersion(const char* pszVersion) = 0;
        virtual IUnit* addUnit(const char* pszName, int nDoorCount) = 0;
        virtual IUnit* getUnit(const char* pszName) = 0;
        virtual int runOnClientMode(const char* pAddr, int port) = 0;
        virtual int runOnServerMode(int port) = 0;
        virtual int repRecipeListComplete() = 0;
        virtual int repLoadReadyComplete(int errorCode) = 0;
    };
}
SourceCode/Bond/BEQLibrary/IRemoteEquipment.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
#pragma once
#include "IUnit.h"
#include <functional>
namespace BEQ {
    enum class REMOTE_EQ_EVENT
    {
        UNKNOWN = 0,
        DEVICE_STATUS_CHANGED,
        DOOR_STATUS_CHANGED,
        ALARM_INFO_CHANGED,
        REMOVE_ALARM_INFO,
        PRODUCTION_PROCESS_CHANGED,
        SERSOR_DATA_CHANGED,
        RECIPE_LIST_CHANGED,
        LOAD_EVENT_CHANGED
    };
    class IRemoteEquipment
    {
    public:
        virtual int getAddr(char* pszBuffer, int nMaxCount) = 0;
        virtual int getPort() = 0;
        virtual int getName(char* pszBuffer, int nMaxCount) = 0;
        virtual int getVersion(char* pszBuffer, int nMaxCount) = 0;
        virtual bool isConnected() = 0;
        virtual int connect() = 0;
        virtual IUnit* addUnit(const char* pszName, int nDoorCount) = 0;
        virtual IUnit* getUnit(const char* pszName) = 0;
        virtual const char** getAllUnitNames() = 0;
        virtual int getUnitCount() const = 0;
        virtual ULONGLONG getConnectTick() = 0;
    };
}
SourceCode/Bond/BEQLibrary/IServo.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
#pragma once
#include "IRemoteEquipment.h"
namespace BEQ {
    typedef std::function<void(void* pServo, void* pRemoteEiuipment)> ONREQCONNECTED;
    typedef std::function<void(void* pServo, void* pRemoteEiuipment, int errorCode)> ONREQCONNECTFAILED;
    typedef std::function<void(void* pServo, void* pRemoteEiuipment, const char* pszData, int len)> ONREQREAD;
    typedef std::function<void(void* pServo, void* pRemoteEquipment, void* pUnit, REMOTE_EQ_EVENT eventCode)> ONREQEVENTUPDATE;
    typedef struct _ServoListener
    {
        ONREQCONNECTED        onRemoteEqConnecting;
        ONREQCONNECTED        onRemoteEqConnected;
        ONREQCONNECTFAILED    onRemoteEqConnectFailed;
        ONREQCONNECTED        onRemoteEqDisconnecting;
        ONREQCONNECTED        onRemoteEqDisconnected;
        ONREQREAD            onRemoteEqReadRawdata;
        ONREQEVENTUPDATE    onRemoteEqEventUpdate;
    } ServoListener;
    class IServo
    {
    public:
        virtual void setListener(BEQ::ServoListener listener) = 0;
        virtual int getName(char* pszBuffer, int nMaxCount) = 0;
        virtual int createRemoteEquipment(IRemoteEquipment*& pRemoteEquipment, const char* pszAddr, int port) = 0;
        virtual int connectRemoteEquipment(IRemoteEquipment* pRemoteEquipment) = 0;
    };
}
SourceCode/Bond/BEQLibrary/IUnit.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
#pragma once
namespace BEQ {
    enum class EQ_STATE
    {
        IDLE = 0,
        RUN,
        DOWN,
        MAINTENANCE,
        MCHG,
        E_TIME
    };
    enum class STEP_STATE
    {
        IDLE = 0,
        MATERIAL_RECEIVED,
        MATERIAL_REMOVEED,
        PROCESSING_STARTED,
        PROCESSING,
        PROCESSING_COMPLETED
    };
    class IUnit
    {
    public:
        virtual int getName(char* pszBuffer, int nMaxCount) = 0;
        virtual void setState(EQ_STATE state) = 0;
        virtual EQ_STATE getState() = 0;
        virtual void setDoorCount(int count) = 0;
        virtual void setDoorState(int state) = 0;
        virtual int  getDoorState() = 0;
        virtual void setLayerCount(int count) = 0;
        virtual int getLayerCount() = 0;
        virtual void setIndex(int index) = 0;
        virtual int getIndex() = 0;
        virtual void setAlarm(int code, int level, const char* pszText) = 0;
        virtual int getAlarmCode() = 0;
        virtual int getAlarmLevel() = 0;
        virtual void stepIdle() = 0;
        virtual void stepMaterialReceived(const char* pszID) = 0;
        virtual void stepMaterialRemoved(const char* pszID) = 0;
        virtual void stepProcessingStarted(const char* pszID) = 0;
        virtual void stepProcessing(const char* pszID, int nSvTime, int nTvTime) = 0;
        virtual void stepProcessingCompleted(const char* pszID) = 0;
        virtual STEP_STATE getStepState() = 0;
        virtual void setDataTime(unsigned long long time) = 0;
        virtual void setDataTimeAndResetData(unsigned long long time) = 0;
        virtual unsigned long long getDataTime() = 0;
        virtual void addData(const char* pszName, const char* pszDataText, bool bComplete) = 0;
        virtual void addRecipe(int id, const char* pszName, bool bComplete) = 0;
        virtual int reqLoad(int layer) = 0;
        virtual int reqUnload(int layer) = 0;
    };
}
SourceCode/Bond/BEQLibrary/ReadMe.txt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
========================================================================
    MICROSOFT åŸºç¡€ç±»åº“ : BEQLibrary é¡¹ç›®æ¦‚è¿°
========================================================================
应用程序向导已为您创建了此 BEQLibrary DLL。此 DLL ä¸ä»…演示 Microsoft åŸºç¡€ç±»çš„基本使用方法,还可作为您编写 DLL çš„起点。
本文件概要介绍组成 BEQLibrary DLL çš„æ¯ä¸ªæ–‡ä»¶çš„内容。
BEQLibrary.vcxproj
    è¿™æ˜¯ä½¿ç”¨åº”用程序向导生成的 VC++ é¡¹ç›®çš„主项目文件,其中包含生成该文件的 Visual C++ çš„版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
BEQLibrary.vcxproj.filters
    è¿™æ˜¯ä½¿ç”¨â€œåº”用程序向导”生成的 VC++ é¡¹ç›®ç­›é€‰å™¨æ–‡ä»¶ã€‚它包含有关项目文件与筛选器之间的关联信息。在 IDE ä¸­ï¼Œé€šè¿‡è¿™ç§å…³è”,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
BEQLibrary.h
    è¿™æ˜¯ DLL çš„主头文件。它声明了 CBEQLibraryApp ç±»ã€‚
BEQLibrary.cpp
    è¿™æ˜¯ä¸» DLL æºæ–‡ä»¶ã€‚它包含 CBEQLibraryApp ç±»ã€‚
BEQLibrary.rc
    è¿™æ˜¯ç¨‹åºä½¿ç”¨çš„æ‰€æœ‰ Microsoft Windows èµ„源的列表。它包括 RES å­ç›®å½•中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ ä¸­è¿›è¡Œç¼–辑。
res\BEQLibrary.rc2
    æ­¤æ–‡ä»¶åŒ…含不在 Microsoft Visual C++ ä¸­è¿›è¡Œç¼–辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。
BEQLibrary.def
    æ­¤æ–‡ä»¶åŒ…含在 Microsoft Windows ä¸­è¿è¡Œæ‰€å¿…需的 DLL çš„æœ‰å…³ä¿¡æ¯ã€‚它定义了 DLL çš„名称和说明等参数,而且还从 DLL å¯¼å‡ºå‡½æ•°ã€‚
/////////////////////////////////////////////////////////////////////////////
其他标准文件:
StdAfx.h, StdAfx.cpp
    è¿™äº›æ–‡ä»¶ç”¨äºŽç”Ÿæˆåä¸º BEQLibrary.pch çš„预编译头 (PCH) æ–‡ä»¶å’Œåä¸º StdAfx.obj çš„预编译类型文件。
Resource.h
    è¿™æ˜¯æ ‡å‡†å¤´æ–‡ä»¶ï¼Œå¯ç”¨äºŽå®šä¹‰æ–°çš„资源 ID。Microsoft Visual C++ å°†è¯»å–并更新此文件。
/////////////////////////////////////////////////////////////////////////////
其他注释:
应用程序向导使用“TODO:”来指示应添加或自定义的源代码部分。
/////////////////////////////////////////////////////////////////////////////
SourceCode/Bond/BEQLibrary/RemoteEquipment.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1061 @@
#include "stdafx.h"
#include "RemoteEquipment.h"
#include <Ws2tcpip.h>
#include <map>
#include <vector>
#include <string>
#include <unordered_map>
#include "BEQCommon.h"
/* è¶…æ—¶æ—¶é—´ */
extern int g_nActionTimeout;
namespace BEQ {
/* socket ç¼“冲区大小 */
#define BUFFER_SIZE            1024
    CRemoteEquipment::CRemoteEquipment()
    {
        m_nPort = 0;
        m_nLocalPort = 0;
        m_listener.onConnected = nullptr;
        m_listener.onConnectFailed = nullptr;
        m_listener.onDisconnecting = nullptr;
        m_listener.onDisconnected = nullptr;
        m_listener.onRead = nullptr;
        m_listener.onEventUpdate = nullptr;
        m_hSocket = NULL;
        m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTED;
        m_bWorking = FALSE;
        m_hWSAEvent = nullptr;
        m_hEventClose = nullptr;
        m_hEventWrite = nullptr;
        m_hEventActions = nullptr;
        m_hEventActionsThreadExit = nullptr;
        m_hEventTimeoutCheckThreadExit = nullptr;
        m_pCurrentAction = nullptr;
        m_data.init(1024);
        ::InitializeCriticalSection(&m_cs);
    }
    CRemoteEquipment::CRemoteEquipment(const char* pszAddr, int port)
    {
        m_nPort = 0;
        m_nLocalPort = 0;
        m_listener.onConnecting = nullptr;
        m_listener.onConnected = nullptr;
        m_listener.onConnectFailed = nullptr;
        m_listener.onDisconnecting = nullptr;
        m_listener.onDisconnected = nullptr;
        m_listener.onRead = nullptr;
        m_listener.onEventUpdate = nullptr;
        m_strAddr = pszAddr;
        m_nPort = port;
        m_hSocket = NULL;
        m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTED;
        m_bWorking = FALSE;
        m_hWSAEvent = nullptr;
        m_hEventClose = nullptr;
        m_hEventWrite = nullptr;
        m_hEventActions = nullptr;
        m_hEventActionsThreadExit = nullptr;
        m_hEventTimeoutCheckThreadExit = nullptr;
        m_pCurrentAction = nullptr;
        m_data.init(1024);
        ::InitializeCriticalSection(&m_cs);
        m_ullConnectTick = 0;
    }
    CRemoteEquipment::~CRemoteEquipment()
    {
        close();
        for (auto iter = m_units.begin(); iter != m_units.end(); iter++) {
            delete iter->second;
        }
        m_units.clear();
        ::DeleteCriticalSection(&m_cs);
    }
    void CRemoteEquipment::setRemoteEquipmentListener(RemoteEquipmentListener listener)
    {
        m_listener.onConnecting = listener.onConnecting;
        m_listener.onConnected = listener.onConnected;
        m_listener.onConnectFailed = listener.onConnectFailed;
        m_listener.onDisconnecting = listener.onDisconnecting;
        m_listener.onDisconnected = listener.onDisconnected;
        m_listener.onRead = listener.onRead;
        m_listener.onEventUpdate = listener.onEventUpdate;
    }
    int CRemoteEquipment::getAddr(char* pszBuffer, int nMaxCount)
    {
        return strcpy_s(pszBuffer, nMaxCount, m_strAddr.c_str());
    }
    int CRemoteEquipment::getPort()
    {
        return m_nPort;
    }
    int CRemoteEquipment::getName(char* pszBuffer, int nMaxCount)
    {
        if (!m_strName.empty()) {
            return strcpy_s(pszBuffer, nMaxCount, m_strName.c_str());
        }
        else {
            return sprintf_s(pszBuffer, nMaxCount, "%s:%d", m_strAddr.c_str(), m_nPort);
        }
    }
    int CRemoteEquipment::getVersion(char* pszBuffer, int nMaxCount)
    {
        return strcpy_s(pszBuffer, nMaxCount, m_strVersion.c_str());
    }
    bool CRemoteEquipment::isConnected()
    {
        return m_hSocket != NULL && m_remoteEqNetState == REMOTE_EQ_NET_STATE::CONNECTED;
    }
    int CRemoteEquipment::connect()
    {
        TRACE("%p, m_remoteEqNetState:%d\n", this, m_remoteEqNetState);
        if (m_remoteEqNetState == REMOTE_EQ_NET_STATE::CONNECTING
            || m_remoteEqNetState == REMOTE_EQ_NET_STATE::CONNECTED
            || m_remoteEqNetState == REMOTE_EQ_NET_STATE::DISCONNECTING) {
            return -1;
        }
        m_remoteEqNetState = REMOTE_EQ_NET_STATE::CONNECTING;
        if (m_listener.onConnecting != nullptr) {
            m_listener.onConnecting(this);
        }
        // å¾…原线程退了先
        m_bWorking = FALSE;
        WSASetEvent(m_hWSAEvent);
        if (m_hEventActions != NULL) {
            SetEvent(m_hEventActions);
        }
        if (m_hEventActionsThreadExit != NULL) {
            ::WaitForSingleObject(m_hEventActionsThreadExit, INFINITE);
        }
        if (m_hEventTimeoutCheckThreadExit != NULL) {
            ::WaitForSingleObject(m_hEventTimeoutCheckThreadExit, INFINITE);
        }
        //准备服务器的信息,这里需要指定服务器的地址
        sockaddr_in addr;
        struct in_addr dst;
        if (InetPton(AF_INET, m_strAddr.c_str(), &dst) != 1) {
            return -1;
        }
        addr.sin_family = AF_INET;
        addr.sin_addr = dst;
        addr.sin_port = htons(m_nPort);   //改变端口号的数据格式
        // å¦‚果原来打开这套接字先关闭
        if (m_hSocket != NULL) {
            closesocket(m_hSocket);
            m_hSocket = NULL;
        }
        // åˆ›å»ºæ–°çš„套接字
        if (m_hSocket == NULL) {
            m_hSocket = socket(AF_INET, SOCK_STREAM, 0);
            ASSERT(m_hSocket != NULL);
            initClient();
        }
        if (m_hEventClose == NULL) {
            m_hEventClose = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        }
        ResetEvent(m_hEventClose);
        if (m_hEventActions == NULL) {
            m_hEventActions = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        }
        ResetEvent(m_hEventActions);
        if (m_hEventActionsThreadExit == NULL) {
            m_hEventActionsThreadExit = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        }
        ResetEvent(m_hEventActionsThreadExit);
        if (m_hEventTimeoutCheckThreadExit == NULL) {
            m_hEventTimeoutCheckThreadExit = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        }
        ResetEvent(m_hEventTimeoutCheckThreadExit);
        // ä¸»åŠ¨è¿žæŽ¥æœåŠ¡å™¨ï¼Œè¯¥è¿‡ç¨‹å°†ç­‰å¾…ä¸€å®šæ—¶é—´
        if (SOCKET_ERROR == ::connect(m_hSocket, (LPSOCKADDR)&addr, sizeof(addr))) {
            if (WSAGetLastError() != WSAEWOULDBLOCK)
                return -2;
        }
        return 0;
    }
    int CRemoteEquipment::close()
    {
        m_bWorking = FALSE;
        WSASetEvent(m_hWSAEvent);
        if (m_hEventActions != NULL) {
            SetEvent(m_hEventActions);
        }
        lock();
        if (m_hSocket != NULL) {
            m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTING;
            if (m_listener.onDisconnecting != nullptr) {
                m_listener.onDisconnecting(this);
            }
            shutdown(m_hSocket, SD_BOTH);
            closesocket(m_hSocket);
            m_hSocket = NULL;
            unlock();
            if (m_hEventClose != NULL) {
                ::WaitForSingleObject(m_hEventClose, INFINITE);
            }
            if (m_hEventActionsThreadExit != NULL) {
                ::WaitForSingleObject(m_hEventActionsThreadExit, INFINITE);
            }
            if (m_hEventTimeoutCheckThreadExit != NULL) {
                ::WaitForSingleObject(m_hEventTimeoutCheckThreadExit, INFINITE);
            }
            m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTED;
            if (m_listener.onDisconnected != nullptr) {
                m_listener.onDisconnected(this);
            }
        }
        else {
            unlock();
        }
        return 0;
    }
    int CRemoteEquipment::reqGetAction(int type, const char* pszCommand, const char* pszUnitName, const char* pszParams)
    {
        std::string strRawText = std::string(pszCommand) + "@EQID=" + m_strName;
        if (pszUnitName) {
            strRawText += ("/UNIT=" + std::string(pszUnitName));
        }
        if (pszParams) {
            strRawText += pszParams;
        }
        strRawText += "#";
        CAction* pAction = new CAction(type);
        ASSERT(pAction);
        pAction->setRawString(strRawText.c_str());
        lock();
        m_actions.push_back(pAction);
        unlock();
        SetEvent(m_hEventActions);
        return pAction->getId();
    }
    int CRemoteEquipment::reqGetName()
    {
        return reqGetAction(ACTION_GETNAME, CMD_GET_EQID_REQ);
    }
    int CRemoteEquipment::reqGetVersion()
    {
        return reqGetAction(ACTION_GETVERSION, CMD_GET_VERSION_REQ);
    }
    int CRemoteEquipment::reqGetState(const char* pszUnitName)
    {
        return reqGetAction(ACTION_GETDEVICESTATE, CMD_GET_STATE_REQ, pszUnitName);
    }
    int CRemoteEquipment::reqGetDoorState(const char* pszUnitName)
    {
        return reqGetAction(ACTION_GETDOORSTATE, CMD_GET_DOOR_REQ, pszUnitName);
    }
    int CRemoteEquipment::reqGetAlarmInfo(const char* pszUnitName)
    {
        return reqGetAction(ACTION_GETALARMINFO, CMD_GET_ERROR_REQ, pszUnitName);
    }
    int CRemoteEquipment::reqGetStep(const char* pszUnitName)
    {
        return reqGetAction(ACTION_GETSTEP, CMD_GET_STEP_REQ, pszUnitName);
    }
    int CRemoteEquipment::reqGetData(const char* pszUnitName)
    {
        return reqGetAction(ACTION_GETDATA, CMD_GET_DATA_REQ, pszUnitName);
    }
    int CRemoteEquipment::reqRecipeList(const char* pszUnitName)
    {
        return reqGetAction(ACTION_GETRECIPELIST, CMD_GET_RECIPE_LIST_REQ, pszUnitName);
    }
    int CRemoteEquipment::reqRunRecipe(const char* pszUnitName, int nRecipeId, const char* pszRecipeName)
    {
        std::string strParams = "/RECIPEID=" + std::to_string(nRecipeId) + "/RECIPENAME=" + pszRecipeName;
        return reqGetAction(ACTION_RUNRECIPE, CMD_RUN_RECIPE_REQ, pszUnitName, strParams.c_str());
    }
    IUnit* CRemoteEquipment::addUnit(const char* pszName, int nDoorCount)
    {
        auto iter = m_units.find(pszName);
        if (iter != m_units.end()) {
            return (IUnit*)iter->second;
        }
        CUnit* pUnit = new CUnit(pszName);
        m_units[pszName] = pUnit;
        pUnit->setDoorCount(nDoorCount);
        UnitListener listener;
        listener.onStateChanged = [&](void* pUnit, EQ_STATE nStete) -> void {
            TRACE("<UnitListener>onStateChanged...\n");
        };
        listener.onDoorStateChanged = [&](void* pUnit, int stete) -> void {
            TRACE("<UnitListener>onDoorStateChanged...\n");
        };
        listener.onAlarm = [&](void* pUnit, int code, int level, const char* pszText) -> void {
            TRACE("<UnitListener>onAlarm...\n");
        };
        listener.onRemoveAlarm = [&](void* pUnit, int code, int level, const char* pszText) -> void {
            TRACE("<UnitListener>onRemoveAlarm...\n");
        };
        listener.onStepChanged = [&](void* pUnit, STEP_STATE) -> void {
            TRACE("<UnitListener>onStepChanged...\n");
        };
        listener.onDataChanged = [&](void* pUnit, unsigned long long time) -> void {
            TRACE("<UnitListener>onDataChanged...\n");
        };
        listener.onReqLoad = [&](void* pUnit, int layer) -> void {
            TRACE("<UnitListener>onReqLoad...\n");
        };
        listener.onReqUnload = [&](void* pUnit, int layer) -> void {
            TRACE("<UnitListener>onReqUnload...\n");
        };
        pUnit->setListener(listener);
        return (IUnit*)pUnit;
    }
    IUnit* CRemoteEquipment::getUnit(const char* pszName)
    {
        auto iter = m_units.find(pszName);
        if (iter != m_units.end()) {
            return (IUnit*)iter->second;
        }
        return nullptr;
    }
    const char** CRemoteEquipment::getAllUnitNames()
    {
        const int maxUnits = 128;
        static const char* unitNames[maxUnits];
        int index = 0;
        for (const auto& pair : m_units) {
            if (index >= maxUnits) break;
            unitNames[index++] = pair.first.c_str();
        }
        return unitNames;
    }
    int CRemoteEquipment::getUnitCount() const
    {
        return m_units.size();
    }
    ULONGLONG CRemoteEquipment::getConnectTick()
    {
        return m_ullConnectTick;
    }
    BOOL CRemoteEquipment::initClient()
    {
        // å¦‚果指定了本地端口(port != 0), åˆ™è¦ç»‘定指定端口
        // ç»‘定一个套接字到本机的地址
        ASSERT(m_hSocket);
        // ref https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
        int reuse = 1;
        setsockopt(m_hSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse));
        if (m_nLocalPort != 0) {
            sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_addr.S_un.S_addr = INADDR_ANY;
            addr.sin_port = htons(m_nLocalPort);
            bind(m_hSocket, (LPSOCKADDR)&addr, sizeof(addr));
        }
        // é‡‡ç”¨äº‹ä»¶é€‰æ‹©æ¨¡åž‹WSAEventSelect
        m_hWSAEvent = WSACreateEvent();
        WSAEventSelect(m_hSocket, m_hWSAEvent, FD_CONNECT | FD_READ | FD_CLOSE | FD_WRITE);
        m_bWorking = TRUE;
        CWinThread* pThread = AfxBeginThread(&CRemoteEquipment::WorkerThreadFunction, (LPVOID)this,
            THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
        if (pThread) {
            pThread->ResumeThread();
        }
        pThread = AfxBeginThread(&CRemoteEquipment::TimeoutCheckThreadFunction, (LPVOID)this,
            THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
        if (pThread) {
            pThread->ResumeThread();
        }
        pThread = AfxBeginThread(&CRemoteEquipment::ActionsThreadFunction, (LPVOID)this,
            THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
        if (pThread) {
            pThread->ResumeThread();
        }
        return TRUE;
    }
    UINT CRemoteEquipment::WorkerThreadFunction(LPVOID lpvData)
    {
        CRemoteEquipment *pRemoteEquipment = (CRemoteEquipment *)lpvData;
        return pRemoteEquipment->WorkerThreadFunctionInner();
    }
    UINT CRemoteEquipment::WorkerThreadFunctionInner()
    {
        int                    nThreadID, ret, index;
        WSANETWORKEVENTS    networkEvents;
        Sleep(100);        // å¿…须等待,使CreateChann...返回
        nThreadID = 0;
        char szRecvBuffer[BUFFER_SIZE];
        while (m_bWorking) {
            // æ£€æµ‹socket是否有效
            lock();
            if (m_hSocket == NULL) {
                unlock();
                break;
            }
            unlock();
            // ç­‰å¾…网络事件
            ret = WSAWaitForMultipleEvents(1, &m_hWSAEvent, FALSE, 1000, FALSE);
            if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT) {
                continue;
            }
            index = ret - WSA_WAIT_EVENT_0;
            WSAEnumNetworkEvents(m_hSocket, m_hWSAEvent, &networkEvents);
            // æœ‰æ•°æ®åˆ°è¾¾
            if (networkEvents.lNetworkEvents & FD_READ) {
                int nRet = recv(m_hSocket, (char*)&szRecvBuffer, BUFFER_SIZE, 0);
                if (nRet != SOCKET_ERROR) {
                    // è§£é‡Šæ•°æ®
                    int nDecodeRet = decode((char*)&szRecvBuffer, nRet);
                    if (m_listener.onRead != nullptr) {
                        m_listener.onRead(this, szRecvBuffer, nRet);
                    }
                }
            }
            // é“¾æŽ¥å…³é—­
            if (networkEvents.lNetworkEvents & FD_CLOSE) {
                TRACE("链接关闭<FD_CLOSE>\n");
                m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTED;
                if (m_listener.onDisconnected != nullptr) {
                    m_listener.onDisconnected(this);
                }
                break;
            }
            // é“¾æŽ¥ç»“æžœ
            if (networkEvents.lNetworkEvents & FD_CONNECT) {
                TRACE("链接结果<FD_CONNECT>\n");
                m_ullConnectTick = GetTickCount64();
                ResetEvent(m_hEventClose);
                if (networkEvents.iErrorCode[FD_CONNECT_BIT] == 0) {
                    reqGetName();
                }
                else {
                    m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTED;
                    if (m_listener.onConnectFailed != nullptr) {
                        m_listener.onConnectFailed(this, networkEvents.iErrorCode[FD_CONNECT_BIT]);
                    }
                    m_bWorking = false;
                    break;
                }
            }
            if (networkEvents.lNetworkEvents & FD_WRITE) {
                if (m_hEventWrite != NULL) {
                    SetEvent(m_hEventWrite);
                }
            }
        }
        // ä½¿m_hEventClose å—ä¿¡, Close函数返回
        if (m_hEventClose != NULL) {
            TRACE("m_hEventClose å—ä¿¡\n");
            ::SetEvent(m_hEventClose);
        }
        return 0;
    }
    UINT CRemoteEquipment::ActionsThreadFunction(LPVOID lpvData)
    {
        CRemoteEquipment *pRemoteEquipment = (CRemoteEquipment *)lpvData;
        return pRemoteEquipment->ActionsThreadFunctionInner();
    }
    UINT CRemoteEquipment::ActionsThreadFunctionInner()
    {
        ULONGLONG lastTick = 0;
        DWORD dwWait = INFINITE;
        while (m_bWorking) {
            DWORD dwRet = WaitForSingleObject(m_hEventActions, dwWait);
            ResetEvent(m_hEventActions);
            if (!m_bWorking) {
                break;
            }
            lock();
            if (m_pCurrentAction == NULL && m_actions.size() > 0) {
                CAction* pAction = m_actions.front();
                m_pCurrentAction = pAction;
                m_actions.pop_front();
                // å‘送数据
                char* pRawData = NULL;
                int size, validLen;
                m_pCurrentAction->getRawData(pRawData, size, validLen);
                send(m_hSocket, pRawData, validLen, 0);
            }
            unlock();
        }
        TRACE("ActionsThreadFunctionInner exit\n");
        SetEvent(m_hEventActionsThreadExit);
        return 0;
    }
    UINT CRemoteEquipment::TimeoutCheckThreadFunction(LPVOID lpvData)
    {
        CRemoteEquipment *pRemoteEquipment = (CRemoteEquipment *)lpvData;
        return pRemoteEquipment->TimeoutCheckThreadFunctionInner();
    }
    UINT CRemoteEquipment::TimeoutCheckThreadFunctionInner()
    {
        BOOL bMatchRemoteEq = TRUE;
        while (m_bWorking) {
            Sleep(1000);
            if (!m_bWorking) {
                break;
            }
            lock();
            if (m_pCurrentAction != NULL) {
                int nTime = m_pCurrentAction->timeIncrease(1000);
                if (nTime > g_nActionTimeout) {
                    CurrentActionTimeout();
                    if (m_pCurrentAction->getType() == ACTION_GETNAME) {
                        bMatchRemoteEq = FALSE;
                    }
                    delete m_pCurrentAction;
                    m_pCurrentAction = NULL;
                    SetEvent(m_hEventActions);
                    if (!bMatchRemoteEq) {
                        unlock();
                        break;
                    }
                }
            }
            unlock();
        }
        SetEvent(m_hEventTimeoutCheckThreadExit);
        if (!bMatchRemoteEq) {
            this->close();
            if (m_listener.onConnectFailed != nullptr) {
                m_listener.onConnectFailed(this, -1);
            }
        }
        TRACE("TimeoutCheckThreadFunctionInner exit\n");
        return 0;
    }
    void CRemoteEquipment::CurrentActionTimeout()
    {
        TRACE("Packer CurrentActionTimeout %d", g_nActionTimeout);
    }
    void CRemoteEquipment::splitCString(const CString& strText, TCHAR delimiter, std::function<void(const CString&, int)> callback)
    {
        // é€šç”¨å­—符串切割函数,支持回调函数处理每次解析后的结果
        CString strGet;
        int index = 0;
        while (AfxExtractSubString(strGet, strText.GetString(), index, delimiter)) {
            // å¦‚果提供了回调函数,则执行回调,传递当前的字符串和索引
            if (callback) {
                callback(strGet, index);
            }
            ++index;
        }
    }
    void CRemoteEquipment::notifyEventUpdate(REMOTE_EQ_EVENT eventCode, CUnit* pUnit)
    {
        if (m_listener.onEventUpdate != nullptr) {
            m_listener.onEventUpdate(this, pUnit, eventCode);
        }
    }
    void CRemoteEquipment::processDoorState(const CString& strPart, int index, int& doorState)
    {
        if (strPart.CompareNoCase(_T("OPEN")) == 0) {
            doorState |= (0x01 << index);
        }
    }
    void CRemoteEquipment::updateDoorState(const CString& strText, int& doorState, CUnit* pUnit)
    {
        // æ•获this指针,使得Lambda可以访问类的成员函数或变量
        splitCString(strText, ',', [this, &doorState](const CString& part, int index) {
            processDoorState(part, index, doorState);
        });
        pUnit->setDoorState(doorState);
    }
    void CRemoteEquipment::parseAlarm(const CString& strText, CUnit* pUnit)
    {
        int alarmCode = -1;
        int alarmLevel = -1;
        CString alarmMessage;
        if (0 == _ttoi(strText))
        {
            pUnit->setAlarm(0, 0, "");
            return;
        }
        splitCString(strText, ',', [&alarmCode, &alarmLevel, &alarmMessage](const CString& part, int index) {
            // æ ¹æ®å½“前索引处理不同的报警信息
            switch (index) {
            case 0: // æŠ¥è­¦ä»£ç 
                alarmCode = _ttoi(part);
                break;
            case 1: // æŠ¥è­¦çº§åˆ«
                alarmLevel = _ttoi(part);
                break;
            case 2: // æŠ¥è­¦æ¶ˆæ¯
                alarmMessage = part;
                break;
            default:
                break;
            }
        });
        // ç¡®ä¿è§£æžåˆ°3个子字符串,并设置报警信息
        if (alarmCode != -1 && alarmLevel != -1 && !alarmMessage.IsEmpty()) {
            pUnit->setAlarm(alarmCode, alarmLevel, alarmMessage.GetString());
        }
    }
    void CRemoteEquipment::handleState(const std::map<std::string, std::string>& params, CUnit* pUnit)
    {
        auto iter = params.find(PARAM_STATE);
        if (iter != params.end()) {
            std::string strState(iter->second);
            pUnit->setStateFromString(strState);
            notifyEventUpdate(REMOTE_EQ_EVENT::DEVICE_STATUS_CHANGED, pUnit);
        }
    }
    void CRemoteEquipment::handleDoorState(const std::map<std::string, std::string>& params, CUnit* pUnit)
    {
        auto iter = params.find(PARAM_DOOR);
        if (iter != params.end()) {
            CString strText = iter->second.c_str();
            int doorState = 0;
            updateDoorState(strText, doorState, pUnit);
            notifyEventUpdate(REMOTE_EQ_EVENT::DOOR_STATUS_CHANGED, pUnit);
        }
    }
    void CRemoteEquipment::handleAlarmInfo(const std::map<std::string, std::string>& params, CUnit* pUnit)
    {
        auto iter = params.find(PARAM_CODE);
        if (iter != params.end()) {
            CString strText = iter->second.c_str();
            parseAlarm(strText, pUnit);
            notifyEventUpdate(REMOTE_EQ_EVENT::ALARM_INFO_CHANGED, pUnit);
        }
    }
    void CRemoteEquipment::handleStep(const std::map<std::string, std::string>& params, CUnit* pUnit)
    {
        auto materialIter = params.find(PARAM_MATERIAL_ID);
        auto stepIter = params.find(PARAM_STEP);
        if (stepIter != params.end()) {
            auto pvIter = params.find(PARAM_PVTIME);
            auto svIter = params.find(PARAM_SVTIME);
            const std::string& strStep = stepIter->second;
            const std::string& strMaterialId = materialIter != params.end() ? materialIter->second : "";
            int iSVTime = svIter != params.end() ? _ttoi(svIter->second.c_str()) : 0;
            int iPVTime = pvIter != params.end() ? _ttoi(pvIter->second.c_str()) : 0;
            handleMachineProcess(strMaterialId, strStep, pUnit, iSVTime, iPVTime);
            notifyEventUpdate(REMOTE_EQ_EVENT::PRODUCTION_PROCESS_CHANGED, pUnit);
        }
    }
    void CRemoteEquipment::handleData(const std::map<std::string, std::string>& params, CUnit* pUnit)
    {
        auto retIter = params.find(PARAM_RESULT);
        auto texIter = params.find(PARAM_TEX);
        if ((retIter != params.end() && retIter->second.compare("FAIL")) || (texIter != params.end() && texIter->second.compare("NO DATA")))
        {
            // èŽ·å–æ•°æ®å¤±è´¥æˆ–æ²¡æœ‰æ•°æ®ï¼Œä¸åšå¤„ç†
        }
        else {
            auto preIter = params.find(PARAM_PRE);
            auto airIter = params.find(PARAM_AIR);
            auto tmpIter = params.find(PARAM_TMP);
            auto timeIter = params.find(PARAM_TIME);
            if (timeIter != params.end() && preIter != params.end() && airIter != params.end() && tmpIter != params.end()) {
                uint64_t timestamp = pUnit->stringToTimeStamp(timeIter->second);
                pUnit->setDataTimeAndResetData(timestamp);
                pUnit->addData("PRE", preIter->second.c_str(), true);
                pUnit->addData("AIR", airIter->second.c_str(), true);
                pUnit->addData("TMP", tmpIter->second.c_str(), true);
                notifyEventUpdate(REMOTE_EQ_EVENT::SERSOR_DATA_CHANGED, pUnit);
            }
        }
    }
    void CRemoteEquipment::handleRecipeList(const std::map<std::string, std::string>& params, CUnit* pUnit)
    {
        auto retIter = params.find(PARAM_RESULT);
        auto texIter = params.find(PARAM_TEX);
        if ((retIter != params.end() && retIter->second.compare("FAIL")) || (texIter != params.end() && texIter->second.compare("NO RECIPE"))) {
            // èŽ·å–é…æ–¹å¤±è´¥æˆ–æ²¡æœ‰é…æ–¹ï¼Œä¸åšå¤„ç†
        }
        else {
            auto recipeIter = params.find(PARAM_RECIPE_LIST);
            if (recipeIter != params.end()) {
                // è§£æžé…æ–¹åˆ—表
                CString strRecipeList = recipeIter->second.c_str();
                splitCString(strRecipeList, ',', [pUnit](const CString& part, int index) {
                    static int iRecipeid = -1;
                    if ((index + 1) % 2 == 0) {
                        pUnit->addRecipe(iRecipeid, part, true);
                    }
                    else {
                        iRecipeid = _ttoi(part);
                    }
                    });
                notifyEventUpdate(REMOTE_EQ_EVENT::RECIPE_LIST_CHANGED, pUnit);
            }
        }
    }
    void CRemoteEquipment::handleIdle(CUnit* pUnit)
    {
        pUnit->stepIdle();
    }
    void CRemoteEquipment::handleMaterialReceived(const std::string& strMaterialId, CUnit* pUnit)
    {
        pUnit->stepMaterialReceived(strMaterialId.c_str());
    }
    void CRemoteEquipment::handleMaterialRemoved(const std::string& strMaterialId, CUnit* pUnit)
    {
        pUnit->stepMaterialRemoved(strMaterialId.c_str());
    }
    void CRemoteEquipment::handleProcessingStarted(const std::string& strMaterialId, CUnit* pUnit)
    {
        pUnit->stepProcessingStarted(strMaterialId.c_str());
    }
    void CRemoteEquipment::handleProcessing(const std::string& strMaterialId, CUnit* pUnit, int svTime, int pvTime)
    {
        pUnit->stepProcessing(strMaterialId.c_str(), svTime, pvTime);
    }
    void CRemoteEquipment::handleProcessingCompleted(const std::string& strMaterialId, CUnit* pUnit)
    {
        pUnit->stepProcessingCompleted(strMaterialId.c_str());
    }
    void CRemoteEquipment::handleMachineProcess(const std::string& strMaterialId, const std::string& strStep, CUnit* pUnit, int svTime, int pvTime)
    {
        // æ˜ å°„步骤到处理函数
        static const std::unordered_map<std::string, std::function<void(const std::string&, CUnit*, int, int)>> stepHandlers = {
            {"IDLE", [this](const std::string&, CUnit* pUnit, int, int) { handleIdle(pUnit); }},
            {"MATERIAL_RECEIVED", [this](const std::string& strMaterialId, CUnit* pUnit, int, int) { handleMaterialReceived(strMaterialId, pUnit); }},
            {"MATERIAL_REMOVED", [this](const std::string& strMaterialId, CUnit* pUnit, int, int) { handleMaterialRemoved(strMaterialId, pUnit); }},
            {"PROCESSING_STARTED", [this](const std::string& strMaterialId, CUnit* pUnit, int, int) { handleProcessingStarted(strMaterialId, pUnit); }},
            {"PROCESSING_COMPLETED", [this](const std::string& strMaterialId, CUnit* pUnit, int, int) { handleProcessingCompleted(strMaterialId, pUnit); }},
            {"PROCESSING", [this](const std::string& strMaterialId, CUnit* pUnit, int svTime, int pvTime) {
                handleProcessing(strMaterialId, pUnit, svTime, pvTime);
            }}
        };
        // æŸ¥æ‰¾å¤„理函数并执行
        auto handler = stepHandlers.find(strStep);
        if (handler != stepHandlers.end()) {
            handler->second(strMaterialId, pUnit, svTime, pvTime); // ä¼ é€’ svTime å’Œ pvTime
        }
    }
    int CRemoteEquipment::decode(char* pszBuffer, int nBufferSize)
    {
        std::string txt = std::string(pszBuffer, nBufferSize);
        TRACE("decode:%s\n", txt.c_str());
        int nRet = REPLY_NOERROR;
        int iParam = 0;
        CString strParam, strCmd, strBody;
        std::map<std::string, std::string> params;
        lock();
        if (-1 == m_data.append(pszBuffer, nBufferSize)) {
            nRet = REPLY_MEMROY_ERROR;
            goto CURACTION;
        }
        // åœ¨æœªæ‰¾åˆ°@符之前,所有的字母必须是 'A' ~ 'Z' æˆ– '_'
        int nCmdEnd = -1;
        BOOL bInvalid = false;
        for (int i = 0; i < m_data.m_nDataLen; i++) {
            if ((char)'@' == m_data.m_pBuffer[i]) {
                nCmdEnd = i;
                break;
            }
            if (!(((char)'A' <= m_data.m_pBuffer[i] && m_data.m_pBuffer[i] <= (char)'Z')
                || (char)'_' == m_data.m_pBuffer[i])) {
                bInvalid = true;
                break;
            }
        }
        if (bInvalid) {
            m_data.clear();
            nRet = REPLY_PACKET_ERROR;
            goto CURACTION;
        }
        if (nCmdEnd <= 0) {
            nRet = REPLY_PACKET_ERROR;
            goto CURACTION;
        }
        // æŸ¥æ‰¾ç»ˆæ­¢ç¬¦
        int nPacketEnd = -1;
        bInvalid = false;
        for (int i = nCmdEnd; i < m_data.m_nDataLen; i++) {
            if ((char)'#' == m_data.m_pBuffer[i]) {
                nPacketEnd = i;
                break;
            }
            /*
            if (!((char)32 <= m_data.m_pBuffer[i] && m_data.m_pBuffer[i] <= (char)127)) {
                bInvalid = true;
                break;
            }
            */
        }
        if (bInvalid) {
            m_data.clear();
            nRet = REPLY_PACKET_ERROR;
            goto CURACTION;
        }
        if (nPacketEnd <= nCmdEnd) {
            nRet = REPLY_PACKET_NOT_END;
            goto CURACTION;
        }
        // å¾—到命令,消息体
        // æ¶ˆæ¯ä½“分解为参数列表
        strCmd = CString(m_data.m_pBuffer, nCmdEnd);
        strBody = CString(&m_data.m_pBuffer[nCmdEnd + 1], nPacketEnd - nCmdEnd - 1);
        do {
            if (!AfxExtractSubString(strParam, (LPCTSTR)strBody, iParam, '/')) break;
            int n = strParam.Find("=");
            if (n > 0) {
                std::string strName = (LPTSTR)(LPCTSTR)strParam.Left(n);
                std::string strValue = (LPTSTR)(LPCTSTR)strParam.Right(strParam.GetLength() - n - 1);
                params[strName] = strValue;
            }
            iParam++;
        } while (true);
    CURACTION:
        m_data.clear();
        // èŽ·å–è®¾å¤‡å•å…ƒæŒ‡é’ˆ
        CUnit* pUnit = nullptr;
        auto unitParamIter = params.find(PARAM_UNIT);
        if (unitParamIter != params.end()) {
            auto unitMapIter = m_units.find(unitParamIter->second);
            if (unitMapIter != m_units.end() && unitMapIter->second != nullptr) {
                pUnit = unitMapIter->second;
            }
        }
        if (m_pCurrentAction != NULL) {
            m_pCurrentAction->setReplyCode(nRet);
            if (m_pCurrentAction->getType() == ACTION_GETNAME
                && strCmd.Compare(CMD_GET_EQID_REP) == 0) {
                auto iter = params.find(PARAM_EQID);
                if (iter != params.end()) {
                    m_strName = iter->second;
                    m_remoteEqNetState = REMOTE_EQ_NET_STATE::CONNECTED;
                    if (m_listener.onConnected != nullptr) {
                        m_listener.onConnected(this);
                    }
                    // test
                    reqGetVersion();
                    reqGetState("UNITA");
                    reqGetDoorState("UNITA");
                }
            }
            else if (m_pCurrentAction->getType() == ACTION_GETVERSION && strCmd.Compare(CMD_GET_VERSION_REP) == 0) {
                auto iter = params.find(PARAM_VERSION);
                if (iter != params.end()) {
                    m_strVersion = iter->second;
                }
            }
            else if (m_pCurrentAction->getType() == ACTION_GETDEVICESTATE && strCmd.Compare(CMD_GET_STATE_REP) == 0 && pUnit != nullptr) {
                handleState(params, pUnit);
            }
            else if (m_pCurrentAction->getType() == ACTION_GETDOORSTATE && strCmd.Compare(CMD_GET_DOOR_REP) == 0 && pUnit != nullptr) {
                handleDoorState(params, pUnit);
            }
            else if (m_pCurrentAction->getType() == ACTION_GETALARMINFO && strCmd.Compare(CMD_GET_ERROR_REP) == 0 && pUnit != nullptr) {
                handleAlarmInfo(params, pUnit);
            }
            else if (m_pCurrentAction->getType() == ACTION_GETSTEP && strCmd.Compare(CMD_GET_STEP_REP) == 0 && pUnit != nullptr) {
                handleStep(params, pUnit);
            }
            else if (m_pCurrentAction->getType() == ACTION_GETDATA && strCmd.Compare(CMD_GET_DATA_REP) == 0 && pUnit != nullptr) {
                handleData(params, pUnit);
            }
            else if (m_pCurrentAction->getType() == ACTION_GETRECIPELIST && strCmd.Compare(CMD_GET_RECIPE_LIST_REP) == 0 && pUnit != nullptr) {
                handleRecipeList(params, pUnit);
            }
            else if (m_pCurrentAction->getType() == ACTION_RUNRECIPE && strCmd.Compare(CMD_RUN_RECIPE_REP) == 0 && pUnit != nullptr) {
                AfxMessageBox("配方执行中... ...");
            }
            else {
                // å…¶ä»–命令
            }
            // åŒ…出错,且不需要拼下一包
            if (nRet != REPLY_PACKET_NOT_END) {
                delete m_pCurrentAction;
                m_pCurrentAction = NULL;
                SetEvent(m_hEventActions);
            }
        }
        else {
            if (pUnit != nullptr) {
                if (strCmd.Compare(AS_MC_STATE_REP) == 0) {
                    // èŽ·å–æœºå™¨çŠ¶æ€
                    handleState(params, pUnit);
                }
                else if (strCmd.Compare(AS_GET_DOOR_REP) == 0) {
                    // èŽ·å–é—¨çŠ¶æ€
                    handleDoorState(params, pUnit);
                }
                else if (strCmd.Compare(AS_SEND_ERROR_REP) == 0) {
                    // èŽ·å–é”™è¯¯ç 
                    handleAlarmInfo(params, pUnit);
                }
                else if (strCmd.Compare(AS_REMOVE_ERROR_REP) == 0) {
                    // è§£é™¤å‘Šè­¦
                    pUnit->setAlarm(0, 0, "");
                    notifyEventUpdate(REMOTE_EQ_EVENT::REMOVE_ALARM_INFO, pUnit);
                }
                else if (strCmd.Compare(AS_SEND_STEP_REP) == 0) {
                    // å¤„理机器制程
                    handleStep(params, pUnit);
                }
                else if (strCmd.Compare(AS_MC_INFO_REP) == 0) {
                    // èŽ·å–æœ€æ–°æ•°æ®ï¼Œä¼ æ„Ÿå™¨ï¼ˆæ¸©åº¦ã€åŽ‹åŠ›ç­‰ï¼‰
                    handleData(params, pUnit);
                }
                else if (strCmd.Compare(AS_SEND_EVENT_REP) == 0) {
                    // å¤„理上报事件
                    notifyEventUpdate(REMOTE_EQ_EVENT::LOAD_EVENT_CHANGED, pUnit);
                }
            }
        }
        unlock();
        return 0;
    }
}
SourceCode/Bond/BEQLibrary/RemoteEquipment.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,147 @@
#pragma once
#include <string>
#include <list>
#include "IRemoteEquipment.h"
#include "Action.h"
#include "Data.h"
#include "Unit.h"
#define ACTION_GETNAME                1
#define ACTION_GETVERSION            2
#define ACTION_GETDEVICESTATE        3
#define ACTION_GETDOORSTATE            4
#define ACTION_GETALARMINFO            5
#define ACTION_GETSTEP                6
#define ACTION_GETDATA                7
#define ACTION_GETRECIPELIST        8
#define ACTION_RUNRECIPE            9
#define ACTION_LOADREADY            10
#define ACTION_LOADCOMPLETE            11
#define ACTION_UNLOADCOMPLETE        12
namespace BEQ {
    typedef std::function<void(void* pRemoteEiuipment)> ONREQCONNECTEDEX;
    typedef std::function<void(void* pRemoteEiuipment, int errorCode)> ONREQCONNECTFAILEDEX;
    typedef std::function<void(void* pRemoteEiuipment, const char* pszData, int len)> ONREQREADEX;
    typedef std::function<void(void* pRemoteEquipment, void* pUnit, REMOTE_EQ_EVENT eventCode)> ONREQEVENTUPDATE_EX;
    typedef struct _RemoteEquipmentListener
    {
        ONREQCONNECTEDEX        onConnecting;
        ONREQCONNECTEDEX        onConnected;
        ONREQCONNECTFAILEDEX    onConnectFailed;
        ONREQCONNECTEDEX        onDisconnecting;
        ONREQCONNECTEDEX        onDisconnected;
        ONREQREADEX                onRead;
        ONREQEVENTUPDATE_EX        onEventUpdate;
    } RemoteEquipmentListener;
    enum class REMOTE_EQ_NET_STATE
    {
        DISCONNECTED = 0,
        CONNECTING,
        CONNECTED,
        DISCONNECTING
    };
    class CRemoteEquipment :
        public IRemoteEquipment
    {
    public:
        CRemoteEquipment();
        CRemoteEquipment(const char* pszAddr, int port);
        ~CRemoteEquipment();
    public:
        virtual void setRemoteEquipmentListener(RemoteEquipmentListener listener);
        virtual int getAddr(char* pszBuffer, int nMaxCount);
        virtual int getPort();
        virtual int getName(char* pszBuffer, int nMaxCount);
        virtual int getVersion(char* pszBuffer, int nMaxCount);
        virtual bool isConnected();
        virtual int connect();
        virtual int close();
        virtual int reqGetAction(int type, const char* pszCommand, const char* pszUnitName = nullptr, const char* pszParams = nullptr);
        virtual int reqGetName();
        virtual int reqGetVersion();
        virtual int reqGetState(const char* pszUnitName);
        virtual int reqGetDoorState(const char* pszUnitName);
        virtual int reqGetAlarmInfo(const char* pszUnitName);
        virtual int reqGetStep(const char* pszUnitName);
        virtual int reqGetData(const char* pszUnitName);
        virtual int reqRecipeList(const char* pszUnitName);
        virtual int reqRunRecipe(const char* pszUnitName, int nRecipeId, const char* pszRecipeName);
        virtual IUnit* addUnit(const char* pszName, int nDoorCount);
        virtual IUnit* getUnit(const char* pszName);
        virtual const char** getAllUnitNames();
        virtual int getUnitCount() const;
        virtual ULONGLONG getConnectTick();
    public:
        inline void lock() { ::EnterCriticalSection(&m_cs); };
        inline void unlock() { ::LeaveCriticalSection(&m_cs); };
    private:
        void splitCString(const CString& strText, TCHAR delimiter = ',', std::function<void(const CString&, int)> callback = nullptr);
        void notifyEventUpdate(REMOTE_EQ_EVENT eventCode, CUnit* pUnit);
        void processDoorState(const CString& strPart, int index, int& doorState);
        void updateDoorState(const CString& strText, int& doorState, CUnit* pUnit);
        void parseAlarm(const CString& strText, CUnit* pUnit);
        void handleIdle(CUnit* pUnit);
        void handleMaterialReceived(const std::string& strMaterialId, CUnit* pUnit);
        void handleMaterialRemoved(const std::string& strMaterialId, CUnit* pUnit);
        void handleProcessingStarted(const std::string& strMaterialId, CUnit* pUnit);
        void handleProcessing(const std::string& strMaterialId, CUnit* pUnit, int svTime, int pvTime);
        void handleProcessingCompleted(const std::string& strMaterialId, CUnit* pUnit);
        void handleMachineProcess(const std::string& strMaterialId, const std::string& strStep, CUnit* pUnit, int svTime = 0, int pvTime = 0);
    private:
        void handleState(const std::map<std::string, std::string>& params, CUnit* pUnit);
        void handleDoorState(const std::map<std::string, std::string>& params, CUnit* pUnit);
        void handleAlarmInfo(const std::map<std::string, std::string>& params, CUnit* pUnit);
        void handleStep(const std::map<std::string, std::string>& params, CUnit* pUnit);
        void handleData(const std::map<std::string, std::string>& params, CUnit* pUnit);
        void handleRecipeList(const std::map<std::string, std::string>& params, CUnit* pUnit);
    private:
        BOOL initClient();
        static UINT WorkerThreadFunction(LPVOID lpvData);
        static UINT ActionsThreadFunction(LPVOID lpvData);
        static UINT TimeoutCheckThreadFunction(LPVOID lpvData);
        UINT WorkerThreadFunctionInner();
        UINT ActionsThreadFunctionInner();
        UINT TimeoutCheckThreadFunctionInner();
        void CurrentActionTimeout();
        int decode(char* pszBuffer, int nBufferSize);
    private:
        CRITICAL_SECTION m_cs;        // åŒæ­¥é”
        RemoteEquipmentListener m_listener;
        std::string m_strAddr;
        int m_nPort;
        int m_nLocalPort;
        std::string m_strName;
        std::string m_strVersion;
    private:
        SOCKET m_hSocket;
        REMOTE_EQ_NET_STATE m_remoteEqNetState;
        BOOL m_bWorking;
        WSAEVENT m_hWSAEvent;
        HANDLE m_hEventClose;        // ç­‰å¾…worker线程退出后, Close函数返回
        HANDLE m_hEventWrite;
        HANDLE m_hEventActions;
        HANDLE m_hEventActionsThreadExit;
        HANDLE m_hEventTimeoutCheckThreadExit;
        CAction * m_pCurrentAction;
        std::list<CAction*> m_actions;
        BEQ::CData m_data;
    private:
        std::map<std::string, BEQ::CUnit*> m_units;
        ULONGLONG m_ullConnectTick;
    };
}
SourceCode/Bond/BEQLibrary/Resource.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by BEQLibrary.rc
//
// æ–°å¯¹è±¡çš„下一组默认值
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE    7000
#define _APS_NEXT_CONTROL_VALUE        7000
#define _APS_NEXT_SYMED_VALUE        7000
#define _APS_NEXT_COMMAND_VALUE        32771
#endif
#endif
SourceCode/Bond/BEQLibrary/Servo.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,177 @@
#include "stdafx.h"
#include "Servo.h"
#include "RemoteEquipment.h"
namespace BEQ {
    CServo::CServo()
    {
        m_pClientListener = nullptr;
        m_servoListener.onRemoteEqConnecting = nullptr;
        m_servoListener.onRemoteEqConnected = nullptr;
        m_servoListener.onRemoteEqConnectFailed = nullptr;
        m_servoListener.onRemoteEqDisconnecting = nullptr;
        m_servoListener.onRemoteEqDisconnected = nullptr;
        m_servoListener.onRemoteEqReadRawdata = nullptr;
        m_servoListener.onRemoteEqEventUpdate = nullptr;
    }
    CServo::CServo(const char* pszName)
    {
        m_strName = pszName;
        m_pClientListener = nullptr;
    }
    CServo::~CServo()
    {
        for (auto iter = m_clients.begin(); iter != m_clients.end(); iter++) {
            delete *iter;
        }
        m_clients.clear();
        if (m_pClientListener != nullptr) {
            delete m_pClientListener;
            m_pClientListener = nullptr;
        }
        if (m_pServer != nullptr) {
            m_pServer->Close();
            delete m_pServer;
            m_pServer = nullptr;
        }
        for (auto item : m_remoteEquipments) {
            delete (CRemoteEquipment*)item;
        }
        m_remoteEquipments.clear();
    }
    void CServo::setListener(BEQ::ServoListener listener)
    {
        m_servoListener.onRemoteEqConnecting = listener.onRemoteEqConnecting;
        m_servoListener.onRemoteEqConnected = listener.onRemoteEqConnected;
        m_servoListener.onRemoteEqConnectFailed = listener.onRemoteEqConnectFailed;
        m_servoListener.onRemoteEqDisconnecting = listener.onRemoteEqDisconnecting;
        m_servoListener.onRemoteEqDisconnected = listener.onRemoteEqDisconnected;
        m_servoListener.onRemoteEqReadRawdata = listener.onRemoteEqReadRawdata;
        m_servoListener.onRemoteEqEventUpdate = listener.onRemoteEqEventUpdate;
    }
    int CServo::getName(char* pszBuffer, int nMaxCount)
    {
        return strcpy_s(pszBuffer, nMaxCount, m_strName.c_str());
    }
    int CServo::createRemoteEquipment(IRemoteEquipment*& pRemoteEquipment, const char* pszAddr, int port)
    {
        CRemoteEquipment* p = new CRemoteEquipment(pszAddr, port);
        pRemoteEquipment = (IRemoteEquipment*)p;
        m_remoteEquipments.push_back(pRemoteEquipment);
        RemoteEquipmentListener listener;
        listener.onConnecting = [&](void* pRemoteEiuipment) -> void {
            if (m_servoListener.onRemoteEqConnecting != nullptr) {
                m_servoListener.onRemoteEqConnecting(this, pRemoteEquipment);
            }
        };
        listener.onConnected = [&](void* pRemoteEiuipment) -> void {
            if (m_servoListener.onRemoteEqConnected != nullptr) {
                m_servoListener.onRemoteEqConnected(this, pRemoteEquipment);
            }
        };
        listener.onConnectFailed = [&](void* pRemoteEiuipment, int errorCode) -> void {
            if (m_servoListener.onRemoteEqConnectFailed != nullptr) {
                m_servoListener.onRemoteEqConnectFailed(this, pRemoteEquipment, errorCode);
            }
        };
        listener.onDisconnecting = [&](void* pRemoteEiuipment) -> void {
            if (m_servoListener.onRemoteEqDisconnecting != nullptr) {
                m_servoListener.onRemoteEqDisconnecting(this, pRemoteEquipment);
            }
        };
        listener.onDisconnected = [&](void* pRemoteEiuipment) -> void {
            if (m_servoListener.onRemoteEqDisconnected != nullptr) {
                m_servoListener.onRemoteEqDisconnected(this, pRemoteEquipment);
            }
        };
        listener.onRead = [&](void* pRemoteEiuipment, const char* pszData, int len) -> void {
            if (m_servoListener.onRemoteEqReadRawdata != nullptr) {
                m_servoListener.onRemoteEqReadRawdata(this, pRemoteEquipment, pszData, len);
            }
        };
        listener.onEventUpdate = [&](void* pRemoteEiuipment, void* pUnit, REMOTE_EQ_EVENT eventCode) -> void {
            if (m_servoListener.onRemoteEqEventUpdate != nullptr) {
                m_servoListener.onRemoteEqEventUpdate(this, pRemoteEquipment, pUnit, eventCode);
            }
        };
        p->setRemoteEquipmentListener(listener);
        return 0;
    }
    int CServo::connectRemoteEquipment(IRemoteEquipment* pRemoteEquipment)
    {
        if (!findRemoteEquipment(pRemoteEquipment)) return -1;
        return pRemoteEquipment->connect();
    }
    bool CServo::findRemoteEquipment(IRemoteEquipment* pRemoteEquipment)
    {
        for (auto item : m_remoteEquipments) {
            if (item == pRemoteEquipment) return true;
        }
        return false;
    }
    int CServo::runOnServerMode(int port)
    {
        return -1;
        // æš‚时不支持Server模式
        m_pClientListener = new AcceptClientListener;
        m_pClientListener->onClose = [&](void* pClient) -> int {
            removeClient((CAcceptClient*)pClient);
            return 0;
        };
        m_pClientListener->onRead = [&](void* pClient, const char* pData, int len) -> int {
            AfxMessageBox(CString(pData, len));
            return 0;
        };
        ServerListener listener;
        listener.onAccept = [&](void* pServer, CAcceptClient* pClient) -> int {
            addClient(pClient);
            return 0;
        };
        listener.onClose = [&](void* pServer) -> int {
            AfxMessageBox("onClose");
            return 0;
        };
        m_pServer = new CSocketServer(port, listener);
        m_pServer->init();
        return 0;
    }
    int CServo::close()
    {
        return 0;
    }
    void CServo::addClient(CAcceptClient* pClient)
    {
        m_clients.push_back(pClient);
        pClient->setListener(*m_pClientListener);
    }
    void CServo::removeClient(CAcceptClient* pClient)
    {
        for (auto iter = m_clients.begin(); iter != m_clients.end(); iter++) {
            if (*iter == pClient) {
                delete *iter;
                m_clients.erase(iter);
                break;
            }
        }
    }
}
SourceCode/Bond/BEQLibrary/Servo.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
#pragma once
#include "IServo.h"
#include <string>
#include "SocketServer.h"
#include <list>
namespace BEQ {
    class CServo :
        public IServo
    {
    public:
        CServo();
        CServo(const char* pszName);
        ~CServo();
    public:
        virtual void setListener(BEQ::ServoListener listener);
        virtual int getName(char* pszBuffer, int nMaxCount);
        virtual int createRemoteEquipment(IRemoteEquipment*& pRemoteEquipment, const char* pszAddr, int port);
        virtual int connectRemoteEquipment(IRemoteEquipment* pRemoteEquipment);
        virtual int runOnServerMode(int port);
    public:
        int close();
    private:
        bool findRemoteEquipment(IRemoteEquipment* pRemoteEquipment);
        void addClient(CAcceptClient* pClient);
        void removeClient(CAcceptClient* pClient);
    private:
        std::string m_strName;
        CSocketServer* m_pServer;
        ServoListener m_servoListener;
        AcceptClientListener* m_pClientListener;
        std::list<CAcceptClient*> m_clients;
        std::list<IRemoteEquipment*> m_remoteEquipments;
    };
}
SourceCode/Bond/BEQLibrary/SocketClient.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
#include "stdafx.h"
#include "SocketClient.h"
namespace BEQ {
    CSocketClient::CSocketClient()
    {
    }
    CSocketClient::~CSocketClient()
    {
    }
}
SourceCode/Bond/BEQLibrary/SocketClient.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
#pragma once
namespace BEQ {
    enum class STATE
    {
        READY = 0,
        CONNECTING,
        CONNECTED,
        CONNECTFAILED,
        DISCONNECTED
    };
    class CSocketClient
    {
    public:
        CSocketClient();
        ~CSocketClient();
    };
}
SourceCode/Bond/BEQLibrary/SocketServer.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,78 @@
#include "stdafx.h"
#include "SocketServer.h"
namespace BEQ {
    CSocketServer::CSocketServer()
    {
        m_port = 80;
        m_listener.onAccept = nullptr;
        m_listener.onClose = nullptr;
    }
    CSocketServer::CSocketServer(int port, BEQ::ServerListener listener)
    {
        m_port = port;
        m_listener.onAccept = listener.onAccept;
        m_listener.onClose = listener.onClose;
    }
    CSocketServer::~CSocketServer()
    {
    }
    void CSocketServer::setPort(UINT port)
    {
        m_port = port;
    }
    void CSocketServer::setListenter(BEQ::ServerListener listener)
    {
        m_listener.onAccept = listener.onAccept;
        m_listener.onClose = listener.onClose;
    }
    void CSocketServer::init()
    {
        AfxSocketInit();
        Create(m_port, 1, FD_ACCEPT | FD_CLOSE);
        Listen(5);
    }
    void CSocketServer::OnAccept(int nErrorCode)
    {
        sockaddr address;
        int address_len = sizeof(address);
        CAcceptClient* pClient = new CAcceptClient();
        if (Accept(*pClient, &address, &address_len))
        {
            int t = 1;
            pClient->SetSockOpt(TCP_NODELAY, &t, sizeof(int), IPPROTO_TCP);
            pClient->AsyncSelect(FD_READ | FD_CLOSE);
            if (m_listener.onAccept != nullptr) {
                m_listener.onAccept(this, pClient);
            }
        }
        __super::OnAccept(nErrorCode);
    }
    void CSocketServer::OnClose(int nErrorCode)
    {
        if (m_listener.onClose != nullptr) {
            m_listener.onClose(this);
        }
        __super::OnClose(nErrorCode);
    }
    void CSocketServer::OnReceive(int nErrorCode)
    {
        TRACE("<CSocketServer>OnReceive此处不应该进入...");
        __super::OnReceive(nErrorCode);
    }
}
SourceCode/Bond/BEQLibrary/SocketServer.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
#pragma once
#include <afxSock.h>
#include "AcceptClient.h"
#include <functional>
namespace BEQ {
    typedef std::function<int(void* pServer, CAcceptClient* pClient)> ONACCEPT;
    typedef std::function<int(void* pServer)> ONCLOSE;
    typedef struct _ServerListener
    {
        ONACCEPT        onAccept;
        ONCLOSE            onClose;
    } ServerListener;
    class CSocketServer :
        public CAsyncSocket
    {
    public:
        CSocketServer();
        CSocketServer::CSocketServer(int port, BEQ::ServerListener listener);
        ~CSocketServer();
    public:
        void setListenter(BEQ::ServerListener listener);
        void setPort(UINT port);
        void init();
    public:
        virtual void OnAccept(int nErrorCode);
        virtual void OnClose(int nErrorCode);
        virtual void OnReceive(int nErrorCode);
    private:
        UINT m_port;
        ServerListener m_listener;
    };
}
SourceCode/Bond/BEQLibrary/Unit.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,425 @@
#include "stdafx.h"
#include "Unit.h"
#include <chrono>
#include <sstream>
#include <iomanip>
#include <unordered_map>
namespace BEQ {
    CUnit::CUnit()
    {
        m_eqState = EQ_STATE::IDLE;
        m_nDoorCount = 1;
        m_doorState = 0;
        m_nAlarmCode = 0;
        m_nAlarmLevel = 0;
        m_stepState = STEP_STATE::IDLE;
        m_stepSvTime = 0;
        m_stepPvTime = 0;
        m_dataTime = 0;
        m_listener.onStateChanged = nullptr;
        m_listener.onDoorStateChanged = nullptr;
        m_listener.onAlarm = nullptr;
        m_listener.onRemoveAlarm = nullptr;
        m_listener.onStepChanged = nullptr;
        m_listener.onDataChanged = nullptr;
        m_nLayerCount = 1;
        resetLoadState();
    }
    CUnit::CUnit(const char* pszName)
    {
        m_strName = pszName;
        m_eqState = EQ_STATE::IDLE;
        m_doorState = 0;
        m_nAlarmCode = 0;
        m_nAlarmLevel = 0;
        m_stepState = STEP_STATE::IDLE;
        m_stepSvTime = 0;
        m_stepPvTime = 0;
        m_dataTime = 0;
        m_listener.onStateChanged = nullptr;
        m_listener.onDoorStateChanged = nullptr;
        m_listener.onAlarm = nullptr;
        m_listener.onRemoveAlarm = nullptr;
        m_listener.onStepChanged = nullptr;
        m_listener.onDataChanged = nullptr;
        m_listener.onReqLoad = nullptr;
        m_listener.onReqUnload = nullptr;
        m_nLayerCount = 1;
    }
    CUnit::~CUnit()
    {
    }
    void CUnit::setListener(UnitListener listener)
    {
        m_listener.onStateChanged = listener.onStateChanged;
        m_listener.onDoorStateChanged = listener.onDoorStateChanged;
        m_listener.onAlarm = listener.onAlarm;
        m_listener.onRemoveAlarm = listener.onRemoveAlarm;
        m_listener.onStepChanged = listener.onStepChanged;
        m_listener.onDataChanged = listener.onDataChanged;
        m_listener.onReqLoad = listener.onReqLoad;
        m_listener.onReqUnload = listener.onReqUnload;
    }
    int CUnit::getName(char* pszBuffer, int nMaxCount)
    {
        return strcpy_s(pszBuffer, nMaxCount, m_strName.c_str());
    }
    std::string& CUnit::getName()
    {
        return m_strName;
    }
    void CUnit::setState(EQ_STATE state)
    {
        m_eqState = state;
        if (m_listener.onStateChanged != nullptr) {
            m_listener.onStateChanged(this, m_eqState);
        }
    }
    EQ_STATE CUnit::getState()
    {
        return m_eqState;
    }
    const char* CUnit::getStateText()
    {
        static char* eqState[] = { "IDLE", "RUN", "DOWN", "MAINTENANCE", "MCHG", "E_TIME" };
        return eqState[(int)m_eqState];
    }
    void CUnit::setStateFromString(std::string& strState)
    {
        static const std::unordered_map<std::string, EQ_STATE> stateMap = {
            {"IDLE", EQ_STATE::IDLE},
            {"RUN", EQ_STATE::RUN},
            {"DOWN", EQ_STATE::DOWN},
            {"MAINTENANCE", EQ_STATE::MAINTENANCE},
            {"MCHG", EQ_STATE::MCHG},
            {"E_TIME", EQ_STATE::E_TIME}
        };
        auto it = stateMap.find(strState);
        if (it != stateMap.end()) {
            m_eqState = it->second;
            if (m_listener.onStateChanged != nullptr) {
                m_listener.onStateChanged(this, m_eqState);
            }
        }
        else {
            // å¤„理未找到的状态(根据需求决定是否抛出异常或设置默认值)
            // m_eqState = EQ_STATE::UNKNOWN;
        }
    }
    void CUnit::setDoorCount(int count)
    {
        m_nDoorCount = count;
    }
    void CUnit::setDoorState(int state)
    {
        m_doorState = state;
        if (m_listener.onDoorStateChanged != nullptr) {
            m_listener.onDoorStateChanged(this, state);
        }
    }
    int  CUnit::getDoorState()
    {
        return m_doorState;
    }
    std::string& CUnit::getDoorState(std::string& strState)
    {
        static char* doorState[] = {"CLOSE", "OPEN"};
        strState = "";
        int temp = (int)m_doorState;
        for (int i = 0; i < m_nDoorCount; i++) {
            if (temp & 0x01) strState += "OPEN";
            else strState += "CLOSE";
            if (i != m_nDoorCount - 1) strState += ",";
            temp = temp >> 1;
        }
        return strState;
    }
    void CUnit::setLayerCount(int count)
    {
        m_nLayerCount = min(8, count);
    }
    int CUnit::getLayerCount()
    {
        return m_nLayerCount;
    }
    void CUnit::setIndex(int index)
    {
        m_nIndex = index;
    }
    int CUnit::getIndex()
    {
        return m_nIndex;
    }
    void CUnit::setAlarm(int code, int level, const char* pszText)
    {
        if (code == 0) {
            if (m_nAlarmCode != 0) {
                m_listener.onRemoveAlarm(this, m_nAlarmCode, m_nAlarmLevel, m_strAlarmText.c_str());
            }
            m_nAlarmCode = code;
            m_nAlarmLevel = level;
            m_strAlarmText = pszText;
        }
        else {
            m_nAlarmCode = code;
            m_nAlarmLevel = level;
            m_strAlarmText = pszText;
            if (m_listener.onAlarm != nullptr) {
                m_listener.onAlarm(this, code, level, pszText);
            }
        }
    }
    int CUnit::getAlarmCode()
    {
        return m_nAlarmCode;
    }
    int CUnit::getAlarmLevel()
    {
        return m_nAlarmLevel;
    }
    std::string& CUnit::getAlarmText()
    {
        return m_strAlarmText;
    }
    int CUnit::reqLoad(int layer)
    {
        ASSERT(m_listener.onReqLoad);
        if (layer <= 0) return -1;
        if (layer > m_nLayerCount) return -2;
        // çŠ¶æ€æ”¹å˜æ‰å›žè°ƒåˆ°ä¸Šå±‚
        if (m_nLayerLoadState[layer - 1] != LAYER_LOAD_REQ) {
            m_nLayerLoadState[layer - 1] = LAYER_LOAD_REQ;
            m_listener.onReqLoad(this, layer);
            return 0;
        }
        return -3;
    }
    int CUnit::reqUnload(int layer)
    {
        ASSERT(m_listener.onReqUnload);
        if (layer <= 0) return -1;
        if (layer > m_nLayerCount) return -2;
        // çŠ¶æ€æ”¹å˜æ‰å›žè°ƒåˆ°ä¸Šå±‚
        if (m_nLayerLoadState[layer - 1] != LAYER_UNLOAD_REQ) {
            m_nLayerLoadState[layer - 1] = LAYER_UNLOAD_REQ;
            m_listener.onReqUnload(this, layer);
            return 0;
        }
        return -3;
    }
    void CUnit::stepIdle()
    {
        m_stepState = STEP_STATE::IDLE;
        if (m_listener.onStepChanged != nullptr) {
            m_listener.onStepChanged(this, m_stepState);
        }
    }
    void CUnit::stepMaterialReceived(const char* pszID)
    {
        m_stepState = STEP_STATE::MATERIAL_RECEIVED;
        m_stepMaterialId = pszID;
        if (m_listener.onStepChanged != nullptr) {
            m_listener.onStepChanged(this, m_stepState);
        }
    }
    void CUnit::stepMaterialRemoved(const char* pszID)
    {
        m_stepState = STEP_STATE::MATERIAL_REMOVEED;
        m_stepMaterialId = pszID;
        if (m_listener.onStepChanged != nullptr) {
            m_listener.onStepChanged(this, m_stepState);
        }
    }
    void CUnit::stepProcessingStarted(const char* pszID)
    {
        m_stepState = STEP_STATE::PROCESSING_STARTED;
        m_stepMaterialId = pszID;
        if (m_listener.onStepChanged != nullptr) {
            m_listener.onStepChanged(this, m_stepState);
        }
    }
    void CUnit::stepProcessing(const char* pszID, int nSvTime, int nTvTime)
    {
        m_stepState = STEP_STATE::PROCESSING;
        m_stepMaterialId = pszID;
        m_stepSvTime = nSvTime;
        m_stepPvTime = nTvTime;
        if (m_listener.onStepChanged != nullptr) {
            m_listener.onStepChanged(this, m_stepState);
        }
    }
    void CUnit::stepProcessingCompleted(const char* pszID)
    {
        m_stepState = STEP_STATE::PROCESSING_COMPLETED;
        m_stepMaterialId = pszID;
        if (m_listener.onStepChanged != nullptr) {
            m_listener.onStepChanged(this, m_stepState);
        }
    }
    STEP_STATE CUnit::getStepState()
    {
        return m_stepState;
    }
    const char* CUnit::getStepStateText()
    {
        static char* stepState[] = { "IDLE", "MATERIAL_RECEIVED", "MATERIAL_REMOVED",
            "PROCESSING_STARTED", "PROCESSING", "PROCESSING_COMPLETED" };
        return stepState[(int)m_stepState];
    }
    std::string& CUnit::getStepMaterialId()
    {
        return m_stepMaterialId;
    }
    int CUnit::getStepSvTime()
    {
        return m_stepSvTime;
    }
    int CUnit::getSetpPvTime()
    {
        return m_stepPvTime;
    }
    void CUnit::setDataTime(unsigned long long time)
    {
        m_dataTime = time;
    }
    void CUnit::setDataTimeAndResetData(unsigned long long time)
    {
        m_dataTime = time;
        m_dataMap.clear();
    }
    void CUnit::addData(const char* pszName, const char* pszDataText, bool bComplete)
    {
        m_dataMap[pszName] = pszDataText;
        if (bComplete) {
            if (m_listener.onDataChanged != nullptr) {
                m_listener.onDataChanged(this, m_dataTime);
            }
        }
    }
    unsigned long long CUnit::getDataTime()
    {
        return m_dataTime;
    }
    uint64_t CUnit::stringToTimeStamp(const std::string& strTime)
    {
        std::tm tm = {};
        std::istringstream ss(strTime);
        ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
        if (ss.fail()) {
            return 0;
        }
        std::time_t time = std::mktime(&tm);
        if (time == -1) {
            return 0;
        }
        return static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::system_clock::from_time_t(time).time_since_epoch()
        ).count());
    }
    const char* CUnit::getDataTimeText(uint64_t time)
    {
        static char buffer[32];
        auto timePoint = std::chrono::time_point<std::chrono::system_clock>(std::chrono::milliseconds(time));
        std::time_t t = std::chrono::system_clock::to_time_t(timePoint);
        std::tm tmPtr;
        if (localtime_s(&tmPtr, &t) == 0) {
            strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tmPtr);
        }
        else {
            snprintf(buffer, sizeof(buffer), "Invalid Time");
        }
        return buffer;
    }
    std::map<std::string, std::string>& CUnit::getDatas()
    {
        return m_dataMap;
    }
    std::map<int, std::string>& CUnit::getRecipes()
    {
        return m_mapRecipe;
    }
    void CUnit::addRecipe(int id, const char* pszName, bool bComplete)
    {
        m_mapRecipe[id] = pszName;
    }
    bool CUnit::checkRecipe(int id, const char* pszName)
    {
        bool bMatched = false;
        for (auto item : m_mapRecipe) {
            if (id == item.first && strcmp(pszName, item.second.c_str()) == 0) {
                bMatched = true;
                break;
            }
        }
        return bMatched;
    }
    void CUnit::resetLoadState()
    {
        for (int i = 0; i < 8; i++) {
            m_nLayerLoadState[i] = LAYER_LOAD_INIT;
        }
    }
}
SourceCode/Bond/BEQLibrary/Unit.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,112 @@
#pragma once
#include <string>
#include "IUnit.h"
#include <functional>
#include <map>
#define LAYER_LOAD_INIT        0
#define LAYER_LOAD_REQ        1
#define LAYER_UNLOAD_REQ    2
namespace BEQ {
    typedef std::function<void(void* pUnit, EQ_STATE)> ONSTATECHANGED;
    typedef std::function<void(void* pUnit, int stete)> ONDOORSTATECHANGED;
    typedef std::function<void(void* pUnit, int code, int level, const char* pszText)> ONALARM;
    typedef std::function<void(void* pUnit, STEP_STATE state)> ONSTEPCHANGED;
    typedef std::function<void(void* pUnit, unsigned long long time)> ONDATACHANGED;
    typedef std::function<void(void* pUnit, int layer)> ONREQLOAD;
    typedef struct _UnitListener
    {
        ONSTATECHANGED        onStateChanged;
        ONDOORSTATECHANGED    onDoorStateChanged;
        ONALARM                onAlarm;
        ONALARM                onRemoveAlarm;
        ONSTEPCHANGED        onStepChanged;
        ONDATACHANGED        onDataChanged;
        ONREQLOAD            onReqLoad;
        ONREQLOAD            onReqUnload;
    } UnitListener;
    class CUnit :
        public IUnit
    {
    public:
        CUnit();
        CUnit(const char* pszName);
        ~CUnit();
    public:
        virtual int getName(char* pszBuffer, int nMaxCount);
        virtual void setState(EQ_STATE state);
        virtual EQ_STATE getState();
        virtual void setDoorCount(int count);
        virtual void setDoorState(int state);
        virtual int getDoorState();
        virtual void setLayerCount(int count);
        virtual int getLayerCount();
        virtual void setIndex(int index);
        virtual int getIndex();
        virtual void setAlarm(int code, int level, const char* pszText);
        virtual int getAlarmCode();
        virtual int getAlarmLevel();
        virtual void stepIdle();
        virtual void stepMaterialReceived(const char* pszID);
        virtual void stepMaterialRemoved(const char* pszID);
        virtual void stepProcessingStarted(const char* pszID);
        virtual void stepProcessing(const char* pszID, int nSvTime, int nTvTime);
        virtual void stepProcessingCompleted(const char* pszID);
        virtual STEP_STATE getStepState();
        virtual void setDataTime(unsigned long long time);
        virtual void setDataTimeAndResetData(unsigned long long time);
        virtual unsigned long long getDataTime();
        virtual void addData(const char* pszName, const char* pszDataText, bool bComplete);
        virtual void addRecipe(int id, const char* pszName, bool bComplete);
        virtual int reqLoad(int layer);
        virtual int reqUnload(int layer);
    public:
        void setListener(UnitListener listener);
        std::string& getName();
        const char* getStateText();
        void setStateFromString(std::string& strState);
        std::string& getDoorState(std::string& strState);
        std::string& getAlarmText();
        const char* getStepStateText();
        std::string& getStepMaterialId();
        int getStepSvTime();
        int getSetpPvTime();
        uint64_t stringToTimeStamp(const std::string& strTime);
        const char* getDataTimeText(uint64_t time);
        std::map<std::string, std::string>& getDatas();
        std::map<int, std::string>& getRecipes();
        bool checkRecipe(int id, const char* pszName);
        void resetLoadState();
    private:
        UnitListener m_listener;
        std::string m_strName;
        EQ_STATE m_eqState;
        int m_nDoorCount;
        int m_doorState;
        int m_nAlarmCode;
        int m_nAlarmLevel;
        std::string m_strAlarmText;
    private:
        STEP_STATE m_stepState;
        std::string m_stepMaterialId;
        int m_stepSvTime;
        int m_stepPvTime;
        unsigned long long m_dataTime;
        std::map<std::string, std::string> m_dataMap;
        std::map<int, std::string> m_mapRecipe;
    private:
        int m_nLayerCount;
        int m_nLayerLoadState[8];        // å„层上下料状态,0:未知;1:上料请求;2:下料请求
        int m_nIndex;
    };
}
SourceCode/Bond/BEQLibrary/res/BEQLibrary.rc2
Binary files differ
SourceCode/Bond/BEQLibrary/stdafx.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,7 @@
// stdafx.cpp : åªåŒ…括标准包含文件的源文件
// BEQLibrary.pch å°†ä½œä¸ºé¢„编译头
// stdafx.obj å°†åŒ…含预编译类型信息
#include "stdafx.h"
SourceCode/Bond/BEQLibrary/stdafx.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
// stdafx.h : æ ‡å‡†ç³»ç»ŸåŒ…含文件的包含文件,
// æˆ–是经常使用但不常更改的
// ç‰¹å®šäºŽé¡¹ç›®çš„包含文件
#pragma once
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN            // ä»Ž Windows å¤´ä¸­æŽ’除极少使用的资料
#endif
#include "targetver.h"
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // æŸäº› CString æž„造函数将是显式的
#include <afxwin.h>         // MFC æ ¸å¿ƒç»„件和标准组件
#include <afxext.h>         // MFC æ‰©å±•
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxole.h>         // MFC OLE ç±»
#include <afxodlgs.h>       // MFC OLE å¯¹è¯æ¡†ç±»
#include <afxdisp.h>        // MFC è‡ªåŠ¨åŒ–ç±»
#endif // _AFX_NO_OLE_SUPPORT
#ifndef _AFX_NO_DB_SUPPORT
#include <afxdb.h>                      // MFC ODBC æ•°æ®åº“ç±»
#endif // _AFX_NO_DB_SUPPORT
#ifndef _AFX_NO_DAO_SUPPORT
#include <afxdao.h>                     // MFC DAO æ•°æ®åº“ç±»
#endif // _AFX_NO_DAO_SUPPORT
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxdtctl.h>           // MFC å¯¹ Internet Explorer 4 å…¬å…±æŽ§ä»¶çš„æ”¯æŒ
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>                     // MFC å¯¹ Windows å…¬å…±æŽ§ä»¶çš„æ”¯æŒ
#endif // _AFX_NO_AFXCMN_SUPPORT
SourceCode/Bond/BEQLibrary/targetver.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
#pragma once
// åŒ…括 SDKDDKVer.h å°†å®šä¹‰å¯ç”¨çš„æœ€é«˜ç‰ˆæœ¬çš„ Windows å¹³å°ã€‚
// å¦‚果要为以前的 Windows å¹³å°ç”Ÿæˆåº”用程序,请包括 WinSDKVer.h,并将
// å°† _WIN32_WINNT å®è®¾ç½®ä¸ºè¦æ”¯æŒçš„平台,然后再包括 SDKDDKVer.h。
#include <SDKDDKVer.h>
SourceCode/Bond/BEQLibrarySDK/Include/BEQLib.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
#pragma once
#include <vector>
#include "IServo.h"
#include "IUnit.h"
#include "IEquipment.h"
#include "IRemoteEquipment.h"
#ifdef _COMPILE_AS_LIB
    #warning "compiling as lib!"
#else
    #ifdef _DEBUG
        #ifndef _WIN64
            #pragma comment(lib, "../BEQibrarySDK/lib/Win32/Debug/BEQ.lib")
        #else
            #pragma comment(lib, "../BEQLibrarySDK/lib/x64/Debug/BEQ.lib")
        #endif
    #else
        #ifndef _WIN64
            #pragma comment(lib, "../BEQLibrarySDK/lib/Win32/Release/BEQ.lib")
        #else
            #pragma comment(lib, "../BEQLibrarySDK/lib/x64/Release/BEQ.lib")
        #endif
    #endif
#endif // !BUILD_AS_LIB
///////////////////////////////////////////////////////////////////////////////////
//// Define C linkage if using a C++ compiler
///////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
    ///////////////////////////////////////////////////////////////////////////////////
    //// Determine callling convention baesd on compiler
    ///////////////////////////////////////////////////////////////////////////////////
#ifdef __BORLANDC__
#ifdef __WIN32__
#define EXPORTED __declspec(dllexport) __stdcall
#else
#define EXPORTED FAR PASCAL __export
#endif // WIN32
#else // __BORLANDC__
#ifdef WIN32
#define EXPORTED __declspec(dllexport)
#else
#define EXPORTED FAR PASCAL __export
#endif // WIN32
#endif //__BORLANDC__
    /////////////////////////////////////////////////////////////////////////////////////
    //// å¯¼å‡ºå‡½æ•°
    ////////////////////////////////////////////////////////////////////////////////////
    int            EXPORTED    BEQ_Initialize();
    int            EXPORTED    BEQ_Term();
    int            EXPORTED    BEQ_CreateServo(BEQ::IServo*& pServo, const char* pszName);
    int            EXPORTED    BEQ_GetServo(BEQ::IServo*& pServo, const char* pszName);
    int            EXPORTED    BEQ_DestroyServo(BEQ::IServo* pServo);
    int            EXPORTED    BEQ_CreateEquipment(BEQ::IEquipment*& pEquipment, const char* pszName);
    int            EXPORTED    BEQ_GetEquipment(BEQ::IEquipment*& pEquipment, const char* pszName);
    int            EXPORTED    BEQ_DestroyEquipment(BEQ::IEquipment*& pEquipment);
#ifdef __cplusplus
};
#endif //__cplusplus
SourceCode/Bond/BEQLibrarySDK/Include/IEquipment.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
#pragma once
#include "IUnit.h"
#include <functional>
namespace BEQ {
    typedef std::function<void(void* pEiuipment, const char* pszAddr, int port)> ONCONNECTED;
    typedef std::function<void(void* pEiuipment, const char* pszAddr, int port)> ONDISCONNECTED;
    typedef std::function<int(void* pEiuipment, void* pUnit, int id)> ONRUNRECIPE;
    typedef std::function<int(void* pEiuipment, void* pUnit)> ONGETRECIPELIST;
    typedef std::function<int(void* pEiuipment, void* pUnit, const char* pszMaterielId, const char* pszRecipeId)> ONLOADREADY;
    typedef std::function<int(void* pEiuipment, void* pUnit, int layer)> ONLOADCOMPLETE;
    typedef struct _EquipmentListener
    {
        ONCONNECTED            onConnected;
        ONDISCONNECTED        onDisconnected;
        ONRUNRECIPE            onRunRecipe;
        ONGETRECIPELIST        onGetRecipeList;
        ONLOADREADY            onLoadReady;
        ONLOADCOMPLETE        onLoadComplete;
        ONLOADCOMPLETE        onUnloadComplete;
    } EquipmentListener;
    class IEquipment
    {
    public:
        virtual void setEquipmentListener(EquipmentListener listener) = 0;
        virtual int getName(char* pszBuffer, int nMaxCount) = 0;
        virtual void setName(const char* pszName) = 0;
        virtual int getVersion(char* pszBuffer, int nMaxCount) = 0;
        virtual void setVersion(const char* pszVersion) = 0;
        virtual IUnit* addUnit(const char* pszName, int nDoorCount) = 0;
        virtual IUnit* getUnit(const char* pszName) = 0;
        virtual int runOnClientMode(const char* pAddr, int port) = 0;
        virtual int runOnServerMode(int port) = 0;
        virtual int repRecipeListComplete() = 0;
        virtual int repLoadReadyComplete(int errorCode) = 0;
    };
}
SourceCode/Bond/BEQLibrarySDK/Include/IRemoteEquipment.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
#pragma once
#include "IUnit.h"
#include <functional>
namespace BEQ {
    enum class REMOTE_EQ_EVENT
    {
        UNKNOWN = 0,
        DEVICE_STATUS_CHANGED,
        DOOR_STATUS_CHANGED,
        ALARM_INFO_CHANGED,
        REMOVE_ALARM_INFO,
        PRODUCTION_PROCESS_CHANGED,
        SERSOR_DATA_CHANGED,
        RECIPE_LIST_CHANGED,
        LOAD_EVENT_CHANGED
    };
    class IRemoteEquipment
    {
    public:
        virtual int getAddr(char* pszBuffer, int nMaxCount) = 0;
        virtual int getPort() = 0;
        virtual int getName(char* pszBuffer, int nMaxCount) = 0;
        virtual int getVersion(char* pszBuffer, int nMaxCount) = 0;
        virtual bool isConnected() = 0;
        virtual int connect() = 0;
        virtual IUnit* addUnit(const char* pszName, int nDoorCount) = 0;
        virtual IUnit* getUnit(const char* pszName) = 0;
        virtual const char** getAllUnitNames() = 0;
        virtual int getUnitCount() const = 0;
        virtual ULONGLONG getConnectTick() = 0;
    };
}
SourceCode/Bond/BEQLibrarySDK/Include/IServo.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
#pragma once
#include "IRemoteEquipment.h"
namespace BEQ {
    typedef std::function<void(void* pServo, void* pRemoteEiuipment)> ONREQCONNECTED;
    typedef std::function<void(void* pServo, void* pRemoteEiuipment, int errorCode)> ONREQCONNECTFAILED;
    typedef std::function<void(void* pServo, void* pRemoteEiuipment, const char* pszData, int len)> ONREQREAD;
    typedef std::function<void(void* pServo, void* pRemoteEquipment, void* pUnit, REMOTE_EQ_EVENT eventCode)> ONREQEVENTUPDATE;
    typedef struct _ServoListener
    {
        ONREQCONNECTED        onRemoteEqConnecting;
        ONREQCONNECTED        onRemoteEqConnected;
        ONREQCONNECTFAILED    onRemoteEqConnectFailed;
        ONREQCONNECTED        onRemoteEqDisconnecting;
        ONREQCONNECTED        onRemoteEqDisconnected;
        ONREQREAD            onRemoteEqReadRawdata;
        ONREQEVENTUPDATE    onRemoteEqEventUpdate;
    } ServoListener;
    class IServo
    {
    public:
        virtual void setListener(BEQ::ServoListener listener) = 0;
        virtual int getName(char* pszBuffer, int nMaxCount) = 0;
        virtual int createRemoteEquipment(IRemoteEquipment*& pRemoteEquipment, const char* pszAddr, int port) = 0;
        virtual int connectRemoteEquipment(IRemoteEquipment* pRemoteEquipment) = 0;
    };
}
SourceCode/Bond/BEQLibrarySDK/Include/IUnit.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
#pragma once
namespace BEQ {
    enum class EQ_STATE
    {
        IDLE = 0,
        RUN,
        DOWN,
        MAINTENANCE,
        MCHG,
        E_TIME
    };
    enum class STEP_STATE
    {
        IDLE = 0,
        MATERIAL_RECEIVED,
        MATERIAL_REMOVEED,
        PROCESSING_STARTED,
        PROCESSING,
        PROCESSING_COMPLETED
    };
    class IUnit
    {
    public:
        virtual int getName(char* pszBuffer, int nMaxCount) = 0;
        virtual void setState(EQ_STATE state) = 0;
        virtual EQ_STATE getState() = 0;
        virtual void setDoorCount(int count) = 0;
        virtual void setDoorState(int state) = 0;
        virtual int  getDoorState() = 0;
        virtual void setLayerCount(int count) = 0;
        virtual int getLayerCount() = 0;
        virtual void setIndex(int index) = 0;
        virtual int getIndex() = 0;
        virtual void setAlarm(int code, int level, const char* pszText) = 0;
        virtual int getAlarmCode() = 0;
        virtual int getAlarmLevel() = 0;
        virtual void stepIdle() = 0;
        virtual void stepMaterialReceived(const char* pszID) = 0;
        virtual void stepMaterialRemoved(const char* pszID) = 0;
        virtual void stepProcessingStarted(const char* pszID) = 0;
        virtual void stepProcessing(const char* pszID, int nSvTime, int nTvTime) = 0;
        virtual void stepProcessingCompleted(const char* pszID) = 0;
        virtual STEP_STATE getStepState() = 0;
        virtual void setDataTime(unsigned long long time) = 0;
        virtual void setDataTimeAndResetData(unsigned long long time) = 0;
        virtual unsigned long long getDataTime() = 0;
        virtual void addData(const char* pszName, const char* pszDataText, bool bComplete) = 0;
        virtual void addRecipe(int id, const char* pszName, bool bComplete) = 0;
        virtual int reqLoad(int layer) = 0;
        virtual int reqUnload(int layer) = 0;
    };
}
SourceCode/Bond/BLControlsSDK/include/BLButton.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,82 @@
#if !defined(AFX_BLBUTTON_H__16C6D980_BD45_11D3_BDA3_00104B133581__INCLUDED_)
#define AFX_BLBUTTON_H__16C6D980_BD45_11D3_BDA3_00104B133581__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// BLButton.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CBLButton by Niek Albers
// Thanks to some people for the tooltip.
// A cool CBitmapButton derived class with 3 states,
// Up/Down/BL.
class AFX_EXT_CLASS CBLButton : public CBitmapButton
{
    DECLARE_DYNAMIC(CBLButton);
    // Construction
public:
    CBLButton();
    void SetToolTipText(CString* spText, BOOL bActivate = TRUE);
    void SetToolTipText(int nId, BOOL bActivate = TRUE);
    void SetWindowText(CString strText);
    void SetFontSize(int nSize);
    void SetTextColor(COLORREF rgbNormal, COLORREF rgbDisable);
    void SetBLButtonStyle(UINT uID, int nImgCount);
    void SetBLButtonStyle(UINT uID, int nImgCount, CString spTipText);
    void SetBLButtonStyle(UINT uID, int nImgCount, CString spTipText, CString spBtnText, int nFontSize);
    CString m_strText;
    CDC      m_gMemDC;
// Attributes
protected:
    void fPaint(CDC* pDC);
    void ActivateTooltip(BOOL bActivate = TRUE);
    BOOL m_bBL;                        // indicates if mouse is over the button
    CSize m_ButtonSize;                    // width and height of the button
    CBitmap m_Bitmap;
    BOOL m_bTracking;
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CBLButton)
    protected:
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    //}}AFX_VIRTUAL
// Implementation
public:
    BOOL LoadBitmap(UINT bitmapid, UINT uiImageCount);
    virtual ~CBLButton();
    // Generated message map functions
protected:
    CToolTipCtrl m_ToolTip;
    void InitToolTip();
    //{{AFX_MSG(CBLButton)
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg LRESULT OnMouseLeave(WPARAM wparam, LPARAM lparam);
    afx_msg LRESULT OnMouseHOver(WPARAM wparam, LPARAM lparam) ;
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
private:
    UINT m_uiImageCount;
    CFont    m_Font;
    LOGFONT        m_lf;
    COLORREF m_RGBTextNormal;
    COLORREF m_RGBTextDisable;
    BOOL m_bIsDisable;    // Disable老 é”­ç»° è‡‚磊祸阑 å®˜æ“æ‰ å›°ç§¦.
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_BLBUTTON_H__16C6D980_BD45_11D3_BDA3_00104B133581__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/BLFolderScheduling.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
// BLFolderScheduling.h: interface for the CBLFolderScheduling class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_BLFOLDERSCHEDULING_H__2C8D9E82_222F_41FD_A78D_C17563334CA1__INCLUDED_)
#define AFX_BLFOLDERSCHEDULING_H__2C8D9E82_222F_41FD_A78D_C17563334CA1__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define TARGETTYPE_FOLDER        1
#define TARGETTYPE_FILE            2
struct SSubPathInfo
{
    CString        s_strItemPath;
    CString        s_strItemName;
    long        s_nCreateDate;
    int            s_nItemType;
    SSubPathInfo()
    {
        Reset();
    }
    void Reset()
    {
        s_strItemPath = _T("");
        s_strItemName = _T("");
        s_nCreateDate = 0;
        s_nItemType = 0;
    }
    // æ±—荤 ç§¯å·±ç£Š.
    SSubPathInfo(const SSubPathInfo& rhs)
    {
        if(this != &rhs)
        {
            s_strItemPath = rhs.s_strItemPath;
            s_strItemName = rhs.s_strItemName;
            s_nCreateDate = rhs.s_nCreateDate;
            s_nItemType = rhs.s_nItemType;
        }
    }
    // æŽªæ¶æ¥·é­‚磊 å·æ»šè‚ºçˆ¹.
    SSubPathInfo& operator=(const SSubPathInfo& rhs)
    {
        if(this != &rhs)
        {
            s_strItemPath = rhs.s_strItemPath;
            s_strItemName = rhs.s_strItemName;
            s_nCreateDate = rhs.s_nCreateDate;
            s_nItemType = rhs.s_nItemType;
        }
        return *this;
    }
};
class AFX_EXT_CLASS CBLFolderScheduling
{
public:
    CBLFolderScheduling();
    CBLFolderScheduling(CString strPath);
    CBLFolderScheduling(CString strPath, int nTargetType);
    virtual ~CBLFolderScheduling();
    BOOL SetRemainDelete(CString strPath, int nTargetType, int nRemainItemCount);
    BOOL CommitSchedule();
    void ResetSchedule();
protected:
    BOOL SearchSubItem(const CString &strMainPath, BOOL bIsAscending);
    BOOL SortSubItem(BOOL bIsAscending);    // å·æŠšçž’鉴 TRUE, éƒ´è¦†çž’鉴 FALSE
    BOOL DeleteFolder(const CString &strFolder);
    // åŒ…府甫 ä¸” å¼¥æƒ‘å›° ç‰ˆè‚º.
    CString                m_strMainPath;
    BOOL                m_bTargetFolder;
    BOOL                m_bTargetFile;
    BOOL                m_bIsAscending;
    // è€ä½•父 å·¢æ‰ç»Š æ˜åŠ›.
    int                    m_nRemainItemCount;
    // åŒ…府 æŽªæƒ‘ æ²¥ç„Š
    SSubPathInfo*        m_pPathInfo;
    int                    m_nSubItemCount;
};
#endif // !defined(AFX_BLFOLDERSCHEDULING_H__2C8D9E82_222F_41FD_A78D_C17563334CA1__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/BLJogBtn2Parent.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,7 @@
// by ChaeBL
typedef struct _BLJOGBTN2PARENT
{
    virtual BOOL SendMessageToParent(LPCTSTR message) = 0;
    virtual BOOL SendMessageToParent(int nMsg) = 0;
} BLJogBtn2Parent, *pBLJogBtn2Parent;
SourceCode/Bond/BLControlsSDK/include/BLJogButton.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
#if !defined(AFX_BLJOGBUTTON_H__51BB375B_98EA_4921_B964_90AC2D952D70__INCLUDED_)
#define AFX_BLJOGBUTTON_H__51BB375B_98EA_4921_B964_90AC2D952D70__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// BLJogButton.h : header file
//
#include "BLJogBtn2Parent.h"
/////////////////////////////////////////////////////////////////////////////
// CBLJogButton window
class AFX_EXT_CLASS CBLJogButton : public CButton
{
// Construction
public:
    CBLJogButton();
// Attributes
public:
// Operations
public:
    void SetJ2M(pBLJogBtn2Parent pJ2M)            { m_pJ2M = pJ2M; }
    void SetStringDown(CString strMsg)            { m_strMessageDown = strMsg; }
    void SetStringUp(CString strMsg)            { m_strMessageUp = strMsg; }
    void SetIntDown(int nMsg)                    { m_nMessageDown = nMsg; }
    void SetIntUp(int nMsg)                        { m_nMessageUp = nMsg; }
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CBLJogButton)
    //}}AFX_VIRTUAL
// Implementation
public:
    virtual ~CBLJogButton();
    // Generated message map functions
protected:
    //{{AFX_MSG(CBLJogButton)
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
private:
    pBLJogBtn2Parent    m_pJ2M;
    CString                m_strMessageDown;
    CString                m_strMessageUp;
    int                    m_nMessageDown;
    int                    m_nMessageUp;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_JOGBUTTON_H__51BB375B_98EA_4921_B964_90AC2D952D70__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/BLLabel.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,77 @@
#if !defined(AFX_BLLABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_)
#define AFX_BLLABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// Label.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CBLLabel window
enum FlashType {None, Text, Background };
class AFX_EXT_CLASS CBLLabel : public CStatic
{
// Construction
public:
    CBLLabel();
    CBLLabel& SetBkColor(COLORREF crBkgnd);
    CBLLabel& SetTextColor(COLORREF crText);
    CBLLabel& SetText(const CString& strText);
    CBLLabel& SetFontBold(BOOL bBold);
    CBLLabel& SetFontName(const CString& strFont);
    CBLLabel& SetFontUnderline(BOOL bSet);
    CBLLabel& SetFontItalic(BOOL bSet);
    CBLLabel& SetFontSize(int nSize);
    CBLLabel& SetSunken(BOOL bSet);
    CBLLabel& SetBorder(BOOL bSet);
    CBLLabel& FlashText(BOOL bActivate);
    CBLLabel& FlashBackground(BOOL bActivate);
    CBLLabel& SetLink(BOOL bLink);
    CBLLabel& SetLinkCursor(HCURSOR hCursor);
// Attributes
public:
protected:
    void ReconstructFont();
    COLORREF    m_crText;
    HBRUSH        m_hBrush;
    HBRUSH        m_hwndBrush;
    LOGFONT        m_lf;
    CFont        m_font;
    CString        m_strText;
    BOOL        m_bState;
    BOOL        m_bTimer;
    BOOL        m_bLink;
    FlashType    m_Type;
    HCURSOR        m_hCursor;
            // Operations
public:
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CBLLabel)
    //}}AFX_VIRTUAL
// Implementation
public:
    virtual ~CBLLabel();
    // Generated message map functions
protected:
    //{{AFX_MSG(CBLLabel)
    afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_BLLABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/BLListBoxLog.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,96 @@
#if !defined(AFX_BLLISTBOXLOG_H__60501A52_5401_435F_996E_F3EABB095333__INCLUDED_)
#define AFX_BLLISTBOXLOG_H__60501A52_5401_435F_996E_F3EABB095333__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// cBLListBoxLog.h : header file
//
#include "BLFolderScheduling.h"
/////////////////////////////////////////////////////////////////////////////
// CBLListBoxLog window
#define LOG_NORMAL        1
#define LOG_HISTORY        2
#define LOG_WARNING        3
#define LOG_ERROR        4
#define LOG_DEBUG        5
#define STRINGBUFFER_COUNT        200
class AFX_EXT_CLASS CBLListBoxLog : public CListBox
{
// Construction
public:
    CBLListBoxLog();
    virtual ~CBLListBoxLog();
// Attributes
public:
// Operations
public:
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CBLListBoxLog)
    //}}AFX_VIRTUAL
    //////////////////////////////////////////////////////////////////////////
    // Logging
    void    SetPath(CString& strPath, CString& strName, BOOL bDelete, int nRemainCount);
    void    DisplayMessages(BOOL bAddMsgBox, int nLevel, TCHAR *str, ...);
    void    DisplayMessages(BOOL bAddMsgBox, TCHAR *str, ...);
    void    DisplayMessage(BOOL bAddMsgBox, int nLevel, TCHAR *str);
    void    DisplayMessage(BOOL bAddMsgBox, TCHAR *str);
    void    SetTextColor(long clbg1 = RGB(255,255,255), long clbg2 = RGB(255,255,255), long clText = RGB(0,0,0));
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS);
    // Generated message map functions
protected:
    //{{AFX_MSG(CBLListBoxLog)
    afx_msg LRESULT OnDisplayMessage(WPARAM wParam, LPARAM lParam);
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    //////////////////////////////////////////////////////////////////////////
    // Folder Management
    CBLFolderScheduling    m_FolderSchedule;
    //////////////////////////////////////////////////////////////////////////
    // Logging
    CString                m_strLogDir;
    CString                m_strFileName;
    CString                m_strLogPath;
    CString                m_strLogFile;
    CTime                m_TimeLogFile;
    CFile*                m_pFileLog;
    TCHAR                m_strBuffer[512];
    BOOL                MakeLogFile();
    BOOL                WriteToFile(CTime& time, CString& strContents);
    BOOL                WriteToFile(CTime& time, TCHAR* strContents);
    DWORD                m_dwThreadID;
    CString                m_strArray[STRINGBUFFER_COUNT];
    BOOL                m_bMustDisplay[STRINGBUFFER_COUNT];
    int                    m_nAddIndex;
    int                    m_nReadIndex;
    CRITICAL_SECTION    m_csLog;
    long                m_clBG1;
    long                m_clBG2;
    long                m_clText;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_BLLISTBOXLOG_H__60501A52_5401_435F_996E_F3EABB095333__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/BLListCtrlExt.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,137 @@
#if !defined(AFX_BLLISTCTRLEXT_H__516D59C3_2F02_47C6_8F4A_D6A78DCDD44A__INCLUDED_)
#define AFX_BLLISTCTRLEXT_H__516D59C3_2F02_47C6_8F4A_D6A78DCDD44A__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// BLListCtrlExt.h : header file
//
#include <afxtempl.h>
#include "InPlaceEdit.h"
#include "InPlaceComboBox.h"
#define EDITDISABLE_NONE    0
#define EDITDISABLE_ROWS    1
#define EDITDISABLE_COLS    2
#define EDITDISABLE_ROWCOL    3
#define INPLACECTRL_EDIT    4
#define INPLACECTRL_COMBO    5
#define INPLACECTRL_EDIT_COMBO    6
#define EDITDISABLE_ROWS_ARRAY    7
#define EDITDISABLE_COLS_ARRAY    8
#define COMBODATASTATE_SINGLE 9
#define COMBODATASTATE_MULTI  10
/////////////////////////////////////////////////////////////////////////////
// CBLListCtrlExt window
typedef struct _LISTROWCOLOR
{
    int            s_nRow;
    COLORREF    s_Color;
} ListRowColor, *pListRowColor;
class AFX_EXT_CLASS CBLListCtrlExt : public CListCtrl
{
// Construction
public:
    CBLListCtrlExt();
    virtual ~CBLListCtrlExt();
// Attributes
public:
// Operations
public:
    void SetComboCtrlCols(CString strCols,int nLength);
    void SetEditCtrlCols(CString strCols,int nLength);
    void SetComboData(TCHAR *pData[],int nState,int nLength);
    void SetComboData(CStringList *pList, int nState);
    void EditDisableRows(CString strRows,int nLength);
    void EditDisableCols(CString strCols,int nLength);
    BOOL GetEnableSortList();
    void SetEnableSortList(BOOL nEnable);
    void SortListCtrl(int nCol);
    void InitListHeader(TCHAR *colList[],int *widthList,int nLength, int nHeight);
    void SetInPlaceCtrl(int nCtrl);
    void SetDefaultEditText(CString strInitText);
    void SetEditDisableState(int nState);
    int GetEditDisableCols();
    int GetEditDisableRows();
    int GetEditDisableState();
    void EditDisableRowCol(int nRow,int nCol);
    void EditDisableCols(int nCols);
    void EditDisableRows(int nRows);
    void SetColNum(int nColNum);
    void AddBlankItem();
    CImageList* SetImageList(CImageList* pImageList, int nImageListType);
    void InsertListItemEx(int nRow, int nCol, const CString& strString);
    void InsertListItemEx(int nRow, int nCol, int nValue);
    void InsertListItemEx(int nRow, int nCol, double dValue, int nRight = 3);
    void SetTextColor(int nRow, COLORREF clrText);
    void SetBKColor(int nRow, COLORREF clrBK);
    void ReleaseTextColor(int nRow);
    void ReleaseBKColor(int nRow);
    void ResetTextColor();
    void ResetBKColor();
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CBLListCtrlExt)
    //}}AFX_VIRTUAL
protected:
    CInPlaceEdit *m_pEdit;
    CInPlaceComboBox *m_pComboBox;
    int m_nInPlaceCtrl;
    int m_nColNum;
    int m_nEditDisableState;
    int m_nDisableCol;
    int m_nDisableRow;
    BOOL m_bSortOrder;
    CString m_strInitEditText;
    BOOL m_bEnableSortList;
    int *m_pEditDisableCols;
    int *m_pEditDisableRows;
    // Generated message map functions
protected:
    int m_nComboCtrlLength;
    int m_nEditCtrlLength;
    int *m_pComboCtrlCols;
    int *m_pEditCtrlCols;
    CStringList *m_pComboData;
    int m_nLength;
    int m_nComboDataState;
    BOOL m_bSetImageList;
// Implementation
public:
    CList<pListRowColor, pListRowColor>    m_ListColorText;
    CList<pListRowColor, pListRowColor>    m_ListColorBk;
    // Generated message map functions
protected:
    //{{AFX_MSG(CBLListCtrlExt)
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
    afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
    afx_msg void OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_BLLISTCTRLEXT_H__516D59C3_2F02_47C6_8F4A_D6A78DCDD44A__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/CellCtrl.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,304 @@
#ifndef _CELLCTRL_H_
#define _CELLCTRL_H_
#define _CELLCTRL_LIB_H_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// CellCtrl.h : header file
//
#include "HeadCtrl.h"
#ifndef  __AFXTEMPL_H
#include <afxtempl.h>
#endif
/////////////////////////////////////////////////////////////////////////////
// CCellCtrl window
#define CCMSG_USE_EDIT            WM_USER+1
#define CCMSG_MOVE_EDIT            WM_USER+2
#define CCMSG_RECT_CHANGE        WM_USER+3
//#define CCMSG_SEL_PRINT        WM_USER+4
#define CCMSG_LIST_PRINT        WM_USER+5
#define CCMSG_FONT_CHANGE        WM_USER+6
#define CCMSG_SAVE_FILE            WM_USER+7
#define CCMSG_OPEN_EXCEL        WM_USER+8
#define CCMSG_OPEN_LIST            WM_USER+9
#define CCMSG_MODIFY_EDIT        WM_USER+10
#define CCMSG_COPY_CLIPBOARD    WM_USER+11
#define CCMSG_PASTE_CLIPBOARD    WM_USER+12
#define CCMSG_CUT_CLIPBOARD        WM_USER+13
#define CCMSG_SELITEM_DELETE    WM_USER+14
#define CCMSG_BACK_COLOR        WM_USER+15
#define CCMSG_TEXT_COLOR        WM_USER+16
#define CCMSG_LIST                WM_USER-1
const COLORREF clrTEXT=0x00000000;
const COLORREF clrBACK=0x00FFFFFF;
class AFX_EXT_CLASS CCellCtrl : public CListCtrl
{
public:
    struct LOCATION
    {
        int nItem;
        int nSubItem;
    };
    struct CELLCOLOR
    {
        COLORREF txtclr;
        COLORREF bkgclr;
    };
    struct CELLINFO
    {
        int nId;            //CONTROL ID
        int nItem;            //LIST ITEM
        int nSubItem;        //LIST SUBITEM
        CELLCOLOR oldClr;    //汲沥傈狼 ç¥¸
        CELLCOLOR newClr;    //汲沥饶狼 ç¥¸
        LPWSTR lpstrOld;    //涝仿傈 å·©ç£Šå‡¯
        LPWSTR lpstrNew;    //涝仿茄 å·©ç£Šå‡¯
    };
    struct CELLDATA
    {
        COLORREF txtclr;//臂磊祸
        COLORREF bkgclr;//硅版祸
        bool     bUseCtl;//牧飘费 è¤ä¾©
        bool     bTurn; //馆娄馆娄
        DWORD    dwData;
    };
    class CCellData : public CELLDATA
    {
    public:
        CCellData()
        {
            bTurn =false;
            bUseCtl=false;//牧飘费 è¤ä¾©
            txtclr=clrTEXT;
            bkgclr=clrBACK;
            dwData=0;
        }
        CCellData(COLORREF TextColor, COLORREF BackColor,
                  bool bTurning, DWORD dwUserData=0)
        {
            bTurn =bTurning;
            bUseCtl=false;//牧飘费 è¤ä¾©
            txtclr=TextColor;
            bkgclr=BackColor;
            dwData=dwUserData;
        }
        virtual ~CCellData(){;}
        void operator=(const CELLDATA& cc)
        {
            (CELLDATA)*this=cc;
        }
    };
    typedef CArray<CCellData, CCellData&> CCSArray;
    virtual void SerializeAllInfo(CArchive& ar);
protected:
    CBrush m_brush;        //俊叼飘冠胶狼 ç¡…版
    CEdit  m_edit;        //俊叼飘 å† èƒ¶
    BOOL    m_bCanEdit;
    CFont* m_pFont;        //府胶飘 è¿„飘
protected:
    void Printing(CDC* pDC);//府胶飘甫 æ©‡èµ´é£˜è‚º å…ä»¿èŒ„促.
    CRect GetLogRect(CDC* pDC, int nItem, int nSubItem);//府胶飘 ä¼ŽRect阑 åŽšå•¦ä¿Š è¶æ‰¼ å‡½åˆ¸èŒ„促.
    void SetCrtToPrintRate(CDC* pDC);//拳搁苞 åŽ˜é’Žç‹¼ åŽšå•¦é˜‘ å¤‡èŒ„促.
    int  GetCrtWidth();//拳搁(府胶飘)狼 æ°”蔼阑 åºœç•”茄促.
protected:
    BOOL m_bSort;//Sort Flag
    BOOL m_bTime;//SetTimer(,,)甫 æ±²æ²¥æ²ç»°ç˜¤ å’¯ä½•
    BOOL m_bTurnDraw;//府胶飘 ç›Žè„šçŸ« ä¼Žç‹¼ ç¥¸å½¬æž å‡½ç§¦å…·çªç»°ç˜¤ å’¯ä½•
    UINT  m_nClipOptin;//努赋焊靛 å¯è®°
    CHeadCtrl m_head;//HeaderCtrl
    LOCATION m_mcLct;//right mouse click
    LOCATION m_edLct;//edit location
    UINT m_nStartColEdit;
    UINT m_nEndColEdit;
    CMenu m_menu;//府胶飘 çš‹æ˜¥
    CMenu* m_pUmenu;//荤侩磊 æ²¥ç‹¼ çš‹æ˜¥
    CELLINFO* m_pInfo;
    //汲沥等 Item Data甫 æ˜åŠ›èŒ„ä¿ƒ.
    void DeleteItemData(int nItem);
    void DeleteAllItemData();
    //俊叼飘冠胶狼 Data甫 èæ²¥æ²ç»°ç˜¤ å’¯ä½•甫 çœ‰å†œçªç»Š
    //何葛扩档快肺 çš‹çŸ«ç˜¤ç”« ç„Šè¾°ä¿ƒ.
    BOOL IsModifyEdit(int nItem, int nSubItem);
    //酒捞袍狼 åº·å¼€æž å‡½æ²é˜‘ ç‰ˆå¿«ä¿Š ä¿Šå¼é£˜å† èƒ¶ç‹¼ å†œæ‰æ¡£ å‡½ç§¦å…· çªéª¨è‚º
    //促澜窃荐甫 æžä¾©çªå’¯ ä¿Šå¼é£˜å† èƒ¶ç”« ç›Žè„šèŒ„促.
    void UpdateEdit(int nItem, int nSubItem);
    //伎狼 åº·å¼€é˜‘ ç›Žè„šèŒ„促.
    void UpdateCell(int nItem, int nSubItem);
    //伎狼 æ‹¿çŸ¾å•Š å‡½çªæ¡£åºŸ æ±²æ²¥ç™»ç»¢ ä¹ç»°ç˜¤ å’¯ä½•
    bool IsTurning(int nItem, int nSubItem);
    //府胶飘狼 æ²¥çºº left,right,center å±ˆä¾¥é˜‘ å¤‡èŒ„促.
    int  GetColumnFmt(int nSubItem);
public:
    enum ListOption
    {
        //MENU OPTION
        menuNO        =    0x00000000,
        menuEXCEL    =    0x00000001,
        menuLIST    =    0x00000002,
        menuPRINT    =    0x00000004,
        menuINPUT    =    0x00000010,
        menuSAVE    =    0x00000020,
        menuFONT    =    0x00000040,
        menuBACKCOLOR=    0x00000100,
        menuTEXTCOLOR=    0x00000200,
        menuCOPY    =    0x00010000,
        menuPASTE    =    0x00020000,
        menuCUT        =    0x00040000,
        menuDELETE    =    0x00080000,
        menuCOMMON    =    0x000000FF,
        menuCLIP    =    0x000F0000,
        menuALL        =    0x000FFFFF,
        menuAceept  =   0x00010000,
        //CLIPBOARD OPTION
        clipNO        =    0x00000000,
        clipCOPY    =    0x00000001,
        clipPASTE    =    0x00000002,
        clipCUT        =    0x00000004,
        clipDELETE    =    0x00000008,
        clipALL        =    0x0000FFFF,
    };
    CCellCtrl();
    //Sort function
    void EnableSort(BOOL bSort=TRUE){m_bSort=bSort;}
    void EnableEdit(BOOL bCanEdit)    { m_bCanEdit = bCanEdit; }
    //menu function
    BOOL CCellCtrl::SetMenu(CMenu* pMenu=NULL){m_pUmenu=pMenu; return TRUE;}
    void UseMenu( UINT nOption=menuCOMMON/*default=menuCOMMON*/);
    //editbox function
    BOOL SetEditMovable( int nStartCol, int nEndCol);
    BOOL UseEdit( int nItem, int nSubItem);
    void EditCtrl( MSG pMsg );
    //Rect捞 å‡½æ²ç»°ç˜¤ é­„窜茄促.
    BOOL IsSubRectChange();
    //府胶飘甫 æ©‡èµ´é£˜è‚º å…ä»¿èŒ„促.
    BOOL ListPrinting(BOOL bDialog, int Orientation=1/*啊肺=1, æŠ€è‚º=2*/);
    //keystate function
    BOOL IsMultiKey();//shift虐, ctrl虐殿捞 å–˜çŸ¾è„¸ç»°ç˜¤ check茄促
    //font function
    void SetLogFont(LOGFONT logfont);//厘钎 è¿„飘
    void SetListFont(LOGFONT* logfont);//府胶飘 è¿„飘
    //
    int GetSubItemCount();        //拿烦荐甫 å¤‡èŒ„促.
    int GetLeftSubItem();        //谅螟栏肺何磐 åŠå·±æ‹³ç­‰ æ‹¿çƒ¦é˜‘ èŒ«ç»°ä¿ƒ.
    int GetRightSubItem();        //快螟栏肺何磐 åŠå·±æ‹³ç­‰ æ‹¿çƒ¦é˜‘ èŒ«ç»°ä¿ƒ.
    //荤侩磊啊 éž˜å¤¸èŒ„ è”¼é˜‘ åŽ†åŽ˜çªç»Š é˜‚矾棵荐 ä¹ç»° çªƒèæžä¿ƒ.
    BOOL SetCellData(int nItem, int nSubItem, DWORD dwData);
    DWORD GetCellData(int nItem, int nSubItem);
    //color function
    BOOL SetItemTextColor(int nItem, COLORREF color);
    BOOL SetItemTextColor(int nItem, int nSubItem, COLORREF color);
    BOOL SetItemBkColor(int nItem, COLORREF color, bool bTurn=false);
    BOOL SetItemBkColor(int nItem, int nSubItem, COLORREF color, bool bTurn=false);
    BOOL GetItemColor(int nItem, int nSubItem, CELLCOLOR* pCellClr);
    //Clipboard function
    void UseClipboard( UINT nOption=clipALL/*default=clipALL*/){m_nClipOptin=nOption;}
    void CopyClipboard();// Ctrl C (select item copy)
    void PasteClipboard();//Ctrl V (paste)
    void CutClipboard();//Ctrl V (paste)
    void SelectItemDelete();
    BOOL DeleteColumn( int nCol );
    int  InsertColumn(int nCol, LPCTSTR lpstTxt,int nFormat=LVCFMT_LEFT,
                        int nWidth = -1, int nSubItem = -1);
    //HeaderCtrl function
    BOOL GetSafeHead();
    int  GetHeadHeight();
    int  GetHeadItemCount();
    void SetHeadItemCount(int nCount);
    void SetHeadItemText(int nItem, int nSubItem, LPCTSTR lpstTxt);
    CString GetHeadItemText(int nItem, int nSubItem);
    void SetHeadItemMerge(int nsItem, int nsSubItem,
                          int neItem, int neSubItem);
protected:
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CCellCtrl)
    public:
    virtual void Serialize(CArchive& ar);
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    protected:
    //}}AFX_VIRTUAL
// Implementation
public:
    void SaveFile();
    virtual ~CCellCtrl();
    // Generated message map functions
protected:
    //{{AFX_MSG(CCellCtrl)
//    afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
    afx_msg void OnRclick(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
    afx_msg void OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
    afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
    afx_msg void OnInsertitem(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnDeleteitem(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnDeleteallitems(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnDestroy();
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    //}}AFX_MSG
    afx_msg void OnCustomdrawList ( NMHDR* pNMHDR, LRESULT* pResult );
    afx_msg void OnSaveFile();
    afx_msg void OnOpenExcel();
    afx_msg void OnOpenList();
    afx_msg void OnUseEdit();
    afx_msg void OnMoveEdit();
    afx_msg void OnRectchange();
    afx_msg void OnListPrint();
    afx_msg void OnFontChange();
    afx_msg void OnBackColor();
    afx_msg void OnTextColor();
    afx_msg void OnCopyClipboard()    {    CopyClipboard();    }
    afx_msg void OnPasteClipboard()    {    PasteClipboard();    }
    afx_msg void OnCutClipboard()    {    CutClipboard();        }
    afx_msg void OnSelItemDelete()    {    SelectItemDelete();    }
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(_CELLCTRL_H_)
SourceCode/Bond/BLControlsSDK/include/ColorButton.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,101 @@
// Written by Marius Bancila (mbancila@yahoo.com)
// Copyright (c) 2004.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included. If
// the source code in  this file is used in any commercial application
// then acknowledgement must be made to the author of this file
// (in whatever form you wish).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
// Please use and enjoy. Please let me know of any bugs/mods/improvements
// that you have found/implemented and I will fix/incorporate them into this
// file.
#if !defined(AFX_COLORBUTTON_H__EB5FACDB_272F_4883_A997_659DDA42FD38__INCLUDED_)
#define AFX_COLORBUTTON_H__EB5FACDB_272F_4883_A997_659DDA42FD38__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ColorButton.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CColorButton window
class AFX_EXT_CLASS CColorButton : public CButton
{
private:
    enum {    BUTTON_IN            = 0x01,
            BUTTON_OUT            = 0x02,
            BUTTON_BLACK_BORDER    = 0x04,};
// Construction
public:
    CColorButton();
    CColorButton(COLORREF text, COLORREF bkgnd);
    CColorButton(COLORREF text, COLORREF bkgnd, COLORREF disabled);
    CColorButton(COLORREF text, COLORREF bkgnd, COLORREF disabled, COLORREF light, COLORREF highlight, COLORREF shadow, COLORREF darkShadow);
// Attributes
public:
private:
    COLORREF m_TextColor;
    COLORREF m_BkgndColor;
    COLORREF m_DisabledBkgndColor;
    COLORREF m_Light;
    COLORREF m_Highlight;
    COLORREF m_Shadow;
    COLORREF m_DarkShadow;
// Operations
public:
    void SetColor(COLORREF text, COLORREF bkgnd);
    void SetColor(COLORREF text, COLORREF bkgnd, COLORREF disabled);
    void SetColor(COLORREF text, COLORREF bkgnd, COLORREF disabled, COLORREF light, COLORREF highlight, COLORREF shadow, COLORREF darkShadow);
    void SetColorToWindowsDefault();
private:
    void DrawFrame(CDC *pDC, CRect rc, int state);
    void DrawFilledRect(CDC *pDC, CRect rc, COLORREF color);
    void DrawLine(CDC *pDC, long sx, long sy, long ex, long ey, COLORREF color);
    void DrawButtonText(CDC *pDC, CRect rc, CString strCaption, COLORREF textcolor);
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CColorButton)
    public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    //}}AFX_VIRTUAL
// Implementation
public:
    virtual ~CColorButton();
    // Generated message map functions
protected:
    //{{AFX_MSG(CColorButton)
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_COLORBUTTON_H__EB5FACDB_272F_4883_A997_659DDA42FD38__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/DefectMap.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,124 @@
// DefectMap.h: interface for the CDefectMap class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_DEFECTMAP_H__CF34B34E_7A0E_4CBB_880F_4C41FF83A64B__INCLUDED_)
#define AFX_DEFECTMAP_H__CF34B34E_7A0E_4CBB_880F_4C41FF83A64B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define ORIGIN_LEFTTOP        1
#define ORIGIN_LEFTBOTTOM    0
#define ORIGIN_RIGHTTOP        2
#define ORIGIN_RIGHTBOTTOM    3
#define UM_MAP_CHANGED            5573
enum OriginDirection        { OD_LeftTop = 0, OD_RightTop = 1, OD_LeftBottom = 10, OD_RightBottom = 11 };
class AFX_EXT_CLASS CDefectMap  : public CStatic
{
public:
    CDefectMap();
    virtual ~CDefectMap();
public:
    void                InitGlass(CWnd* pParent, int nMapWidth, int nMapHeight, int nMapMargin);    // Pixel çªœå›° ä»˜æŸ³.
    void                DeinitGlass();
    int                    GetMapTotalWidth()        { return m_nMapTotalWidth; }
    int                    GetMapTotalHeight()        { return m_nMapTotalHeight; }
    int                    GetMapWidth()            { return m_nMapWidth; }
    int                    GetMapHeight()            { return m_nMapHeight; }
    void                SetMiniMap(BOOL bIsMiniMap, int nUnitSize)    { m_bIsMiniMap = bIsMiniMap; m_nUnitSize = nUnitSize; }
    int                    GetUnitSize()            { return m_nUnitSize; }
    virtual void        DrawGlass(CDC* pDC)                        { }
    virtual void        MouseRBtnDwn(CPoint& point)                { }
    virtual void        MouseLBtnDwn(CPoint& point)                { }
    virtual void        MouseLBtnUp(CPoint& point)                { }
    virtual void        MouseLBtnMove(CPoint& point)            { }
    virtual void        MouseLBtnDblClk(CPoint& point)            { }
    virtual void        Timer(UINT_PTR nIDEvent)                    { }
    // çŠ¬æŽª/绵家
    void                IncreaseRatio();
    void                DecreaseRatio();
    void                ResetRatio();
    CPoint&                GetDisplayStart()        { return m_PointGlassStart; }
    CPoint&                GetDisplayEnd()            { return m_PointGlassEnd; }
    void                SetDisplayRect(CPoint& PointStart, CPoint& PointEnd);
    void                SetShowShot(BOOL bShow)    { m_bShowShot = bShow; }
    void                ConvertGlassToView(CRect &rect);
    void                ConvertGlassToView(CPoint &pt);
    CRect                ConvertViewToGlass(CRect &rect);
    CPoint                ConvertViewToGlass(CPoint &pt);
    // åŽ†åŽ˜
    void                SaveMapToFile(CString strFileName);
    // Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CStaticMap)
    //}}AFX_VIRTUAL
protected:
    CWnd*                m_pParentWnd;
    int                    m_nMapTotalWidth;
    int                    m_nMapTotalHeight;
    int                    m_nMapWidth;
    int                    m_nMapHeight;
    CRect                m_RectWnd;
    CRect                m_RectMap;
    //////////////////////////////////////////////////////////////////////////
    // å¼Šåºœæ‰ æ²¥ç„Š
    HBITMAP                m_hDrawingSurface;
    BITMAPINFOHEADER    m_BMIH;
    CRect                m_RectDrawingSurface;
    BYTE*                m_pDrawingSurfaceBits;
    OriginDirection        m_OriginDir;
    int                    m_nUnitSize;
    // Cell å¼Šåºœæ‰
    BOOL                m_bShowShot;
    // çŠ¬æŽª/绵家
    CRect                m_RectShowWnd;
    double                m_dWidthRatio;
    double                m_dHeightRatio;
    double                m_dRatio;
    CPoint                m_PointWindowStart;
    BOOL                m_bDragMove;
    CPoint                m_PointDragStart;
    BOOL                m_bIsMiniMap;            // Minimap篮 çŠ¬æŽª/绵家甫 æ•‘茄促.
    CPoint                m_PointGlassStart;        // Glass å æ³…犁 ç„Šå’¯ç˜¤ç»° åº·å¼€.
    CPoint                m_PointGlassEnd;
    CPoint                m_PointCCut[3];            //内呈钠 å¼Šåºœæ‰ è°…é’Ž
    int                    m_nCCutSize;
    int                    m_nCoordGabX;            // è°…钎甫 è°Žå‰¯ èŠ­åºœ.
    int                    m_nCoordGabY;            // è°…钎甫 è°Žå‰¯ èŠ­åºœ.
    //{{AFX_MSG(CStaticGlass)
    afx_msg void OnPaint();
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg long OnUpdateMap(WPARAM wParam, LPARAM lParam);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
#endif // !defined(AFX_DEFECTMAP_H__CF34B34E_7A0E_4CBB_880F_4C41FF83A64B__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/FontStatic.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
#pragma once
// Defines for the font style
#define FS_NORMAL            0x00
#define FS_BOLD                0x01
#define FS_ITALIC            0x02
#define FS_UNDERLINED        0x04
#define FS_STRIKETHROUGH    0x08
#define FS_ANTIALIAS        0x10
// Defines for horizontal alignment
#define FS_CENTER            0x20
#define FS_LEFT                0x40
#define FS_RIGHT            0x80
// CFontStatic
class AFX_EXT_CLASS CFontStatic :
    public CStatic
{
    DECLARE_DYNAMIC(CFontStatic)
public:
    CFontStatic();
    // Attributes
public:
    bool m_bBold;
    bool m_bItalic;
    bool m_bUnderlined;
    bool m_bStrikethrough;
    bool m_bAntialias;
    bool m_bBgColor;
    bool m_bCenter;
    bool m_bLeft;
    bool m_bRight;
    CString m_szText;
    CString m_szFont;
    DWORD m_dwColor;
    DWORD m_dwBgColor;
    int m_nSize;
    // Operations
public:
    // Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CFontStatic)
protected:
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUAL
    // Implementation
public:
    void SetWindowText(LPCTSTR a_lpstr);
    void SetFontStyle(DWORD dwStyle);
    void SetBackground(DWORD dwBgColor);
    void SetFontStatic(CString szFont, int nSize, DWORD dwColor, DWORD dwStyle);
    virtual ~CFontStatic();
protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnPaint();
};
SourceCode/Bond/BLControlsSDK/include/GradientStatic.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,149 @@
#pragma once
// CGradientStatic
typedef UINT (CALLBACK* LPFNDLLFUNC1)(HDC,CONST PTRIVERTEX,DWORD,CONST PVOID,DWORD,DWORD);
class CDoubleBuff : public CDC {
private:
    CBitmap        m_bitmap;        // Offscreen bitmap
    CBitmap*    m_oldBitmap;    // bitmap originally found in CDoubleBuff
    CDC*        m_pDC;            // Saves CDC passed in constructor
    CRect        m_rect;            // Rectangle of drawing area.
    BOOL        m_bMemDC;        // TRUE if CDC really is a Memory DC.
public:
    CDoubleBuff(CDC* pDC, const CRect* pRect = NULL) : CDC()
    {
        ASSERT(pDC != NULL);
        // Some initialization
        m_pDC = pDC;
        m_oldBitmap = NULL;
        m_bMemDC = !pDC->IsPrinting();
        // Get the rectangle to draw
        if (pRect == NULL) {
            pDC->GetClipBox(&m_rect);
        } else {
            m_rect = *pRect;
        }
        if (m_bMemDC) {
            // Create a Memory DC
            CreateCompatibleDC(pDC);
            pDC->LPtoDP(&m_rect);
            m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
            m_oldBitmap = SelectObject(&m_bitmap);
            SetMapMode(pDC->GetMapMode());
            SetWindowExt(pDC->GetWindowExt());
            SetViewportExt(pDC->GetViewportExt());
            pDC->DPtoLP(&m_rect);
            SetWindowOrg(m_rect.left, m_rect.top);
        } else {
            // Make a copy of the relevent parts of the current DC for printing
            m_bPrinting = pDC->m_bPrinting;
            m_hDC       = pDC->m_hDC;
            m_hAttribDC = pDC->m_hAttribDC;
        }
        // Fill background
        FillSolidRect(m_rect, pDC->GetBkColor());
    }
    virtual ~CDoubleBuff()
    {
        if (m_bMemDC) {
            // Copy the offscreen bitmap onto the screen.
            m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
                this, m_rect.left, m_rect.top, SRCCOPY);
            //Swap back the original bitmap.
            SelectObject(m_oldBitmap);
        } else {
            // All we need to do is replace the DC with an illegal value,
            // this keeps us from accidently deleting the handles associated with
            // the CDC that was passed to the constructor.
            m_hDC = m_hAttribDC = NULL;
        }
    }
    // Allow usage as a pointer
    CDoubleBuff* operator->()
    {
        return this;
    }
    // Allow usage as a pointer
    operator CDoubleBuff*()
    {
        return this;
    }
    CDC *GetOriginalDC()
    {
        return m_pDC;
    }
};
class AFX_EXT_CLASS CGradientStatic : public CStatic
{
    DECLARE_DYNAMIC(CGradientStatic)
public:
    enum    EN_ANI_MODE{EN_ANI_NONE=0,EN_ANI_LEFTRIGHT,EN_ANI_LAMP};
    CGradientStatic();
    virtual ~CGradientStatic();
    void SetWindowText(LPCTSTR a_lpstr);
    void SetColor(long cl) {clLeft=cl;};
    BOOL SetControlFont(int nHeight, int nWidth, int nEscapement,
        int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline,
        BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision,
        BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily,
        LPCTSTR lpszFacename);
    void SetGradientColor(long cl) {clRight=cl; SetDrawColor(clLeft, clRight); };
    void SetTextColor(long cl) {clText=cl;};
    void SetReverseGradient();
    void SetLeftSpacing(int iNoOfPixels) { m_iLeftSpacing = iNoOfPixels; };
    void SetTextAlign(int iAlign ) { m_iAlign = iAlign; }; //0 - left, 1 - center, 2 -right
    void SetVerticalGradient(BOOL a_bVertical = TRUE) { m_bVertical = a_bVertical; };
    void SetOulineColor(long cl1, long cl2) { clOut1 = cl1; clOut2 = cl2; m_bDrawOutLine = TRUE; }
    void SetDrawColor(long cl1, long cl2);
    void MoveDrawColor();
    void SetAnimationMode(int nMode, int nTime, int nIndex);
    static void DrawGradRect(CDC *pDC, CRect r, COLORREF cLeft, COLORREF cRight, BOOL a_bVertical);
    void DrawGradRect(CDC *pDC, CRect r, BOOL a_bVertical, COLORREF *cl);
protected:
    CString m_sTEXT;
    int m_iLeftSpacing;
    long clLeft;
    long clRight;
    long clText;
    long clOut1;
    long clOut2;
    COLORREF clDrawColor[510];
    int m_iAlign;
    BOOL m_bDrawOutLine;
    EN_ANI_MODE m_enAnimation;
    int m_nAniColorCount;
    HINSTANCE hinst_msimg32;
    BOOL m_bCanDoGradientFill;
    BOOL m_bVertical;
    LPFNDLLFUNC1 dllfunc_GradientFill;
    CFont m_font;
    afx_msg void OnPaint();
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    DECLARE_MESSAGE_MAP()
public:
};
SourceCode/Bond/BLControlsSDK/include/HeadCtrl.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,104 @@
#if !defined(AFX_HEADCTRL_H__E483AE98_F737_4DBF_8508_8E934A8F6988__INCLUDED_)
#define AFX_HEADCTRL_H__E483AE98_F737_4DBF_8508_8E934A8F6988__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// HeadCtrl.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CHeadCtrl window
#ifndef __AFXTEMPL_H
#include <afxtempl.h>
#endif
class CHeadCtrl : public CHeaderCtrl
{
// Construction
public:
    struct HEADCELL
    {
        DWORD   state;
        CString string;
    };
    class CHeadCell : public HEADCELL
    {
    public:
        CHeadCell()
        {
            state=0;
            string="";
        }
        CHeadCell(HEADCELL& hcell)
        {
            *this=hcell;
        }
        CHeadCell operator=(HEADCELL& hcell)
        {
            state=hcell.state;
            string=hcell.string;
            return *this;
        }
    };
    typedef CArray<CHeadCell,CHeadCell&> CHeadItem;
    typedef CArray<CHeadItem,CHeadItem&> CHeadInfo;
public:
    CHeadCtrl();
    void SetCount(int nCount, CFont* pFont);
    int  GetCount(){return m_count;}
    int  GetHeadHeight();
    void InsertColumn(int nCol);
    void DeleteColumn(int nCol);
    void FontChange(LOGFONT logfont);
    BOOL SetItemText(int nItem, int nSubItem, LPCSTR lpcstr);
    CString GetItemText(int nItem, int nSubItem);
    BOOL SetItemMerge(int nsItem, int nsSubItem, int neItem, int neSubItem);
    UINT GetItemState(int nItem, int nSubItem, int& down, int& right);
    BOOL GetRect(int nItem, int nSubItem, CRect& rect);
protected:
    BOOL m_bclick;
    CPoint m_pnt;
    CFont m_font;
    int m_count;
    CHeadInfo m_Info;
    BOOL IsDraw(CRect rect);
    BOOL GetTextRect(CDC* pDC, CString strText, CRect& rect);
// Attributes
public:
// Operations
public:
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CHeadCtrl)
    virtual void OnPaint();
    //}}AFX_VIRTUAL
// Implementation
public:
    virtual ~CHeadCtrl();
    // Generated message map functions
protected:
    //{{AFX_MSG(CHeadCtrl)
    afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_HEADCTRL_H__E483AE98_F737_4DBF_8508_8E934A8F6988__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/InPlaceComboBox.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
#if !defined(AFX_INPLACECOMBOBOX_H__2909C5E5_6C2D_42DE_AB56_904A78606462__INCLUDED_)
#define AFX_INPLACECOMBOBOX_H__2909C5E5_6C2D_42DE_AB56_904A78606462__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// InPlaceComboBox.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CInPlaceComboBox window
class CInPlaceComboBox : public CComboBox
{
// Construction
public:
    CInPlaceComboBox(int iItem,int iSubItem);
// Attributes
public:
// Operations
public:
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CInPlaceComboBox)
    //}}AFX_VIRTUAL
// Implementation
public:
    virtual ~CInPlaceComboBox();
    // Generated message map functions
protected:
    //{{AFX_MSG(CInPlaceComboBox)
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnSelchange();
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    //}}AFX_MSG
    int m_iSubItem;
    int m_iItem;
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_INPLACECOMBOBOX_H__2909C5E5_6C2D_42DE_AB56_904A78606462__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/InPlaceEdit.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
#if !defined(AFX_INPLACEEDIT_H__89FB99E1_386B_11D3_B257_00104BBB4F35__INCLUDED_)
#define AFX_INPLACEEDIT_H__89FB99E1_386B_11D3_B257_00104BBB4F35__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// InPlaceEdit.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CInPlaceEdit window
class CInPlaceEdit : public CEdit
{
// Construction
public:
    CInPlaceEdit(int iItem, int iSubItem, CString sInitText);
// Attributes
public:
// Operations
public:
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CInPlaceEdit)
    public:
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    //}}AFX_VIRTUAL
// Implementation
public:
    CString m_strNewValue;
    virtual ~CInPlaceEdit();
    // Generated message map functions
protected:
    //{{AFX_MSG(CInPlaceEdit)
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    afx_msg void OnNcDestroy();
    afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
private:
    BOOL m_bESC;
    CString m_sInitText;
    int m_iSubItem;
    int m_iItem;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_INPLACEEDIT_H__89FB99E1_386B_11D3_B257_00104BBB4F35__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/LogCtrl.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,213 @@
//LogCtrl.h
//LogCtrl.h
#ifndef __LOGCTRL_H
#define __LOGCTRL_H
#define __LOGCTRL_LIB_H
#ifndef __AFXTEMPL_H
#include <afxtempl.h>
#endif
//LOG CELL STATE
//MERGE
#define LCS_NORML        0x0000
#define LCS_MERGE        0x0001
#define LCS_UNUSE        0x0002
//LINE
#define LCS_TLINE        0x0001    //TOP LINE DRAW
#define LCS_BLINE        0x0002    //BOTTOM LINE DRAW
#define LCS_LLINE        0x0004    //LEFT LINE DRAW
#define LCS_RLINE        0x0008    //RIGHT LINE DRAW
#define LCS_RECT        LCS_TLINE|LCS_BLINE|LCS_LLINE|LCS_RLINE
//merge state
#define SetFlag(n)  DWORD(BYTE(n)<<16)
#define GetFlag(d)  int((d & 0x00FF0000)>>16)
#define SetDown(n)  DWORD(BYTE(n)<<8)
#define GetDown(d)  int((d & 0x0000FF00)>>8)
#define SetRight(n) DWORD(BYTE(n))
#define GetRight(d) int((d & 0x000000FF))
#define LOGCHECK(b) if(b){return;}
#define LOGCHECK0(b) if(b){return 0;}
#define LOGCHECK1(b) if(b){return -1;}
class CPrintDC;
class CLogCell;
class CLogPage;
class CLogCtrl;
typedef CArray<CLogCell,CLogCell&> CLogItem;
typedef CArray<CLogItem,CLogItem&> CLogItemArray;
typedef CArray<CLogPage,CLogPage&> CLogPageArray;
typedef struct tagLOGCELL
{
    BYTE        m_nLine; //惑窍谅快 æ‰¼ç‰¢
    UINT        m_nState;//促弗伎苞 æé’¦ç¯ç»°ç˜¤ ..
    UINT        m_nFormat;//沥纺葛靛
    RECT        m_rect;  //伎狼 åº·å¼€
    COLORREF    m_txtclr;//臂磊祸
    COLORREF    m_bkgclr;//硅版祸
    CString        m_strTxt;//臂磊
    CFont*        m_pfont; //迄飘
    CBitmap*    m_pBitmap;//厚飘甘
}LOGCELL;
//Orientation=啊肺(1), æŠ€è‚º(2)  bDialog=DoModal()
class CPrintDC
{
public:
    CPrintDC();
    virtual ~CPrintDC();
    CDC* GetPrintDC(int Orientation, BOOL bDialog=FALSE);
protected:
    CDC *m_pDC;
};
class CLogCell : public tagLOGCELL
{
public:
    CLogCell();
    CLogCell(LPCSTR lpstr,
            CRect    rect,
            int nFormat=DT_CENTER,
            COLORREF textColor=0x00000000,
            COLORREF backColor=0x00ffffff,
            CFont* pf=NULL);
    void operator=(const CLogCell& log);
    void InitCell();
    void Draw(CDC* pDC);
};
class CLogPage
{
public:
    CLogPage();
    CLogPage(CPoint startPnt);
    virtual ~CLogPage();
    void RemoveAll();
    void operator=(CLogPage& page);
    //青,凯 è‚®èç”« æ±²æ²¥èŒ„促.
    void SetColCount(int nCount);
    void SetRowCount(int nCount);
    BOOL RemoveRow(int nRow);
    //厘钎 å…ä»¿å›°æ‘¹
    void SetStartPoint(CPoint startPnt);
    CPoint GetStartPoint() const;
    //青,凯 è‚®èç”« åºœç•”茄促.
    int GetColCount() const;
    int GetRowCount() const;
    //气,臭捞甫 æ±²æ²¥èŒ„促.
    BOOL SetColWidth(int nCol, int nWidth);
    BOOL SetRowHeight(int nRow, int nHeight);
    //迄飘甫 æ±²æ²¥èŒ„促.
    BOOL SetCellFont(int nRow, int nCol, CFont* pf);
    BOOL SetCellFont(int nsRow, int nsCol, int neRow, int neCol, CFont* pf);
    CFont* GetCellFont(int nRow, int nCol);
    //硅版祸阑 æ±²æ²¥èŒ„促.
    BOOL SetCellBkgColor(int nRow, int nCol, COLORREF color);
    COLORREF GetCellBkgColor(int nRow, int nCol);
    //臂磊祸阑 æ±²æ²¥èŒ„促.
    BOOL SetCellTxtColor(int nRow, int nCol, COLORREF color);
    COLORREF GetCellTxtColor(int nRow, int nCol);
    //臂磊困摹 æ±²æ²¥
    BOOL SetCellFormat(int nRow, int nCol, int nFormat);
    int GetCellFormat(int nRow, int nCol);
    //Rect阑 æ±²æ²¥èŒ„促.
    BOOL SetCellRect(int nRow, int nCol, CRect rect);
    BOOL GetCellRect(int nRow, int nCol, CRect& rect);
    //BITMAP阑 æ±²æ²¥èŒ„促.
    BOOL SetCellBmp(int nRow, int nCol, CBitmap* pBmp);
    CBitmap* GetCellBmp(int nRow, int nCol);
    //荤阿屈 å¼Šå‰¯é”­ ç»¢è ¢ å›°æ‘¹ç”« å¼Šå‰¯ å·´ç‰¢å•Š æ±²æ²¥èŒ„ä¿ƒ.
    BOOL SetCellLine(int nRow, int nCol, int nState=LCS_RECT/*LCS_RECT*/);
    int GetCellLine(int nRow, int nCol);
    //伎俊 è‡‚磊阑 æ¶ä»¿èŒ„促.
    BOOL SetItemText(int nRow, int nCol, LPCTSTR lpstr, int nFormat=DT_CENTER|DT_VCENTER|DT_SINGLELINE);
    CString GetItemText(int nRow, int nCol);
    BOOL SetCell(int nRow, int nCol, CLogCell lc);
    CLogCell* GetCell(int nRow, int nCol);
    //伎阑 æé’¦èŒ„促.
    BOOL CellMerge(int nsCol, int nsRow, int neCol ,int neRow );
    //免仿茄促.(nPageNOç»° å…¶æžç˜¤ é”…龋捞哥 0老 ç‰ˆå¿« å…ä»¿ç™»ç˜¤ è‡¼ç»°ä¿ƒ.)
    void Draw(CDC* pDC, int nPageNO=0);
    //SetPageRect(,)窃荐甫 è¤ä¾©çŸ«
    //Draw(CDC* pDC, int nPageNO=0);窃荐甫 é¾‹å…çªæ‰ å®˜è‚ºå‚ˆä¿Š è¤ä¾©ç§¦å…·çªƒ
    //侩档:
    //   <<page>>                                 <<device>>
    //  0                               100      0                               1000
    //  Î“ΑΑΑΑΑΑΑΑΑΑΑΑΑΑΑΔ        Î“ΑΑΑΑΑΑΑΑΑΑΑΑΑΑΑΔ
    //  Î’  (10,10)              (90,10)Β        Î’ (100,100)           (900,100)Β
    //  Î’  Î“ΑΑΑΑΑΑΑΑΑΑΑΔ  Î’        Î’  Î“ΑΑΑΑΑΑΑΑΑΑΑΔ  Î’
    //  Î’  Î’                      Î’  Î’        Î’  Î’                      Î’  Î’
    //  Î’  Î’                      Î’ ÎœÎœÎœÎœÎœÎœÎœ>Β                      Î’  Î’
    //  Î’  Î’                      Î’  Î’        Î’  Î’                      Î’  Î’
    //  Î’  Î’                      Î’  Î’        Î’  Î’                      Î’  Î’
    //  Î’  Î–ΑΑΑΑΑΑΑΑΑΑΑΕ  Î’        Î’  Î–ΑΑΑΑΑΑΑΑΑΑΑΕ  Î’
    //  Î’  (10,40)              (90,40)Β        Î’ (100,400)           (900,400)Β
    //  Î’                              Î’        Î’                              Î’
    //  Î’                              Î’        Î’                              Î’
    //  Î’                              Î’        Î’                              Î’
    //  Î’                              Î’        Î’                              Î’
    //  Î’                              Î’        Î’                              Î’
    //  Î’                              Î’        Î’                              Î’
    //  Î’                              Î’        Î’                              Î’
    //  Î’                              Î’        Î’                              Î’
    //  Î’                              Î’        Î’                              Î’
    //  Î’                              Î’        Î’                              Î’
    //  Î’                              Î’        Î’                              Î’
    //  Î–ΑΑΑΑΑΑΑΑΑΑΑΑΑΑΑΕ        Î–ΑΑΑΑΑΑΑΑΑΑΑΑΑΑΑΕ
    //  200                            100,200    2000                            1000,2000
    //
    //   CRect page(0,0,100,200);
    //   CRect device(0,0,1000,2000);
    //   å’¯å½’阑 ç‚¼é™› æž—妨搁: CRect device(100,100,900,1900);
    //   SetPageRect(pDC, page, device);
    BOOL SetPageRect(CDC* pDC, CRect page, CRect device);
protected:
    bool m_IsViewPort;
    int m_RowCnt;
    int m_ColCnt;
    CPoint          m_startPnt;
    CLogItemArray m_liAry;
};
//厘钎 å‚ˆçœ‰ç”« åŒ…府茄促.
//厘钎甫 å…ä»¿çªæ‰ å›°ç§¦ æ€– éž˜å¤¸çªæŸ³ è‡¼ä¿ƒ.
//CLogPage甫 è¤ä¾©ç§¦æ¡£ å…¬è§„窍促.
class CLogCtrl
{
public:
    CLogCtrl();
    virtual ~CLogCtrl();
    int  GetLogPageCount();
    void AddLogPage(CLogPage& lp);
    CLogPage* GetLogPage(int nPage);
    void DelLogPage(int nPage);
    void Draw(CDC* pDC, DOCINFO* pDocInfo);
protected:
    CLogPageArray m_log;
};
#endif
SourceCode/Bond/BLControlsSDK/include/SortClass.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
class CSortClass
{
public:
    CSortClass(CListCtrl * _pWnd, const int _iCol, const bool _bIsNumeric);
    //CSortClass(CListCtrl * _pWnd, const int _iCol, const bool _bIsNumeric, int iStartingItem, int iEndingItem );
    virtual ~CSortClass();
    int iCol;
    int m_iStartingItem;
    int m_iEndingItem;
    CListCtrl * pWnd;
    bool bIsNumeric;
    void Sort(const bool bAsc);
    static int CALLBACK CompareAsc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
    static int CALLBACK CompareDes(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
    static int CALLBACK CompareAscI(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
    static int CALLBACK CompareDesI(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
public:
    class CSortItem
    {
        public:
            virtual  ~CSortItem();
            CSortItem(const DWORD _dw, const CString &_txt);
            CString txt;
            DWORD dw;
    };
    class CSortItemInt
    {
        public:
            CSortItemInt(const DWORD _dw, const CString &_txt);
            int iInt ;
            DWORD dw;
    };
};
SourceCode/Bond/BLControlsSDK/include/StaticMap.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,149 @@
#if !defined(AFX_STATICMAP_H__5A9433C1_E8A9_4393_9E0D_B7A996B9AF3F__INCLUDED_)
#define AFX_STATICMAP_H__5A9433C1_E8A9_4393_9E0D_B7A996B9AF3F__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// StaticMap.h : header file
//
#define ORIGIN_LEFTTOP        1
#define ORIGIN_LEFTBOTTOM    0
#define ORIGIN_RIGHTTOP        2
#define ORIGIN_RIGHTBOTTOM    3
#define UM_MAP_CHANGED            5573
#define _MENU_DEFECT_LIST_ID_            8000
/////////////////////////////////////////////////////////////////////////////
// CStaticMap window
enum OriginDirection        { OD_LeftTop = 0, OD_RightTop = 1, OD_LeftBottom = 10, OD_RightBottom = 11 };
class AFX_EXT_CLASS CStaticMap : public CStatic
{
    // Construction
public:
    CStaticMap();
    // Attributes
public:
    // Operations
public:
    void                InitGlass(CWnd* pParent, int nMapWidth, int nMapHeight, int nMapMargin);    // Pixel çªœå›° ä»˜æŸ³.
    void                DeinitGlass();
    int                    GetMapTotalWidth()        { return m_nMapTotalWidth; }
    int                    GetMapTotalHeight()        { return m_nMapTotalHeight; }
    int                    GetMapWidth()            { return m_nMapWidth; }
    int                    GetMapHeight()            { return m_nMapHeight; }
    void                SetMiniMap(BOOL bIsMiniMap, int nUnitSize)    { m_bIsMiniMap = bIsMiniMap; m_nUnitSize = nUnitSize; }
    int                    GetUnitSize()            { return m_nUnitSize; }
    virtual void        DrawGlass(CDC* pDC)                        { }
    virtual void        MouseLBtnDwn(CPoint& point)                { }
    virtual void        MouseLBtnUp(CPoint& point)                { }
    virtual void        MouseLBtnMove(CPoint& point)            { }
    virtual void        MouseLBtnDblClk(CPoint& point)            { }
    virtual void        MouseRBtnDwn(CPoint& point)                { }
    virtual void        MouseRBtnUp(CPoint& point)                { }
    virtual void        MouseRBtnDblClk(CPoint& point)            { }
    virtual void        RegistNoDefect()                        { }
    virtual void        Timer(UINT nIDEvent)                    { }
    // çŠ¬æŽª/绵家
    void                IncreaseRatio();
    void                DecreaseRatio();
    void                ResetRatio();
    CPoint&                GetDisplayStart()        { return m_PointGlassStart; }
    CPoint&                GetDisplayEnd()            { return m_PointGlassEnd; }
    void                SetDisplayRect(CPoint& PointStart, CPoint& PointEnd);
    void                SetShowShot(BOOL bShow)    { m_bShowShot = bShow; }
    // åŽ†åŽ˜
    void                SaveMapToFile(CString strFileName);
    void                SetBGColor(COLORREF color) { m_clBGColor = color; }
    // Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CStaticMap)
    //}}AFX_VIRTUAL
    // Implementation
public:
    virtual ~CStaticMap();
    // Generated message map functions
protected:
    void                SetMappingMode(CDC *pDC);
    CPoint                SetWindowToGlass(CPoint pt);
    CPoint                SetGlassToWindow(CPoint pt);
    void                ControlZoom(BOOL bZoomIn, CPoint ptMouse);
    void                PopupMenu(int nBaseID, CPoint point);
    CWnd*                m_pParentWnd;
    int                    m_nMapTotalWidth;
    int                    m_nMapTotalHeight;
    int                    m_nMapWidth;
    int                    m_nMapHeight;
    int                    m_nMapMarginWidth;
    int                    m_nMapMarginHeight;
    CRect                m_RectWnd;
    CRect                m_RectMap;
    long                m_clBGColor;
    long                m_clPatColor;
    //////////////////////////////////////////////////////////////////////////
    // å¼Šåºœæ‰ æ²¥ç„Š
    HBITMAP                m_hDrawingSurface;
    BITMAPINFOHEADER    m_BMIH;
    CRect                m_RectDrawingSurface;
    BYTE*                m_pDrawingSurfaceBits;
    OriginDirection        m_OriginDir;
    int                    m_nUnitSize;
    // Cell å¼Šåºœæ‰
    BOOL                m_bShowShot;
    // çŠ¬æŽª/绵家
    CRect                m_RectShowWnd;
    double                m_dRatio;
    CPoint                m_PointWindowStart;
    BOOL                m_bDragMove;
    CPoint                m_PointDragStart;
    BOOL                m_bIsMiniMap;            // Minimap篮 çŠ¬æŽª/绵家甫 æ•‘茄促.
    CPoint                m_PointGlassStart;        // Glass å æ³…犁 ç„Šå’¯ç˜¤ç»° åº·å¼€.
    CPoint                m_PointGlassEnd;
    POINT                m_PointCCut[3];            //内呈钠 å¼Šåºœæ‰ è°…é’Ž
    int                    m_nCCutSize;
    int                    m_nCoordGabX;            // è°…钎甫 è°Žå‰¯ èŠ­åºœ.
    int                    m_nCoordGabY;            // è°…钎甫 è°Žå‰¯ èŠ­åºœ.
    //{{AFX_MSG(CStaticGlass)
    afx_msg void OnPaint();
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point);
    afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg long OnUpdateMap(WPARAM wParam, LPARAM lParam);
    afx_msg void OnMenuChangeViewMode(UINT nID);
    afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STATICMAP_H__5A9433C1_E8A9_4393_9E0D_B7A996B9AF3F__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/WKButton.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,119 @@
#if !defined(AFX_WKBUTTON_H__99FB32BE_6D54_4845_BD51_1BC64E774CC6__INCLUDED_)
#define AFX_WKBUTTON_H__99FB32BE_6D54_4845_BD51_1BC64E774CC6__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// WKButton.h : header file
/******************************< æ©‡è‚ºå¼Šä¼ æ²¥ç„Š >****************************/
/*   åŠª è´° èƒ¶ ç–™ : WKButton                                                */
/*   æ»š       å‚ˆ :                                                         */
/*   å¼¥è¾† èæ²¥è€ : 2006. 05. 28                                            */
/***************************************************************************/
/////////////////////////////////< æ²¥  ç‹¼ >//////////////////////////////////
// æ»šç“¢ å±ˆæ€•
#define        WK_BUTTON_SHPAE_RECTANGLE                0x0001
#define        WK_BUTTON_SHAPE_CIRCLE                    0x0002
#define        WK_BUTTON_SHAPE_ROUNDRECT                0x0004
// æ»šç“¢ ç¥¸æƒ‘
#define        WK_BUTTON_COLOR_ONE                        0x0001
#define        WK_BUTTON_COLOR_TWO                        0x0002
#define        WK_BUTTON_COLOR_GRADATION_UP            0x0011
#define        WK_BUTTON_COLOR_GRADATION_RIGHT            0x0012
#define        WK_BUTTON_COLOR_GRADATION_DOWN            0x0014
#define        WK_BUTTON_COLOR_GRADATION_LEFT            0x0018
// æ»šç“¢ æƒ‘怕
#define        WK_BUTTON_STATUS_MOUSEOVER                0x0001
#define        WK_BUTTON_STATUS_MOUSELEAVE                0x0002
#define        WK_BUTTON_STATUS_MOUSECLICK                0x0004
///////////////////////////////< åŠªè´°èƒ¶ å¤‡ç‚¼ >///////////////////////////////
class AFX_EXT_CLASS CWKButton : public CButton
{
public://<<<<<<<<<<<<<<<<<<<<<< å¯‡ä½• ç«‹è¾Ÿ çªƒè >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    CWKButton();
    virtual ~CWKButton();
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CWKButton)
    public:
    virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
    virtual BOOL Create(LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    virtual BOOL DestroyWindow();
    protected:
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUAL
public:
/*****************************< æ»šç“¢ æ±²æ²¥ çªƒè >****************************/
    /* å’†èƒ¶é£˜ è‘›å‰§ æ£º éƒ´ä¾© ç˜¤æ²¥ */
    BOOL SetButtonText(CString strCaption);
    BOOL SetButtonText(CString strCaption, COLORREF rgbText);
    BOOL SetButtonText(CString strCaption, CFont *font, COLORREF rgbText);
    /* æ»šç“¢ å±ˆæ€• æ£º ç¥¸æƒ‘ ç˜¤æ²¥ */
    BOOL SetButtonStyle(DWORD dShape, COLORREF rgbColor1);
    BOOL SetButtonStyle(DWORD dShape, DWORD dStyle,    COLORREF rgbColor1,    COLORREF rgbColor2);
    /***************************************************************************/
protected://<<<<<<<<<<<<<<<< éƒ´ä½• è´¸åºœ çªƒè æ£º å‡½è >>>>>>>>>>>>>>>>>>>>>>>>>
    /* æƒ‘怕喊 æ»šç“¢ æžå›ºç˜¤ */
    CBitmap m_bmpImage1;    //乞惑矫
    CBitmap m_bmpImage2;    //付快胶 å·æ»š
    CBitmap m_bmpImage3;    //努腐
    /* æƒ‘怕喊 æ»šç“¢ æžå›ºç˜¤ ç§¯å·± */
    BOOL CreateButtonImage();
    /* æ»šç“¢ å±ˆæ€• ç§¯å·± */
    BOOL DrawFormRectangle();    // è¤é˜¿
    BOOL DrawFormCircle();        // ç›”
    BOOL DrawFormRoundRect();    // å«¡è¾Ÿè¤é˜¿
    /* æžå›ºç˜¤ è´¸åºœ */
    COLORREF LightValueControl(COLORREF rgb, int nValue);                        // ç¥¸æƒ‘ çŒæ‰ ç‚¼ä¾‹
    void DrawGradation(CBitmap* bmpImage, COLORREF color1, COLORREF color2);    // å¼Šæ‰¼å•捞记 æžå›ºç˜¤ ç§¯å·±
    BOOL DrawBorder(CBitmap* pbmpImage, COLORREF color1, COLORREF color2, int nWidth = 2);        // æ»šç“¢ æŠ›æ»´åºœ å¼Šåºœæ‰
    BOOL DrawText(CBitmap* pBitmap, int nStatus);                                // æ»šç“¢ä¿Š è‡‚揪 æŒæ‰
    /* æ»šç“¢ æžå›ºç˜¤ æ²¥ç„Š */
    DWORD m_dShape;            // æ»šç“¢ å±ˆæ€•
    DWORD m_dStyle;            // æ‹¿çŸ¾ èƒ¶é¸¥è€
    COLORREF m_rgbColor1;    // éœ‰é”…掳 æ‹¿çŸ¾
    COLORREF m_rgbColor2;    // æ»´é”…掳 æ‹¿çŸ¾
    CRect m_rtButton;        // æ»šç“¢å†œæ‰
    int m_nWidth;            // æ»šç“¢ å‘ˆåŽš
    int m_nHeight;            // æ»šç“¢ è‡­æž
    /* å’†èƒ¶é£˜ æ²¥ç„Š */
    CString m_strCaption;    // æ¯è®° éƒ´ä¾©
    CFont m_Font;            // æ¯è®° è‡‚裁
    COLORREF m_rgbText;        // æ¯è®° ç¥¸æƒ‘
    BOOL m_bValueChange;    // æ¯è®° å‡½ç‰ˆ
    /* æ»šç“¢ æƒ‘怕 æ²¥ç„Š */
    DWORD m_dButtonStatus;
    //{{AFX_MSG(CWKButton)
    afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
    afx_msg void OnPaint();
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_WKBUTTON_H__99FB32BE_6D54_4845_BD51_1BC64E774CC6__INCLUDED_)
SourceCode/Bond/BLControlsSDK/include/XTabCtrl.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,90 @@
#if !defined(AFX_XTABCTRL_H__A11951B3_2F95_11D3_A896_00A0C9B6FB28__INCLUDED_)
#define AFX_XTABCTRL_H__A11951B3_2F95_11D3_A896_00A0C9B6FB28__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// XTabCtrl.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CXTabCtrl window
#include <afxtempl.h>
class AFX_EXT_CLASS CXTabCtrl : public CTabCtrl
{
// Construction
public:
    CXTabCtrl();
// Attributes
public:
// Operations
public:
    void AddTab(CWnd* pWnd, LPTSTR lpszCaption, int iImage =0);
    void AddTab(CWnd* pWnd, LPTSTR lpszCaption, int Width, int Height, int iImage =0);
    void EnableTab(int iIndex, BOOL bEnable = TRUE);
    BOOL SelectTab(int iIndex);
    void DeleteAllTabs();
    void DeleteTab(int iIndex);
    void SetTopLeftCorner(CPoint pt);
    BOOL IsTabEnabled(int iIndex);
    void SetDisabledColor(COLORREF cr);
    void SetSelectedColor(COLORREF cr);
    void SetNormalColor(COLORREF cr);
    void SetMouseOverColor(COLORREF cr);
    void SetParentWnd(CWnd* pWnd)    { m_pParentWnd = pWnd; }
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CXTabCtrl)
    protected:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUAL
// Implementation
public:
    virtual ~CXTabCtrl();
    // Generated message map functions
protected:
    CArray<BOOL, BOOL> m_arrayStatusTab; //** enabled Y\N
    int m_iSelectedTab;
    POINT m_ptTabs;
    COLORREF m_crSelected;
    COLORREF m_crDisabled;
    COLORREF m_crNormal;
    COLORREF m_crMouseOver;
    COLORREF m_crBKColor;
    int m_iIndexMouseOver;
    bool m_bMouseOver;
    bool m_bColorMouseOver;
    bool m_bColorNormal;
    bool m_bColorDisabled;
    bool m_bColorSelected;
    //{{AFX_MSG(CXTabCtrl)
    afx_msg void OnSelchange(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    CWnd*        m_pParentWnd;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_XTABCTRL_H__A11951B3_2F95_11D3_A896_00A0C9B6FB28__INCLUDED_)
SourceCode/Bond/BondEq/AccordionWnd.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,777 @@
#include "stdafx.h"
#include "AccordionWnd.h"
#define ITEM_HEIGHT                32
#define ITEM_SPACE                5
#define TIMER_ID_CHECKHOVER        1
#define EXPAND_ICON_WIDE        16
#define BORDER            5
#define SHADOWWIDE        5
CAccordionWnd::CAccordionWnd()
{
    m_hWnd = NULL;
    m_crFrame = GetSysColor(COLOR_WINDOWFRAME);
    m_crBkgnd = RGB(255, 255, 255);//GetSysColor(COLOR_BTNFACE); ;
    m_nPadding[PADDING_LEFT] = 5;
    m_nPadding[PADDING_TOP] = 5;
    m_nPadding[PADDING_RIGHT] = 5;
    m_nPadding[PADDING_BOTTOM] = 5;
    m_crItemBackground[0] = RGB(218, 218, 218);
    m_crItemBackground[1] = RGB(34, 177, 76);
    m_crItemFrame[0] = RGB(128, 128, 128);
    m_crItemFrame[1] = RGB(128, 128, 128);
    m_crItemText[0] = RGB(68, 84, 111);
    m_crItemText[1] = RGB(0, 0, 0);
    m_crSeparateLine = RGB(222, 222, 222);
    m_crHoverItemBackground = RGB(244, 245, 247);
    m_crHoverItemFrame = RGB(200, 222, 255);
    m_hIconExpand = NULL;
    m_hIconClose = NULL;
    m_nHoverItem = -1;
    m_nCheckHoverItem = -1;
    m_bShadow = FALSE;
    m_crShadowBkgnd = GetSysColor(COLOR_BTNFACE);
}
CAccordionWnd::~CAccordionWnd()
{
    for (size_t i = 0; i < m_vectorItems.size(); i++) {
        delete m_vectorItems[i];
    }
    m_vectorItems.clear();
}
BOOL CAccordionWnd::RegisterWndClass()
{
    WNDCLASS wc;
    wc.lpszClassName = ACCORDIONWND_CLASS;
    wc.hInstance = AfxGetInstanceHandle();
    wc.lpfnWndProc = WindowProc;
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = 0;
    wc.lpszMenuName = NULL;
    wc.hbrBackground = NULL;
    wc.style = CS_GLOBALCLASS | CS_DBLCLKS;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    // æ³¨å†Œè‡ªå®šä¹‰ç±»
    return (::RegisterClass(&wc) != 0);
}
CAccordionWnd * CAccordionWnd::FromHandle(HWND hWnd)
{
    CAccordionWnd *pAccordionWnd = (CAccordionWnd *)::GetProp(hWnd, ACCORDIONWND_TAG);
    return pAccordionWnd;
}
CAccordionWnd* CAccordionWnd::Hook(HWND hWnd)
{
    CAccordionWnd* pAccordionWnd = (CAccordionWnd*)GetProp(hWnd, ACCORDIONWND_TAG);
    if (pAccordionWnd == NULL) {
        pAccordionWnd = new CAccordionWnd();
        pAccordionWnd->m_hWnd = hWnd;
        SetProp(hWnd, ACCORDIONWND_TAG, (HANDLE)pAccordionWnd);
    }
    return pAccordionWnd;
}
void CAccordionWnd::LoadExpandIcon(CString strExpandFile, CString strCloseFile)
{
    m_hIconExpand = (HICON)::LoadImage(AfxGetInstanceHandle(), strExpandFile, IMAGE_ICON, EXPAND_ICON_WIDE, EXPAND_ICON_WIDE,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    m_hIconClose = (HICON)::LoadImage(AfxGetInstanceHandle(), strCloseFile, IMAGE_ICON, EXPAND_ICON_WIDE, EXPAND_ICON_WIDE,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
}
void CAccordionWnd::Setpadding(int type, unsigned int nPadding)
{
    if (type >= PADDING_LEFT && PADDING_LEFT <= PADDING_BOTTOM) {
        m_nPadding[type] = nPadding;
    }
}
void CAccordionWnd::SetDefaultItemBackgroundColor(COLORREF crNormal, COLORREF crSel)
{
    m_crItemBackground[0] = crNormal;
    m_crItemBackground[1] = crSel;
}
void CAccordionWnd::SetDefaultItemFrameColor(COLORREF crNormal, COLORREF crSel)
{
    m_crItemFrame[0] = crNormal;
    m_crItemFrame[1] = crSel;
}
void CAccordionWnd::SetDefaultItemTextColor(COLORREF crNormal, COLORREF crSel)
{
    m_crItemText[0] = crNormal;
    m_crItemText[1] = crSel;
}
void CAccordionWnd::Init()
{
}
void CAccordionWnd::Release()
{
    // delete
    delete this;
}
/*
 * æ·»åŠ é¡¹ç›®
 * pszName -- åç§°
 * pWnd -- ç»‘定的窗口
 * nExpandHeight -- å±•开高度,如果为0则自动设置为窗口高
 */
void CAccordionWnd::AddItem(char *pszName, CWnd *pWnd, int nExpandHeight, BOOL bExpand/* = TRUE*/, BOOL bEnable/* = TRUE*/)
{
    ACCORDIONITEM *pItem = new ACCORDIONITEM;
    memset(pItem, 0, sizeof(ACCORDIONITEM));
    pItem->pWnd = pWnd;
    pItem->bExpand = bExpand;
    pItem->bEnable = bEnable;
    strcpy_s(pItem->text, sizeof(pItem->text), pszName);
    if (nExpandHeight == 0) {
        RECT rect;
        pWnd->GetWindowRect(&rect);
        pItem->nExpandHeight = rect.bottom - rect.top;
    }
    else if (nExpandHeight == -1) {
        pItem->nExpandHeight = -1;
    }
    else {
        pItem->nExpandHeight = nExpandHeight;
    }
    m_vectorItems.push_back(pItem);
    // é‡æ–°è°ƒæ•´ä¸ªå­çª—口的位置
    ResizeItemWnd();
}
void CAccordionWnd::ResizeItemWnd()
{
    RECT rcClient, rcItemClient;
    GetClientRect(m_hWnd, &rcClient);
    for (size_t i = 0; i < m_vectorItems.size(); i++) {
        ACCORDIONITEM *pItem = m_vectorItems.at(i);
        if (pItem->pWnd != NULL) {
            GetItemRect(rcClient, i, &rcItemClient);
            rcItemClient.top += ITEM_HEIGHT;
            if (pItem->nExpandHeight == -1) {
                rcItemClient.bottom = rcClient.bottom;
            }
            else {
                rcItemClient.bottom = rcItemClient.top + pItem->nExpandHeight;
            }
            pItem->pWnd->MoveWindow(&rcItemClient);
            pItem->pWnd->ShowWindow(pItem->bExpand ? SW_SHOW : SW_HIDE);
        }
    }
}
BOOL CAccordionWnd::GetItemHeaderRect(RECT rcClient, unsigned int nIndex, LPRECT lpRect)
{
    RECT rcItem;
    if (!GetItemRect(rcClient, nIndex, &rcItem)) {
        return FALSE;
    }
    rcItem.bottom = rcItem.top + ITEM_HEIGHT;
    CopyRect(lpRect, &rcItem);
    return TRUE;
}
BOOL CAccordionWnd::GetItemRect(RECT rcClient, unsigned int nIndex, LPRECT lpRect)
{
    if (nIndex >= m_vectorItems.size()) {
        return FALSE;
    }
    RECT rcItemHeader;
    rcItemHeader.left = rcClient.left + m_nPadding[PADDING_LEFT];
    rcItemHeader.right = rcClient.right - m_nPadding[PADDING_RIGHT];
    rcItemHeader.top = rcClient.top + m_nPadding[PADDING_TOP];
    rcItemHeader.bottom = rcItemHeader.top + ITEM_HEIGHT;
    for (size_t i = 0; i < m_vectorItems.size(); i++) {
        ACCORDIONITEM *pItem = m_vectorItems.at(i);
        if (pItem->bExpand) {
            rcItemHeader.bottom += pItem->nExpandHeight;
        }
        if (i == nIndex) {
            break;;
        }
        rcItemHeader.top = rcItemHeader.bottom + ITEM_SPACE;
        rcItemHeader.bottom = rcItemHeader.top + ITEM_HEIGHT;
    }
    CopyRect(lpRect, &rcItemHeader);
    return TRUE;
}
int CAccordionWnd::HitTest(POINT pt, int &nHitTest)
{
    int nRet = -1;
    nHitTest = -1;
    RECT rcClient;
    GetClientRect(m_hWnd, &rcClient);
    if (PtInRect(&rcClient, pt)) {
        nRet = 1;
    }
    int nItemIndex = -1;
    RECT rcItemHeader;
    for (size_t i = 0; i < m_vectorItems.size(); i++) {
        GetItemHeaderRect(rcClient, (unsigned int)i, &rcItemHeader);
        if (PtInRect(&rcItemHeader, pt)) {
            nItemIndex = (unsigned int)i;
            break;
        }
    }
    if (nItemIndex != -1) {
        nRet = 2;
        nHitTest = nItemIndex;
    }
    return nRet;
}
BOOL CAccordionWnd::Togle(unsigned int nIndex)
{
    if (nIndex >= m_vectorItems.size()) {
        return FALSE;
    }
    ACCORDIONITEM *pItem = m_vectorItems[nIndex];
    pItem->bExpand = !pItem->bExpand;
    // é‡æ–°è°ƒæ•´ä¸ªå­çª—口的位置
    ResizeItemWnd();
    RECT rcClient;
    GetClientRect(m_hWnd, &rcClient);
    ::InvalidateRect(m_hWnd, &rcClient, TRUE);
    return TRUE;
}
void CAccordionWnd::Notify(int nCode, int dwData, int dwData1/* = 0*/, int dwData2/* = 0*/)
{
    HWND hParent;
    hParent = GetParent(m_hWnd);
    if (hParent != NULL) {
        ACCORDION_NMHDR accordionWndnmhdr;
        accordionWndnmhdr.nmhdr.hwndFrom = m_hWnd;
        accordionWndnmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
        accordionWndnmhdr.nmhdr.code = nCode;
        accordionWndnmhdr.dwData = dwData;
        accordionWndnmhdr.dwData1 = dwData1;
        accordionWndnmhdr.dwData2 = dwData2;
        SendMessage(hParent, WM_NOTIFY, (WPARAM)accordionWndnmhdr.nmhdr.idFrom, (LPARAM)&accordionWndnmhdr);
    }
}
/*
 * æ‹¦æˆªçª—口消息函数
 */
LRESULT CALLBACK CAccordionWnd::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CAccordionWnd* pAccordionWnd = (CAccordionWnd *)GetProp(hWnd, ACCORDIONWND_TAG);
    if (pAccordionWnd == NULL && uMsg != WM_NCCREATE)
    {
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    // å¦‚æžœHook则响应消息
    ASSERT(hWnd);
    switch (uMsg)
    {
    case WM_NCCREATE:
        return CAccordionWnd::OnNcCreate(hWnd, wParam, lParam);
    case WM_DESTROY:
        return pAccordionWnd->OnDestroy(wParam, lParam);
    case WM_NCCALCSIZE:
        return pAccordionWnd->OnNcCalcsize(wParam, lParam);
    case WM_NCPAINT:
        return pAccordionWnd->OnNcPaint(wParam, lParam);
    case WM_PAINT:
        return pAccordionWnd->OnPaint(wParam, lParam);
    case WM_TIMER:
        return pAccordionWnd->OnTimer(wParam, lParam);
    case WM_MOUSEMOVE:
        return pAccordionWnd->OnMouseMove(wParam, lParam);
    case WM_LBUTTONDOWN:
        return pAccordionWnd->OnLButtonDown(wParam, lParam);
    case WM_LBUTTONUP:
        return pAccordionWnd->OnLButtonUp(wParam, lParam);
    case WM_MOUSEWHEEL:
        return pAccordionWnd->OnMouseWheel(wParam, lParam);
    case WM_SIZE:
        return pAccordionWnd->OnSize(wParam, lParam);
    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS;
    default:
        break;
    }
    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
/*
 * WM_NCCREATE
 * çª—口创建前的初始化工作
 */
LRESULT CAccordionWnd::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    CAccordionWnd* pAccordionWnd = (CAccordionWnd *)GetProp(hWnd, ACCORDIONWND_TAG);
    ASSERT(pAccordionWnd == NULL);
    Hook(hWnd);
    return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
}
/*
 * WM_NCCALCSIZE
 */
LRESULT CAccordionWnd::OnNcCalcsize(WPARAM wParam, LPARAM lParam)
{
    if (!m_bShadow) {
        return ::DefWindowProc(m_hWnd, WM_NCCALCSIZE, wParam, lParam);
    }
    LPRECT lprcWnd = (LPRECT)lParam;
    lprcWnd->left += BORDER;
    lprcWnd->top += BORDER;
    lprcWnd->right -= (BORDER + SHADOWWIDE);
    lprcWnd->bottom -= (BORDER + SHADOWWIDE);
    return 0;
}
/*
 * WM_DESTROY
 * çª—口销毁时
 */
LRESULT CAccordionWnd::OnDestroy(WPARAM wParam, LPARAM lParam)
{
    Release();
    return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
}
/*
 * WM_TIMER
 */
LRESULT CAccordionWnd::OnTimer(WPARAM wParam, LPARAM lParam)
{
    int nTimerId = (int)wParam;
    if (m_nTimerId == nTimerId) {
        POINT pt;
        ::GetCursorPos(&pt);
        ::ScreenToClient(m_hWnd, &pt);
        int nRet, nHitTest;
        nRet = HitTest(pt, nHitTest);
        if (m_nCheckHoverItem != nHitTest) {
            KillTimer(m_hWnd, m_nTimerId);
            m_nHoverItem = nHitTest;
            m_nCheckHoverItem = nHitTest;
            RECT rcClient;
            GetClientRect(m_hWnd, &rcClient);
            ::InvalidateRect(m_hWnd, &rcClient, TRUE);
        }
    }
    return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
}
/*
 * WM_MOUSEMOVE
 * é¼ æ ‡ç§»åŠ¨æ—¶ï¼Œæ£€æµ‹é¼ æ ‡ä½ç½®å¹¶å›žè°ƒç»™ä¸»çª—å£
 */
LRESULT CAccordionWnd::OnMouseMove(WPARAM wParam, LPARAM lParam)
{
    POINT pt;
    pt.x = (int)LOWORD(lParam);
    pt.y = (int)HIWORD(lParam);
    int nRet, nHitTest;
    nRet = HitTest(pt, nHitTest);
    if (nRet == 2) {
        ACCORDIONITEM *pItem = m_vectorItems[nHitTest];
        if (pItem != NULL && pItem->bEnable) {
            ::SetCursor(LoadCursor(NULL, IDC_HAND));
        }
    }
    else {
        ::SetCursor(LoadCursor(NULL, IDC_ARROW));
    }
    int nLastItem = m_nHoverItem;
    if (m_nHoverItem != nHitTest) {
        m_nHoverItem = nHitTest;
        RECT rcClient, rcLastItemClient, rcCurItemClient;
        GetClientRect(m_hWnd, &rcClient);
        GetItemRect(rcClient, nLastItem, &rcLastItemClient);
        ::InvalidateRect(m_hWnd, &rcLastItemClient, nHitTest < 0);
        if (nHitTest >= 0) {
            ACCORDIONITEM *pItem = m_vectorItems.at(nHitTest);
            if (!pItem->bEnable) {
                m_nHoverItem = -1;
            }
            else {
                KillTimer(m_hWnd, m_nTimerId);
                m_nTimerId = SetTimer(m_hWnd, TIMER_ID_CHECKHOVER, 200, NULL);
                m_nCheckHoverItem = m_nHoverItem;
                GetItemRect(rcClient, m_nHoverItem, &rcCurItemClient);
                ::InvalidateRect(m_hWnd, &rcCurItemClient, TRUE);
            }
        }
    }
    return ::DefWindowProc(m_hWnd, WM_MOUSEMOVE, wParam, lParam);
}
/*
 * WM_LBUTTONDOWN
 * é¼ æ ‡å·¦é”®ä¸‹åŽ‹
 */
LRESULT CAccordionWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
    POINT pt;
    pt.x = (int)LOWORD(lParam);
    pt.y = (int)HIWORD(lParam);
    int nRet, nHitTest;
    nRet = HitTest(pt, nHitTest);
    if (nRet == 2) {
        ACCORDIONITEM *pItem = m_vectorItems[nHitTest];
        if (pItem != NULL && pItem->bEnable) {
            ::SetCursor(LoadCursor(NULL, IDC_HAND));
        }
    }
    else {
        ::SetCursor(LoadCursor(NULL, IDC_ARROW));
    }
    return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
}
/*
 * WM_LBUTTONUP
 * é¼ æ ‡å·¦é”®é‡Šæ”¾
 */
LRESULT CAccordionWnd::OnLButtonUp(WPARAM wParam, LPARAM lParam)
{
    POINT pt;
    pt.x = (int)LOWORD(lParam);
    pt.y = (int)HIWORD(lParam);
    int nRet, nHitTest;
    nRet = HitTest(pt, nHitTest);
    if (nRet == 2) {
        ACCORDIONITEM *pItem = m_vectorItems[nHitTest];
        if (pItem != NULL && pItem->bEnable) {
            ::SetCursor(LoadCursor(NULL, IDC_HAND));
            Togle(nHitTest);
        }
    }
    else {
        ::SetCursor(LoadCursor(NULL, IDC_ARROW));
    }
    return ::DefWindowProc(m_hWnd, WM_LBUTTONUP, wParam, lParam);
}
/*
 * WM_MOUSEWHEEL
 * é¼ æ ‡æ»šè½®æ»šåŠ¨æ—¶ï¼Œç¼©æ”¾å›¾åƒ
 */
LRESULT CAccordionWnd::OnMouseWheel(WPARAM wParam, LPARAM lParam)
{
    return ::DefWindowProc(m_hWnd, WM_MOUSEWHEEL, wParam, lParam);
}
/*
 * WM_NCPAINT
 */
LRESULT CAccordionWnd::OnNcPaint(WPARAM wParam, LPARAM lParam)
{
    LRESULT lRet = ::DefWindowProc(m_hWnd, WM_NCPAINT, wParam, lParam);
    // ç„¶åŽç”»è¾¹æ¡†
    long styleEx = GetWindowLong(m_hWnd, GWL_EXSTYLE);
    if ((styleEx & WS_EX_CLIENTEDGE) == WS_EX_CLIENTEDGE) {
        RECT rcWindow, rcClient;
        GetClientRect(m_hWnd, &rcClient);
        ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.left);
        ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.right);
        GetWindowRect(m_hWnd, &rcWindow);
        ::OffsetRect(&rcClient, -rcWindow.left, -rcWindow.top);
        ::OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
        HRGN hRgnWnd = CreateRectRgnIndirect(&rcWindow);
        HRGN hRgnClient = CreateRectRgnIndirect(&rcClient);
        HDC hDC = GetWindowDC(m_hWnd);
        ::SelectClipRgn(hDC, hRgnWnd);
        ::ExtSelectClipRgn(hDC, hRgnClient, RGN_DIFF);
        // æ²¡æœ‰é˜´å½±çš„边框
        if (!m_bShadow) {
            HBRUSH hBrushBK, hBrushFrame;
            hBrushBK = CreateSolidBrush(m_crBkgnd);
            ::FillRect(hDC, &rcWindow, hBrushBK);
            DeleteObject(hBrushBK);
            hBrushFrame = CreateSolidBrush(m_crFrame);
            ::FrameRect(hDC, &rcWindow, hBrushFrame);
            DeleteObject(hBrushFrame);
        }
        // æœ‰é˜´å½±çš„边框
        else {
            RECT rcFrame0, rcFrame1;
            rcFrame0.left = rcWindow.left + SHADOWWIDE;
            rcFrame0.top = rcWindow.top + SHADOWWIDE;
            rcFrame0.right = rcWindow.right;
            rcFrame0.bottom = rcWindow.bottom;
            rcFrame1.left = rcWindow.left;
            rcFrame1.top = rcWindow.top;
            rcFrame1.right = rcWindow.right - SHADOWWIDE;
            rcFrame1.bottom = rcWindow.bottom - SHADOWWIDE;
            // èƒŒæ™¯æ¡†å’Œå¯¹è¯æ¡†(父窗体)背景色一致
            HBRUSH hBrushBK, hBrushFrame;
            hBrushBK = CreateSolidBrush(m_crShadowBkgnd);
            ::FillRect(hDC, &rcWindow, hBrushBK);
            DeleteObject(hBrushBK);
            // é˜´å½±æ¡†
            BYTE r = GetRValue(m_crShadowBkgnd);
            BYTE g = GetGValue(m_crShadowBkgnd);
            BYTE b = GetBValue(m_crShadowBkgnd);
            BYTE rstep = (r - GetRValue(m_crFrame)) / SHADOWWIDE;
            BYTE gstep = (r - GetGValue(m_crFrame)) / SHADOWWIDE;
            BYTE bstep = (r - GetBValue(m_crFrame)) / SHADOWWIDE;
            for (int i = 0; i < SHADOWWIDE; i++) {
                hBrushBK = CreateSolidBrush(RGB(r - i*rstep, g - i*gstep, b - i*bstep));
                ::FillRect(hDC, &rcFrame0, hBrushBK);
                DeleteObject(hBrushBK);
                rcFrame0.bottom -= 1;
                rcFrame0.right -= 1;
            }
            // å‰æ™¯æ¡†
            hBrushBK = CreateSolidBrush(m_crBkgnd);
            ::FillRect(hDC, &rcFrame1, hBrushBK);
            DeleteObject(hBrushBK);
            hBrushFrame = CreateSolidBrush(m_crFrame);
            ::FrameRect(hDC, &rcFrame1, hBrushFrame);
            DeleteObject(hBrushFrame);
        }
        ::DeleteObject(hRgnWnd);
        ::DeleteObject(hRgnClient);
        ReleaseDC(m_hWnd, hDC);
    }
    return lRet;
}
/*
 * WM_PAINT
 */
LRESULT CAccordionWnd::OnPaint(WPARAM wParam, LPARAM lParam)
{
    HDC hDC, hMemDC;
    HBITMAP hBitmap;
    RECT rcClient;
    CString strText;
    HFONT hFont;
    HBRUSH hBrushBK;
    // BeginPaint
    PAINTSTRUCT ps;
    hDC = BeginPaint(m_hWnd, &ps);
    GetClientRect(m_hWnd, &rcClient);
    hMemDC = ::CreateCompatibleDC(hDC);
    hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left,
        rcClient.bottom - rcClient.top);
    ::SelectObject(hMemDC, hBitmap);
    ::SetBkMode(hMemDC, TRANSPARENT);
    // èƒŒæ™¯é¢œè‰²
    hBrushBK = CreateSolidBrush(m_crBkgnd);
    ::FillRect(hMemDC, &rcClient, hBrushBK);
    DeleteObject(hBrushBK);
    // ç»˜å­é¡¹åˆ—表
    hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    ::SelectObject(hMemDC, hFont);
    HPEN hPenSeparate = ::CreatePen(PS_SOLID, 1, m_crSeparateLine);
    RECT rcItem, rcItemHeader;
    for (size_t i = 0; i < m_vectorItems.size(); i++) {
        ACCORDIONITEM *pItem = m_vectorItems[i];
        GetItemRect(rcClient, i, &rcItem);
        GetItemHeaderRect(rcClient, i, &rcItemHeader);
        // çƒ­ç‚¹é¡¹çš„背景色和边框
        if (m_nHoverItem == (int)i) {
            HBRUSH hbrItemHeaderBackground = CreateSolidBrush(m_crHoverItemBackground);
            HBRUSH hbrItemFrame = CreateSolidBrush(m_crHoverItemFrame);
            HRGN hRgn = CreateRoundRectRgn(rcItemHeader.left, rcItemHeader.top, rcItemHeader.right, rcItemHeader.bottom, 2, 2);
            ::FillRgn(hMemDC, hRgn, hbrItemHeaderBackground);
            ::FrameRgn(hMemDC, hRgn, hbrItemFrame, 1, 1);
            ::DeleteObject(hbrItemHeaderBackground);
            ::DeleteObject(hbrItemFrame);
            ::DeleteObject(hRgn);
        }
        // ç®­å¤´
        BOOL bDrawIcon = DrawIconEx(hMemDC, rcItemHeader.left + (ITEM_HEIGHT - EXPAND_ICON_WIDE) / 2, rcItemHeader.top + (ITEM_HEIGHT - EXPAND_ICON_WIDE)/2,
            pItem->bExpand ? m_hIconExpand : m_hIconClose, EXPAND_ICON_WIDE, EXPAND_ICON_WIDE, 0, 0, DI_NORMAL);
        // æ–‡æœ¬
        ::SetTextColor(hMemDC, m_nHoverItem == (int)i ? m_crItemText[1] : m_crItemText[0]);
        RECT rcText;
        rcText.left = rcItemHeader.left + (bDrawIcon ? ITEM_HEIGHT : (ITEM_HEIGHT - EXPAND_ICON_WIDE) / 2);
        rcText.top = rcItemHeader.top;
        rcText.right = rcItemHeader.right;
        rcText.bottom = rcItemHeader.bottom;
        ::DrawText(hMemDC, pItem->text, (int)strlen(pItem->text), &rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
        // æ–‡æœ¬å³è¾¹åˆ†éš”线
        SIZE sizeText;
        GetTextExtentPoint32(hMemDC, pItem->text, (int)strlen(pItem->text), &sizeText);
        HPEN hOldPen = (HPEN)::SelectObject(hMemDC, hPenSeparate);
        MoveToEx(hMemDC, rcText.left + sizeText.cx + 10, rcItemHeader.top+(rcItemHeader.bottom- rcItemHeader.top-1)/2, NULL);
        LineTo(hMemDC, rcItemHeader.right-10, rcItemHeader.top+(rcItemHeader.bottom - rcItemHeader.top - 1) / 2);
        ::SelectObject(hMemDC, hOldPen);
        rcItemHeader.top = rcItemHeader.bottom + ITEM_SPACE;
        rcItemHeader.bottom = rcItemHeader.top + ITEM_HEIGHT;
    }
    ::DeleteObject(hPenSeparate);
    // EndPaint
    ::BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
        hMemDC, 0, 0, SRCCOPY);
    EndPaint(m_hWnd, &ps);
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
    return 1;
}
/*
 * WM_SIZE
 */
LRESULT CAccordionWnd::OnSize(WPARAM wParam, LPARAM lParam)
{
    LRESULT lRet = ::DefWindowProc(m_hWnd, WM_SIZE, wParam, lParam);
    ResizeItemWnd();
    return lRet;
}
/*
 * è®¾ç½®èƒŒæ™¯è‰²
 * color -- èƒŒæ™¯è‰²
 */
void CAccordionWnd::SetBkgndColor(COLORREF color)
{
    m_crBkgnd = color;
}
/*
 * è®¾ç½®é˜´å½±çš„背景色(即父窗口的背景)
 * color -- èƒŒæ™¯è‰²
 */
void CAccordionWnd::SetShadowBkgnd(COLORREF color)
{
    m_crShadowBkgnd = color;
}
/*
 * è®¾ç½®è¾¹æ¡†é¢œè‰²
 * color -- è¾¹æ¡†é¢œè‰²
 */
void CAccordionWnd::SetFrameColor(COLORREF color, BOOL bShadow/* = FALSE*/)
{
    m_crFrame = color;
    m_bShadow = bShadow;
    SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
SourceCode/Bond/BondEq/AccordionWnd.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,129 @@
#pragma once
#include <functional>
#include <vector>
#ifndef ACCORDIONWND_TAG
#ifdef _WIN32
#define ACCORDIONWND_CLASSA        "AccordionWnd"
#define ACCORDIONWND_CLASSW        L"AccordionWnd"
#ifdef UNICODE
#define ACCORDIONWND_CLASS        ACCORDIONWND_CLASSW
#else
#define ACCORDIONWND_CLASS        ACCORDIONWND_CLASSA
#endif
#else
#define ACCORDIONWND_CLASS      "AccordionWnd"
#endif
#define ACCORDIONWND_TAG        _T("ACCORDIONWND_TAG")
#define ACCORDIONWND_FIRST        (0U-3590U)
#define ACCORDIONWND_LAST        (0U-5350U)
#define ACCORDIONWND_            (ACCORDIONWND_FIRST - 1)
typedef struct tagACCORDION_NMHDR
{
    NMHDR        nmhdr;
    DWORD        dwData;
    DWORD        dwData1;
    DWORD        dwData2;
} ACCORDION_NMHDR;
typedef struct tagACCORDIONITEM
{
    unsigned int id;
    int nExpandHeight;
    COLORREF crBackground[2];
    COLORREF crFrame[2];
    COLORREF crText[2];
    char text[256];
    CWnd *pWnd;
    BOOL bExpand;
    BOOL bEnable;                // æ˜¯å¦å¯ä»¥ç‚¹å‡»å±•开和收起
} ACCORDIONITEM;
#endif
#define PADDING_LEFT        0
#define PADDING_TOP            1
#define PADDING_RIGHT        2
#define PADDING_BOTTOM        3
class CAccordionWnd
{
public:
    CAccordionWnd();
    ~CAccordionWnd();
public:
    static BOOL RegisterWndClass();
    static CAccordionWnd * FromHandle(HWND hWnd);
    void SetFrameColor(COLORREF color, BOOL bShadow = FALSE);
    void SetBkgndColor(COLORREF color);
    void SetShadowBkgnd(COLORREF color);
public:
    void LoadExpandIcon(CString strExpandFile, CString strCloseFile);
    void Setpadding(int type, unsigned int nPadding);
    void SetDefaultItemBackgroundColor(COLORREF crNormal, COLORREF crSel);
    void SetDefaultItemFrameColor(COLORREF crNormal, COLORREF crSel);
    void SetDefaultItemTextColor(COLORREF crNormal, COLORREF crSel);
    void AddItem(char *pszName, CWnd *pWnd, int nExpandHeight, BOOL bExpand = TRUE, BOOL bEnable = TRUE);
    BOOL Togle(unsigned int nIndex);
private:
    void Init();
    void Notify(int nCode, int dwData, int dwData1 = 0, int dwData2 = 0);
    void Release();
    void ResizeItemWnd();
    static CAccordionWnd* Hook(HWND hWnd);
    static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    static LRESULT OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
    LRESULT OnDestroy(WPARAM wParam, LPARAM lParam);
    LRESULT OnTimer(WPARAM wParam, LPARAM lParam);
    LRESULT OnNcPaint(WPARAM wParam, LPARAM lParam);
    LRESULT OnNcCalcsize(WPARAM wParam, LPARAM lParam);
    LRESULT OnPaint(WPARAM wParam, LPARAM lParam);
    LRESULT OnMouseMove(WPARAM wParam, LPARAM lParam);
    LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam);
    LRESULT OnLButtonUp(WPARAM wParam, LPARAM lParam);
    LRESULT OnMouseWheel(WPARAM wParam, LPARAM lParam);
    LRESULT OnSize(WPARAM wParam, LPARAM lParam);
private:
    HWND        m_hWnd;
    COLORREF    m_crBkgnd;
    COLORREF    m_crFrame;
    HICON        m_hIconClose;
    HICON        m_hIconExpand;
    int            m_nHoverItem;
    int            m_nCheckHoverItem;
    BOOL        m_bShadow;                // é˜´å½±
    COLORREF    m_crShadowBkgnd;        // é˜´å½±èƒŒæ™¯è‰²(即父窗口的颜色)
private:
    unsigned int m_nPadding[4];
    COLORREF m_crItemBackground[2];
    COLORREF m_crItemFrame[2];
    COLORREF m_crItemText[2];
    COLORREF m_crSeparateLine;
    COLORREF m_crHoverItemBackground;
    COLORREF m_crHoverItemFrame;
    CString m_strExpandIconFilepath[2];
private:
    std::vector<ACCORDIONITEM *> m_vectorItems;
    int m_nTimerId;
private:
    int HitTest(POINT pt, int &nHitTest);
    BOOL GetItemHeaderRect(RECT rcClient, unsigned int nIndex, LPRECT lpRect);
    BOOL GetItemRect(RECT rcClient, unsigned int nIndex, LPRECT lpRect);
};
SourceCode/Bond/BondEq/ApredTreeCtrl.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,466 @@
#include "stdafx.h"
#include "ApredTreeCtrl.h"
#define ROFFSET 7
#define WIDE    10
#define WIDE2    5
#define EXPANDED_WIDE    8
#define BADGE_HIDE                  0
#define BADGE_DOT                   1
#define BADGE_NUMBER                2
#define BADGE_DOT_WIDTH             12
#define BADGE_NUMBER_WIDTH          20
IMPLEMENT_DYNAMIC(CApredTreeCtrl, CTreeCtrl)
CApredTreeCtrl::CApredTreeCtrl()
{
    m_hBrushItem[0] = NULL;
    m_hBrushItem[1] = NULL;
    m_hBrushItem[2] = NULL;
    m_hPenItem[0] = nullptr;
    m_hPenItem[1] = nullptr;
    m_hPenItem[2] = nullptr;
    m_hBrushBtn[0] = nullptr;
    m_hBrushBtn[1] = nullptr;
    m_hBrushBtn[2] = nullptr;
    m_crItemBk[0] = RGB(255,255,255);
    m_crItemBk[1] = RGB(228, 229, 234);
    m_crItemBk[2] = RGB(236, 237, 241);
    m_crText[0] = RGB(28, 28, 28);
    m_crText[1] = RGB(28, 28, 28);
    m_crText[2] = RGB(28, 28, 28);
    m_hHoverItem = nullptr;
    m_bTracking = FALSE;
}
CApredTreeCtrl::~CApredTreeCtrl()
{
    if (m_hBrushItem[0] != NULL) {
        ::DeleteObject(m_hBrushItem[0]);
    }
    if (m_hBrushItem[1] != NULL) {
        ::DeleteObject(m_hBrushItem[1]);
    }
    if (m_hBrushItem[2] != NULL) {
        ::DeleteObject(m_hBrushItem[2]);
    }
    if (m_hBrushBtn[0] != NULL) {
        ::DeleteObject(m_hBrushBtn[0]);
    }
    if (m_hBrushBtn[1] != NULL) {
        ::DeleteObject(m_hBrushBtn[1]);
    }
    if (m_hBrushBtn[2] != NULL) {
        ::DeleteObject(m_hBrushBtn[2]);
    }
    if (m_hPenItem[0] != nullptr) {
        ::DeleteObject(m_hPenItem[0]);
    }
    if (m_hPenItem[1] != nullptr) {
        ::DeleteObject(m_hPenItem[1]);
    }
    if (m_hPenItem[2] != nullptr) {
        ::DeleteObject(m_hPenItem[2]);
    }
}
BEGIN_MESSAGE_MAP(CApredTreeCtrl, CTreeCtrl)
    ON_WM_PAINT()
    ON_WM_MOUSEMOVE()
    ON_WM_MOUSEHOVER()
    ON_WM_MOUSELEAVE()
    ON_WM_TIMER()
    ON_WM_LBUTTONDOWN()
    ON_WM_CREATE()
END_MESSAGE_MAP()
void CApredTreeCtrl::DrawItemButton(HTREEITEM hItem, HDC hDC, CRect* pRect)
{
    // æŒ‰é’®è¦åˆ·ä¸€ä¸‹
    POINT pt[3];
    if ((GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED) == TVIS_EXPANDED) {
        int nBottomOffset = (pRect->Height() - EXPANDED_WIDE) / 2;
        pt[0].x = pRect->right - ROFFSET - EXPANDED_WIDE;
        pt[0].y = pRect->bottom - nBottomOffset;
        pt[1].x = pRect->right - ROFFSET;
        pt[1].y = pRect->bottom - nBottomOffset;
        pt[2].x = pRect->right - ROFFSET;
        pt[2].y = pRect->bottom - nBottomOffset - EXPANDED_WIDE;
    }
    else {
        int nBottomOffset = (pRect->Height() - WIDE) / 2;
        pt[0].x = pRect->right - ROFFSET - WIDE2;
        pt[0].y = pRect->bottom - nBottomOffset - WIDE;
        pt[1].x = pRect->right - ROFFSET - WIDE2;
        pt[1].y = pRect->bottom - nBottomOffset;
        pt[2].x = pRect->right - ROFFSET;
        pt[2].y = pRect->bottom - nBottomOffset - WIDE2;
    }
    ::Polygon(hDC, pt, 3);
}
void CApredTreeCtrl::OnPaint()
{
    HDC hDC, hMemDC;
    HBITMAP hBitmap;
    RECT rcClient;
    CString strText;
    HFONT hFont;
    HBRUSH hBrushBK;
    if (m_hBrushItem[0] == nullptr) {
        m_hBrushItem[0] = CreateSolidBrush(m_crItemBk[0]);
    }
    if (m_hBrushItem[1] == nullptr) {
        m_hBrushItem[1] = CreateSolidBrush(m_crItemBk[1]);
    }
    if (m_hBrushItem[2] == nullptr) {
        m_hBrushItem[2] = CreateSolidBrush(m_crItemBk[2]);
    }
    if (m_hBrushBtn[0] == nullptr) {
        m_hBrushBtn[0] = CreateSolidBrush(m_crText[0]);
    }
    if (m_hBrushBtn[1] == nullptr) {
        m_hBrushBtn[1] = CreateSolidBrush(m_crText[1]);
    }
    if (m_hBrushBtn[2] == nullptr) {
        m_hBrushBtn[2] = CreateSolidBrush(m_crText[2]);
    }
    if (m_hPenItem[0] == nullptr) {
        m_hPenItem[0] = ::CreatePen(PS_SOLID, 1, m_crText[0]);
    }
    if (m_hPenItem[1] == nullptr) {
        m_hPenItem[1] = ::CreatePen(PS_SOLID, 1, m_crText[1]);
    }
    if (m_hPenItem[2] == nullptr) {
        m_hPenItem[2] = ::CreatePen(PS_SOLID, 1, m_crText[2]);
    }
    // BeginPaint
    PAINTSTRUCT ps;
    hDC = ::BeginPaint(m_hWnd, &ps);
    GetClientRect(&rcClient);
    hMemDC = ::CreateCompatibleDC(hDC);
    hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left,
        rcClient.bottom - rcClient.top);
    ::SelectObject(hMemDC, hBitmap);
    hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    ::SelectObject(hMemDC, hFont);
    ::SetBkMode(hMemDC, TRANSPARENT);
    // èƒŒæ™¯é¢œè‰²
    hBrushBK = CreateSolidBrush(GetBkColor());
    ::FillRect(hMemDC, &rcClient, hBrushBK);
    DeleteObject(hBrushBK);
    // ç»˜åˆ¶å­é¡¹
    DrawItems(hMemDC);
    // EndPaint
    ::BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
        hMemDC, 0, 0, SRCCOPY);
    ::EndPaint(m_hWnd, &ps);
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
}
void CApredTreeCtrl::DrawItems(HDC hDC)
{
    HTREEITEM hCurrentItem;
    int      itemState;
    CRect rcClient, rcItem, rcText;
    GetClientRect(&rcClient);
    Gdiplus::Graphics graphics(hDC);
    graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
    // ç»˜åˆ¶å¯è§çš„子项
    hCurrentItem = GetFirstVisibleItem();//获取第一个课可见的项
    do {
        if (GetItemRect(hCurrentItem, &rcItem, FALSE) && GetItemRect(hCurrentItem, &rcText, TRUE)) {
            rcText.right = rcItem.right - 8;
            rcText.left += 8;
            CRect fillRect(0, rcItem.top, rcClient.right, rcItem.bottom);
            if (rcItem.top > rcClient.bottom) {
                break;
            }
            // ç»˜åˆ¶å­é¡¹èƒŒæ™¯
            itemState = GetItemState(hCurrentItem, TVIF_STATE);
            COLORREF crText = m_crText[0];
            if (itemState & TVIS_SELECTED) {
                crText = m_crText[1];
                HRGN hRgn = CreateRoundRectRgn(rcItem.left, rcItem.top, rcItem.right, rcItem.bottom, 4, 4);
                ::FillRgn(hDC, hRgn, m_hBrushItem[1]);
                ::DeleteObject(hRgn);
                ::SelectObject(hDC, m_hBrushBtn[1]);
                ::SelectObject(hDC, m_hPenItem[1]);
            }
            else if (hCurrentItem == m_hHoverItem) {
                crText = m_crText[2];
                HRGN hRgn = CreateRoundRectRgn(rcItem.left, rcItem.top, rcItem.right, rcItem.bottom, 4, 4);
                ::FillRgn(hDC, hRgn, m_hBrushItem[2]);
                ::DeleteObject(hRgn);
                ::SelectObject(hDC, m_hBrushBtn[2]);
                ::SelectObject(hDC, m_hPenItem[2]);
            }
            else {
                crText = m_crText[0];
                ::SelectObject(hDC, m_hBrushBtn[0]);
                ::SelectObject(hDC, m_hPenItem[0]);
            }
            //绘制展开图片
            if (ItemHasChildren(hCurrentItem)) {
                CRect rcBtn = rcText;
                rcBtn.right = rcText.left - 2;
                rcBtn.left -= rcBtn.right - 30;
                DrawItemButton(hCurrentItem, hDC, &rcBtn);
            }
            // å›¾æ ‡
            if (m_icons.find(hCurrentItem) != m_icons.end()) {
                HICON hIcon = m_icons[hCurrentItem];
                DrawIconEx(hDC, 8, (rcItem.bottom - rcItem.top - 32) / 2,
                    hIcon, 32, 32, 0, 0, DI_NORMAL);
                rcText.left += 32;
                rcText.left += 8;
            }
            //绘制文字
            HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
            ::SelectObject(hDC, hFont);
            LOGFONT lf;
            ::GetObject(hFont, sizeof(LOGFONT), &lf);
            lf.lfWeight = FW_BOLD;
            HFONT hFontBold = CreateFontIndirect(&lf);
            ::SetTextColor(hDC, crText);
            CString strText = GetItemText(hCurrentItem);
            if (FindBoldItem(hCurrentItem)) {
                ::SelectObject(hDC, hFontBold);
            }
            else {
                ::SelectObject(hDC, hFont);
            }
            DrawText(hDC, strText, strText.GetLength(), &rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
            ::DeleteObject(hFontBold);
            // æ˜¯å¦æœ‰å°åœ†ç‚¹
            if (m_badges.find(hCurrentItem) != m_badges.end()) {
                BADGE& badge = m_badges[hCurrentItem];
                if (badge.type == BADGE_DOT) {
                    Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(badge.badgeBackground), GetGValue(badge.badgeBackground), GetBValue(badge.badgeBackground)));
                    int x = rcItem.right - 18 - BADGE_DOT_WIDTH;
                    int y = rcItem.top + (rcItem.Height() - BADGE_DOT_WIDTH) / 2;
                    graphics.FillEllipse(&brush, x, y, BADGE_DOT_WIDTH, BADGE_DOT_WIDTH);
                }
                else if (badge.type == BADGE_NUMBER) {
                    Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(badge.badgeBackground), GetGValue(badge.badgeBackground), GetBValue(badge.badgeBackground)));
                    int x = rcItem.right - 18 - BADGE_NUMBER_WIDTH;
                    int y = rcItem.top + (rcItem.Height() - BADGE_NUMBER_WIDTH) / 2;
                    graphics.FillEllipse(&brush, x, y, BADGE_NUMBER_WIDTH, BADGE_NUMBER_WIDTH);
                    RECT rcBadge;
                    rcBadge.left = x;
                    rcBadge.right = rcBadge.left + BADGE_NUMBER_WIDTH;
                    rcBadge.top = y;
                    rcBadge.bottom = rcBadge.top + BADGE_NUMBER_WIDTH;
                    ::SetTextColor(hDC, badge.badgeForeground);
                    char szBuffer[32];
                    sprintf_s(szBuffer, 32, "%d%s", min(badge.number, 9), badge.number > 9 ? "+" : "");
                    DrawText(hDC, szBuffer, (int)strlen(szBuffer), &rcBadge, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
                }
            }
        }
    } while ((hCurrentItem = GetNextVisibleItem(hCurrentItem)) != NULL);
}
void CApredTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
    // æ£€æµ‹å¹¶è®°å½•热点项
    HTREEITEM hHoverItem = HitTest(point);
    if (m_hHoverItem != hHoverItem) {
        m_hHoverItem = hHoverItem;
        InvalidateRect(NULL);
    }
    if (!m_bTracking) {
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(tme);
        tme.dwFlags = TME_HOVER | TME_LEAVE;        // å‘送WM_MOUSEHOVER和WM_MOUSELEAVE
        tme.hwndTrack = m_hWnd;                        // æŒ‡å®šè¦è¿½è¸ªçš„窗口
        tme.dwHoverTime = 10;                        // é¼ æ ‡åœ¨æŒ‰é’®ä¸Šåœç•™è¶…过10ms,才认为状态为HOVER
        m_bTracking = _TrackMouseEvent(&tme);        // å¼€å¯Windows的WM_MOUSELEAVEWM_MOUSEHOVER事件支持
    }
    CTreeCtrl::OnMouseMove(nFlags, point);
}
void CApredTreeCtrl::OnTimer(UINT_PTR nIDEvent)
{
    if (1 == nIDEvent) {
        BOOL bNeedInvalidate = FALSE;
        for (auto& item : m_badges) {
            if (item.second.showTime > 0) {
                item.second.showTime--;
                if (item.second.showTime == 0) {
                    item.second.type = BADGE_HIDE;
                    bNeedInvalidate = TRUE;
                }
            }
        }
        if(bNeedInvalidate)
            InvalidateRect(NULL, TRUE);
    }
    CTreeCtrl::OnTimer(nIDEvent);
}
void CApredTreeCtrl::OnMouseHover(UINT nFlags, CPoint point)
{
}
void CApredTreeCtrl::OnMouseLeave()
{
    m_hHoverItem = nullptr;
    m_bTracking = FALSE;    // è‹¥å·²ç»ç¦»å¼€ï¼Œåˆ™åœæ­¢è¿½è¸ª
    InvalidateRect(NULL);
    CTreeCtrl::OnMouseLeave();
}
void CApredTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
    HTREEITEM hItem = HitTest(point);
    if (hItem != nullptr) {
        SelectItem(hItem);
        GetParent()->SendMessage(ID_MSG_TREE_CLICK_ITEM, (WPARAM)hItem, 0);
    }
    CTreeCtrl::OnLButtonDown(nFlags, point);
}
void CApredTreeCtrl::SetItemBadge(HTREEITEM hItem, COLORREF badgeBackground, COLORREF badgeForeground)
{
    if (m_badges.find(hItem) == m_badges.end()) {
        BADGE badge;
        badge.badgeBackground = badgeBackground;
        badge.badgeForeground = badgeForeground;
        badge.type = BADGE_HIDE;
        badge.showTime = 0;
        m_badges[hItem] = badge;
    }
    else {
        BADGE& badge = m_badges[hItem];
        badge.badgeBackground = badgeBackground;
        badge.badgeForeground = badgeForeground;
        badge.type = BADGE_HIDE;
    }
}
void CApredTreeCtrl::ShowItemBadgeNumber(HTREEITEM hItem, int number)
{
    if (m_badges.find(hItem) == m_badges.end()) {
        return;
    }
    BADGE& badge = m_badges[hItem];
    badge.type = BADGE_NUMBER;
    badge.number = number;
    InvalidateRect(NULL, TRUE);
}
void CApredTreeCtrl::ShowItemBadgeDotMode(HTREEITEM hItem, int nSecond/* = 0*/)
{
    if (m_badges.find(hItem) == m_badges.end()) {
        return;
    }
    BADGE& badge = m_badges[hItem];
    if (badge.type != BADGE_DOT) {
        badge.type = BADGE_DOT;
        badge.showTime = nSecond;
        InvalidateRect(NULL, TRUE);
    }
}
void CApredTreeCtrl::HideItemBadge(HTREEITEM hItem)
{
    BADGE& badge = m_badges[hItem];
    if (badge.type != BADGE_HIDE) {
        badge.type = BADGE_HIDE;
        badge.showTime = 0;
        InvalidateRect(NULL, TRUE);
    }
}
void CApredTreeCtrl::SetItemBold(HTREEITEM item)
{
    if (!FindBoldItem(item)) {
        m_itemBolds.push_back(item);
    }
}
void CApredTreeCtrl::CancelItemBold(HTREEITEM item)
{
    for (auto iter = m_itemBolds.begin(); iter != m_itemBolds.end(); iter++) {
        if (*iter == item) {
            m_itemBolds.erase(iter);
            break;
        }
    }
    InvalidateRect(NULL, TRUE);
}
BOOL CApredTreeCtrl::FindBoldItem(HTREEITEM item)
{
    BOOL bFound = FALSE;
    for (auto i : m_itemBolds) {
        if (i == item) return TRUE;
    }
    return FALSE;
}
int CApredTreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CTreeCtrl::OnCreate(lpCreateStruct) == -1)
        return -1;
    SetTimer(1, 1000, nullptr);
    return 0;
}
void CApredTreeCtrl::PreSubclassWindow()
{
    SetTimer(1, 1000, nullptr);
    CTreeCtrl::PreSubclassWindow();
}
void CApredTreeCtrl::SetItemIcon(HTREEITEM hItem, HICON hIcon)
{
    m_icons[hItem] = hIcon;
}
SourceCode/Bond/BondEq/ApredTreeCtrl.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,66 @@
#pragma once
#include <afxcmn.h>
#include <map>
#include <vector>
#define ID_MSG_TREE_CLICK_ITEM      WM_USER+2080
class CApredTreeCtrl :
    public CTreeCtrl
{
public:
    typedef struct tagBADGE
    {
        HTREEITEM hTreeItem;
        COLORREF badgeBackground;
        COLORREF badgeForeground;
        int type;                       /* 0: æ— ,不显示*/
        int number;
        int showTime;                    /* æ˜¾ç¤ºæ—¶é•¿ï¼Œ0:永远*/
    } BADGE;
    DECLARE_DYNAMIC(CApredTreeCtrl)
public:
    CApredTreeCtrl();
    virtual ~CApredTreeCtrl();
public:
    void SetItemBadge(HTREEITEM hItem, COLORREF badgeBackground, COLORREF badgeForeground);
    void ShowItemBadgeNumber(HTREEITEM hItem, int number);
    void ShowItemBadgeDotMode(HTREEITEM hItem, int nSecond = 0);
    void HideItemBadge(HTREEITEM hItem);
    void SetItemBold(HTREEITEM item);
    void CancelItemBold(HTREEITEM item);
    BOOL FindBoldItem(HTREEITEM item);
    void SetItemIcon(HTREEITEM hItem, HICON hIcon);
private:
    void DrawItemButton(HTREEITEM hItem, HDC hDC, CRect* pRect);
    void DrawItems(HDC hDC);
private:
    std::map<HTREEITEM, BADGE> m_badges;
    std::map<HTREEITEM, HICON> m_icons;
    std::vector< HTREEITEM> m_itemBolds;
    HBRUSH m_hBrushItem[3];
    COLORREF m_crItemBk[3];
    COLORREF m_crText[3];
    HBRUSH m_hBrushBtn[3];
    HPEN m_hPenItem[3];
    HTREEITEM m_hHoverItem;
    BOOL m_bTracking;        // è·Ÿè¸ª
public:
    DECLARE_MESSAGE_MAP()
    afx_msg void OnPaint();
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnMouseHover(UINT nFlags, CPoint point);
    afx_msg void OnMouseLeave();
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    virtual void PreSubclassWindow();
};
SourceCode/Bond/BondEq/BaseSetPage.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
#include "stdafx.h"
#include "BaseSetPage.h"
#include "Common.h"
CBaseSetPage::CBaseSetPage(UINT nIDTemplate, CWnd *pParent)
    : CDialogEx(nIDTemplate, pParent)
{
    m_crBkgnd = SETPAGE_BACKGROUND_COLOR;
    m_hbrBkgnd = nullptr;
}
CBaseSetPage::~CBaseSetPage()
{
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
}
BEGIN_MESSAGE_MAP(CBaseSetPage, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_NCLBUTTONDOWN()
    ON_WM_NCRBUTTONDOWN()
END_MESSAGE_MAP()
HBRUSH CBaseSetPage::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    if (m_hbrBkgnd == nullptr) {
        m_hbrBkgnd = CreateSolidBrush(m_crBkgnd);
    }
    if (nCtlColor == CTLCOLOR_STATIC) {
        pDC->SetBkColor(m_crBkgnd);
    }
    else if (nCtlColor == CTLCOLOR_EDIT || nCtlColor == CTLCOLOR_LISTBOX) {
        pDC->SetBkColor(m_crBkgnd);
        return m_hbrBkgnd;
    }
    return m_hbrBkgnd;
}
void CBaseSetPage::OnApply()
{
}
void CBaseSetPage::OnModify()
{
    GetParent()->SendMessageA(ID_MSG_PAGE_MODIFY);
}
SourceCode/Bond/BondEq/BaseSetPage.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
#pragma once
#include "afxdialogex.h"
#define ID_MSG_PAGE_MODIFY        WM_USER + 1278
class CBaseSetPage :
    public CDialogEx
{
public:
    CBaseSetPage(UINT nIDTemplate, CWnd *pParent = NULL);
    ~CBaseSetPage();
public:
    virtual void OnApply();
    virtual void OnModify();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
public:
    DECLARE_MESSAGE_MAP()
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};
SourceCode/Bond/BondEq/BlButton.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,448 @@
#include "stdafx.h"
#include "BlButton.h"
#define BADGE_HIDE                  0
#define BADGE_DOT                   1
#define BADGE_NUMBER                2
#define BADGE_DOT_WIDTH             12
#define BADGE_NUMBER_WIDTH          20
CBlButton::CBlButton()
{
    m_nState = BS_NORMAL;
    m_crFrame[BS_NORMAL] = RGB(225, 225, 225);
    m_crFrame[BS_HOVER] = RGB(0, 120, 215);
    m_crFrame[BS_PRESS] = RGB(0, 84, 153);
    m_crFrame[BS_FOCUS] = RGB(0, 120, 215);
    m_crFrame[BS_DISABLE] = RGB(191, 191, 191);
    m_crBkgnd[BS_NORMAL] = RGB(225, 225, 225);
    m_crBkgnd[BS_HOVER] = RGB(229, 241, 251);
    m_crBkgnd[BS_PRESS] = RGB(204, 228, 247);
    m_crBkgnd[BS_FOCUS] = RGB(225, 225, 225);
    m_crBkgnd[BS_DISABLE] = RGB(204, 204, 204);
    m_crText[BS_NORMAL] = RGB(0, 0, 0);
    m_crText[BS_HOVER] = RGB(0, 0, 0);
    m_crText[BS_PRESS] = RGB(0, 0, 0);
    m_crText[BS_FOCUS] = RGB(0, 0, 0);
    m_crText[BS_DISABLE] = RGB(131, 131, 131);
    m_bHover = FALSE;
    m_bSelected = FALSE;
    m_bTracking = FALSE;
    memset(&m_badge, 0, sizeof(BADGE));
    m_nRoundWidth = 0;
    m_hMenu = nullptr;
    m_hIcon[0] = nullptr;
    m_hIcon[1] = nullptr;
    m_nIconWidth = 0;
}
CBlButton::~CBlButton()
{
}
void CBlButton::SetFrameColor(int index, COLORREF color)
{
    if (BS_NORMAL <= index && index <= BS_DISABLE) {
        m_crFrame[index] = color;
    }
}
void CBlButton::SetRoundWidth(int width)
{
    m_nRoundWidth = width;
}
void CBlButton::SetBkgndColor(int index, COLORREF color)
{
    if (BS_NORMAL <= index && index <= BS_DISABLE) {
        m_crBkgnd[index] = color;
    }
}
void CBlButton::SetTextColor(int index, COLORREF color)
{
    if (BS_NORMAL <= index && index <= BS_DISABLE) {
        m_crText[index] = color;
    }
}
void CBlButton::SetFaceColor(COLORREF color)
{
    m_crBkgnd[BS_NORMAL] = color;
    m_crBkgnd[BS_HOVER] = color;
    m_crBkgnd[BS_PRESS] = color;
    m_crBkgnd[BS_FOCUS] = color;
    Invalidate();
}
void CBlButton::SetTextColor(COLORREF color)
{
    m_crText[BS_NORMAL] = color;
    m_crText[BS_HOVER] = color;
    m_crText[BS_PRESS] = color;
    m_crText[BS_FOCUS] = color;
    Invalidate();
}
void CBlButton::SetBadgeNumber(int number)
{
    m_badge.badgeBackground = RGB(255, 0, 0);
    m_badge.badgeForeground = RGB(255, 255, 255);
    m_badge.type = number > 0 ? BADGE_NUMBER : BADGE_HIDE;
    m_badge.number = number;
    Invalidate();
}
void CBlButton::ShowDotBadge(BOOL bShow, COLORREF color)
{
    m_badge.badgeBackground = color;
    m_badge.type = bShow ? BADGE_DOT : BADGE_HIDE;
    Invalidate();
}
void CBlButton::SetBkgndBmp(const char* pszBmpFile)
{
    m_strBkgndBmp = pszBmpFile;
}
void CBlButton::SetMenu(HMENU hMenu)
{
    m_hMenu = hMenu;
}
void CBlButton::SetCurrentMenuItem(UINT nPosition)
{
    char szTxt[256];
    GetMenuString(::GetSubMenu(m_hMenu, 0), nPosition, szTxt, 256, MF_BYPOSITION);
    SetWindowText(szTxt);
}
HMENU CBlButton::GetMenu()
{
    return m_hMenu;
}
void CBlButton::SetIcon(HICON hIcon, HICON hIconGray, int width)
{
    m_hIcon[0] = hIcon;
    m_hIcon[1] = hIconGray;
    m_nIconWidth = width;
}
void CBlButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    HDC hDC = lpDrawItemStruct->hDC;
    RECT rcClient;
    GetClientRect(&rcClient);
    // è¾¹æ¡†+背景
    int state = GetDrawState();
    HBRUSH hBrush = CreateSolidBrush(m_crBkgnd[state]);
    HPEN hPen = CreatePen(PS_SOLID, state == BS_FOCUS ? 2 : 1, m_crFrame[state]);
    HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
    HPEN hOldBrush = (HPEN)::SelectObject(hDC, hBrush);
    ::RoundRect(hDC, state == BS_FOCUS ? rcClient.left + 1 : rcClient.left,
        state == BS_FOCUS ? rcClient.top + 1 : rcClient.top, rcClient.right,
        rcClient.bottom, m_nRoundWidth, m_nRoundWidth);
    ::SelectObject(hDC, hOldPen);
    ::SelectObject(hDC, hOldBrush);
    ::DeleteObject(hBrush);
    ::DeleteObject(hPen);
    // è´´å›¾
    CustomBitBlt(hDC, &rcClient, m_strBkgndBmp, state, 5, 2, 2, 2, 2, RGB(255,0,255));
    // èŽ·å¾—æ–‡æœ¬
    char szText[64];
    int nTextLen = GetWindowText(szText, 64);
    // å›¾æ ‡
    RECT rcText = rcClient;
    if (m_hIcon != nullptr) {
        int xIcon = (rcClient.right - rcClient.top - m_nIconWidth) / 2;
        if (m_hMenu != nullptr) xIcon -= 10;
        int yIcon = (rcClient.bottom - rcClient.top - m_nIconWidth) / 2;
        if (nTextLen != 0) {
            yIcon -= 8;
        }
        DrawIconEx(hDC, xIcon, yIcon,
            this->IsWindowEnabled() ? m_hIcon[0] : m_hIcon[01], m_nIconWidth, m_nIconWidth, 0, 0, DI_NORMAL);
        rcText.top = yIcon + m_nIconWidth + 2;
    }
    // æ–‡æœ¬
    HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    ::SelectObject(hDC, hFont);
    ::SetBkMode(hDC, TRANSPARENT);
    ::SetTextColor(hDC, m_crText[state]);
    if ((BS_MULTILINE & GetStyle()) == BS_MULTILINE) {
        CRect rcBound;
        int height = DrawTextA(hDC, szText, (int)strlen(szText), &rcBound,  DT_CENTER | DT_CALCRECT | DT_EDITCONTROL);
        rcText.top = rcBound.top + (rcClient.bottom - rcClient.top - height) / 2;
        rcText.bottom = rcText.top + height;
        DrawTextA(hDC, szText, (int)strlen(szText), &rcText,  DT_CENTER | DT_EDITCONTROL);
    }
    else {
        if (m_hMenu != nullptr) {
            rcText.right -= (10);
        }
        DrawTextA(hDC, szText, (int)strlen(szText), &rcText, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    }
    // æ˜¯å¦æœ‰å°åœ†ç‚¹
    if (m_badge.type == BADGE_DOT) {
        Gdiplus::Graphics graphics(hDC);
        graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
        Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(m_badge.badgeBackground), GetGValue(m_badge.badgeBackground), GetBValue(m_badge.badgeBackground)));
        int x = rcClient.right - 8 - BADGE_DOT_WIDTH;
        int y = rcClient.top + 8;
        graphics.FillEllipse(&brush, x, y, BADGE_DOT_WIDTH, BADGE_DOT_WIDTH);
    }
    else if (m_badge.type == BADGE_NUMBER) {
        Gdiplus::Graphics graphics(hDC);
        graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
        Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(m_badge.badgeBackground), GetGValue(m_badge.badgeBackground), GetBValue(m_badge.badgeBackground)));
        int x = rcClient.right - 8 - BADGE_NUMBER_WIDTH;
        int y = rcClient.top + 8;
        graphics.FillEllipse(&brush, x, y, BADGE_NUMBER_WIDTH, BADGE_NUMBER_WIDTH);
        RECT rcBadge;
        rcBadge.left = x;
        rcBadge.right = rcBadge.left + BADGE_NUMBER_WIDTH;
        rcBadge.top = y;
        rcBadge.bottom = rcBadge.top + BADGE_NUMBER_WIDTH;
        ::SetTextColor(hDC, m_badge.badgeForeground);
        char szBuffer[32];
        sprintf_s(szBuffer, 32, "%d%s", min(m_badge.number, 9), m_badge.number > 9 ? "+" : "");
        DrawText(hDC, szBuffer, (int)strlen(szBuffer), &rcBadge, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    }
    // èœå•项小三角
    if (m_hMenu != nullptr) {
        HPEN hPenDrop = CreatePen(PS_SOLID, 1, m_crText[state]);
        HBRUSH hbrDrop = CreateSolidBrush(m_crText[state]);
        HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC, hbrDrop);
        HPEN hOldPen = (HPEN)::SelectObject(hDC, hPenDrop);
        POINT pt[3];
        pt[0].x = rcClient.right - 20;
        pt[0].y = rcClient.top + (rcClient.bottom - rcClient.top - 5) / 2;
        pt[1].x = pt[0].x + 10;
        pt[1].y = pt[0].y;
        pt[2].x = pt[0].x + (pt[1].x - pt[0].x) / 2;
        pt[2].y = pt[0].y + 5;
        ::Polygon(hDC, pt, 3);
        ::SelectObject(hDC, hOldBrush);
        ::SelectObject(hDC, hOldPen);
        ::DeleteObject(hBrush);
        ::DeleteObject(hPen);
    }
}
int CBlButton::GetDrawState()
{
    if (!IsWindowEnabled()) {
        return BS_DISABLE;
    }
    //if (GetFocus() == this) {
    //    return BS_FOCUS;
    //}
    return m_nState;
}
void CBlButton::PreSubclassWindow()
{
    m_bHover = false;
    m_bSelected = false;
    m_bTracking = FALSE;
    ModifyStyle(0, BS_OWNERDRAW);
    CButton::PreSubclassWindow();
}
BEGIN_MESSAGE_MAP(CBlButton, CButton)
    ON_WM_MOUSEMOVE()
    ON_WM_MOUSEHOVER()
    ON_WM_MOUSELEAVE()
    ON_WM_LBUTTONDOWN()
    ON_CONTROL_REFLECT_EX(BN_CLICKED, &CBlButton::OnBnClicked)
    ON_WM_LBUTTONUP()
END_MESSAGE_MAP()
void CBlButton::OnMouseMove(UINT nFlags, CPoint point)
{
    if (!m_bTracking)
    {
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(tme);
        tme.dwFlags = TME_HOVER | TME_LEAVE;        // å‘送WM_MOUSEHOVER和WM_MOUSELEAVE
        tme.hwndTrack = m_hWnd;                        // æŒ‡å®šè¦è¿½è¸ªçš„窗口
        tme.dwHoverTime = 10;                        // é¼ æ ‡åœ¨æŒ‰é’®ä¸Šåœç•™è¶…过10ms,才认为状态为HOVER
        m_bTracking = _TrackMouseEvent(&tme);        // å¼€å¯Windows的WM_MOUSELEAVEWM_MOUSEHOVER事件支持
    }
    CButton::OnMouseMove(nFlags, point);
}
void CBlButton::OnMouseHover(UINT nFlags, CPoint point)
{
    m_bHover = true;
    m_nState = BS_HOVER;
    InvalidateRect(NULL);
    return;
    // CButton::OnMouseHover(nFlags, point);
}
void CBlButton::OnMouseLeave()
{
    m_bHover = false;
    m_bTracking = FALSE;    // è‹¥å·²ç»ç¦»å¼€ï¼Œåˆ™åœæ­¢è¿½è¸ª
    m_nState = BS_NORMAL;
    InvalidateRect(NULL);
    CButton::OnMouseLeave();
}
BOOL CBlButton::CustomBitBlt(HDC hDC, LPRECT lprc, CString& strBkgndBmp, int nFrame, int nAllFrame,
    int nB0, int nB1, int nB2, int nB3, COLORREF crTransparent)
{
    // è½½å…¥BMP
    HBITMAP hBmpTemp = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
        strBkgndBmp, IMAGE_BITMAP, 0, 0,
        LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
    if (hBmpTemp == NULL)
        return FALSE;
    HDC hDCTemp = ::CreateCompatibleDC(hDC);
    ::SelectObject(hDCTemp, hBmpTemp);
    BITMAP bitmap;
    ::GetObject(hBmpTemp, sizeof(BITMAP), &bitmap);
    int nFrameWidth = bitmap.bmWidth / nAllFrame;        // æ¯å¸§çš„宽
    int nFrameX = nFrameWidth*nFrame;                // æŒ‡å®šå¸§ç›¸ç´ èµ·ç‚¹
                                                    // å¦‚果角或边厚为0
    if (nB0 == 0 && nB1 == 0 &&
        nB2 == 0 && nB3 == 0) {
        ::TransparentBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top,
            hDCTemp, nFrameX, 0, nFrameWidth, bitmap.bmHeight, crTransparent);
        ::DeleteObject(hBmpTemp);
        ::DeleteDC(hDCTemp);
        return TRUE;
    }
    // å…¶å®ƒ
    int x = lprc->left + nB3;
    int y = lprc->top + nB0;
    ::TransparentBlt(hDC, x, y, lprc->right - lprc->left - (nB1 + nB3), lprc->bottom - lprc->top - (nB0 + nB2),
        hDCTemp, nFrameX + nB3, nB0, nFrameWidth - (nB1 + nB3), bitmap.bmHeight - (nB0 + nB2), crTransparent);
    x = lprc->left;
    y = lprc->top;
    ::TransparentBlt(hDC, x, y, nB3, nB0,
        hDCTemp, nFrameX + 0, 0, nB3, nB0, crTransparent);
    x += nB3;
    y = lprc->top;
    ::TransparentBlt(hDC, x, y, lprc->right - lprc->left - (nB1 + nB3), nB0,
        hDCTemp, nFrameX + nB3, 0, nFrameWidth - (nB1 + nB3), nB0, crTransparent);
    x = lprc->right - nB1;
    y = lprc->top;
    ::TransparentBlt(hDC, x, y, nB1, nB0,
        hDCTemp, nFrameX + nFrameWidth - nB1, 0, nB1, nB0, crTransparent);
    x = lprc->right - nB1;
    y = lprc->top + nB0;
    ::TransparentBlt(hDC, x, y, nB1, lprc->bottom - lprc->top - (nB0 + nB2),
        hDCTemp, nFrameX + nFrameWidth - nB1, nB0, nB1, bitmap.bmHeight - (nB0 + nB2), crTransparent);
    x = lprc->right - nB1;
    y = lprc->bottom - nB2;
    ::TransparentBlt(hDC, x, y, nB1, nB2,
        hDCTemp, nFrameX + nFrameWidth - nB1, bitmap.bmHeight - nB2, nB1, nB2, crTransparent);
    x = lprc->left + nB3;
    y = lprc->bottom - nB2;
    ::TransparentBlt(hDC, x, y, lprc->right - lprc->left - (nB1 + nB3), nB2,
        hDCTemp, nFrameX + nB3, bitmap.bmHeight - nB2, nFrameWidth - (nB1 + nB3), nB2, crTransparent);
    x = lprc->left;
    y = lprc->bottom - nB2;
    ::TransparentBlt(hDC, x, y, nB3, nB2,
        hDCTemp, nFrameX + 0, bitmap.bmHeight - nB2, nB3, nB2, crTransparent);
    x = lprc->left;
    y = lprc->top + nB0;
    ::TransparentBlt(hDC, x, y, nB3, lprc->bottom - lprc->top - (nB0 + nB2),
        hDCTemp, nFrameX + 0, nB0, nB3, bitmap.bmHeight - (nB0 + nB2), crTransparent);
    ::DeleteObject(hBmpTemp);
    ::DeleteDC(hDCTemp);
    return TRUE;
}
void CBlButton::OnLButtonDown(UINT nFlags, CPoint point)
{
    m_nState = BS_PRESS;
    CButton::OnLButtonDown(nFlags, point);
}
void CBlButton::OnLButtonUp(UINT nFlags, CPoint point)
{
    m_nState = BS_HOVER;
    CButton::OnLButtonUp(nFlags, point);
}
BOOL CBlButton::OnBnClicked()
{
    if (m_hMenu != NULL) {
        RECT rect;
        GetWindowRect(&rect);
        int cmd = ::TrackPopupMenu(::GetSubMenu(m_hMenu, 0),
            TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, rect.left, rect.bottom, 0, m_hWnd, NULL);
        if (cmd > 0) {
            int position = cmd - GetMenuItemID(::GetSubMenu(m_hMenu, 0), 0);
            Notify((int)BLBUTTON_MENU_ITEM_CLICKED, position);
        }
    }
    return FALSE;
}
void CBlButton::Notify(int nCode, DWORD_PTR dwData, DWORD_PTR dwData1/* = 0*/, DWORD_PTR dwData2/* = 0*/)
{
    CWnd* pParent;
    pParent = GetParent();
    if (pParent != nullptr) {
        BLBUTTON_NMHDR blbNmhdr;
        blbNmhdr.nmhdr.code = nCode;
        blbNmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
        blbNmhdr.nmhdr.hwndFrom = m_hWnd;
        blbNmhdr.dwData = dwData;
        blbNmhdr.dwData1 = dwData1;
        blbNmhdr.dwData2 = dwData2;
        pParent->SendMessage(WM_NOTIFY, (WPARAM)blbNmhdr.nmhdr.idFrom, (LPARAM)&blbNmhdr);
    }
}
SourceCode/Bond/BondEq/BlButton.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,88 @@
#pragma once
#include "afxwin.h"
#define BS_NORMAL        0
#define BS_HOVER        1
#define BS_PRESS        2
#define BS_FOCUS        3
#define BS_DISABLE        4
#define BLBUTTON_MENU_ITEM_CLICKED        0x1345
typedef struct tagBLBUTTON_NMHDR
{
    NMHDR        nmhdr;
    DWORD_PTR    dwData;
    DWORD_PTR    dwData1;
    DWORD_PTR    dwData2;
} BLBUTTON_NMHDR;
class CBlButton :
    public CButton
{
private:
    typedef struct tagBADGE
    {
        COLORREF badgeBackground;
        COLORREF badgeForeground;
        int type;                       /* 0: æ— ,不显示*/
        int number;
    } BADGE;
public:
    CBlButton();
    ~CBlButton();
public:
    void SetRoundWidth(int width);
    int GetDrawState();
    void SetFrameColor(int index, COLORREF color);
    void SetBkgndColor(int index, COLORREF color);
    void SetTextColor(int index, COLORREF color);
    void SetBkgndBmp(const char* pszBmpFile);
    void SetFaceColor(COLORREF color);
    void SetTextColor(COLORREF color);
    void SetBadgeNumber(int number);
    void ShowDotBadge(BOOL bShow, COLORREF color);
    void SetMenu(HMENU hMenu);
    void SetCurrentMenuItem(UINT nPosition);
    HMENU GetMenu();
    void SetIcon(HICON hIcon, HICON hIconGray, int width);
private:
    BOOL CustomBitBlt(HDC hDC, LPRECT lprc, CString& strBkgndBmp, int nFrame, int nAllFrame,
        int nB0, int nB1, int nB2, int nB3, COLORREF crTransparent);
    void CBlButton::Notify(int nCode, DWORD_PTR dwData, DWORD_PTR dwData1 = 0, DWORD_PTR dwData2 = 0);
private:
    bool m_bHover;            // æ‚¬åœ
    bool m_bSelected;        // æŒ‰ä¸‹
    BOOL m_bTracking;        // è·Ÿè¸ª
    int m_nState;
    int m_nRoundWidth;
private:
    COLORREF m_crFrame[5];    // è¾¹æ¡†é¢œè‰²
    COLORREF m_crBkgnd[5];    // èƒŒæ™¯é¢œè‰²
    COLORREF m_crText[5];    // æ–‡æœ¬é¢œè‰²
    CString m_strBkgndBmp;
private:
    BADGE m_badge;
    HMENU m_hMenu;
    HICON m_hIcon[2];
    int m_nIconWidth;
public:
    virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
    virtual void PreSubclassWindow();
    DECLARE_MESSAGE_MAP()
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnMouseHover(UINT nFlags, CPoint point);
    afx_msg void OnMouseLeave();
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg BOOL OnBnClicked();
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
};
SourceCode/Bond/BondEq/BondEq.vcxproj
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,290 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{7864134E-C538-4C0F-AF24-215FFCCBBAB4}</ProjectGuid>
    <RootNamespace>BondServo</RootNamespace>
    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
    <Keyword>MFCProj</Keyword>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Dynamic</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Dynamic</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>MultiByte</CharacterSet>
    <UseOfMfc>Dynamic</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>MultiByte</CharacterSet>
    <UseOfMfc>Dynamic</UseOfMfc>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="Shared">
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
      <AdditionalIncludeDirectories>.;.\View;.\DBManager;..\DatabaseSDK\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AccordionWnd.h" />
    <ClInclude Include="ApredTreeCtrl.h" />
    <ClInclude Include="BaseSetPage.h" />
    <ClInclude Include="BlButton.h" />
    <ClInclude Include="BondServo.h" />
    <ClInclude Include="BondServoDlg.h" />
    <ClInclude Include="CBaseView.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="DBManager\UserManager.h" />
    <ClInclude Include="HmTab.h" />
    <ClInclude Include="HmVerticalTab.h" />
    <ClInclude Include="HorizontalLine.h" />
    <ClInclude Include="Log.h" />
    <ClInclude Include="LogEdit.h" />
    <ClInclude Include="Model.h" />
    <ClInclude Include="CPageAlarm.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="Servo.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="View\ChangePasswordDlg.h" />
    <ClInclude Include="View\LoginDlg.h" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="AccordionWnd.cpp" />
    <ClCompile Include="ApredTreeCtrl.cpp" />
    <ClCompile Include="BaseSetPage.cpp" />
    <ClCompile Include="BlButton.cpp" />
    <ClCompile Include="BondServo.cpp" />
    <ClCompile Include="BondServoDlg.cpp" />
    <ClCompile Include="CBaseView.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="DBManager\UserManager.cpp" />
    <ClCompile Include="HmTab.cpp" />
    <ClCompile Include="HmVerticalTab.cpp" />
    <ClCompile Include="HorizontalLine.cpp" />
    <ClCompile Include="Log.cpp" />
    <ClCompile Include="LogEdit.cpp" />
    <ClCompile Include="Model.cpp" />
    <ClCompile Include="CPageAlarm.cpp" />
    <ClCompile Include="Servo.cpp" />
    <ClCompile Include="SetPage1.cpp" />
    <ClCompile Include="SetPage2.cpp" />
    <ClCompile Include="SettingsDlg.cpp" />
    <ClCompile Include="stdafx.cpp">
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
    </ClCompile>
    <ClCompile Include="ToolUnits.cpp" />
    <ClCompile Include="TopToolbar.cpp" />
    <ClCompile Include="VerticalLine.cpp" />
    <ClCompile Include="View\ChangePasswordDlg.cpp" />
    <ClCompile Include="View\LoginDlg.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="BondServo.rc" />
  </ItemGroup>
  <ItemGroup>
    <None Include="res\BondServo.rc2" />
  </ItemGroup>
  <ItemGroup>
    <Image Include="res\BondServo.ico" />
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="res\application.exe.manifest" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
  <ProjectExtensions>
    <VisualStudio>
      <UserProperties RESOURCE_FILE="BondServo.rc" />
    </VisualStudio>
  </ProjectExtensions>
</Project>
SourceCode/Bond/BondEq/BondSEq.vcxproj.filters
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,255 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="源文件">
      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
    </Filter>
    <Filter Include="头文件">
      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
    </Filter>
    <Filter Include="资源文件">
      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
    </Filter>
    <Filter Include="DBManager">
      <UniqueIdentifier>{223a97a4-3935-4383-b097-ccae2f176660}</UniqueIdentifier>
    </Filter>
    <Filter Include="View">
      <UniqueIdentifier>{ac8ea0ef-ae05-4436-9d51-4cc145e4c1b0}</UniqueIdentifier>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="BondServo.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="BondServoDlg.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="stdafx.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="targetver.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Resource.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Model.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Log.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="ToolUnits.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Common.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Configuration.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Servo.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="AccordionWnd.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="HorizontalLine.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="VerticalLine.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CPanelProject.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="ApredTreeCtrl.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CProjectPageRemoteEqs.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CMainContainer.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CHomeDialog.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="HmTab.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CPageLogcat.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CBaseView.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="BlButton.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="LogEdit.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="HmVerticalTab.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="SettingsDlg.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="SetPage1.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="SetPage2.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="BaseSetPage.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CRemoteEqView.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CPageAlarm.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="TopToolbar.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CRemoteEqUnitView.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="DBManager\UserManager.h">
      <Filter>DBManager</Filter>
    </ClInclude>
    <ClInclude Include="View\LoginDlg.h">
      <Filter>View</Filter>
    </ClInclude>
    <ClInclude Include="View\ChangePasswordDlg.h">
      <Filter>View</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="BondServo.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="BondServoDlg.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="stdafx.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Model.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Log.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="ToolUnits.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Configuration.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Servo.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="AccordionWnd.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="HorizontalLine.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="VerticalLine.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CPanelProject.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="ApredTreeCtrl.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CProjectPageRemoteEqs.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CMainContainer.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CHomeDialog.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="HmTab.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CPageLogcat.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CBaseView.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="BlButton.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="LogEdit.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="HmVerticalTab.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="SettingsDlg.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="SetPage1.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="SetPage2.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="BaseSetPage.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CRemoteEqView.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CPageAlarm.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="TopToolbar.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CRemoteEqUnitView.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="DBManager\UserManager.cpp">
      <Filter>DBManager</Filter>
    </ClCompile>
    <ClCompile Include="View\LoginDlg.cpp">
      <Filter>View</Filter>
    </ClCompile>
    <ClCompile Include="View\ChangePasswordDlg.cpp">
      <Filter>View</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="BondServo.rc">
      <Filter>资源文件</Filter>
    </ResourceCompile>
  </ItemGroup>
  <ItemGroup>
    <None Include="res\BondServo.rc2">
      <Filter>资源文件</Filter>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Image Include="res\BondServo.ico">
      <Filter>资源文件</Filter>
    </Image>
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="res\application.exe.manifest" />
  </ItemGroup>
</Project>
SourceCode/Bond/BondEq/BondServo.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,148 @@
// BondServo.cpp : å®šä¹‰åº”用程序的类行为。
//
#include "stdafx.h"
#include "BondServo.h"
#include "BondServoDlg.h"
#include "AccordionWnd.h"
#include "VerticalLine.h"
#include "HorizontalLine.h"
#include "HmTab.h"
#include "HmVerticalTab.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CBondServoApp
BEGIN_MESSAGE_MAP(CBondServoApp, CWinApp)
    ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// CBondServoApp æž„造
CBondServoApp::CBondServoApp()
{
    // æ”¯æŒé‡æ–°å¯åŠ¨ç®¡ç†å™¨
    m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
    // TODO: åœ¨æ­¤å¤„添加构造代码,
    // å°†æ‰€æœ‰é‡è¦çš„初始化放置在 InitInstance ä¸­
}
// å”¯ä¸€çš„一个 CBondServoApp å¯¹è±¡
CBondServoApp theApp;
// CBondServoApp åˆå§‹åŒ–
BOOL CBondServoApp::InitInstance()
{
    // å¦‚果一个运行在 Windows XP ä¸Šçš„应用程序清单指定要
    // ä½¿ç”¨ ComCtl32.dll ç‰ˆæœ¬ 6 æˆ–更高版本来启用可视化方式,
    //则需要 InitCommonControlsEx()。  å¦åˆ™ï¼Œå°†æ— æ³•创建窗口。
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    // å°†å®ƒè®¾ç½®ä¸ºåŒ…括所有要在应用程序中使用的
    // å…¬å…±æŽ§ä»¶ç±»ã€‚
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);
    CWinApp::InitInstance();
    AfxEnableControlContainer();
    // åˆ›å»º shell ç®¡ç†å™¨ï¼Œä»¥é˜²å¯¹è¯æ¡†åŒ…含
    // ä»»ä½• shell æ ‘视图控件或 shell åˆ—表视图控件。
    CShellManager *pShellManager = new CShellManager;
    // æ¿€æ´»â€œWindows Native”视觉管理器,以便在 MFC æŽ§ä»¶ä¸­å¯ç”¨ä¸»é¢˜
    CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
    // æ ‡å‡†åˆå§‹åŒ–
    // å¦‚果未使用这些功能并希望减小
    // æœ€ç»ˆå¯æ‰§è¡Œæ–‡ä»¶çš„大小,则应移除下列
    // ä¸éœ€è¦çš„特定初始化例程
    // æ›´æ”¹ç”¨äºŽå­˜å‚¨è®¾ç½®çš„æ³¨å†Œè¡¨é¡¹
    // TODO: åº”适当修改该字符串,
    // ä¾‹å¦‚修改为公司或组织名
    SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
    // æœ¬ç¨‹åºæ–‡ä»¶ç›®å½•
    TCHAR sDrive[_MAX_DRIVE];
    TCHAR sDir[_MAX_DIR];
    TCHAR sFilename[_MAX_FNAME], sAppFilename[_MAX_FNAME];
    TCHAR sExt[_MAX_EXT];
    GetModuleFileName(AfxGetInstanceHandle(), sAppFilename, _MAX_FNAME);
    _tsplitpath_s(sAppFilename, sDrive, sDir, sFilename, sExt);
    m_strAppDir = CString(sDrive) + CString(sDir);
    m_strAppFile = CString(sFilename);
    m_model.setWorkDir((LPTSTR)(LPCTSTR)m_strAppDir);
    m_hAppMutex = CreateMutexA(NULL, FALSE, _T("BondServoApp"));
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        AfxMessageBox(_T("已经运行了一个实例,启动失败!"));
        return FALSE;
    }
    // åˆå§‹åŒ–BEQ库
    BEQ_Initialize();
    RX_Init();
    // è‡ªå®šä¹‰ç»„ä»¶
    CAccordionWnd::RegisterWndClass();
    CVerticalLine::RegisterWndClass();
    CHorizontalLine::RegisterWndClass();
    CHmTab::RegisterWndClass();
    CHmVerticalTab::RegisterWndClass();
    CBondServoDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
        // TODO: åœ¨æ­¤æ”¾ç½®å¤„理何时用
        //  â€œç¡®å®šâ€æ¥å…³é—­å¯¹è¯æ¡†çš„代码
    }
    else if (nResponse == IDCANCEL)
    {
        // TODO: åœ¨æ­¤æ”¾ç½®å¤„理何时用
        //  â€œå–消”来关闭对话框的代码
    }
    else if (nResponse == -1)
    {
        TRACE(traceAppMsg, 0, "警告: å¯¹è¯æ¡†åˆ›å»ºå¤±è´¥ï¼Œåº”用程序将意外终止。\n");
        TRACE(traceAppMsg, 0, "警告: å¦‚果您在对话框上使用 MFC æŽ§ä»¶ï¼Œåˆ™æ— æ³• #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
    }
    // åˆ é™¤ä¸Šé¢åˆ›å»ºçš„ shell ç®¡ç†å™¨ã€‚
    if (pShellManager != NULL)
    {
        delete pShellManager;
    }
    // ç”±äºŽå¯¹è¯æ¡†å·²å…³é—­ï¼Œæ‰€ä»¥å°†è¿”回 FALSE ä»¥ä¾¿é€€å‡ºåº”用程序,
    //  è€Œä¸æ˜¯å¯åŠ¨åº”ç”¨ç¨‹åºçš„æ¶ˆæ¯æ³µã€‚
    return FALSE;
}
int CBondServoApp::ExitInstance()
{
    BEQ_Term();
    RX_Term();
    return CWinApp::ExitInstance();
}
SourceCode/Bond/BondEq/BondServo.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
// BondServo.h : PROJECT_NAME åº”用程序的主头文件
//
#pragma once
#ifndef __AFXWIN_H__
    #error "在包含此文件之前包含“stdafx.h”以生成 PCH æ–‡ä»¶"
#endif
#include "resource.h"        // ä¸»ç¬¦å·
#include "Model.h"
// CBondServoApp:
// æœ‰å…³æ­¤ç±»çš„实现,请参阅 BondServo.cpp
//
class CBondServoApp : public CWinApp
{
public:
    CBondServoApp();
// é‡å†™
public:
    virtual BOOL InitInstance();
public:
    CModel m_model;
    HANDLE m_hAppMutex;
    CString m_strAppDir;
    CString m_strAppFile;
    int m_nVersionNumber;
    CString m_strVersionName;
// å®žçް
    DECLARE_MESSAGE_MAP()
    virtual int ExitInstance();
};
extern CBondServoApp theApp;
SourceCode/Bond/BondEq/BondServo.rc
Binary files differ
SourceCode/Bond/BondEq/BondServoDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,627 @@
// BondServoDlg.cpp : å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "BondServoDlg.h"
#include "afxdialogex.h"
#include "Common.h"
#include "Servo.h"
#include "SettingsDlg.h"
#include "UserManager.h"
#include "LoginDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// ç”¨äºŽåº”用程序“关于”菜单项的 CAboutDlg å¯¹è¯æ¡†
class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_ABOUTBOX };
#endif
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
// å®žçް
protected:
    DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CBondServoDlg å¯¹è¯æ¡†
CBondServoDlg::CBondServoDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_BONDSERVO_DIALOG, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_pObserver = nullptr;
    m_pPanelProject = nullptr;
    m_crBkgnd = APPDLG_BACKGROUND_COLOR;
    m_hbrBkgnd = nullptr;
    m_pTopToolbar = nullptr;
    m_pMainContainer = nullptr;
    m_pHomeDialog = nullptr;
    m_pActiveView = nullptr;
}
void CBondServoDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CBondServoDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_CLOSE()
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_COMMAND(ID_MENU_FILE_EXIT, &CBondServoDlg::OnMenuFileExit)
    ON_UPDATE_COMMAND_UI(ID_MENU_FILE_EXIT, &CBondServoDlg::OnUpdateMenuFileExit)
    ON_COMMAND(ID_MENU_FILE_SETTINGS, &CBondServoDlg::OnMenuFileSettings)
    ON_UPDATE_COMMAND_UI(ID_MENU_FILE_SETTINGS, &CBondServoDlg::OnUpdateMenuFileSettings)
    ON_COMMAND(ID_MENU_HELP_ABOUT, &CBondServoDlg::OnMenuHelpAbout)
    ON_WM_INITMENUPOPUP()
    ON_MESSAGE(ID_MSG_VIEW_ACTIVE, &CBondServoDlg::OnViewActive)
    ON_MESSAGE(ID_MSG_BTN_CLICKED, &CBondServoDlg::OnViewBtnClicked)
    ON_MESSAGE(ID_MSG_BTN_MENU_ITEM, &CBondServoDlg::OnViewBtnMenuItem)
    ON_MESSAGE(ID_MSG_TOOLBAR_BTN_CLICKED, &CBondServoDlg::OnToolbarBtnClicked)
    ON_WM_TIMER()
END_MESSAGE_MAP()
// CBondServoDlg æ¶ˆæ¯å¤„理程序
void CBondServoDlg::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 (RX_CODE_SELECT_EQ == code) {
                BEQ::IRemoteEquipment* pEquipment;
                if (pAny->getPtrValue("ptr", (void*&)pEquipment)) {
                    if (m_pMainContainer != nullptr) {
                        if (m_pActiveView != nullptr) {
                            if (m_pActiveView->GetContext() != (void*)pEquipment) {
                                m_pActiveView->DestroyWindow();
                                delete m_pActiveView;
                                m_pActiveView = nullptr;
                            }
                        }
                        if (m_pActiveView == nullptr) {
                            m_pActiveView = CreateRemoteEqView(pEquipment);
                        }
                    }
                }
            }
            pAny->release();
        }, [&]() -> void {
            // onComplete
        }, [&](IThrowable* pThrowable) -> void {
            // onErrorm
            pThrowable->printf();
        });
        theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
            ->subscribe(m_pObserver);
    }
}
BOOL CBondServoDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // å°†â€œå…³äºŽ...”菜单项添加到系统菜单中。
    // IDM_ABOUTBOX å¿…须在系统命令范围内。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);
    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }
    // è®¾ç½®æ­¤å¯¹è¯æ¡†çš„图标。  å½“应用程序主窗口不是对话框时,框架将自动
    //  æ‰§è¡Œæ­¤æ“ä½œ
    SetIcon(m_hIcon, TRUE);            // è®¾ç½®å¤§å›¾æ ‡
    SetIcon(m_hIcon, FALSE);        // è®¾ç½®å°å›¾æ ‡
    // åˆå§‹åŒ–用户管理
    UserManager& userManager = UserManager::getInstance();
#if !defined(_DEBUG)
    userManager.initializeIdleDetection(AfxGetMainWnd()->m_hWnd);
    SetTimer(1, 60000, nullptr);
#endif
    userManager.loadSession();
    // èœå•
    CMenu menu;
    menu.LoadMenu(IDR_MENU_APP);
    SetMenu(&menu);
    // model init
    theApp.m_model.init();
    // toolbar
    m_pTopToolbar = new CTopToolbar();
    m_pTopToolbar->Create(IDD_TOP_TOOLBAR, this);
    m_pTopToolbar->ShowWindow(SW_SHOW);
    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
    // è®¾å¤‡é¢æ¿
    m_pPanelProject = new CPanelProject();
    m_pPanelProject->Create(IDD_PANEL_PROJECT, this);
    m_pPanelProject->ShowWindow(SW_SHOW);
    // ä¸»çª—口页
    m_pMainContainer = new CMainContainer();
    m_pMainContainer->Create(IDD_MAIN_CONTAINER, this);
    m_pMainContainer->ShowWindow(SW_SHOW);
    // HomeÒ³
    m_pHomeDialog = CreateHomeDlg();
    ShowWindow(SW_SHOWMAXIMIZED);
    SetTimer(2, 1000, nullptr);
    InitRxWindows();
    // ç™»å½•管理
    if (userManager.isLoggedIn()) {
        m_pTopToolbar->SetOperatorBtnText(userManager.getCurrentUser().c_str());
    }
    return TRUE;  // é™¤éžå°†ç„¦ç‚¹è®¾ç½®åˆ°æŽ§ä»¶ï¼Œå¦åˆ™è¿”回 TRUE
}
void CBondServoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}
// å¦‚果向对话框添加最小化按钮,则需要下面的代码
//  æ¥ç»˜åˆ¶è¯¥å›¾æ ‡ã€‚  å¯¹äºŽä½¿ç”¨æ–‡æ¡£/视图模型的 MFC åº”用程序,
//  è¿™å°†ç”±æ¡†æž¶è‡ªåŠ¨å®Œæˆã€‚
void CBondServoDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // ç”¨äºŽç»˜åˆ¶çš„设备上下文
        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
        // ä½¿å›¾æ ‡åœ¨å·¥ä½œåŒºçŸ©å½¢ä¸­å±…中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;
        // ç»˜åˆ¶å›¾æ ‡
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CBondServoDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}
void CBondServoDlg::OnClose()
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    CServo& servo = theApp.m_model.getServo();
    if (servo.isRunning()) {
        AfxMessageBox("程序和机器正在运行中,请先停止工作再退出程序!");
        return;
    }
    CDialogEx::OnClose();
}
HBRUSH CBondServoDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    // TODO:  åœ¨æ­¤æ›´æ”¹ DC çš„任何特性
    // TODO:  å¦‚果默认的不是所需画笔,则返回另一个画笔
    return hbr;
}
void CBondServoDlg::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_pTopToolbar != nullptr) {
        m_pTopToolbar->DestroyWindow();
        delete m_pTopToolbar;
        m_pTopToolbar = nullptr;
    }
    if (m_pPanelProject != nullptr) {
        m_pPanelProject->DestroyWindow();
        delete m_pPanelProject;
        m_pPanelProject = nullptr;
    }
    if (m_pMainContainer != nullptr) {
        m_pMainContainer->DestroyWindow();
        delete m_pMainContainer;
        m_pMainContainer = nullptr;
    }
    if (m_pHomeDialog != nullptr) {
        m_pHomeDialog->DestroyWindow();
        delete m_pHomeDialog;
        m_pHomeDialog = nullptr;
    }
    if (m_pActiveView != nullptr) {
        m_pActiveView->DestroyWindow();
        delete m_pActiveView;
        m_pActiveView = nullptr;
    }
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
    ASSERT(m_pObserver != NULL);
    m_pObserver->unsubscribe();
    m_pObserver = NULL;
#if !defined(_DEBUG)
    // æ¸…除 UserManager çš„æ— æ“ä½œæ£€æµ‹
    UserManager::getInstance().terminateIdleDetection();
    KillTimer(1);
#endif
}
void CBondServoDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (m_pPanelProject == nullptr) return;
    Resize();
}
#define TOOLBAR_HEIGHT        78
void CBondServoDlg::Resize()
{
    CRect rcClient, rcItem;
    GetClientRect(&rcClient);
    int y = 0;
    m_pTopToolbar->MoveWindow(0, 0, rcClient.Width(), TOOLBAR_HEIGHT);
    y += TOOLBAR_HEIGHT;
    ASSERT(m_pPanelProject);
    int nPanelEquipmentWidth = m_pPanelProject->GetPanelWidth();
    m_pPanelProject->MoveWindow(0, y, nPanelEquipmentWidth, rcClient.bottom - y);
    int x = nPanelEquipmentWidth;
    m_pMainContainer->MoveWindow(x + 1, y, rcClient.Width() - x - 0, rcClient.bottom - y - 2);
}
void CBondServoDlg::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
    ASSERT(pPopupMenu != NULL);
    CCmdUI state;
    state.m_pMenu = pPopupMenu;
    ASSERT(state.m_pOther == NULL);
    ASSERT(state.m_pParentMenu == NULL);
    HMENU hParentMenu;
    if (AfxGetThreadState()->m_hTrackingMenu == pPopupMenu->m_hMenu)
        state.m_pParentMenu = pPopupMenu;
    else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)
    {
        CWnd* pParent = this;
        if (pParent != NULL &&
            (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)
        {
            int nIndexMax = ::GetMenuItemCount(hParentMenu);
            for (int nIndex = 0; nIndex < nIndexMax; nIndex++)
            {
                if (::GetSubMenu(hParentMenu, nIndex) == pPopupMenu->m_hMenu)
                {
                    state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
                    break;
                }
            }
        }
    }
    state.m_nIndexMax = pPopupMenu->GetMenuItemCount();
    for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
    state.m_nIndex++)
    {
        state.m_nID = pPopupMenu->GetMenuItemID(state.m_nIndex);
        if (state.m_nID == 0)
            continue;
        ASSERT(state.m_pOther == NULL);
        ASSERT(state.m_pMenu != NULL);
        if (state.m_nID == (UINT)-1)
        {
            state.m_pSubMenu = pPopupMenu->GetSubMenu(state.m_nIndex);
            if (state.m_pSubMenu == NULL ||
                (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
                state.m_nID == (UINT)-1)
            {
                continue;
            }
            state.DoUpdate(this, TRUE);
        }
        else
        {
            state.m_pSubMenu = NULL;
            state.DoUpdate(this, FALSE);
        }
        UINT nCount = pPopupMenu->GetMenuItemCount();
        if (nCount < state.m_nIndexMax)
        {
            state.m_nIndex -= (state.m_nIndexMax - nCount);
            while (state.m_nIndex < nCount &&
                pPopupMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)
            {
                state.m_nIndex++;
            }
        }
        state.m_nIndexMax = nCount;
    }
}
void CBondServoDlg::OnMenuFileSettings()
{
    CSettingsDlg dlg;
    dlg.DoModal();
}
void CBondServoDlg::OnUpdateMenuFileSettings(CCmdUI* pCmdUI)
{
    pCmdUI->Enable(!theApp.m_model.getServo().isRunning());
}
void CBondServoDlg::OnMenuFileExit()
{
    PostMessage(WM_CLOSE);
}
void CBondServoDlg::OnUpdateMenuFileExit(CCmdUI* pCmdUI)
{
    pCmdUI->Enable(!theApp.m_model.getServo().isRunning());
}
void CBondServoDlg::OnMenuHelpAbout()
{
    CAboutDlg dlgAbout;
    dlgAbout.DoModal();
}
BOOL CBondServoDlg::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) {
        return TRUE;
    }
    return CDialogEx::PreTranslateMessage(pMsg);
}
LRESULT CBondServoDlg::OnViewActive(WPARAM wParam, LPARAM lParam)
{
    CBaseView* pView = (CBaseView*)wParam;
    int code = (int)lParam;
    if (code == MA_ACTIVATE || code == MA_ACTIVATEANDEAT) {
    }
    return 0;
}
LRESULT CBondServoDlg::OnViewBtnClicked(WPARAM wParam, LPARAM lParam)
{
    int id = (int)lParam;
    if (id == VIEW_TOOL_BTN_CLOSE) {
        CloseView((CBaseView*)wParam);
    }
    return 0;
}
LRESULT CBondServoDlg::OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam)
{
    int id = (int)lParam;
    if (id == IDC_BUTTON_RUN) {
        m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
        m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(TRUE);
    }
    else if (id == IDC_BUTTON_STOP) {
        m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
        m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
    }
    else if (id == IDC_BUTTON_SETTINGS) {
        CSettingsDlg dlg;
        dlg.DoModal();
    }
    else if (id == IDC_BUTTON_OPERATOR) {
        int menuId = (int)wParam;
        UserManager& userManager = UserManager::getInstance();
        if (menuId == 0) {
            ShowLoginDlg();
        }
        else if (1 == menuId) {
            if (userManager.isLoggedIn()) {
                userManager.logout();
            }
            ShowLoginDlg();
        }
        else if (2 == menuId) {
            if (userManager.isLoggedIn()) {
                userManager.logout();
                m_pTopToolbar->SetOperatorBtnText(_T("未登录"));
            }
        }
    }
    return 0;
}
LRESULT CBondServoDlg::OnViewBtnMenuItem(WPARAM wParam, LPARAM lParam)
{
    UINT id = (UINT)lParam;
    return 0;
}
void CBondServoDlg::CloseView(CBaseView* pView)
{
    pView->DestroyWindow();
    delete (CBaseView*)pView;
    m_pActiveView = nullptr;
    m_pMainContainer->Resize();
}
CHomeDialog* CBondServoDlg::CreateHomeDlg()
{
    CHomeDialog* pDlg = new CHomeDialog(m_pMainContainer);
    pDlg->Create(IDD_DIALOG_HOME, m_pMainContainer);
    ::SetProp(pDlg->GetSafeHwnd(), _T("Home"), (HANDLE)(void*)1);
    m_pMainContainer->Resize();
    return pDlg;
}
void CBondServoDlg::OnTimer(UINT_PTR nIDEvent)
{
    if (1 == nIDEvent) {
        UserManager& userManager = UserManager::getInstance();
        if (userManager.isLoggedIn()) {
            if (userManager.isInactiveTimeout()) {
                AfxMessageBox(_T("You have been logged out automatically due to a long period of no action."));
                userManager.logout();
            }
        }
    }
    else if (2 == nIDEvent) {
        KillTimer(2);
        theApp.m_model.createRemoteEqs();
    }
    CDialogEx::OnTimer(nIDEvent);
}
CBaseView* CBondServoDlg::CreateRemoteEqView(BEQ::IRemoteEquipment* pEquipment)
{
    CBaseView* pDlg = new CRemoteEqView(m_pMainContainer);
    pDlg->Create(IDD_COMPONENT_REMOTE_EQ, m_pMainContainer);
    pDlg->SetContext(pEquipment);
    CString strIcon0, strIcon1, strIcon2, strIcon3;
    strIcon0.Format(_T("%s\\Res\\small_close0.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    strIcon1.Format(_T("%s\\Res\\small_close1.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    strIcon2.Format(_T("%s\\Res\\small_close2.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    strIcon3.Format(_T("%s\\Res\\small_close3.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    pDlg->AddToolBtn(VIEW_TOOL_BTN_CLOSE,
        (LPTSTR)(LPCTSTR)strIcon0,
        (LPTSTR)(LPCTSTR)strIcon1,
        (LPTSTR)(LPCTSTR)strIcon2,
        (LPTSTR)(LPCTSTR)strIcon3, "关闭");
    pDlg->ShowWindow(SW_SHOW);
    char szName[256];
    pEquipment->getName(szName, 256);
    pDlg->SetWindowText(szName);
    m_pMainContainer->Resize();
    return pDlg;
}
void CBondServoDlg::ShowLoginDlg()
{
    CLoginDlg loginDlg;
    loginDlg.DoModal();
    UserManager& userManager = UserManager::getInstance();
    if (userManager.isLoggedIn())
    {
        m_pTopToolbar->SetOperatorBtnText(userManager.getCurrentUser().c_str());
    }
    else {
        m_pTopToolbar->SetOperatorBtnText(_T("未登录"));
    }
}
SourceCode/Bond/BondEq/BondServoDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
// BondServoDlg.h : å¤´æ–‡ä»¶
//
#pragma once
#include "CPanelProject.h"
#include "CMainContainer.h"
#include "CHomeDialog.h"
#include "CBaseView.h"
#include "CRemoteEqView.h"
#include "TopToolbar.h"
// CBondServoDlg å¯¹è¯æ¡†
class CBondServoDlg : public CDialogEx
{
// æž„造
public:
    CBondServoDlg(CWnd* pParent = NULL);    // æ ‡å‡†æž„造函数
private:
    void InitRxWindows();
    void Resize();
    void CloseView(CBaseView* pView);
    CHomeDialog* CreateHomeDlg();
    CBaseView* CreateRemoteEqView(BEQ::IRemoteEquipment* pEquipment);
    void ShowLoginDlg();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    IObserver* m_pObserver;
    CTopToolbar* m_pTopToolbar;
    CMainContainer* m_pMainContainer;
    CPanelProject* m_pPanelProject;
    CHomeDialog* m_pHomeDialog;
    CBaseView* m_pActiveView;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_BONDSERVO_DIALOG };
#endif
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
// å®žçް
protected:
    HICON m_hIcon;
    // ç”Ÿæˆçš„æ¶ˆæ¯æ˜ å°„函数
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnClose();
    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 OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu);
    afx_msg void OnMenuFileSettings();
    afx_msg void OnUpdateMenuFileSettings(CCmdUI* pCmdUI);
    afx_msg void OnMenuFileExit();
    afx_msg void OnUpdateMenuFileExit(CCmdUI* pCmdUI);
    afx_msg void OnMenuHelpAbout();
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    LRESULT OnViewActive(WPARAM wParam, LPARAM lParam);
    LRESULT OnViewBtnClicked(WPARAM wParam, LPARAM lParam);
    LRESULT OnViewBtnMenuItem(WPARAM wParam, LPARAM lParam);
    LRESULT OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
};
SourceCode/Bond/BondEq/CBaseView.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,415 @@
#include "stdafx.h"
#include "CBaseView.h"
#include "Common.h"
#define CAPTION_HEIGHT        36
#define CAPBTN                99
IMPLEMENT_DYNAMIC(CBaseView, CDialogEx)
CBaseView::CBaseView(UINT id, CWnd* pPage) : CDialogEx(id, pPage)
{
    m_crBkgnd = BASE_VIEW_BACKGROUND;
    m_hbrBkgnd = nullptr;
    m_pContext = nullptr;
    m_nState = 0;
    m_pHotBtn = nullptr;
    m_pPressBtn = nullptr;
}
CBaseView::~CBaseView()
{
}
BEGIN_MESSAGE_MAP(CBaseView, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_ACTIVATE()
    ON_WM_NCPAINT()
    ON_WM_MOUSEACTIVATE()
    ON_WM_SIZE()
    ON_WM_NCCALCSIZE()
    ON_WM_LBUTTONDOWN()
    ON_WM_NCHITTEST()
    ON_WM_NCMOUSEMOVE()
    ON_WM_NCLBUTTONDOWN()
    ON_WM_NCLBUTTONUP()
END_MESSAGE_MAP()
HBRUSH CBaseView::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 CBaseView::OnDestroy()
{
    CDialogEx::OnDestroy();
}
void CBaseView::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
    CDialogEx::OnActivate(nState, pWndOther, bMinimized);
    if (WA_INACTIVE == nState) {
        OnApply();
    }
}
void CBaseView::OnNcPaint()
{
    // TODO: åœ¨æ­¤å¤„添加消息处理程序代码
    // ä¸ä¸ºç»˜å›¾æ¶ˆæ¯è°ƒç”¨ CDialogEx::OnNcPaint()
    RECT rect, rcClient;
    ::GetClientRect(m_hWnd, &rcClient);
    ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.left);
    ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.right);
    ::GetWindowRect(m_hWnd, &rect);
    ::OffsetRect(&rcClient, -rect.left, -rect.top);
    rect.right -= rect.left;
    rect.bottom -= rect.top;
    rect.left = 0;
    rect.top = 0;
    HRGN hRgnWnd = CreateRectRgnIndirect(&rect);
    HRGN hRgnClient = CreateRectRgnIndirect(&rcClient);
    HBRUSH hBrushBK, hBrushFrame;
    HDC hDC = ::GetWindowDC(m_hWnd);
    ::SelectClipRgn(hDC, hRgnWnd);
    ::ExtSelectClipRgn(hDC, hRgnClient, RGN_DIFF);
    // èƒŒæ™¯
    hBrushBK = CreateSolidBrush(m_crBkgnd);
    ::FillRect(hDC, &rect, hBrushBK);
    DeleteObject(hBrushBK);
    // æ ‡é¢˜æ ï¼Œæ–‡å­—,横线
    HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    ::SelectObject(hDC, hFont);
    RECT rcCaption, rcText;
    rcCaption = rect;
    rcCaption.bottom = rcCaption.top + CAPTION_HEIGHT;
    rcText = rcCaption;
    rcText.left += 12;
    char szCaption[64];
    int nCaptionLen = GetWindowText(szCaption, 64);
    ::DrawText(hDC, szCaption, nCaptionLen, &rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    HPEN hPen = CreatePen(PS_SOLID, 1, RGB(222, 222, 222));
    HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
    ::MoveToEx(hDC, 0, rcCaption.bottom, NULL);
    ::LineTo(hDC, rect.right, rcCaption.bottom);
    ::SelectObject(hDC, hOldPen);
    ::DeleteObject(hPen);
    // ç»˜åˆ¶æŒ‰é’®
    int y = (rcCaption.bottom - rcCaption.top - 24) / 2;
    int x = rcCaption.right - 12;
    for (auto& item : m_toolbtns) {
        if (item.hIcon != nullptr) {
            if (!item.bEnable) {
                DrawIconEx(hDC, x - 24, y,
                    item.hIcon[3], 24, 24, 0, 0, DI_NORMAL);
            }
            else if (m_pPressBtn == &item) {
                DrawIconEx(hDC, x - 24, y,
                    item.hIcon[2], 24, 24, 0, 0, DI_NORMAL);
            }
            else if (m_pHotBtn == &item) {
                DrawIconEx(hDC, x - 24, y,
                    item.hIcon[1], 24, 24, 0, 0, DI_NORMAL);
            }
            else {
                DrawIconEx(hDC, x - 24, y,
                    item.hIcon[0], 24, 24, 0, 0, DI_NORMAL);
            }
            x -= 24;
            x -= 3;
        }
    }
    hBrushFrame = CreateSolidBrush(RGB(255, 0, 0));
    // ::FrameRect(hDC, &rect, hBrushFrame);
    ::DeleteObject(hRgnWnd);
    ::DeleteObject(hRgnClient);
    DeleteObject(hBrushFrame);
    ::ReleaseDC(m_hWnd, hDC);
}
int CBaseView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    int nRet = CDialogEx::OnMouseActivate(pDesktopWnd, nHitTest, message);
    GetParent()->GetParent()->SendMessage(ID_MSG_VIEW_ACTIVE, (WPARAM)this, nRet);
    return nRet;
}
void CBaseView::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
    lpncsp->rgrc[0].top += (CAPTION_HEIGHT);
    CDialogEx::OnNcCalcSize(bCalcValidRects, lpncsp);
}
void CBaseView::SetContext(void* pContext)
{
    m_pContext = pContext;
}
void* CBaseView::GetContext()
{
    return m_pContext;
}
void CBaseView::OnApply()
{
}
void CBaseView::Show(CWnd* pParent, LPRECT lprcBtn)
{
    RECT rcClient, rcBox;
    pParent->GetClientRect(&rcClient);
    pParent->ClientToScreen(&rcClient);
    GetWindowRect(&rcBox);
    int x = lprcBtn->left;
    if (x + (rcBox.right - rcBox.left) > rcClient.right) {
        x = rcClient.right - (rcBox.right - rcBox.left);
    }
    SetWindowPos(NULL, x, lprcBtn->bottom + 2, 0, 0, SWP_NOSIZE);
    ShowWindow(SW_SHOW);
}
void CBaseView::OnViewActive()
{
    m_nState = 1;
    SendMessage(WM_NCPAINT, 0, 0);
}
void CBaseView::OnViewInactive()
{
    m_nState = 0;
    SendMessage(WM_NCPAINT, 0, 0);
}
void CBaseView::AddToolBtn(int id, const char* pszIcon0Path, const char* pszIcon1Path, const char* pszIcon2Path, const char* pszIcon3Path, const char* pszTooltip)
{
    TOOLBTN tb;
    memset(&tb, 0, sizeof(TOOLBTN));
    tb.id = id;
    tb.hIcon[0] = (HICON)::LoadImage(GetModuleHandle(NULL), pszIcon0Path, IMAGE_ICON, 24, 24,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    tb.hIcon[1] = (HICON)::LoadImage(GetModuleHandle(NULL), pszIcon1Path, IMAGE_ICON, 24, 24,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    tb.hIcon[2] = (HICON)::LoadImage(GetModuleHandle(NULL), pszIcon2Path, IMAGE_ICON, 24, 24,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    tb.hIcon[3] = (HICON)::LoadImage(GetModuleHandle(NULL), pszIcon3Path, IMAGE_ICON, 24, 24,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    strcpy_s(tb.szTooltip, 256, pszTooltip);
    tb.bEnable = TRUE;
    m_toolbtns.push_back(tb);
    EnableToolTips(TRUE);
}
void CBaseView::SetToolBtnEnable(int id, BOOL bEnable)
{
    CBaseView::TOOLBTN* pBtn = GetToolBtn(id);
    if (pBtn != nullptr) {
        pBtn->bEnable = bEnable;
        SendMessage(WM_NCPAINT);
    }
}
void CBaseView::SetToolBtnMenu(int id, HMENU hMenu)
{
    CBaseView::TOOLBTN* pBtn = GetToolBtn(id);
    if (pBtn != nullptr) {
        pBtn->hMenu = hMenu;
    }
}
void CBaseView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    CDialogEx::OnLButtonDown(nFlags, point);
}
LRESULT CBaseView::OnNcHitTest(CPoint point)
{
    TOOLBTN* pBtn;
    LRESULT hit = MyHitTest(point, pBtn);
    if (hit == HTCAPTION || hit == CAPBTN) {
        return hit;
    }
    return CDialogEx::OnNcHitTest(point);
}
void CBaseView::OnNcMouseMove(UINT nHitTest, CPoint point)
{
    TOOLBTN* pLastHot = m_pHotBtn;
    int code = MyHitTest(point, m_pHotBtn);
    if (pLastHot != m_pHotBtn) {
        SendMessage(WM_NCPAINT, 0, 0);
    }
    CDialogEx::OnNcMouseMove(nHitTest, point);
}
void CBaseView::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
    int code = MyHitTest(point, m_pPressBtn);
    SendMessage(WM_NCPAINT, 0, 0);
    GetParent()->GetParent()->SendMessage(ID_MSG_VIEW_ACTIVE, (WPARAM)this, MA_ACTIVATE);
    CDialogEx::OnNcLButtonDown(nHitTest, point);
}
void CBaseView::OnNcLButtonUp(UINT nHitTest, CPoint point)
{
    MyHitTest(point, m_pHotBtn);
    if (m_pPressBtn == m_pHotBtn && m_pPressBtn != nullptr && m_pPressBtn->bEnable) {
        if (m_pPressBtn->hMenu != nullptr) {
            int cmd = ::TrackPopupMenu(::GetSubMenu(m_pPressBtn->hMenu, 0),
                TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
                point.x, point.y + 2, 0, m_hWnd, NULL);
            GetParent()->GetParent()->PostMessage(ID_MSG_BTN_MENU_ITEM, (WPARAM)this, cmd);
        }
        else {
            GetParent()->GetParent()->PostMessage(ID_MSG_BTN_CLICKED, (WPARAM)this, m_pPressBtn->id);
        }
    }
    m_pPressBtn = nullptr;
    SendMessage(WM_NCPAINT, 0, 0);
    CDialogEx::OnNcLButtonUp(nHitTest, point);
}
int CBaseView::MyHitTest(POINT& point, TOOLBTN*& pBtn)
{
    RECT rcWnd, rcCaption;
    GetWindowRect(&rcWnd);
    LRESULT hit = HTNOWHERE;
    pBtn = nullptr;
    rcCaption.left = rcWnd.left + 2;
    rcCaption.right = rcWnd.right - 2;
    rcCaption.top = rcWnd.top += 2;
    rcCaption.bottom = rcCaption.top + 2 + CAPTION_HEIGHT;
    if (::PtInRect(&rcCaption, point)) {
        hit = HTCAPTION;
        RECT rcIcon;
        rcIcon.top = rcCaption.top + (rcCaption.bottom - rcCaption.top - 24) / 2;
        rcIcon.bottom = rcIcon.top + 24;
        rcIcon.right = rcCaption.right - 12;
        for (auto& item : m_toolbtns) {
            rcIcon.left = rcIcon.right - 24;
            if (::PtInRect(&rcIcon, point)) {
                pBtn = &item;
                hit = CAPBTN;
                break;
            }
            rcIcon.right = rcIcon.left - 3;
        }
    }
    return (int)hit;
}
CBaseView::TOOLBTN* CBaseView::GetToolBtn(int id)
{
    for (auto& item : m_toolbtns) {
        if (item.id == id) return &item;
    }
    return nullptr;
}
BOOL CBaseView::GetBtnRect(int id, LPRECT lprcBtn)
{
    RECT rcWnd, rcCaption;
    GetWindowRect(&rcWnd);
    ::OffsetRect(&rcWnd, -rcWnd.left, -rcWnd.top);
    rcCaption.left = rcWnd.left + 2;
    rcCaption.right = rcWnd.right - 2;
    rcCaption.top = rcWnd.top += 2;
    rcCaption.bottom = rcCaption.top + 2 + CAPTION_HEIGHT;
    lprcBtn->top = rcCaption.top + (rcCaption.bottom - rcCaption.top - 24) / 2;
    lprcBtn->bottom = lprcBtn->top + 24;
    lprcBtn->right = rcCaption.right - 12;
    for (auto& item : m_toolbtns) {
        lprcBtn->left = lprcBtn->right - 24;
        if (item.id == id) {
            return TRUE;
        }
        lprcBtn->right = lprcBtn->left - 3;
    }
    return FALSE;
}
INT_PTR CBaseView::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
    RECT rcClient, rcCaption, rcBtn;
    ::GetClientRect(m_hWnd, &rcClient);
    rcCaption.bottom = 0;
    rcCaption.top = rcCaption.bottom - CAPTION_HEIGHT;
    rcCaption.left = rcClient.left;
    rcCaption.right = rcClient.right;
    rcBtn.top = rcCaption.top + (rcCaption.bottom - rcCaption.top - 24) / 2;
    rcBtn.bottom = rcBtn.top + 24;
    rcBtn.right = rcCaption.right - 12;
    ::OffsetRect(&rcBtn, +5, -5);        // 5为边框粗的修正
    if ((point.y <= 0)) {
        for (auto& item : m_toolbtns) {
            rcBtn.left = rcBtn.right - 24;
            if (::PtInRect(&rcBtn, point)) {
                pTI->rect = rcBtn;
                pTI->hwnd = m_hWnd;
                pTI->uId = (UINT)1020; // Tooltip should show `1020
                pTI->lpszText = _tcsdup(item.szTooltip);
                return pTI->uId;
            }
            rcBtn.right = rcBtn.left - 3;
        }
    }
    return CDialogEx::OnToolHitTest(point, pTI);
}
SourceCode/Bond/BondEq/CBaseView.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
#pragma once
#define ID_MSG_VIEW_ACTIVE        WM_USER+2356
#define ID_MSG_BTN_CLICKED        WM_USER+2357
#define ID_MSG_BTN_MENU_ITEM    WM_USER+2358
class CBaseView : public CDialogEx
{
private:
    typedef struct _TOOLBTN
    {
        int id;
        HICON hIcon[4];
        char szTooltip[256];
        BOOL bEnable;
        HMENU hMenu;
    } TOOLBTN;
    DECLARE_DYNAMIC(CBaseView)
public:
    CBaseView(UINT id, CWnd* pPage);   // æ ‡å‡†æž„造函数
    virtual ~CBaseView();
public:
    void OnViewActive();
    void OnViewInactive();
    void AddToolBtn(int id, const char* pszIcon0Path, const char* pszIcon1Path, const char* pszIcon2Path, const char* pszIcon3Path, const char* pszTooltip);
    void SetToolBtnEnable(int id, BOOL bEnable);
    void SetToolBtnMenu(int id, HMENU hMenu);
    void Show(CWnd* pParent, LPRECT lprcBtn);
    void SetContext(void* pContext);
    void* GetContext();
    virtual void OnApply();
private:
    int MyHitTest(POINT& point, TOOLBTN*& pBtn);
    CBaseView::TOOLBTN* GetToolBtn(int id);
    BOOL GetBtnRect(int id, LPRECT lprcBtn);
private:
    std::vector<TOOLBTN> m_toolbtns;
    TOOLBTN* m_pHotBtn;
    TOOLBTN* m_pPressBtn;
    int m_nState;
protected:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    void* m_pContext;
    DECLARE_MESSAGE_MAP()
public:
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnDestroy();
    afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
    afx_msg void OnNcPaint();
    afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
    afx_msg void OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg LRESULT OnNcHitTest(CPoint point);
    afx_msg void OnNcMouseMove(UINT nHitTest, CPoint point);
    afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point);
    afx_msg void OnNcLButtonUp(UINT nHitTest, CPoint point);
    virtual INT_PTR OnToolHitTest(CPoint point, TOOLINFO* pTI) const;
};
SourceCode/Bond/BondEq/CHomeDialog.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,155 @@
// CHomeDialog.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "Common.h"
#include "CHomeDialog.h"
#include "afxdialogex.h"
// CHomeDialog å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CHomeDialog, CDialogEx)
CHomeDialog::CHomeDialog(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_HOME, pParent)
{
    m_pTab = nullptr;
    m_pPageLogcat = nullptr;
    m_pPageAlarm = nullptr;
    m_crBkgnd = HOMEPAGE_BACKGROUND;
    m_hbrBkgnd = nullptr;
}
CHomeDialog::~CHomeDialog()
{
}
void CHomeDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CHomeDialog, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_NOTIFY(BYHMTAB_SEL_CHANGED, IDC_HMTAB1, &CHomeDialog::OnTabSelChanged)
END_MESSAGE_MAP()
// CHomeDialog æ¶ˆæ¯å¤„理程序
BOOL CHomeDialog::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // å­é¡µé¢
    m_pPageAlarm = new CPageAlarm();
    m_pPageAlarm->Create(IDD_PAGE_ALARM, this);
    m_pPageLogcat = new CPageLogcat();
    m_pPageLogcat->Create(IDD_PAGE_LOGCAT, this);
    // Tab
    m_pTab = CHmTab::Hook(GetDlgItem(IDC_HMTAB1)->m_hWnd);
    m_pTab->SetPaddingLeft(20);
    m_pTab->SetItemMarginLeft(18);
    m_pTab->SetBkgndColor(RGB(255, 255, 255));
    m_pTab->AddItem("警告", FALSE);
    m_pTab->AddItem("日志", TRUE);
    m_pTab->SetCurSel(0);
    ShowChildPage(0);
    ShowWindow(SW_MAXIMIZE);
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CHomeDialog::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 CHomeDialog::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_pPageAlarm != nullptr) {
        m_pPageAlarm->DestroyWindow();
        delete m_pPageAlarm;
        m_pPageAlarm = nullptr;
    }
    if (m_pPageLogcat != nullptr) {
        m_pPageLogcat->DestroyWindow();
        delete m_pPageLogcat;
        m_pPageLogcat = nullptr;
    }
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
}
void CHomeDialog::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (GetDlgItem(IDC_HMTAB1) == nullptr) return;
    Resize();
}
void CHomeDialog::ShowChildPage(int index)
{
    ASSERT(0 <= index && index < 2);
    static CWnd* pPages[] = { m_pPageAlarm, m_pPageLogcat };
    for (int i = 0; i < 2; i++) {
        pPages[i]->ShowWindow(i == index ? SW_SHOW : SW_HIDE);
    }
}
void CHomeDialog::OnTabSelChanged(NMHDR* nmhdr, LRESULT* result)
{
    BYHMTAB_NMHDR* pNmhdrex = (BYHMTAB_NMHDR*)nmhdr;
    ShowChildPage((int)pNmhdrex->dwData);
    *result = 0;
}
void CHomeDialog::Resize()
{
    CRect rcClient, rcItem;
    GetClientRect(&rcClient);
    int x = 8;
    int y = 12;
    GetDlgItem(IDC_HMTAB1)->GetWindowRect(&rcItem);
    GetDlgItem(IDC_HMTAB1)->MoveWindow(x, y, rcClient.Width() - x * 2, rcItem.Height());
    y += rcItem.Height();
    y += 1;
    m_pPageAlarm->MoveWindow(x, y, rcClient.Width() - x * 2, rcClient.Height() - y);
    m_pPageLogcat->MoveWindow(x, y, rcClient.Width() - x * 2, rcClient.Height() - y);
}
SourceCode/Bond/BondEq/CHomeDialog.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
#pragma once
#include "HmTab.h"
#include "CPageLogcat.h"
#include "CPageAlarm.h"
// CHomeDialog å¯¹è¯æ¡†
class CHomeDialog : public CDialogEx
{
    DECLARE_DYNAMIC(CHomeDialog)
public:
    CHomeDialog(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CHomeDialog();
public:
    void ShowChildPage(int index);
    void Resize();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    CHmTab* m_pTab;
    CPageLogcat* m_pPageLogcat;
    CPageAlarm* m_pPageAlarm;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_HOME };
#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 OnTabSelChanged(NMHDR* nmhdr, LRESULT* result);
};
SourceCode/Bond/BondEq/CMainContainer.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,110 @@
// CMainContainer.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "Common.h"
#include "CMainContainer.h"
#include "afxdialogex.h"
// CMainContainer å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CMainContainer, CDialogEx)
CMainContainer::CMainContainer(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_MAIN_CONTAINER, pParent)
{
    m_crBkgnd = MAIN_CONTAINER_BACKGROUND;
    m_hbrBkgnd = nullptr;
}
CMainContainer::~CMainContainer()
{
}
void CMainContainer::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMainContainer, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
END_MESSAGE_MAP()
// CMainContainer æ¶ˆæ¯å¤„理程序
BOOL CMainContainer::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CMainContainer::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 CMainContainer::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
}
void CMainContainer::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    Resize();
}
void CMainContainer::Resize()
{
    CRect rcClient;
    GetClientRect(&rcClient);
    // å…ˆå–得子窗口数量
    int count = 0;
    CWnd* pClild = FindWindowEx(m_hWnd, NULL, NULL, NULL);
    while (pClild != nullptr) {
        count++;
        pClild = FindWindowEx(m_hWnd, pClild->m_hWnd, NULL, NULL);
    }
    pClild = FindWindowEx(m_hWnd, NULL, NULL, NULL);
    while (pClild != nullptr) {
        pClild->MoveWindow(&rcClient);
        if (::GetProp(pClild->GetSafeHwnd(), "Home") == (HANDLE)1) {
            pClild->ShowWindow(count == 1 ? SW_SHOW : SW_HIDE);
        }
        else {
            pClild->ShowWindow(SW_SHOW);
        }
        pClild = FindWindowEx(m_hWnd, pClild->m_hWnd, NULL, NULL);
    }
}
SourceCode/Bond/BondEq/CMainContainer.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
#pragma once
// CMainContainer å¯¹è¯æ¡†
class CMainContainer : public CDialogEx
{
    DECLARE_DYNAMIC(CMainContainer)
public:
    CMainContainer(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CMainContainer();
public:
    void Resize();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_MAIN_CONTAINER };
#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);
};
SourceCode/Bond/BondEq/CPageAlarm.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,116 @@
// PageAlarm.cpp : å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "CPageAlarm.h"
#include "afxdialogex.h"
#include "Common.h"
// CPageAlarm å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CPageAlarm, CDialogEx)
CPageAlarm::CPageAlarm(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_PAGE_ALARM, pParent)
{
    m_crBkgnd = PAGE_BACKGROUND_COLOR;
    m_hbrBkgnd = nullptr;
    m_pObserver = nullptr;
}
CPageAlarm::~CPageAlarm()
{
}
void CPageAlarm::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CPageAlarm, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
END_MESSAGE_MAP()
// CPageAlarm æ¶ˆæ¯å¤„理程序
void CPageAlarm::InitRxWindow()
{
    /* 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 (RX_CODE_LOG == code && ::IsWindow(m_hWnd)) {
            }
            pAny->release();
        }, [&]() -> void {
            // onComplete
        }, [&](IThrowable* pThrowable) -> void {
            // onErrorm
            pThrowable->printf();
        });
        theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
            ->subscribe(m_pObserver);
    }
}
BOOL CPageAlarm::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    InitRxWindow();
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CPageAlarm::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 CPageAlarm::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
    if (m_pObserver != NULL) {
        m_pObserver->unsubscribe();
        m_pObserver = NULL;
    }
}
void CPageAlarm::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    // TODO: åœ¨æ­¤å¤„添加消息处理程序代码
}
SourceCode/Bond/BondEq/CPageAlarm.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
#pragma once
// CPageAlarm å¯¹è¯æ¡†
class CPageAlarm : public CDialogEx
{
    DECLARE_DYNAMIC(CPageAlarm)
public:
    CPageAlarm(CWnd* pParent = NULL);   // æ ‡å‡†æž„造函数
    virtual ~CPageAlarm();
private:
    void InitRxWindow();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    IObserver* m_pObserver;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_PAGE_ALARM };
#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);
};
SourceCode/Bond/BondEq/CPageLogcat.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,300 @@
// CPageLogcat.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "Common.h"
#include "CPageLogcat.h"
#include "afxdialogex.h"
#include <regex>
// CPageLogcat å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CPageLogcat, CDialogEx)
CPageLogcat::CPageLogcat(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_PAGE_LOGCAT, pParent)
{
    m_crBkgnd = PAGE_BACKGROUND_COLOR;
    m_hbrBkgnd = nullptr;
    m_pObserver = nullptr;
    m_nLevel = 0;
    m_strIncludeText = _T("");
    m_bIncludeRegex = FALSE;
}
CPageLogcat::~CPageLogcat()
{
}
void CPageLogcat::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_BUTTON_LEVEL, m_btnLevel);
    DDX_Control(pDX, IDC_BUTTON_INCLUDE, m_btnInclude);
    DDX_Control(pDX, IDC_EDIT_LOG, m_logEdit);
}
BEGIN_MESSAGE_MAP(CPageLogcat, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_LEVEL, &CPageLogcat::OnButtonLevelMenuClicked)
    ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_INCLUDE, &CPageLogcat::OnButtonIncludeMenuClicked)
    ON_EN_CHANGE(IDC_EDIT_INCLUDE, &CPageLogcat::OnEnChangeEditInclude)
    ON_BN_CLICKED(IDC_CHECK_REGEX, &CPageLogcat::OnBnClickedCheckRegex)
END_MESSAGE_MAP()
// CPageLogcat æ¶ˆæ¯å¤„理程序
void CPageLogcat::InitRxWindow()
{
    /* 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 (RX_CODE_LOG == code && ::IsWindow(m_hWnd)) {
                const char* pszLogMsg;
                int level;
                if (pAny->getStringValue("text", pszLogMsg)
                    && pAny->getIntValue("exCode", level)) {
                    if (level >= m_nLevel) {
                        CString strText = pszLogMsg;
                        BOOL bInclude = TRUE;
                        if (!m_strIncludeText.IsEmpty()) {
                            if (!m_bIncludeRegex) {
                                bInclude = (strText.Find(m_strIncludeText) >= 0);
                            }
                            else {
                                bInclude = std::regex_search((LPTSTR)(LPCTSTR)strText,
                                    std::regex((LPTSTR)(LPCTSTR)m_strIncludeText));
                            }
                        }
                        if (bInclude) {
                            strText.Replace("\n", "\r\n");
                            AppendLog(level, (LPTSTR)(LPCTSTR)strText);
                        }
                    }
                }
            }
            pAny->release();
            }, [&]() -> void {
                // onComplete
            }, [&](IThrowable* pThrowable) -> void {
                // onErrorm
                pThrowable->printf();
            });
        theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
            ->subscribe(m_pObserver);
    }
}
BOOL CPageLogcat::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // ç¼“å­˜
    m_nLevel = theApp.m_model.m_configuration.getLogcatLevel();
    theApp.m_model.m_configuration.getLogcatIncludeText(m_strIncludeText);
    m_bIncludeRegex = theApp.m_model.m_configuration.isLogcatIncludeRegex();
    theApp.m_model.m_configuration.getCustomLogcatIncludeTexts(m_customIncludeTexts);
    // Level
    HMENU hMenu = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCEA(IDR_MENU_LOGCAT_LEVEL));
    m_btnLevel.SetMenu(hMenu);
    m_btnLevel.SetCurrentMenuItem(m_nLevel);
    m_btnLevel.SetBkgndColor(BS_NORMAL, RGB(241, 242, 244));
    m_btnLevel.SetBkgndColor(BS_HOVER, RGB(220, 223, 228));
    m_btnLevel.SetBkgndColor(BS_PRESS, RGB(179, 185, 196));
    m_btnLevel.SetFrameColor(BS_NORMAL, RGB(133, 144, 162));
    m_btnLevel.SetFrameColor(BS_HOVER, RGB(56, 139, 255));
    m_btnLevel.SetFrameColor(BS_PRESS, RGB(56, 139, 255));
    m_btnLevel.SetFrameColor(BS_FOCUS, RGB(56, 139, 255));
    // åŒ…含字符串
    CString strIcon1;
    strIcon1.Format(_T("%s\\Res\\logcat_include.ico"), theApp.m_strAppDir);
    HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(),
        strIcon1, IMAGE_ICON, 24, 24,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    m_btnInclude.SetIcon(hIcon, hIcon, 24);
    {
        HMENU hMenu = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCEA(IDR_MENU_INCLUDE));
        HMENU hSubMenu = GetSubMenu(hMenu, 0);
        DeleteMenu(hSubMenu, 0, MF_BYPOSITION);
        int i = 0;
        for (auto& item : m_customIncludeTexts) {
            i++;
            InsertMenu(hSubMenu, 0, MF_BYPOSITION, 0x1998+i, item.c_str());
            m_btnInclude.SetMenu(hMenu);
        }
    }
    SetDlgItemText(IDC_EDIT_INCLUDE, m_strIncludeText);
    CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK_REGEX);
    pCheckBox->SetCheck(m_bIncludeRegex ? BST_CHECKED : BST_UNCHECKED);
    // å†…容
    m_logEdit.SetMaxLineCount(20);
    m_logEdit.SetLimitText(-1);
    InitRxWindow();
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CPageLogcat::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 CPageLogcat::OnDestroy()
{
    CDialogEx::OnDestroy();
    {
        HMENU hMenu = m_btnLevel.GetMenu();
        if (hMenu != NULL) {
            ::DestroyMenu(hMenu);
        }
    }
    {
        HMENU hMenu = m_btnInclude.GetMenu();
        if (hMenu != NULL) {
            ::DestroyMenu(hMenu);
        }
    }
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
    ASSERT(m_pObserver != NULL);
    m_pObserver->unsubscribe();
    m_pObserver = NULL;
}
void CPageLogcat::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (GetDlgItem(IDC_EDIT_LOG) == nullptr) return;
    int x, y, temp;
    CRect rcClient, rcItem;
    CWnd* pItem;
    GetClientRect(&rcClient);
    x = 12;
    pItem = GetDlgItem(IDC_BUTTON_LEVEL);
    pItem->GetWindowRect(&rcItem);
    ScreenToClient(&rcItem);
    pItem->MoveWindow(x, 12, rcItem.Width(), rcItem.Height());
    x += rcItem.Width();
    x += 18;
    y = rcItem.bottom;
    y += 12;
    pItem = GetDlgItem(IDC_BUTTON_INCLUDE);
    pItem->GetWindowRect(&rcItem);
    pItem->MoveWindow(x, 12, rcItem.Width(), rcItem.Height());
    x += rcItem.Width();
    x += 2;
    pItem = GetDlgItem(IDC_EDIT_INCLUDE);
    pItem->GetWindowRect(&rcItem);
    pItem->MoveWindow(x, 12, rcItem.Width(), rcItem.Height());
    x += rcItem.Width();
    x += 12;
    temp = rcItem.Height();
    pItem = GetDlgItem(IDC_CHECK_REGEX);
    pItem->GetWindowRect(&rcItem);
    pItem->MoveWindow(x, 12 + (temp - rcItem.Height()) / 2, rcItem.Width(), rcItem.Height());
    pItem = GetDlgItem(IDC_EDIT_LOG);
    pItem->MoveWindow(12, y, rcClient.Width() - 24, rcClient.Height() - 12 - y);
}
void CPageLogcat::AppendLog(int level, const char* pszText)
{
    if (!::IsWindow(m_logEdit.m_hWnd)) {
        return;
    }
    m_logEdit.AppendText(pszText);
}
void CPageLogcat::OnButtonLevelMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
    BLBUTTON_NMHDR* pblbNmhdr = reinterpret_cast<BLBUTTON_NMHDR*>(pNMHDR);
    m_nLevel = (int)pblbNmhdr->dwData;
    theApp.m_model.m_configuration.setLogcatLevel(m_nLevel);
    m_btnLevel.SetCurrentMenuItem(m_nLevel);
    *pResult = 0;
}
void CPageLogcat::OnButtonIncludeMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
    BLBUTTON_NMHDR* pblbNmhdr = reinterpret_cast<BLBUTTON_NMHDR*>(pNMHDR);
    int position = (int)pblbNmhdr->dwData;
    std::string& strInclude = m_customIncludeTexts.at(position);
    SetDlgItemText(IDC_EDIT_INCLUDE, strInclude.c_str());
    CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK_REGEX);
    m_bIncludeRegex = FALSE;
    pCheckBox->SetCheck(BST_UNCHECKED);
    theApp.m_model.m_configuration.setLogcatIncludeRegex(m_bIncludeRegex);
    theApp.m_model.m_configuration.setLogcatIncludeText(m_strIncludeText);
    *pResult = 0;
}
void CPageLogcat::OnEnChangeEditInclude()
{
    GetDlgItemText(IDC_EDIT_INCLUDE, m_strIncludeText);
    theApp.m_model.m_configuration.setLogcatIncludeText(m_strIncludeText);
}
void CPageLogcat::OnBnClickedCheckRegex()
{
    CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK_REGEX);
    m_bIncludeRegex = pCheckBox->GetCheck();
    theApp.m_model.m_configuration.setLogcatIncludeRegex(m_bIncludeRegex);
}
SourceCode/Bond/BondEq/CPageLogcat.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
#pragma once
#include "BlButton.h"
#include "LogEdit.h"
#include <vector>
#include <string>
// CPageLogcat å¯¹è¯æ¡†
class CPageLogcat : public CDialogEx
{
    DECLARE_DYNAMIC(CPageLogcat)
public:
    CPageLogcat(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CPageLogcat();
private:
    void InitRxWindow();
    void AppendLog(int level, const char* pszText);
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    IObserver* m_pObserver;
    int m_nLevel;
    CString m_strIncludeText;
    BOOL m_bIncludeRegex;
    std::vector<std::string> m_customIncludeTexts;
private:
    CBlButton m_btnLevel;
    CBlButton m_btnInclude;
    CLogEdit m_logEdit;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_PAGE_LOGCAT };
#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 OnButtonLevelMenuClicked(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnButtonIncludeMenuClicked(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnEnChangeEditInclude();
    afx_msg void OnBnClickedCheckRegex();
};
SourceCode/Bond/BondEq/CPanelProject.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,154 @@
// CPanelProject.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "CPanelProject.h"
#include "afxdialogex.h"
// CPanelEquipment å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CPanelProject, CDialogEx)
CPanelProject::CPanelProject(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_PANEL_PROJECT, pParent)
{
    m_crBkgnd = RGB(252, 252, 255);
    m_hbrBkgnd = nullptr;
    m_nPanelWidth = int((double)GetSystemMetrics(SM_CXSCREEN) * 0.25);
    m_pAccordionWnd = nullptr;
    m_pPageRemoteEqs = nullptr;
}
CPanelProject::~CPanelProject()
{
}
void CPanelProject::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CPanelProject, CDialogEx)
    ON_WM_SIZE()
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_NOTIFY(BYVERTICALLINE_MOVEX, IDC_LINE1, &CPanelProject::OnVLineMoveX)
END_MESSAGE_MAP()
// CPanelEquipment æ¶ˆæ¯å¤„理程序
BOOL CPanelProject::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // è¯»å–面板宽
    CString strIniFile;
    strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    m_nPanelWidth = GetPrivateProfileInt(_T("App"), _T("PanelEquipmentWidth"),
        int((double)GetSystemMetrics(SM_CXSCREEN) * 0.25), (LPTSTR)(LPCTSTR)strIniFile);
    CVerticalLine* pLine = CVerticalLine::Hook(GetDlgItem(IDC_LINE1)->GetSafeHwnd());
    pLine->EnableResize();
    // åˆ†ç»„展开收起控件
    CString strExpandIcon, strCloseIcon;
    strExpandIcon.Format(_T("%s\\res\\arrow_down.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    strCloseIcon.Format(_T("%s\\res\\arrow_right.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    m_pAccordionWnd = CAccordionWnd::FromHandle(GetDlgItem(IDC_ACCORDION_WND1)->m_hWnd);
    m_pAccordionWnd->SetFrameColor(RGB(220, 220, 220), TRUE);
    m_pAccordionWnd->Setpadding(PADDING_LEFT, 2);
    m_pAccordionWnd->Setpadding(PADDING_TOP, 2);
    m_pAccordionWnd->Setpadding(PADDING_RIGHT, 2);
    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);
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
void CPanelProject::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if(GetDlgItem(IDC_LINE1) == nullptr) return;
    Resize();
}
HBRUSH CPanelProject::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 CPanelProject::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
    if (m_pPageRemoteEqs != nullptr) {
        m_pPageRemoteEqs->DestroyWindow();
        delete m_pPageRemoteEqs;
        m_pPageRemoteEqs = nullptr;
    }
}
void CPanelProject::Resize()
{
    CRect rcClient, rcItem;
    GetClientRect(&rcClient);
    CWnd* pLine = GetDlgItem(IDC_LINE1);
    pLine->MoveWindow(rcClient.right - 2, 0, 2, rcClient.Height());
    GetDlgItem(IDC_ACCORDION_WND1)->MoveWindow(0, 0, rcClient.Width() - 2, rcClient.Height());
}
#define LEFT_PANEL_MIN_WIDTH        80
#define LEFT_PANEL_MAX_WIDTH        880
void CPanelProject::OnVLineMoveX(NMHDR* nmhdr, LRESULT* result)
{
    BYVERTICALLINE_NMHDR* pNmhdrex = (BYVERTICALLINE_NMHDR*)nmhdr;
    int x = pNmhdrex->dwData;
    m_nPanelWidth += x;
    m_nPanelWidth = max(m_nPanelWidth, LEFT_PANEL_MIN_WIDTH);
    m_nPanelWidth = min(m_nPanelWidth, LEFT_PANEL_MAX_WIDTH);
    GetParent()->SendMessage(WM_SIZE, 0, 0);
    CString strIniFile, strValue;
    strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    strValue.Format(_T("%d"), m_nPanelWidth);
    WritePrivateProfileString(_T("App"), _T("PanelEquipmentWidth"),
        (LPTSTR)(LPCTSTR)strValue, (LPTSTR)(LPCTSTR)strIniFile);
    *result = 0;
}
int CPanelProject::GetPanelWidth()
{
    return m_nPanelWidth;
}
SourceCode/Bond/BondEq/CPanelProject.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
#pragma once
#include "VerticalLine.h"
#include "CProjectPageRemoteEqs.h"
#include "AccordionWnd.h"
// CPanelProject å¯¹è¯æ¡†
class CPanelProject : public CDialogEx
{
    DECLARE_DYNAMIC(CPanelProject)
public:
    CPanelProject(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CPanelProject();
public:
    int GetPanelWidth();
private:
    void Resize();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    int m_nPanelWidth;
    CAccordionWnd* m_pAccordionWnd;
    CProjectPageRemoteEqs* m_pPageRemoteEqs;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_PANEL_PROJECT };
#endif
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 HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnDestroy();
    afx_msg void OnVLineMoveX(NMHDR* nmhdr, LRESULT* result);
};
SourceCode/Bond/BondEq/CProjectPageRemoteEqs.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,211 @@
// CProjectPageRemoteEqs.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "Common.h"
#include "BondServo.h"
#include "CProjectPageRemoteEqs.h"
#include "afxdialogex.h"
// CProjectPageRemoteEqs å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CProjectPageRemoteEqs, CDialogEx)
CProjectPageRemoteEqs::CProjectPageRemoteEqs(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_PROJECT_PAGE_REMOTEEQS, pParent)
{
    m_crBkgnd = PROPAGE_BACKGROUND_COLOR;
    m_hbrBkgnd = nullptr;
    m_pObserver = nullptr;
}
CProjectPageRemoteEqs::~CProjectPageRemoteEqs()
{
}
void CProjectPageRemoteEqs::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_TREE1, m_treeRemoteEqs);
}
BEGIN_MESSAGE_MAP(CProjectPageRemoteEqs, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, &CProjectPageRemoteEqs::OnTvnSelchangedTree1)
    ON_MESSAGE(ID_MSG_TREE_CLICK_ITEM, OnTreeClickItem)
    ON_WM_TIMER()
END_MESSAGE_MAP()
// CProjectPageRemoteEqs æ¶ˆæ¯å¤„理程序
void CProjectPageRemoteEqs::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 (RX_CODE_REMOTEEQ_STATE_CHANGED == code) {
                BEQ::IRemoteEquipment* pRemoteEq;
                if (pAny->getPtrValue("ptr", (void*&)pRemoteEq)) {
                    HTREEITEM hItem = getTreeItem(pRemoteEq);
                    if (hItem != nullptr) {
                        char szBuffer[256];
                        pRemoteEq->getName(szBuffer, 256);
                        m_treeRemoteEqs.SetItemText(hItem, szBuffer);
                        m_treeRemoteEqs.SetItemIcon(hItem,
                            pRemoteEq->isConnected() ? m_hIconRemoteEqLight : m_hIconRemoteEqDark);
                    }
                }
            }
            pAny->release();
        }, [&]() -> void {
            // onComplete
        }, [&](IThrowable* pThrowable) -> void {
            // onErrorm
            pThrowable->printf();
        });
        theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
            ->subscribe(m_pObserver);
    }
}
BOOL CProjectPageRemoteEqs::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    CString strFilepath;
    strFilepath.Format(_T("%s\\Res\\remote_eq_light_32.ico"), theApp.m_strAppDir);
    m_hIconRemoteEqLight = (HICON)::LoadImage(AfxGetInstanceHandle(),
        strFilepath, IMAGE_ICON, 32, 32,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    strFilepath.Format(_T("%s\\Res\\remote_eq_dark_32.ico"), theApp.m_strAppDir);
    m_hIconRemoteEqDark = (HICON)::LoadImage(AfxGetInstanceHandle(),
        strFilepath, IMAGE_ICON, 32, 32,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    m_treeRemoteEqs.SetBkColor(PROPAGE_BACKGROUND_COLOR);
    m_treeRemoteEqs.SetItemHeight(50);
    SetTimer(1, 2000, nullptr);
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CProjectPageRemoteEqs::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 CProjectPageRemoteEqs::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
    ASSERT(m_pObserver != NULL);
    m_pObserver->unsubscribe();
    m_pObserver = NULL;
}
void CProjectPageRemoteEqs::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (GetDlgItem(IDC_TREE1) == nullptr) return;
    CRect rcClient;
    CWnd* pItem;
    GetClientRect(&rcClient);
    pItem = GetDlgItem(IDC_TREE1);
    pItem->MoveWindow(12, 12, rcClient.Width() - 24, rcClient.Height() - 24);
}
void CProjectPageRemoteEqs::OnTvnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    HTREEITEM hItem = pNMTreeView->itemNew.hItem;
    ASSERT(hItem);
    BEQ::IRemoteEquipment* pEquipment = (BEQ::IRemoteEquipment*)m_treeRemoteEqs.GetItemData(hItem);
    ASSERT(pEquipment);
    theApp.m_model.notifyPtr(RX_CODE_SELECT_EQ, pEquipment);
    *pResult = 0;
}
LRESULT CProjectPageRemoteEqs::OnTreeClickItem(WPARAM wParam, LPARAM lParam)
{
    HTREEITEM hItem = (HTREEITEM)wParam;
    ASSERT(hItem);
    BEQ::IRemoteEquipment* pEquipment = (BEQ::IRemoteEquipment*)m_treeRemoteEqs.GetItemData(hItem);
    ASSERT(pEquipment);
    theApp.m_model.notifyPtr(RX_CODE_SELECT_EQ, pEquipment);
    return 0;
}
HTREEITEM CProjectPageRemoteEqs::getTreeItem(BEQ::IRemoteEquipment* pEquipment)
{
    HTREEITEM hItem = m_treeRemoteEqs.GetChildItem(nullptr);
    while (hItem != nullptr) {
        BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)m_treeRemoteEqs.GetItemData(hItem);
        if (p == pEquipment) {
            return hItem;
        }
        hItem = m_treeRemoteEqs.GetNextSiblingItem(hItem);
    }
    return nullptr;
}
void CProjectPageRemoteEqs::OnTimer(UINT_PTR nIDEvent)
{
    if (1 == nIDEvent) {
        KillTimer(1);
        InitRxWindows();
        // è¿œç¨‹è®¾å¤‡åˆ—表
        char szEqName[256];
        BEQ::IRemoteEquipment* pRemoteEq = theApp.m_model.getBond1();
        ASSERT(pRemoteEq);
        pRemoteEq->getName(szEqName, 256);
        HTREEITEM hItemEq = m_treeRemoteEqs.InsertItem(szEqName);
        m_treeRemoteEqs.SetItemIcon(hItemEq, pRemoteEq->isConnected() ? m_hIconRemoteEqLight : m_hIconRemoteEqDark);
        m_treeRemoteEqs.SetItemData(hItemEq, (DWORD_PTR)pRemoteEq);
    }
    CDialogEx::OnTimer(nIDEvent);
}
SourceCode/Bond/BondEq/CProjectPageRemoteEqs.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
#pragma once
#include "ApredTreeCtrl.h"
// CProjectPageRemoteEqs å¯¹è¯æ¡†
class CProjectPageRemoteEqs : public CDialogEx
{
    DECLARE_DYNAMIC(CProjectPageRemoteEqs)
public:
    CProjectPageRemoteEqs(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CProjectPageRemoteEqs();
private:
    void InitRxWindows();
    HTREEITEM getTreeItem(BEQ::IRemoteEquipment* pEquipment);
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    CApredTreeCtrl m_treeRemoteEqs;
    IObserver* m_pObserver;
    HICON m_hIconRemoteEqLight;
    HICON m_hIconRemoteEqDark;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_PROJECT_PAGE_REMOTEEQS
    };
#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 OnTvnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg LRESULT OnTreeClickItem(WPARAM wParam, LPARAM lParam);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
};
SourceCode/Bond/BondEq/CRemoteEqUnitView.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
// CRemoteEqUnitView.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "afxdialogex.h"
#include "CRemoteEqUnitView.h"
#include "Log.h"
#include "ToolUnits.h"
#include "Common.h"
// CRemoteEqUnitView å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CRemoteEqUnitView, CBaseView)
CRemoteEqUnitView::CRemoteEqUnitView(CWnd* pParent /*=nullptr*/)
    : CBaseView(IDD_COMPONENT_REMOTE_EQ_UNIT, pParent)
{
    m_pObserver = nullptr;
    m_crBkgnd = REMOTE_EQ_VIEW_BACKGROUND;
    m_hbrBkgnd = nullptr;
}
CRemoteEqUnitView::~CRemoteEqUnitView()
{
}
void CRemoteEqUnitView::DoDataExchange(CDataExchange* pDX)
{
    CBaseView::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CRemoteEqUnitView, CBaseView)
END_MESSAGE_MAP()
// CRemoteEqUnitView æ¶ˆæ¯å¤„理程序
HBRUSH CRemoteEqUnitView::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 CRemoteEqUnitView::OnDestroy()
{
    CBaseView::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
    ASSERT(m_pObserver != NULL);
    m_pObserver->unsubscribe();
    m_pObserver = NULL;
}
SourceCode/Bond/BondEq/CRemoteEqUnitView.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
#pragma once
#include "CBaseView.h"
// CRemoteEqUnitView å¯¹è¯æ¡†
class CRemoteEqUnitView : public CBaseView
{
    DECLARE_DYNAMIC(CRemoteEqUnitView)
public:
    CRemoteEqUnitView(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CRemoteEqUnitView();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    IObserver* m_pObserver;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_COMPONENT_REMOTE_EQ_UNIT };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
public:
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnDestroy();
};
SourceCode/Bond/BondEq/CRemoteEqView.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,206 @@
// CComponentData1Dlg.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "CRemoteEqView.h"
#include "afxdialogex.h"
#include "Log.h"
#include "ToolUnits.h"
#include "Common.h"
// CComponentData1Dlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CRemoteEqView, CBaseView)
CRemoteEqView::CRemoteEqView(CWnd* pParent /*=nullptr*/)
    : CBaseView(IDD_COMPONENT_REMOTE_EQ, pParent)
{
    m_pObserver = nullptr;
    m_crBkgnd = REMOTE_EQ_VIEW_BACKGROUND;
    m_hbrBkgnd = nullptr;
}
CRemoteEqView::~CRemoteEqView()
{
    for (CRemoteEqUnitView* pView : m_tabViews) {
        if (pView) {
            pView->DestroyWindow();
            delete pView;
        }
    }
    m_tabViews.clear();
}
void CRemoteEqView::DoDataExchange(CDataExchange* pDX)
{
    CBaseView::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CRemoteEqView, CBaseView)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_WM_TIMER()
    ON_NOTIFY(TCN_SELCHANGE, IDC_TAB_UNITS, &CRemoteEqView::OnSelchangeUnitTab)
END_MESSAGE_MAP()
// CComponentData1Dlg æ¶ˆæ¯å¤„理程序
void CRemoteEqView::InitRxWindows()
{
    /* code */
    // è®¢é˜…数据
    IRxWindows* pRxWindows = RX_GetRxWindows();
    if (m_pObserver == NULL) {
        m_pObserver = pRxWindows->allocObserver([&](IAny* pAny) -> void {
            // onNext
            pAny->addRef();
            int code = pAny->getCode();
            pAny->release();
            }, [&]() -> void {
                // onComplete
            }, [&](IThrowable* pThrowable) -> void {
                // onErrorm
                pThrowable->printf();
            });
        theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
            ->subscribe(m_pObserver);
    }
}
BOOL CRemoteEqView::OnInitDialog()
{
    CBaseView::OnInitDialog();
    SetTimer(1, 200, NULL);
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CRemoteEqView::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 CRemoteEqView::OnDestroy()
{
    CBaseView::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
    ASSERT(m_pObserver != NULL);
    m_pObserver->unsubscribe();
    m_pObserver = NULL;
}
void CRemoteEqView::OnSize(UINT nType, int cx, int cy)
{
    CBaseView::OnSize(nType, cx, cy);
}
void CRemoteEqView::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    if (1 == nIDEvent) {
        KillTimer(1);
        InitRxWindows();
        LoadData();
    }
    CBaseView::OnTimer(nIDEvent);
}
void CRemoteEqView::LoadData()
{
    BEQ::IRemoteEquipment* pEquipment = (BEQ::IRemoteEquipment*)GetContext();
    if (pEquipment == nullptr) {
        return;
    }
    CTabCtrl* pTabCtrl = (CTabCtrl*)GetDlgItem(IDC_TAB_UNITS);
    const char** names = pEquipment->getAllUnitNames();
    AddUnitTabs(*pTabCtrl, names);
    if (m_tabViews.size() > 0 && !m_tabViews.empty()) {
        m_tabViews[0]->ShowWindow(SW_SHOW);
    }
}
void CRemoteEqView::Resize()
{
    int y = 12;
    int x = 0;
    CRect rcClient, rcItem;
    CWnd* pItem;
    GetClientRect(&rcClient);
}
void CRemoteEqView::AddUnitTabs(CTabCtrl& tabCtrl, const char** names)
{
    BEQ::IRemoteEquipment* pEquipment = (BEQ::IRemoteEquipment*)GetContext();
    if (pEquipment == nullptr) {
        return;
    }
    int tabIndex = 0;
    while (names[tabIndex] != nullptr) {
        BEQ::IUnit* pUnit = pEquipment->getUnit(names[tabIndex]);
        if (pUnit == nullptr) {
            ++tabIndex;
            continue;
        }
        CString tabText(names[tabIndex]);
        tabCtrl.InsertItem(tabIndex, tabText);
        CRemoteEqUnitView* pView = new CRemoteEqUnitView();
        if (pView->Create(IDD_COMPONENT_REMOTE_EQ_UNIT, &tabCtrl)) {
            CRect rect;
            tabCtrl.GetClientRect(&rect);
            tabCtrl.AdjustRect(FALSE, &rect);
            rect.DeflateRect(10, 10);
            pView->MoveWindow(rect);
            pView->ShowWindow(SW_HIDE);
            pView->SetContext(pUnit);
            m_tabViews.push_back(pView);
        }
        ++tabIndex;
    }
}
void CRemoteEqView::OnSelchangeUnitTab(NMHDR* pNMHDR, LRESULT* pResult)
{
    CTabCtrl* pTabCtrl = (CTabCtrl*)GetDlgItem(IDC_TAB_UNITS);
    int selectedIndex = pTabCtrl->GetCurSel();
    for (CRemoteEqUnitView* pView : m_tabViews) {
        pView->ShowWindow(SW_HIDE);
    }
    if (selectedIndex >= 0 && selectedIndex < m_tabViews.size()) {
        m_tabViews[selectedIndex]->ShowWindow(SW_SHOW);
    }
    *pResult = 0;
}
SourceCode/Bond/BondEq/CRemoteEqView.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
#pragma once
#include "CBaseView.h"
#include "CRemoteEqUnitView.h"
// CComponentData1Dlg å¯¹è¯æ¡†
class CRemoteEqView : public CBaseView
{
    DECLARE_DYNAMIC(CRemoteEqView)
public:
    CRemoteEqView(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CRemoteEqView();
private:
    void InitRxWindows();
    void LoadData();
    void Resize();
    void AddUnitTabs(CTabCtrl& tabCtrl, const char** names);
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    IObserver* m_pObserver;
    std::vector<CRemoteEqUnitView*> m_tabViews;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_COMPONENT_DATA1 };
#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 OnSelchangeUnitTab(NMHDR* pNMHDR, LRESULT* pResult);
};
SourceCode/Bond/BondEq/Common.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,89 @@
#pragma once
#define MC_TIME_SEPAR                1000
/* Context Ret code */
#define CRC_ACK_REJECT                            -3
#define CRC_TIMEOUT                                -2
#define CRC_NG                                    -1
#define CRC_UNKNOWN                                0
#define CRC_SUCCEED                                1
/* Rx Code */
#define RX_CODE_TEST                    0
#define RX_CODE_LOG                        1000
#define RX_CODE_BONDER_STATE_CHANGED    1001
#define RX_CODE_PASSIVE_STATUS_CHANGED    1002
#define RX_CODE_PLC1_CONNECTTD            1003
#define RX_CODE_PLC1_DISCONNECTTD        1004
#define RX_CODE_SELECT_EQ                1005
#define RX_CODE_DATA1_MATERIAL_RECEIVED    1006
#define RX_CODE_DATA1_BEGIN_SAMPLING    1007
#define RX_CODE_DATA1_UPDATE            1008
#define RX_CODE_DATA1_END_SAMPLING        1009
#define RX_CODE_DATA1_MATERIAL_REMOVEED    1010
#define RX_CODE_PANEL_COMPLATE            1011
#define RX_CODE_ALARM_EVENT                1012
#define RX_CODE_EQSTATE_EVENT            1013
#define RX_CODE_EFEM_STATUS_CHANGED        1014
#define RX_CODE_REMOTEEQ_STATE_CHANGED    1015
/* å¹¿æ’­ä»£ç  */
#define BC_CODE_DATA1_MATERIAL_RECEIVED    5000
#define BC_CODE_DATA1_BEGIN_SAMPLING    5001
#define BC_CODE_DATA1_UPDATE            5002
#define BC_CODE_DATA1_END_SAMPLING        5003
#define BC_CODE_DATA1_MATERIAL_REMOVED    5004
#define BC_CODE_ALARM_EVENT                5005
#define BC_CODE_EQSTATE_EVENT            5006
#define BC_CODE_RUN_RECIPE_RESULT        5007
/* Channel Name */
#define MC_CHANNEL1_NAME        "McChannel1"
/* é¢œè‰² */
#define APPDLG_BACKGROUND_COLOR            RGB(252, 252, 255)
#define PAGE_BACKGROUND_COLOR            RGB(252, 252, 255)
#define SETPAGE_BACKGROUND_COLOR        RGB(250, 250, 255)
#define PROPAGE_BACKGROUND_COLOR        RGB(252, 252, 255)
#define REMOTE_EQ_VIEW_BACKGROUND        RGB(252, 252, 255)
#define TOP_TOOLBAR_BACKGROUND            RGB(240, 240, 240)
#define INACTIVE_BACKGROUND                RGB(188, 188, 188)
#define INACTIVE_FOREGROUND                RGB(68, 68, 68)
#define ACTIVE_BACKGROUND                RGB(34, 177, 76)
#define ACTIVE_FOREGROUND                RGB(68, 68, 68)
#define NOT_SELECTED_BACKGROUND            RGB(181, 230, 29)
#define NOT_SELECTED_FOREGROUND            RGB(68, 68, 68)
#define SELECTED_BACKGROUND                RGB(34, 177, 76)
#define SELECTED_FOREGROUND                RGB(68, 68, 68)
#define DISCONNECTED_BACKGROUND            RGB(255, 127, 39)
#define DISCONNECTED_FOREGROUND            RGB(68, 68, 68)
#define CONNECTED_BACKGROUND            RGB(34, 177, 76)
#define CONNECTED_FOREGROUND            RGB(68, 68, 68)
#define BASE_VIEW_BACKGROUND            RGB(252, 252, 255)
#define MAIN_CONTAINER_BACKGROUND        RGB(252, 252, 255)
#define TREE_BADGE_BACKGROUND            RGB(34, 177, 76)
#define TREE_BADGE_FOREGROUND            RGB(222, 222, 222)
#define TREE_BADGE2_BACKGROUND            RGB(255, 127, 39)
#define TREE_BADGE2_FOREGROUND            RGB(222, 222, 222)
#define HOMEPAGE_BACKGROUND                RGB(252, 252, 255)
/* æŒ‰é’®é¢œè‰²å®šä¹‰ é£Žæ ¼1*/
#define BTN1_BKGND_NORMAL                RGB(245, 245, 245)
#define BTN1_BKGND_HOVER                RGB(229, 241, 251)
#define BTN1_BKGND_PRESS                RGB(185, 209, 234)
#define BTN1_BKGND_FOCUS                RGB(245, 245, 245)
#define BTN1_BKGND_DISABLE                RGB(245, 245, 245)
#define BTN1_TEXT_NORMAL                RGB(51, 51, 51)
#define BTN1_TEXT_HOVER                    RGB(51, 51, 51)
#define BTN1_TEXT_PRESS                    RGB(51, 51, 51)
#define BTN1_TEXT_FOCUS                    RGB(51, 51, 51)
#define BTN1_TEXT_DISABLE                RGB(191, 191, 191)
/* æŒ‰é’®id */
#define VIEW_TOOL_BTN_CLOSE                0x1016
SourceCode/Bond/BondEq/Configuration.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,105 @@
#include "stdafx.h"
#include "Configuration.h"
CConfiguration::CConfiguration()
{
}
CConfiguration::CConfiguration(const char* pszFilepath)
{
    m_strFilepath = pszFilepath;
}
CConfiguration::~CConfiguration()
{
}
void CConfiguration::setFilepath(const char* pszFilepath)
{
    m_strFilepath = pszFilepath;
}
void CConfiguration::getUnitId(CString& strUnitId)
{
    char szTemp[256];
    GetPrivateProfileString("App", _T("UnitId"), _T(""), szTemp, 256, m_strFilepath);
    strUnitId = szTemp;
}
void CConfiguration::getBond1(CString& strIp, UINT& port, UINT& doorCount)
{
    char szTemp[256];
    // è¯»IP和端口
    GetPrivateProfileString("Bond1", _T("IP"), _T(""), szTemp, 256, m_strFilepath);
    strIp = szTemp;
    port = GetPrivateProfileInt("Bond1", _T("Port"), 0, m_strFilepath);
    doorCount = GetPrivateProfileInt("Bond1", _T("DoorCount"), 0, m_strFilepath);
}
int CConfiguration::getLogcatLevel()
{
    return GetPrivateProfileInt(_T("Logcat"), _T("Level"), 0, m_strFilepath);
}
void CConfiguration::setLogcatLevel(int level)
{
    WritePrivateProfileString(_T("Logcat"), _T("Level"),
        std::to_string(level).c_str(), m_strFilepath);
}
int CConfiguration::setLogcatIncludeText(CString& strInclude)
{
    WritePrivateProfileString(_T("Logcat"), _T("IncludeText"),
        strInclude, m_strFilepath);
    return 0;
}
int CConfiguration::getLogcatIncludeText(CString& strInclude)
{
    char szTemp[256];
    GetPrivateProfileString("Logcat", _T("IncludeText"), _T(""), szTemp, 256, m_strFilepath);
    strInclude = szTemp;
    return 0;
}
void CConfiguration::setLogcatIncludeRegex(BOOL bRegex)
{
    WritePrivateProfileString(_T("Logcat"), _T("IncludeRegex"),
        bRegex ? "1" : "0", m_strFilepath);
}
BOOL CConfiguration::isLogcatIncludeRegex()
{
    return GetPrivateProfileInt(_T("Logcat"), _T("IncludeRegex"), 0, m_strFilepath);
}
int CConfiguration::getCustomLogcatIncludeTexts(std::vector<std::string>& texts)
{
    char szSection[256], szTemp[256];
    for (int i = 0; i < 10; i++) {
        sprintf_s(szSection, 256, "CustomInclude%d", i + 1);
        GetPrivateProfileString("Logcat", szSection, _T(""),
            szTemp, 256, m_strFilepath);
        std::string strInclude(szTemp);
        if (!strInclude.empty()) {
            texts.push_back(strInclude);
        }
    }
    return (int)texts.size();
}
int CConfiguration::getP2RemoteEqReconnectInterval()
{
    return GetPrivateProfileInt(_T("P2"), _T("RemoteEqReconnectInterval"), 20, m_strFilepath);
}
void CConfiguration::setP2RemoteEqReconnectInterval(int second)
{
    WritePrivateProfileString(_T("P2"), _T("RemoteEqReconnectInterval"),
        std::to_string(second).c_str(), m_strFilepath);
}
SourceCode/Bond/BondEq/Configuration.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
#pragma once
#include <vector>
#include <string>
class CConfiguration
{
public:
    CConfiguration();
    CConfiguration(const char* pszFilepath);
    ~CConfiguration();
public:
    void setFilepath(const char* pszFilepath);
    void getUnitId(CString& strUnitId);
    void getBond1(CString& strIp, UINT& port, UINT& doorCount);
    int getLogcatLevel();
    void setLogcatLevel(int level);
    int setLogcatIncludeText(CString& strInclude);
    int getLogcatIncludeText(CString& strInclude);
    void setLogcatIncludeRegex(BOOL bRegex);
    BOOL isLogcatIncludeRegex();
    int getCustomLogcatIncludeTexts(std::vector<std::string>& texts);
public:
    void setP2RemoteEqReconnectInterval(int second);
    int getP2RemoteEqReconnectInterval();
private:
    CString m_strFilepath;
};
SourceCode/Bond/BondEq/DBManager/UserManager.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,484 @@
#include "stdafx.h"
#include "UserManager.h"
#include <chrono>
#include <iostream>
#include <fstream>
#include <ctime>
#include <sstream>
const std::string SESSION_FILE = R"(session.dat)";
const std::string DATABASE_FILE = R"(BondServo.db)";
const std::string INITIAL_ADMIN_USERNAME = "admin";
const std::string INITIAL_ADMIN_PASSWORD = "admin";
// èŽ·å–å•ä¾‹å®žä¾‹
UserManager& UserManager::getInstance() {
    static UserManager instance;
    return instance;
}
UserManager::UserManager()
    : m_isLoggedIn(false), m_isRememberMe(false), m_tmSessionTimeout(std::chrono::minutes(30)),
    m_tmSessionExpiration(std::chrono::hours(72)), m_hMouseHook(nullptr), m_hKeyboardHook(nullptr),
    m_pDB(std::make_unique<BL::SQLiteDatabase>()) {
    initializeDatabase();
}
UserManager::~UserManager() {
    terminateIdleDetection();
}
// åˆå§‹åŒ–数据库,创建用户表并插入初始管理员用户
bool UserManager::initializeDatabase() {
    std::string dbFilePath = getDatabaseFilePath();
    if (!m_pDB->connect(dbFilePath, true)) {
        throw std::runtime_error("Failed to connect to database.");
    }
    std::string createTableQuery = R"(
        CREATE TABLE IF NOT EXISTS users (
            username VARCHAR(50) PRIMARY KEY,
            password_hash VARCHAR(255) NOT NULL,
            role INT NOT NULL,
            session_timeout INT DEFAULT 30,
            session_expiration INT DEFAULT 72,
            last_login TIMESTAMP
        )
    )";
    m_pDB->executeQuery(createTableQuery);
    std::string checkAdminQuery = "SELECT COUNT(*) FROM users WHERE role = 0";
    auto result = m_pDB->fetchResults(checkAdminQuery);
    if (result.empty() || result[0][0] == "0") {
        std::string insertAdminQuery = "INSERT INTO users (username, password_hash, role, session_timeout, session_expiration) VALUES ('" +
            INITIAL_ADMIN_USERNAME + "', '" + hashPassword(INITIAL_ADMIN_PASSWORD) + "', 0, 30, 72)";
        m_pDB->executeQuery(insertAdminQuery);
    }
    return true;
}
// å¯¹å¯†ç è¿›è¡Œå“ˆå¸Œå¤„理
std::string UserManager::hashPassword(const std::string& password) {
    return std::to_string(std::hash<std::string>{}(password));
}
// ç®€å•的加密和解密函数
std::string UserManager::simpleEncryptDecrypt(const std::string& data, const std::string& key) {
    std::string result = data;
    for (size_t i = 0; i < data.size(); ++i) {
        result[i] ^= key[i % key.size()];  // ç®€å•异或加密
    }
    return result;
}
// ä»Žä¼šè¯æ–‡ä»¶åŠ è½½ä¼šè¯ä¿¡æ¯
bool UserManager::loadSession() {
    std::ifstream sessionFile(getSessionFilePath(), std::ios::binary);
    if (!sessionFile.is_open()) {
        return false;
    }
    // ä»Žæ–‡ä»¶è¯»å–加密数据
    std::string encryptedData((std::istreambuf_iterator<char>(sessionFile)), std::istreambuf_iterator<char>());
    sessionFile.close();
    // è§£å¯†æ•°æ®
    std::string decryptedData = simpleEncryptDecrypt(encryptedData, "my_secret_key");
    // è§£æžè§£å¯†çš„æ•°æ®
    std::istringstream sessionData(decryptedData);
    std::string username;
    std::string password;
    std::time_t lastLoginTime;
    int timeoutMinutes;
    int expirationHours;
    sessionData >> username >> password >> lastLoginTime >> timeoutMinutes >> expirationHours;
    // éªŒè¯æ—¶é—´æˆ³æœ‰æ•ˆæ€§
    auto now = std::chrono::system_clock::now();
    auto lastLogin = std::chrono::system_clock::from_time_t(lastLoginTime);
    auto sessionDuration = std::chrono::duration_cast<std::chrono::hours>(now - lastLogin);
    if (sessionDuration > std::chrono::hours(expirationHours)) {
        clearSession();
        return false;
    }
    // æ¢å¤ä¼šè¯æ•°æ®
    m_strCurrentUser = username;
    m_strCurrentPass = password;
    m_tpLastLogin = lastLogin;
    m_tmSessionTimeout = std::chrono::minutes(timeoutMinutes);
    m_tmSessionExpiration = std::chrono::hours(expirationHours);
    m_isLoggedIn = true;
    m_isRememberMe = true;
    updateActivityTime();
    return true;
}
// ä¿å­˜ä¼šè¯ä¿¡æ¯åˆ°æ–‡ä»¶
void UserManager::saveSession() {
    if (!m_isRememberMe) {
        clearSession();
        return;
    }
    // åŽŸå§‹ä¼šè¯æ•°æ®
    std::stringstream sessionData;
    std::time_t lastLoginTime = std::chrono::system_clock::to_time_t(m_tpLastLogin);
    sessionData << m_strCurrentUser << " " << m_strCurrentPass << " " << lastLoginTime << " "
        << m_tmSessionTimeout.count() << " " << m_tmSessionExpiration.count();
    // åŠ å¯†æ•°æ®
    std::string encryptedData = simpleEncryptDecrypt(sessionData.str(), "my_secret_key");
    // å†™å…¥åŠ å¯†æ•°æ®åˆ°æ–‡ä»¶
    std::ofstream sessionFile(getSessionFilePath(), std::ios::binary);
    if (sessionFile.is_open()) {
        sessionFile << encryptedData;
        sessionFile.close();
    }
}
// æ¸…除会话文件
void UserManager::clearSession() {
    std::remove(getSessionFilePath().c_str());
}
// èŽ·å–ç¨‹åºè·¯å¾„ä¸‹çš„config文件夹路径
std::string UserManager::getConfigFolderPath() {
    char path[MAX_PATH];
    GetModuleFileName(NULL, path, MAX_PATH);
    std::string exePath = std::string(path).substr(0, std::string(path).find_last_of("\\/"));
    std::string configPath = exePath + "\\Config\\";
    // æ£€æŸ¥å¹¶åˆ›å»ºconfig文件夹
    DWORD fileAttr = GetFileAttributes(configPath.c_str());
    if (fileAttr == INVALID_FILE_ATTRIBUTES) {
        CreateDirectory(configPath.c_str(), NULL);
    }
    return configPath;
}
// èŽ·å–session.dat文件路径
std::string UserManager::getSessionFilePath() {
    return getConfigFolderPath() + SESSION_FILE;
}
// èŽ·å–æ•°æ®åº“æ–‡ä»¶è·¯å¾„
std::string UserManager::getDatabaseFilePath() {
    return getConfigFolderPath() + DATABASE_FILE;
}
// ç™»å½•方法
bool UserManager::login(const std::string& username, const std::string& password, bool rememberMeFlag) {
    std::string query = "SELECT username, password_hash, role, session_timeout, session_expiration FROM users WHERE username = '" + username + "'";
    auto result = m_pDB->fetchResults(query);
    if (result.empty() || result[0][1] != hashPassword(password)) {
        std::cerr << "Login failed: Invalid username or password." << std::endl;
        return false;
    }
    m_strCurrentUser = username;
    m_strCurrentPass = password;
    m_enCurrentUserRole = static_cast<UserRole>(std::stoi(result[0][2]));
    m_tmSessionTimeout = std::chrono::minutes(std::stoi(result[0][3]));
    m_tmSessionExpiration = std::chrono::hours(std::stoi(result[0][4]));
    m_isLoggedIn = true;
    m_isRememberMe = rememberMeFlag;
    updateActivityTime();
    m_tpLastLogin = std::chrono::system_clock::now();
    std::string updateLoginTime = "UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE username = '" + username + "'";
    m_pDB->executeQuery(updateLoginTime);
    saveSession();
    return true;
}
// ç™»å‡ºæ–¹æ³•
void UserManager::logout() {
    if (m_isLoggedIn) {
        std::cout << "User logged out: " << m_strCurrentUser << std::endl;
        m_strCurrentUser.clear();
        m_strCurrentPass.clear();
        m_isLoggedIn = false;
        m_isRememberMe = false;
        clearSession();
    }
}
// è¿”回当前用户的登录状态
bool UserManager::isLoggedIn() const {
    return m_isLoggedIn;
}
// è¿”回当前用户的记住登录状态
bool UserManager::isRememberMe() const {
    return m_isRememberMe;
}
// åˆ›å»ºæ–°ç”¨æˆ·ï¼Œä»…超级管理员有权限
bool UserManager::createUser(const std::string& username, const std::string& password, UserRole role,
    std::chrono::minutes timeout, std::chrono::hours expiration) {
    if (m_enCurrentUserRole != UserRole::SuperAdmin) {
        std::cerr << "Only SuperAdmin can create new users." << std::endl;
        return false;
    }
    std::string query = "INSERT INTO users (username, password_hash, role, session_timeout, session_expiration) VALUES ('" +
        username + "', '" + hashPassword(password) + "', " + std::to_string(static_cast<int>(role)) + ", " +
        std::to_string(timeout.count()) + ", " + std::to_string(expiration.count()) + ")";
    return m_pDB->executeQuery(query);
}
// åˆ é™¤ç”¨æˆ·ï¼Œä»…超级管理员有权限,且不能删除自己
bool UserManager::deleteUser(const std::string& username) {
    if (m_enCurrentUserRole != UserRole::SuperAdmin) {
        std::cerr << "Only SuperAdmin can delete users." << std::endl;
        return false;
    }
    if (username == m_strCurrentUser) {
        std::cerr << "SuperAdmin cannot delete their own account." << std::endl;
        return false;
    }
    std::string query = "DELETE FROM users WHERE username = '" + username + "'";
    return m_pDB->executeQuery(query);
}
// èŽ·å–æ‰€æœ‰ç”¨æˆ·ä¿¡æ¯ï¼Œä»…è¶…çº§ç®¡ç†å‘˜æœ‰æƒé™
std::vector<std::vector<std::string>> UserManager::getUsers() {
    if (m_enCurrentUserRole != UserRole::SuperAdmin) {
        std::cerr << "Only SuperAdmin can retrieve user data." << std::endl;
        return {};
    }
    // æŸ¥è¯¢æ•´ä¸ªç”¨æˆ·è¡¨
    std::string query = "SELECT username, password_hash, role, session_timeout, session_expiration, last_login FROM users";
    return m_pDB->fetchResults(query);
}
// è®¾ç½®æ•´ä¸ªç”¨æˆ·è¡¨çš„æ•°æ®ï¼Œä»…超级管理员有权限
bool UserManager::setUsers(const std::vector<std::vector<std::string>>& usersData) {
    if (m_enCurrentUserRole != UserRole::SuperAdmin) {
        std::cerr << "Only SuperAdmin can set user data." << std::endl;
        return false;
    }
    // æ¸…空用户表
    std::string deleteQuery = "DELETE FROM users";
    if (!m_pDB->executeQuery(deleteQuery)) {
        std::cerr << "Failed to clear the users table." << std::endl;
        return false;
    }
    // æ’入新的用户数据
    for (const auto& user : usersData) {
        if (user.size() != 6) {
            std::cerr << "Invalid data format for user. Each user must have 6 fields." << std::endl;
            return false;
        }
        std::string insertQuery = "INSERT INTO users (username, password_hash, role, session_timeout, session_expiration, last_login) VALUES ('" +
            user[0] + "', '" + user[1] + "', " + user[2] + ", " + user[3] + ", " + user[4] + ", '" + user[5] + "')";
        if (!m_pDB->executeQuery(insertQuery)) {
            std::cerr << "Failed to insert user: " << user[0] << std::endl;
            return false;
        }
    }
    return true;
}
// ä¿®æ”¹ç”¨æˆ·åï¼Œä»…超级管理员有权限
bool UserManager::changeUsername(const std::string& username, const std::string& newUsername) {
    if (m_enCurrentUserRole != UserRole::SuperAdmin) {
        std::cerr << "Only SuperAdmin can change usernames." << std::endl;
        return false;
    }
    std::string query = "UPDATE users SET username = '" + newUsername + "' WHERE username = '" + username + "'";
    bool success = m_pDB->executeQuery(query);
    // å¦‚果是当前登录用户修改自己的用户名,更新成员变量并保存会话文件
    if (success && m_strCurrentUser == username) {
        m_strCurrentUser = newUsername;
        // å¦‚果“记住密码”已启用,更新会话文件
        if (m_isRememberMe) {
            saveSession();
        }
    }
    return success;
}
// ä¿®æ”¹ç”¨æˆ·å¯†ç ï¼ˆä»…允许当前用户或超级管理员)
bool UserManager::changePassword(const std::string& username, const std::string& newPassword) {
    if (username != m_strCurrentUser && m_enCurrentUserRole != UserRole::SuperAdmin) {
        std::cerr << "Permission denied: Only the user or SuperAdmin can change passwords." << std::endl;
        return false;
    }
    std::string query = "UPDATE users SET password_hash = '" + hashPassword(newPassword) +
        "' WHERE username = '" + username + "'";
    bool success = m_pDB->executeQuery(query);
    // å¦‚果是当前用户修改自己的密码,退出登录并清除会话文件
    if (success && m_strCurrentUser == username) {
        logout();
        std::cout << "Password changed successfully. Please log in again." << std::endl;
    }
    return success;
}
// æ›´æ”¹ç”¨æˆ·è§’色,仅超级管理员有权限
bool UserManager::changeUserRole(const std::string& username, UserRole newRole) {
    if (m_enCurrentUserRole != UserRole::SuperAdmin) {
        std::cerr << "Only SuperAdmin can change user roles." << std::endl;
        return false;
    }
    // é˜²æ­¢ç®¡ç†å‘˜æ›´æ”¹è‡ªå·±çš„角色
    if (m_strCurrentUser == username) {
        std::cerr << "SuperAdmin cannot change their own role." << std::endl;
        return false;
    }
    std::string query = "UPDATE users SET role = " + std::to_string(static_cast<int>(newRole)) +
        " WHERE username = '" + username + "'";
    return m_pDB->executeQuery(query);
}
// ä¿®æ”¹ç”¨æˆ·çš„ session_timeout,仅超级管理员有权限
bool UserManager::changeUserSessionTimeout(const std::string& username, int newTimeoutMinutes) {
    if (m_enCurrentUserRole != UserRole::SuperAdmin) {
        std::cerr << "Only SuperAdmin can change session timeout." << std::endl;
        return false;
    }
    std::string query = "UPDATE users SET session_timeout = " + std::to_string(newTimeoutMinutes) +
        " WHERE username = '" + username + "'";
    bool success = m_pDB->executeQuery(query);
    // å¦‚果是当前登录用户修改自己的超时设置,更新成员变量
    if (success && m_strCurrentUser == username) {
        m_tmSessionTimeout = std::chrono::minutes(newTimeoutMinutes);
        if (m_isRememberMe) {
            saveSession();
        }
    }
    return success;
}
// ä¿®æ”¹ç”¨æˆ·çš„ session_expiration,仅超级管理员有权限
bool UserManager::changeUserSessionExpiration(const std::string& username, int newExpirationHours) {
    if (m_enCurrentUserRole != UserRole::SuperAdmin) {
        std::cerr << "Only SuperAdmin can change session expiration." << std::endl;
        return false;
    }
    std::string query = "UPDATE users SET session_expiration = " + std::to_string(newExpirationHours) +
        " WHERE username = '" + username + "'";
    bool success = m_pDB->executeQuery(query);
    // å¦‚果是当前登录用户修改自己的过期设置,更新成员变量
    if (success && m_strCurrentUser == username) {
        m_tmSessionExpiration = std::chrono::hours(newExpirationHours);
        if (m_isRememberMe) {
            saveSession();
        }
    }
    return success;
}
// æ›´æ–°æœ€åŽæ´»åŠ¨æ—¶é—´ï¼Œç”¨äºŽæ— æ“ä½œè¶…æ—¶æ£€æµ‹
void UserManager::updateActivityTime() {
    m_tpLastActivity = std::chrono::system_clock::now();
    std::cout << "Activity updated at: " << std::chrono::system_clock::to_time_t(m_tpLastActivity) << std::endl;
}
// è®¾ç½®æ— æ“ä½œè¶…æ—¶æ—¶é—´
void UserManager::setSessionTimeout(std::chrono::minutes timeout) {
    m_tmSessionTimeout = timeout;
}
// æ£€æŸ¥æ˜¯å¦è¶…过无操作超时时间
bool UserManager::isInactiveTimeout() const {
    auto now = std::chrono::system_clock::now();
    auto elapsedSeconds = std::chrono::duration_cast<std::chrono::seconds>(now - m_tpLastActivity).count();
    return elapsedSeconds > m_tmSessionTimeout.count() * 60;
}
// åˆå§‹åŒ–无操作检测,包括设置全局鼠标和键盘钩子
void UserManager::initializeIdleDetection(HWND hwnd) {
    updateActivityTime();
    m_hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc, (HINSTANCE) nullptr, 0);
    m_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, (HINSTANCE) nullptr, 0);
    ::SetTimer(hwnd, 1, 60000, nullptr);
}
// ç»ˆæ­¢æ— æ“ä½œæ£€æµ‹ï¼Œæ¸…除鼠标和键盘钩子
void UserManager::terminateIdleDetection() {
    if (m_hMouseHook) {
        UnhookWindowsHookEx(m_hMouseHook);
        m_hMouseHook = nullptr;
    }
    if (m_hKeyboardHook) {
        UnhookWindowsHookEx(m_hKeyboardHook);
        m_hKeyboardHook = nullptr;
    }
    ::KillTimer(nullptr, 1);
}
// èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·å
std::string UserManager::getCurrentUser() const {
    return m_strCurrentUser;
}
// èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·å¯†ç 
std::string UserManager::getCurrentPass() const {
    return m_strCurrentPass;
}
// èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·è§’è‰²
UserRole UserManager::getCurrentUserRole() const {
    return m_enCurrentUserRole;
}
// èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·çš„æ— æ“ä½œè¶…æ—¶æ—¶é—´
std::chrono::minutes UserManager::getSessionTimeout() const {
    return m_tmSessionTimeout;
}
// èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·çš„ä¼šè¯è¿‡æœŸæ—¶é—´
std::chrono::hours UserManager::getSessionExpiration() const {
    return m_tmSessionExpiration;
}
// å…¨å±€é¼ æ ‡é’©å­å›žè°ƒï¼Œè®°å½•活动时间
LRESULT CALLBACK UserManager::LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        UserManager::getInstance().updateActivityTime();
        std::cout << "Mouse event detected. Activity time updated." << std::endl;
    }
    return CallNextHookEx(nullptr, nCode, wParam, lParam);
}
// å…¨å±€é”®ç›˜é’©å­å›žè°ƒï¼Œè®°å½•活动时间
LRESULT CALLBACK UserManager::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        UserManager::getInstance().updateActivityTime();
        std::cout << "Keyboard event detected. Activity time updated." << std::endl;
    }
    return CallNextHookEx(nullptr, nCode, wParam, lParam);
}
SourceCode/Bond/BondEq/DBManager/UserManager.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,116 @@
#ifndef USER_MANAGER_H
#define USER_MANAGER_H
#include <string>
#include <memory>
#include <chrono>
#include <windows.h>
#include "Database.h"
// ç”¨æˆ·è§’色定义
enum class UserRole {
    SuperAdmin = 0,     // è¶…级管理员
    Engineer,           // å·¥ç¨‹å¸ˆ
    Operator            // æ“ä½œå‘˜
};
// ç”¨æˆ·ç®¡ç†ç±»ï¼Œé‡‡ç”¨å•例模式
class UserManager {
public:
    static UserManager& getInstance();
    UserManager(const UserManager&) = delete;
    UserManager& operator=(const UserManager&) = delete;
    // ç”¨æˆ·æ“ä½œ
    bool login(const std::string& username, const std::string& password, bool rememberMe = false);
    void logout();
    bool isLoggedIn() const;
    bool isRememberMe() const;
    bool createUser(const std::string& username, const std::string& password, UserRole role,
        std::chrono::minutes timeout = std::chrono::minutes(30),
        std::chrono::hours expiration = std::chrono::hours(72));
    bool deleteUser(const std::string& username);
    std::vector<std::vector<std::string>> getUsers();
    bool setUsers(const std::vector<std::vector<std::string>>& usersData);
    bool changeUsername(const std::string& username, const std::string& newUsername);
    bool changePassword(const std::string& username, const std::string& newPassword);
    bool changeUserRole(const std::string& username, UserRole newRole);
    bool changeUserSessionTimeout(const std::string& username, int newTimeoutMinutes);
    bool changeUserSessionExpiration(const std::string& username, int newExpirationHours);
    // ä¼šè¯æ–‡ä»¶æ“ä½œ
    bool loadSession();     // ä»Žä¼šè¯æ–‡ä»¶åŠ è½½ä¼šè¯ä¿¡æ¯
    void saveSession();     // ä¿å­˜ä¼šè¯ä¿¡æ¯åˆ°æ–‡ä»¶
    void clearSession();    // æ¸…除会话文件
    // é…ç½®æ–‡ä»¶å¤¹è·¯å¾„管理
    static std::string getConfigFolderPath();
    static std::string getSessionFilePath();
    static std::string getDatabaseFilePath();
    // æ›´æ–°æœ€åŽæ´»åŠ¨æ—¶é—´ï¼ˆç”¨äºŽæ— æ“ä½œè¶…æ—¶æ£€æµ‹ï¼‰
    void updateActivityTime();
    // è®¾ç½®ç”¨æˆ·çš„æ— æ“ä½œè¶…æ—¶æ—¶é—´
    void setSessionTimeout(std::chrono::minutes timeout);
    // æ£€æŸ¥æ˜¯å¦æ— æ“ä½œè¶…æ—¶
    bool isInactiveTimeout() const;
    // åˆå§‹åŒ–无操作检测(设置全局钩子和定时器)
    void initializeIdleDetection(HWND hwnd);
    // ç»ˆæ­¢æ— æ“ä½œæ£€æµ‹ï¼ˆæ¸…除钩子和定时器)
    void terminateIdleDetection();
    // èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·å
    std::string getCurrentUser() const;
    // èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·å¯†ç 
    std::string getCurrentPass() const;
    // èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·è§’è‰²
    UserRole getCurrentUserRole() const;
    // èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·çš„æ— æ“ä½œè¶…æ—¶æ—¶é—´
    std::chrono::minutes getSessionTimeout() const;
    // èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·çš„ä¼šè¯è¿‡æœŸæ—¶é—´
    std::chrono::hours getSessionExpiration() const;
private:
    UserManager();
    ~UserManager();
    // åˆå§‹åŒ–数据库连接和用户表
    bool initializeDatabase();
    // å“ˆå¸Œå¯†ç ï¼Œç”¨äºŽåŠ å¯†ç”¨æˆ·å¯†ç 
    std::string hashPassword(const std::string& password);
    // åŠ å¯†å’Œè§£å¯†å‡½æ•°
    std::string simpleEncryptDecrypt(const std::string& data, const std::string& key);
    // é”®ç›˜å’Œé¼ æ ‡é’©å­å‡½æ•°
    static LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam);
    static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
    // å±žæ€§å®šä¹‰
    std::string m_strCurrentUser;                     // å½“前登录用户名
    std::string m_strCurrentPass;                     // å½“前登录密码
    UserRole m_enCurrentUserRole;                     // å½“前登录用户角色
    bool m_isLoggedIn;                                // æ˜¯å¦å·²ç™»å½•
    bool m_isRememberMe;                              // æ˜¯å¦è®°ä½ç™»å½•状态
    std::chrono::time_point<std::chrono::system_clock> m_tpLastLogin;     // ä¸Šæ¬¡ç™»å½•æ—¶é—´
    std::chrono::time_point<std::chrono::system_clock> m_tpLastActivity;  // æœ€åŽæ´»åŠ¨æ—¶é—´
    std::chrono::minutes m_tmSessionTimeout;          // æ— æ“ä½œè¶…æ—¶æ—¶é—´
    std::chrono::hours m_tmSessionExpiration;         // ä¼šè¯è¿‡æœŸæ—¶é—´
    HHOOK m_hMouseHook;                               // é¼ æ ‡é’©å­å¥æŸ„
    HHOOK m_hKeyboardHook;                            // é”®ç›˜é’©å­å¥æŸ„
    std::unique_ptr<BL::Database> m_pDB;              // æ•°æ®åº“接口
};
#endif // USER_MANAGER_H
SourceCode/Bond/BondEq/HmTab.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,529 @@
// HmTab.cpp: implementation of the CHmTab class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HmTab.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CHmTab::CHmTab()
{
    m_hWnd = NULL;
    m_crBkgnd = RGB(250, 250, 255);
    m_nPaddingLeft = 28;
    m_nPaddingBottom = 12;
    m_nItemMarginLeft = 8;
    m_crText[0] = RGB(88, 88, 88);
    m_crText[1] = RGB(18, 18, 18);
    m_pPressItem = nullptr;
    m_pHighItem = nullptr;
    LOGBRUSH lb;
    lb.lbColor = RGB(225, 127, 39);
    lb.lbHatch = 0;
    lb.lbStyle = BS_SOLID;
    DWORD iStyle = PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_SQUARE | PS_JOIN_MITER;
    m_hPenUnder[0] = ExtCreatePen(iStyle, 3, &lb, 0, NULL);
    lb.lbColor = RGB(225, 127, 39);
    m_hPenUnder[1] = ExtCreatePen(iStyle, 2, &lb, 0, NULL);
    lb.lbColor = RGB(223, 226, 230);
    m_hPenUnderWnd = ExtCreatePen(iStyle, 1, &lb, 0, NULL);
    m_nCurSel = 0;
}
CHmTab::~CHmTab()
{
    if (m_hPenUnder[0] != nullptr) {
        ::DeleteObject(m_hPenUnder[0]);
    }
    if (m_hPenUnder[1] != nullptr) {
        ::DeleteObject(m_hPenUnder[1]);
    }
    if (m_hPenUnderWnd != nullptr) {
        ::DeleteObject(m_hPenUnderWnd);
    }
}
BOOL CHmTab::RegisterWndClass()
{
    WNDCLASS wc;
    wc.lpszClassName = BYHMTAB_CLASS;
    wc.hInstance = AfxGetInstanceHandle();
    wc.lpfnWndProc = WindowProc;
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = 0;
    wc.lpszMenuName = NULL;
    wc.hbrBackground = NULL;
    wc.style = CS_GLOBALCLASS|CS_DBLCLKS;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    // æ³¨å†Œè‡ªå®šä¹‰ç±»
    return (::RegisterClass(&wc) != 0);
}
CHmTab* CHmTab::Hook(HWND hWnd)
{
    CHmTab* pHmTab = (CHmTab*)GetProp(hWnd, BYSTAG_HMTAB);
    if(pHmTab == NULL)
    {
        pHmTab = new CHmTab;
        pHmTab->m_hWnd = hWnd;
        SetProp(hWnd, BYSTAG_HMTAB, (HANDLE)pHmTab);
    }
    return pHmTab;
}
void CHmTab::Release()
{
    // delete
    delete this;
}
void CHmTab::SetPaddingLeft(int value)
{
    m_nPaddingLeft = value;
}
void CHmTab::SetItemMarginLeft(int value)
{
    m_nItemMarginLeft = value;
}
void CHmTab::SetTextColor(COLORREF color1, COLORREF color2)
{
    m_crText[0] = color1;
    m_crText[1] = color2;
    InvalidateRect(m_hWnd, NULL, TRUE);
}
int CHmTab::AddItem(const char* pszText,BOOL bUpdate/* = TRUE*/)
{
    HMTABITEM item;
    memset(&item, 0, sizeof(HMTABITEM));
    strcpy_s(item.szText, MHITEM_TEXT_MAX, pszText);
    m_items.push_back(item);
    if (bUpdate) {
        InvalidateRect(m_hWnd, NULL, TRUE);
    }
    return 0;
}
int CHmTab::DeleteItem(const char* pszText, BOOL bUpdate/* = TRUE*/)
{
    for (auto iter = m_items.begin(); iter != m_items.end(); iter++) {
        if (strcmp((*iter).szText, pszText) == 0) {
            m_items.erase(iter);
            break;
        }
    }
    if (bUpdate) {
        InvalidateRect(m_hWnd, NULL, TRUE);
    }
    return 0;
}
void CHmTab::Notify(int nCode, DWORD_PTR dwData, DWORD_PTR dwData1/* = 0*/, DWORD_PTR dwData2/* = 0*/)
{
    HWND hParent;
    hParent = GetParent(m_hWnd);
    if (hParent != NULL) {
        BYHMTAB_NMHDR iii_nmhdr;
        iii_nmhdr.nmhdr.hwndFrom = m_hWnd;
        iii_nmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
        iii_nmhdr.nmhdr.code = nCode;
        iii_nmhdr.dwData = dwData;
        iii_nmhdr.dwData1 = dwData1;
        iii_nmhdr.dwData2 = dwData2;
        SendMessage(hParent, WM_NOTIFY, (WPARAM)iii_nmhdr.nmhdr.idFrom, (LPARAM)&iii_nmhdr);
    }
}
////////////////////////////////
// æ‹¦æˆªçª—口消息函数
LRESULT CALLBACK CHmTab::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CHmTab* pHmTab = (CHmTab *)GetProp(hWnd, BYSTAG_HMTAB);
    if(pHmTab == NULL && uMsg != WM_NCCREATE)
    {
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    // å¦‚æžœHook则响应消息
    ASSERT(hWnd);
    switch(uMsg)
    {
    case WM_NCCREATE:
        return OnNcCreate(hWnd, wParam, lParam);
    case WM_DESTROY:
        return pHmTab->OnDestroy(wParam, lParam);
    case WM_PAINT:
        return pHmTab->OnPaint(wParam, lParam);
    case WM_TIMER:
        return pHmTab->OnTimer(wParam, lParam);
    case WM_MOUSEMOVE:
        return pHmTab->OnMouseMove(wParam, lParam);
    case WM_LBUTTONDOWN:
        return pHmTab->OnLButtonDown(wParam, lParam);
    case WM_SETCURSOR:
        return pHmTab->OnSetCursor(wParam, lParam);
    case WM_SIZE:
        return pHmTab->OnSize(wParam, lParam);
    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS;
    default:
        break;
    }
    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
///////////////////////////////
// WM_NCCREATE
// çª—口创建前的初始化工作
LRESULT CHmTab::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    CHmTab* pHmTab = (CHmTab *)GetProp(hWnd, BYSTAG_HMTAB);
    ASSERT(pHmTab == NULL);
    Hook(hWnd);
    return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
}
///////////////////////////////
// WM_DESTROY
LRESULT CHmTab::OnDestroy(WPARAM wParam, LPARAM lParam)
{
    Release();
    return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
}
///////////////////////////////
// WM_TIMER
LRESULT CHmTab::OnTimer(WPARAM wParam, LPARAM lParam)
{
    if (wParam == 1) {
        POINT pt;
        GetCursorPos(&pt);
        ::ScreenToClient(m_hWnd, &pt);
        HMTABITEM* pLastHighItem = m_pHighItem;
        HighTest(pt, m_pHighItem, nullptr);
        if (m_pHighItem != pLastHighItem) {
            ::InvalidateRect(m_hWnd, NULL, TRUE);
        }
        if (m_pHighItem == nullptr) {
            ::KillTimer(m_hWnd, 1);
        }
    }
    return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
}
///////////////////////////////
// WM_MOUSEMOVE
LRESULT CHmTab::OnMouseMove(WPARAM wParam, LPARAM lParam)
{
    POINT pt;
    pt.x = LOWORD(lParam);
    pt.y = HIWORD(lParam);
    HMTABITEM* pLastHighItem = m_pHighItem;
    int nHitCode = HighTest(pt, m_pHighItem, nullptr);
    if (m_pHighItem != pLastHighItem) {
        RECT rcClient;
        GetClientRect(m_hWnd, &rcClient);
        ::InvalidateRect(m_hWnd, &rcClient, TRUE);
    }
    if (m_pHighItem != NULL) {
        ::KillTimer(m_hWnd, 1);
        ::SetTimer(m_hWnd, 1, 100, NULL);
    }
    ::SetProp(m_hWnd, HMTAB_HITCODETEST, (HANDLE)(__int64)nHitCode);
    return ::DefWindowProc(m_hWnd, WM_MOUSEMOVE, wParam, lParam);
}
/*
 * WM_LBUTTONDOWN
 * é¼ æ ‡å·¦é”®æŒ‰ä¸‹
 */
LRESULT CHmTab::OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
    POINT pt, ptNew;
    pt.x = LOWORD(lParam);
    pt.y = HIWORD(lParam);
    BOOL bButtonUp = FALSE;
    int nClickIndex = -1;
    HighTest(pt, m_pPressItem, &nClickIndex);
    if (m_pPressItem != NULL) {
        m_pHighItem = NULL;
        ::InvalidateRect(m_hWnd, NULL, TRUE);
    }
    // æ•捉鼠标消息,检测是否拖动
    HMTABITEM* pPressItem = NULL;
    if (m_pPressItem != NULL) {
        ::KillTimer(m_hWnd, 1);
        if (::GetCapture() == NULL) {
            SetCapture(m_hWnd);
            ASSERT(m_hWnd == GetCapture());
            AfxLockTempMaps();
            for (;;)
            {
                MSG msg;
                VERIFY(::GetMessage(&msg, NULL, 0, 0));
                if (GetCapture() != m_hWnd) break;
                switch (msg.message)
                {
                case WM_MOUSEMOVE:
                    ptNew = msg.pt;
                    ::ScreenToClient(m_hWnd, &ptNew);
                    HighTest(ptNew, pPressItem, &nClickIndex);
                    if (pPressItem != m_pPressItem) {
                        m_pPressItem = nullptr;
                        ::InvalidateRect(m_hWnd, NULL, TRUE);
                    }
                    break;
                case WM_LBUTTONUP:
                    ptNew = msg.pt;
                    ::ScreenToClient(m_hWnd, &ptNew);
                    HighTest(ptNew, pPressItem, &nClickIndex);
                    if (m_pPressItem != nullptr && pPressItem == m_pPressItem) {
                        m_nCurSel = nClickIndex;
                        bButtonUp = TRUE;
                    }
                    goto ExitLoop;
                case WM_KEYDOWN:
                    if (msg.wParam == VK_ESCAPE) {
                        goto ExitLoop;
                    }
                    break;
                default:
                    DispatchMessage(&msg);
                    break;
                }
            }
        ExitLoop:
            m_pPressItem = NULL;
            ReleaseCapture();
            ::InvalidateRect(m_hWnd, NULL, TRUE);
            if (bButtonUp) {
                Notify((int)BYHMTAB_SEL_CHANGED, m_nCurSel);
            }
            AfxUnlockTempMaps(FALSE);
        }
    }
    return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
}
///////////////////////////////
// WM_SETCURSOR
LRESULT CHmTab::OnSetCursor(WPARAM wParam, LPARAM lParam)
{
    int nHitCode = (int)(__int64)GetProp(m_hWnd, HMTAB_HITCODETEST);
    switch (nHitCode)
    {
    case HMTAB_HT_NOWHERE:
    case HMTAB_HT_ITEM:
        SetCursor(::LoadCursor(NULL, IDC_ARROW));
        return TRUE;
    case HMTAB_HT_HIGT_ITEM:
        SetCursor(::LoadCursor(NULL, IDC_HAND));
        return TRUE;
    default:
        break;
    }
    return ::DefWindowProc(m_hWnd, WM_SETCURSOR, wParam, lParam);
}
/*
 * WM_SIZE
 */
LRESULT CHmTab::OnSize(WPARAM wParam, LPARAM lParam)
{
    ::InvalidateRect(m_hWnd, NULL, TRUE);
    return ::DefWindowProc(m_hWnd, WM_SIZE, wParam, lParam);
}
///////////////////////////////
// WM_PAINT
LRESULT CHmTab::OnPaint(WPARAM wParam, LPARAM lParam)
{
    HDC hDC, hMemDC;
    HBITMAP hBitmap;
    RECT rcClient;
    CString strText;
    HFONT hFont1, hFont2;
    HBRUSH hBrushBK;
    // BeginPaint
    PAINTSTRUCT ps;
    hDC = BeginPaint(m_hWnd, &ps);
    GetClientRect(m_hWnd, &rcClient);
    hMemDC = ::CreateCompatibleDC(hDC);
    hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left,
        rcClient.bottom - rcClient.top);
    ::SelectObject(hMemDC, hBitmap);
    ::SetBkMode(hMemDC, TRANSPARENT);
    HFONT hFontDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    CFont* pFont = CFont::FromHandle(hFontDefault);
    LOGFONT lf;
    pFont->GetLogFont(&lf);
    hFont1 = ::CreateFontIndirect(&lf);
    lf.lfHeight -= 5;
    hFont2 = ::CreateFontIndirect(&lf);
    // èƒŒæ™¯é¢œè‰²
    hBrushBK = CreateSolidBrush(m_crBkgnd);
    ::FillRect(hMemDC, &rcClient, hBrushBK);
    DeleteObject(hBrushBK);
    SelectObject(hMemDC, m_hPenUnderWnd);
    ::MoveToEx(hMemDC, rcClient.left, rcClient.bottom - 2, NULL);
    ::LineTo(hMemDC, rcClient.right, rcClient.bottom - 2);
    // ç»˜åˆ¶å­é¡¹
    SIZE sizeItem;
    RECT rcItem, rcText;
    rcItem.top = rcClient.top;
    rcItem.bottom = rcClient.bottom-1;
    rcItem.left = m_nPaddingLeft;
    int index = 0;
    for (int i = 0; i < m_items.size(); i++) {
        auto& item = m_items.at(i);
        ::SelectObject(hMemDC, i == m_nCurSel ? hFont2 : hFont1);
        ::SetTextColor(hMemDC, i == m_nCurSel ? m_crText[1] : m_crText[0]);
        ::GetTextExtentPoint32(hMemDC, item.szText, (int)strlen(item.szText), &sizeItem);
        rcItem.left += m_nItemMarginLeft;
        rcItem.right = rcItem.left + (int)sizeItem.cx;
        ::CopyRect(&rcText, &rcItem);
        rcText.bottom -= m_nPaddingBottom;
        ::DrawText(hMemDC, item.szText, (int)strlen(item.szText), &rcText,
            DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_END_ELLIPSIS);
        ::CopyRect(&item.rect, &rcItem);
        // ä¸‹åˆ’线?
        if (i == m_nCurSel || &item == m_pHighItem) {
            HPEN hOldPen = (HPEN)::SelectObject(hMemDC, i == m_nCurSel ? m_hPenUnder[0] : m_hPenUnder[1]);
            ::MoveToEx(hMemDC, item.rect.left, item.rect.bottom - 3, NULL);
            ::LineTo(hMemDC, item.rect.right, item.rect.bottom - 3);
            ::SelectObject(hMemDC, hOldPen);
        }
        index++;
        rcItem.left = rcItem.right;
    }
    ::DeleteObject(hFont1);
    ::DeleteObject(hFont2);
    // EndPaint
    ::BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
        hMemDC, 0, 0, SRCCOPY);
    EndPaint(m_hWnd, &ps);
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
    return 1;
}
void CHmTab::SetBkgndColor(COLORREF cr)
{
    m_crBkgnd = cr;
}
/*
 * æ£€æµ‹åæ ‡ç‚¹æ‰€åœ¨çš„项
 * è¿”回, TYGTLITEM
 */
int CHmTab::HighTest(POINT pt, OUT HMTABITEM*& pItem, int* pnIndex)
{
    // æ£€æµ‹æ˜¯å¦åœ¨æŸä¸ªå­é¡¹
    int nRet = HMTAB_HT_NOWHERE;
    pItem = NULL;
    for (int i = 0; i < m_items.size(); i++) {
        auto& item = m_items.at(i);
        if (::PtInRect(&item.rect, pt)) {
            pItem = &item;
            nRet = pItem == m_pHighItem ? HMTAB_HT_HIGT_ITEM : HMTAB_HT_ITEM;
            if (pnIndex != nullptr) *pnIndex = i;
            break;
        }
    }
    return nRet;
}
int CHmTab::GetCurSel()
{
    return m_nCurSel;
}
void CHmTab::SetCurSel(int index)
{
    if (0 <= index && index <= m_items.size()) {
        m_nCurSel = index;
        InvalidateRect(m_hWnd, NULL, TRUE);
    }
}
int CHmTab::GetItemCount()
{
    return (int)m_items.size();
}
SourceCode/Bond/BondEq/HmTab.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,130 @@
// HmTab.h: interface for the CHmTab class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_HMTAB_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)
#define AFX_HMTAB_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_
#pragma comment(lib, "Msimg32.lib")            // TransparentBlt
#include <vector>
//====== HmTab =====================================================
#ifndef NOHMTAB
#ifdef _WIN32
#define BYHMTAB_CLASSA       "BYHmTab"
#define BYHMTAB_CLASSW       L"BYHmTab"
#ifdef UNICODE
#define  BYHMTAB_CLASS       BYHMTAB_CLASSW
#else
#define  BYHMTAB_CLASS       BYHMTAB_CLASSA
#endif
#else
#define BYHMTAB_CLASS        "BYHmTab"
#endif
#define BYSTAG_HMTAB         _T("ISHMTAB")
//====== WM_NOTIFY codes (NMHDR.code values) ==================================
#define BYHMTAB_FIRST                 (0U-1190U)       //
#define BYHMTAB_LAST                 (0U-1150U)
#define BYHMTAB_SEL_CHANGED              (BYHMTAB_FIRST - 1)
typedef struct tagBYHMTAB_NMHDR
{
    NMHDR        nmhdr;
    DWORD_PTR    dwData;
    DWORD_PTR    dwData1;
    DWORD_PTR    dwData2;
} BYHMTAB_NMHDR;
#define MHITEM_TEXT_MAX        64
typedef struct tagHMTABITEM
{
    int id;
    char szText[MHITEM_TEXT_MAX];
    RECT rect;
} HMTABITEM;
#define HMTAB_HITCODETEST            _T("HitCode")
#define HMTAB_HT_NOWHERE            0x1
#define HMTAB_HT_ITEM                0x2
#define HMTAB_HT_HIGT_ITEM            0x4
#endif
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CHmTab
{
public:
    CHmTab();
    virtual ~CHmTab();
public:
    static BOOL RegisterWndClass();
    static CHmTab* Hook(HWND hWnd);
    void Notify(int nCode, DWORD_PTR dwData, DWORD_PTR dwData1 = 0, DWORD_PTR dwData2 = 0);
    void Release();
    void SetBkgndColor(COLORREF cr);
    static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    static LRESULT OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
    LRESULT OnDestroy(WPARAM wParam, LPARAM lParam);
    LRESULT OnTimer(WPARAM wParam, LPARAM lParam);
    LRESULT OnPaint(WPARAM wParam, LPARAM lParam);
    LRESULT OnSetCursor(WPARAM wParam, LPARAM lParam);
    LRESULT OnSize(WPARAM wParam, LPARAM lParam);
    LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam);
    LRESULT OnMouseMove(WPARAM wParam, LPARAM lParam);
public:
    void SetPaddingLeft(int value);
    void SetItemMarginLeft(int value);
    void SetTextColor(COLORREF color1, COLORREF color2);
    int AddItem(const char* pszText, BOOL bUpdate = TRUE);
    int DeleteItem(const char* pszText, BOOL bUpdate = TRUE);
    int HighTest(POINT pt, OUT HMTABITEM*& pItem, int* pnIndex);
    int GetCurSel();
    void SetCurSel(int index);
    int GetItemCount();
private:
    HWND        m_hWnd;
    COLORREF m_crBkgnd;
private:
    int m_nCurSel;
    std::vector< HMTABITEM > m_items;
    HMTABITEM* m_pHighItem;
    HMTABITEM* m_pPressItem;
    int m_nPaddingLeft;
    int m_nPaddingBottom;
    int m_nItemMarginLeft;
    COLORREF m_crText[2];
    HPEN m_hPenUnder[2];
    HPEN m_hPenUnderWnd;
};
#endif // !defined(AFX_HMTAB_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)
SourceCode/Bond/BondEq/HmVerticalTab.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,576 @@
// HmVerticalTab.cpp: implementation of the CHmVerticalTab class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HmVerticalTab.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CHmVerticalTab::CHmVerticalTab()
{
    m_hWnd = NULL;
    m_crBkgnd = RGB(250, 250, 255);
    m_nPaddingTop = 12;
    m_nItemMarginTop = 1;
    m_crText[0] = RGB(17, 14, 39);
    m_crText[1] = RGB(255, 255, 255);
    m_crItemBkgnd[0] = RGB(67, 153, 233);
    m_crItemBkgnd[1] = RGB(188, 219, 248);
    m_hbrItemBkgnd[0] = CreateSolidBrush(m_crItemBkgnd[0]);
    m_hbrItemBkgnd[1] = CreateSolidBrush(m_crItemBkgnd[1]);
    m_pPressItem = nullptr;
    m_pHighItem = nullptr;
    LOGBRUSH lb;
    lb.lbColor = RGB(225, 127, 39);
    lb.lbHatch = 0;
    lb.lbStyle = BS_SOLID;
    DWORD iStyle = PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_SQUARE | PS_JOIN_MITER;
    m_hPenUnder[0] = ExtCreatePen(iStyle, 3, &lb, 0, NULL);
    lb.lbColor = RGB(225, 127, 39);
    m_hPenUnder[1] = ExtCreatePen(iStyle, 2, &lb, 0, NULL);
    lb.lbColor = RGB(223, 226, 230);
    m_hPenUnderWnd = ExtCreatePen(iStyle, 1, &lb, 0, NULL);
    m_nCurSel = 0;
    m_nItemHeight = 36;
    m_bShowHightLine = FALSE;
}
CHmVerticalTab::~CHmVerticalTab()
{
    if (m_hPenUnder[0] != nullptr) {
        ::DeleteObject(m_hPenUnder[0]);
    }
    if (m_hPenUnder[1] != nullptr) {
        ::DeleteObject(m_hPenUnder[1]);
    }
    if (m_hPenUnderWnd != nullptr) {
        ::DeleteObject(m_hPenUnderWnd);
    }
}
BOOL CHmVerticalTab::RegisterWndClass()
{
    WNDCLASS wc;
    wc.lpszClassName = HMVERTICALTAB_CLASS;
    wc.hInstance = AfxGetInstanceHandle();
    wc.lpfnWndProc = WindowProc;
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = 0;
    wc.lpszMenuName = NULL;
    wc.hbrBackground = NULL;
    wc.style = CS_GLOBALCLASS|CS_DBLCLKS;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    // æ³¨å†Œè‡ªå®šä¹‰ç±»
    return (::RegisterClass(&wc) != 0);
}
CHmVerticalTab* CHmVerticalTab::Hook(HWND hWnd)
{
    CHmVerticalTab* pHmTab = (CHmVerticalTab*)GetProp(hWnd, TAG_HMVERTICALTAB);
    if(pHmTab == NULL)
    {
        pHmTab = new CHmVerticalTab();
        pHmTab->m_hWnd = hWnd;
        SetProp(hWnd, TAG_HMVERTICALTAB, (HANDLE)pHmTab);
    }
    return pHmTab;
}
void CHmVerticalTab::Release()
{
    ::DeleteObject(m_hbrItemBkgnd[0]);
    ::DeleteObject(m_hbrItemBkgnd[1]);
    // delete
    delete this;
}
void CHmVerticalTab::SetPaddingTop(int value)
{
    m_nPaddingTop = value;
}
void CHmVerticalTab::SetItemMarginTop(int value)
{
    m_nItemMarginTop = value;
}
void CHmVerticalTab::SetTextColor(COLORREF color1, COLORREF color2)
{
    m_crText[0] = color1;
    m_crText[1] = color2;
    InvalidateRect(m_hWnd, NULL, TRUE);
}
void CHmVerticalTab::SetItemBkgndColor(COLORREF color1, COLORREF color2)
{
    m_crItemBkgnd[0] = color1;
    m_crItemBkgnd[1] = color2;
    ::DeleteObject(m_hbrItemBkgnd[0]);
    ::DeleteObject(m_hbrItemBkgnd[1]);
    m_hbrItemBkgnd[0] = CreateSolidBrush(m_crItemBkgnd[0]);
    m_hbrItemBkgnd[1] = CreateSolidBrush(m_crItemBkgnd[1]);
    InvalidateRect(m_hWnd, NULL, TRUE);
}
void CHmVerticalTab::SetHightLineVisible(BOOL bVisible)
{
    m_bShowHightLine = bVisible;
}
int CHmVerticalTab::AddItem(const char* pszText, void* pContext/* = nullptr*/, BOOL bUpdate/* = TRUE*/)
{
    HMVERTICALTABITEM item;
    memset(&item, 0, sizeof(HMVERTICALTABITEM));
    strcpy_s(item.szText, HMVERTICALTAB_ITEM_TEXT_MAX, pszText);
    item.context = pContext;
    m_items.push_back(item);
    if (bUpdate) {
        InvalidateRect(m_hWnd, NULL, TRUE);
    }
    return 0;
}
int CHmVerticalTab::DeleteItem(const char* pszText, BOOL bUpdate/* = TRUE*/)
{
    for (auto iter = m_items.begin(); iter != m_items.end(); iter++) {
        if (strcmp((*iter).szText, pszText) == 0) {
            m_items.erase(iter);
            break;
        }
    }
    if (bUpdate) {
        InvalidateRect(m_hWnd, NULL, TRUE);
    }
    return 0;
}
void* CHmVerticalTab::GetContext(unsigned int index)
{
    if (index >= m_items.size()) return nullptr;
    auto& item = m_items.at(index);
    return item.context;
}
void CHmVerticalTab::Notify(int nCode, DWORD_PTR dwData, DWORD_PTR dwData1/* = 0*/, DWORD_PTR dwData2/* = 0*/)
{
    HWND hParent;
    hParent = GetParent(m_hWnd);
    if (hParent != NULL) {
        HMVERTICALTAB_NMHDR tab_nmhdr;
        tab_nmhdr.nmhdr.hwndFrom = m_hWnd;
        tab_nmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
        tab_nmhdr.nmhdr.code = nCode;
        tab_nmhdr.dwData = dwData;
        tab_nmhdr.dwData1 = dwData1;
        tab_nmhdr.dwData2 = dwData2;
        SendMessage(hParent, WM_NOTIFY, (WPARAM)tab_nmhdr.nmhdr.idFrom, (LPARAM)&tab_nmhdr);
    }
}
////////////////////////////////
// æ‹¦æˆªçª—口消息函数
LRESULT CALLBACK CHmVerticalTab::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CHmVerticalTab* pHmTab = (CHmVerticalTab *)GetProp(hWnd, TAG_HMVERTICALTAB);
    if(pHmTab == NULL && uMsg != WM_NCCREATE)
    {
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    // å¦‚æžœHook则响应消息
    ASSERT(hWnd);
    switch(uMsg)
    {
    case WM_NCCREATE:
        return OnNcCreate(hWnd, wParam, lParam);
    case WM_DESTROY:
        return pHmTab->OnDestroy(wParam, lParam);
    case WM_PAINT:
        return pHmTab->OnPaint(wParam, lParam);
    case WM_TIMER:
        return pHmTab->OnTimer(wParam, lParam);
    case WM_MOUSEMOVE:
        return pHmTab->OnMouseMove(wParam, lParam);
    case WM_LBUTTONDOWN:
        return pHmTab->OnLButtonDown(wParam, lParam);
    case WM_SETCURSOR:
        return pHmTab->OnSetCursor(wParam, lParam);
    case WM_SIZE:
        return pHmTab->OnSize(wParam, lParam);
    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS;
    default:
        break;
    }
    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
///////////////////////////////
// WM_NCCREATE
// çª—口创建前的初始化工作
LRESULT CHmVerticalTab::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    CHmVerticalTab* pHmTab = (CHmVerticalTab *)GetProp(hWnd, TAG_HMVERTICALTAB);
    ASSERT(pHmTab == NULL);
    Hook(hWnd);
    return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
}
///////////////////////////////
// WM_DESTROY
LRESULT CHmVerticalTab::OnDestroy(WPARAM wParam, LPARAM lParam)
{
    Release();
    return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
}
///////////////////////////////
// WM_TIMER
LRESULT CHmVerticalTab::OnTimer(WPARAM wParam, LPARAM lParam)
{
    if (wParam == 1) {
        POINT pt;
        GetCursorPos(&pt);
        ::ScreenToClient(m_hWnd, &pt);
        HMVERTICALTABITEM* pLastHighItem = m_pHighItem;
        HighTest(pt, m_pHighItem, nullptr);
        if (m_pHighItem != pLastHighItem) {
            ::InvalidateRect(m_hWnd, NULL, TRUE);
        }
        if (m_pHighItem == nullptr) {
            ::KillTimer(m_hWnd, 1);
        }
    }
    return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
}
///////////////////////////////
// WM_MOUSEMOVE
LRESULT CHmVerticalTab::OnMouseMove(WPARAM wParam, LPARAM lParam)
{
    POINT pt;
    pt.x = LOWORD(lParam);
    pt.y = HIWORD(lParam);
    HMVERTICALTABITEM* pLastHighItem = m_pHighItem;
    int nHitCode = HighTest(pt, m_pHighItem, nullptr);
    if (m_pHighItem != pLastHighItem) {
        RECT rcClient;
        GetClientRect(m_hWnd, &rcClient);
        ::InvalidateRect(m_hWnd, &rcClient, TRUE);
    }
    if (m_pHighItem != NULL) {
        ::KillTimer(m_hWnd, 1);
        ::SetTimer(m_hWnd, 1, 100, NULL);
    }
    ::SetProp(m_hWnd, HMTAB_HITCODETEST, (HANDLE)(__int64)nHitCode);
    return ::DefWindowProc(m_hWnd, WM_MOUSEMOVE, wParam, lParam);
}
/*
 * WM_LBUTTONDOWN
 * é¼ æ ‡å·¦é”®æŒ‰ä¸‹
 */
LRESULT CHmVerticalTab::OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
    POINT pt, ptNew;
    pt.x = LOWORD(lParam);
    pt.y = HIWORD(lParam);
    BOOL bButtonUp = FALSE;
    int nClickIndex = -1;
    HighTest(pt, m_pPressItem, &nClickIndex);
    if (m_pPressItem != NULL) {
        m_pHighItem = NULL;
        ::InvalidateRect(m_hWnd, NULL, TRUE);
    }
    // æ•捉鼠标消息,检测是否拖动
    HMVERTICALTABITEM* pPressItem = NULL;
    if (m_pPressItem != NULL) {
        ::KillTimer(m_hWnd, 1);
        if (::GetCapture() == NULL) {
            SetCapture(m_hWnd);
            ASSERT(m_hWnd == GetCapture());
            AfxLockTempMaps();
            for (;;)
            {
                MSG msg;
                VERIFY(::GetMessage(&msg, NULL, 0, 0));
                if (GetCapture() != m_hWnd) break;
                switch (msg.message)
                {
                case WM_MOUSEMOVE:
                    ptNew = msg.pt;
                    ::ScreenToClient(m_hWnd, &ptNew);
                    HighTest(ptNew, pPressItem, &nClickIndex);
                    if (pPressItem != m_pPressItem) {
                        m_pPressItem = nullptr;
                        ::InvalidateRect(m_hWnd, NULL, TRUE);
                    }
                    break;
                case WM_LBUTTONUP:
                    ptNew = msg.pt;
                    ::ScreenToClient(m_hWnd, &ptNew);
                    HighTest(ptNew, pPressItem, &nClickIndex);
                    if (m_pPressItem != nullptr && pPressItem == m_pPressItem) {
                        m_nCurSel = nClickIndex;
                        bButtonUp = TRUE;
                    }
                    goto ExitLoop;
                case WM_KEYDOWN:
                    if (msg.wParam == VK_ESCAPE) {
                        goto ExitLoop;
                    }
                    break;
                default:
                    DispatchMessage(&msg);
                    break;
                }
            }
        ExitLoop:
            m_pPressItem = NULL;
            ReleaseCapture();
            ::InvalidateRect(m_hWnd, NULL, TRUE);
            if (bButtonUp) {
                Notify((int)HMVERTICALTAB_SEL_CHANGED, m_nCurSel);
            }
            AfxUnlockTempMaps(FALSE);
        }
    }
    return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
}
///////////////////////////////
// WM_SETCURSOR
LRESULT CHmVerticalTab::OnSetCursor(WPARAM wParam, LPARAM lParam)
{
    int nHitCode = (int)(__int64)GetProp(m_hWnd, HMTAB_HITCODETEST);
    switch (nHitCode)
    {
    case HMTAB_HT_NOWHERE:
    case HMTAB_HT_ITEM:
        SetCursor(::LoadCursor(NULL, IDC_ARROW));
        return TRUE;
    case HMTAB_HT_HIGT_ITEM:
        SetCursor(::LoadCursor(NULL, IDC_HAND));
        return TRUE;
    default:
        break;
    }
    return ::DefWindowProc(m_hWnd, WM_SETCURSOR, wParam, lParam);
}
/*
 * WM_SIZE
 */
LRESULT CHmVerticalTab::OnSize(WPARAM wParam, LPARAM lParam)
{
    ::InvalidateRect(m_hWnd, NULL, TRUE);
    return ::DefWindowProc(m_hWnd, WM_SIZE, wParam, lParam);
}
///////////////////////////////
// WM_PAINT
LRESULT CHmVerticalTab::OnPaint(WPARAM wParam, LPARAM lParam)
{
    HDC hDC, hMemDC;
    HBITMAP hBitmap;
    RECT rcClient;
    CString strText;
    HFONT hFont1, hFont2;
    HBRUSH hBrushBK;
    // BeginPaint
    PAINTSTRUCT ps;
    hDC = BeginPaint(m_hWnd, &ps);
    GetClientRect(m_hWnd, &rcClient);
    hMemDC = ::CreateCompatibleDC(hDC);
    hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left,
        rcClient.bottom - rcClient.top);
    ::SelectObject(hMemDC, hBitmap);
    ::SetBkMode(hMemDC, TRANSPARENT);
    HFONT hFontDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    CFont* pFont = CFont::FromHandle(hFontDefault);
    LOGFONT lf;
    pFont->GetLogFont(&lf);
    hFont1 = ::CreateFontIndirect(&lf);
    lf.lfWeight = FW_BOLD;
    hFont2 = ::CreateFontIndirect(&lf);
    // èƒŒæ™¯é¢œè‰²
    hBrushBK = CreateSolidBrush(m_crBkgnd);
    ::FillRect(hMemDC, &rcClient, hBrushBK);
    DeleteObject(hBrushBK);
    SelectObject(hMemDC, m_hPenUnderWnd);
    ::MoveToEx(hMemDC, rcClient.left, rcClient.bottom - 2, NULL);
    ::LineTo(hMemDC, rcClient.right, rcClient.bottom - 2);
    // ç»˜åˆ¶å­é¡¹
    SIZE sizeItem;
    RECT rcItem, rcText;
    rcItem.left = rcClient.left;
    rcItem.right = rcClient.right-1;
    rcItem.top = m_nPaddingTop;
    int index = 0;
    for (int i = 0; i < m_items.size(); i++) {
        auto& item = m_items.at(i);
        ::SelectObject(hMemDC, i == m_nCurSel ? hFont2 : hFont1);
        ::SetTextColor(hMemDC, i == m_nCurSel ? m_crText[1] : m_crText[0]);
        ::GetTextExtentPoint32(hMemDC, item.szText, (int)strlen(item.szText), &sizeItem);
        rcItem.top += m_nItemMarginTop;
        rcItem.bottom = rcItem.top + m_nItemHeight;
        if (i == m_nCurSel) {
            ::FillRect(hMemDC, &rcItem, m_hbrItemBkgnd[0]);
        }
        else if(&item == m_pHighItem) {
            ::FillRect(hMemDC, &rcItem, m_hbrItemBkgnd[1]);
        }
        ::CopyRect(&rcText, &rcItem);
        ::DrawText(hMemDC, item.szText, (int)strlen(item.szText), &rcText,
            DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
        ::CopyRect(&item.rect, &rcItem);
        // å³ä¾§é«˜äº®åˆ’线?
        if (m_bShowHightLine && (i == m_nCurSel || &item == m_pHighItem)) {
            HPEN hOldPen = (HPEN)::SelectObject(hMemDC, i == m_nCurSel ? m_hPenUnder[0] : m_hPenUnder[1]);
            ::MoveToEx(hMemDC, item.rect.right - 3, item.rect.top, NULL);
            ::LineTo(hMemDC, item.rect.right - 3, item.rect.bottom);
            ::SelectObject(hMemDC, hOldPen);
        }
        index++;
        rcItem.top = rcItem.bottom;
    }
    ::DeleteObject(hFont1);
    ::DeleteObject(hFont2);
    // ä¾§è¾¹çº¿
    HPEN hPen = CreatePen(PS_SOLID, 1, RGB(202, 204, 211));
    HPEN hOldPen = (HPEN)::SelectObject(hMemDC, hPen);
    ::MoveToEx(hMemDC, rcClient.right - 1, 0, NULL);
    ::LineTo(hMemDC, rcClient.right - 1, rcClient.bottom - 1);
    ::SelectObject(hMemDC, hOldPen);
    // EndPaint
    ::BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
        hMemDC, 0, 0, SRCCOPY);
    EndPaint(m_hWnd, &ps);
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
    return 1;
}
void CHmVerticalTab::SetBkgndColor(COLORREF cr)
{
    m_crBkgnd = cr;
}
/*
 * æ£€æµ‹åæ ‡ç‚¹æ‰€åœ¨çš„项
 * è¿”回, TYGTLITEM
 */
int CHmVerticalTab::HighTest(POINT pt, OUT HMVERTICALTABITEM*& pItem, int* pnIndex)
{
    // æ£€æµ‹æ˜¯å¦åœ¨æŸä¸ªå­é¡¹
    int nRet = HMTAB_HT_NOWHERE;
    pItem = NULL;
    for (int i = 0; i < m_items.size(); i++) {
        auto& item = m_items.at(i);
        if (::PtInRect(&item.rect, pt)) {
            pItem = &item;
            nRet = pItem == m_pHighItem ? HMTAB_HT_HIGT_ITEM : HMTAB_HT_ITEM;
            if (pnIndex != nullptr) *pnIndex = i;
            break;
        }
    }
    return nRet;
}
int CHmVerticalTab::GetCurSel()
{
    return m_nCurSel;
}
void CHmVerticalTab::SetCurSel(int index)
{
    if (0 <= index && index <= m_items.size()) {
        m_nCurSel = index;
        InvalidateRect(m_hWnd, NULL, TRUE);
    }
}
int CHmVerticalTab::GetItemCount()
{
    return (int)m_items.size();
}
SourceCode/Bond/BondEq/HmVerticalTab.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,136 @@
// HmVerticalTab.h: interface for the CHmTab class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_HMVERTICALTAB_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)
#define AFX_HMVERTICALTAB_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_
#pragma comment(lib, "Msimg32.lib")            // TransparentBlt
#include <vector>
//====== HmTab =====================================================
#ifndef NOHMVERTICALTAB
#ifdef _WIN32
#define HMVERTICALTAB_CLASSA       "HmVerticalTab"
#define HMVERTICALTAB_CLASSW       L"HmVerticalTab"
#ifdef UNICODE
#define  HMVERTICALTAB_CLASS       HMVERTICALTAB_CLASSW
#else
#define  HMVERTICALTAB_CLASS       HMVERTICALTAB_CLASSA
#endif
#else
#define HMVERTICALTAB_CLASS        "HmVerticalTab"
#endif
#define TAG_HMVERTICALTAB         _T("IsHmVerticalTab")
//====== WM_NOTIFY codes (NMHDR.code values) ==================================
#define HMVERTICALTAB_FIRST            (0U-3370U)       //
#define HMVERTICALTAB_LAST            (0U-3350U)
#define HMVERTICALTAB_SEL_CHANGED    (HMVERTICALTAB_FIRST - 1)
typedef struct tagHMVERTICALTAB_NMHDR
{
    NMHDR        nmhdr;
    DWORD_PTR    dwData;
    DWORD_PTR    dwData1;
    DWORD_PTR    dwData2;
} HMVERTICALTAB_NMHDR;
#define HMVERTICALTAB_ITEM_TEXT_MAX        64
typedef struct tagHMVERTICALTABITEM
{
    int id;
    char szText[HMVERTICALTAB_ITEM_TEXT_MAX];
    RECT rect;
    void* context;
} HMVERTICALTABITEM;
#define HMTAB_HITCODETEST            _T("HitCode")
#define HMTAB_HT_NOWHERE            0x1
#define HMTAB_HT_ITEM                0x2
#define HMTAB_HT_HIGT_ITEM            0x4
#endif
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CHmVerticalTab
{
public:
    CHmVerticalTab();
    virtual ~CHmVerticalTab();
public:
    static BOOL RegisterWndClass();
    static CHmVerticalTab* Hook(HWND hWnd);
    void Notify(int nCode, DWORD_PTR dwData, DWORD_PTR dwData1 = 0, DWORD_PTR dwData2 = 0);
    void Release();
    void SetBkgndColor(COLORREF cr);
    static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    static LRESULT OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
    LRESULT OnDestroy(WPARAM wParam, LPARAM lParam);
    LRESULT OnTimer(WPARAM wParam, LPARAM lParam);
    LRESULT OnPaint(WPARAM wParam, LPARAM lParam);
    LRESULT OnSetCursor(WPARAM wParam, LPARAM lParam);
    LRESULT OnSize(WPARAM wParam, LPARAM lParam);
    LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam);
    LRESULT OnMouseMove(WPARAM wParam, LPARAM lParam);
public:
    void SetPaddingTop(int value);
    void SetItemMarginTop(int value);
    void SetTextColor(COLORREF color1, COLORREF color2);
    void SetItemBkgndColor(COLORREF color1, COLORREF color2);
    void SetHightLineVisible(BOOL bVisible);
    int AddItem(const char* pszText, void* pContext = nullptr, BOOL bUpdate = TRUE);
    int DeleteItem(const char* pszText, BOOL bUpdate = TRUE);
    void* GetContext(unsigned int index);
    int HighTest(POINT pt, OUT HMVERTICALTABITEM*& pItem, int* pnIndex);
    int GetCurSel();
    void SetCurSel(int index);
    int GetItemCount();
private:
    HWND        m_hWnd;
    COLORREF m_crBkgnd;
private:
    int m_nCurSel;
    int m_nItemHeight;
    std::vector< HMVERTICALTABITEM > m_items;
    HMVERTICALTABITEM* m_pHighItem;
    HMVERTICALTABITEM* m_pPressItem;
    int m_nPaddingTop;
    int m_nItemMarginTop;
    COLORREF m_crText[2];
    COLORREF m_crItemBkgnd[2];        // å­é¡¹èƒŒæ™¯è‰²ï¼Œ0:选中,1:高亮
    HBRUSH m_hbrItemBkgnd[2];        // ä¸Šè¿°ä¸¤é¡¹é¢„创建
    HPEN m_hPenUnder[2];
    HPEN m_hPenUnderWnd;
    BOOL m_bShowHightLine;
};
#endif // !defined(AFX_HMVERTICALTAB_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)
SourceCode/Bond/BondEq/HorizontalLine.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,203 @@
// HorizontalLine.cpp: implementation of the CHorizontalLine class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HorizontalLine.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CHorizontalLine::CHorizontalLine()
{
    m_hWnd = NULL;
    m_crBkgnd = RGB(255, 255, 255);
    m_crLineColor = RGB(222, 222, 222);
}
CHorizontalLine::~CHorizontalLine()
{
}
BOOL CHorizontalLine::RegisterWndClass()
{
    WNDCLASS wc;
    wc.lpszClassName = BYHORIZONTALLINE_CLASS;
    wc.hInstance = AfxGetInstanceHandle();
    wc.lpfnWndProc = WindowProc;
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = 0;
    wc.lpszMenuName = NULL;
    wc.hbrBackground = NULL;
    wc.style = CS_GLOBALCLASS|CS_DBLCLKS;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    // æ³¨å†Œè‡ªå®šä¹‰ç±»
    return (::RegisterClass(&wc) != 0);
}
CHorizontalLine* CHorizontalLine::Hook(HWND hWnd)
{
    CHorizontalLine* pHorizontalLine = (CHorizontalLine*)GetProp(hWnd, BYSTAG_HORIZONTALLINE);
    if(pHorizontalLine == NULL)
    {
        pHorizontalLine = new CHorizontalLine;
        pHorizontalLine->m_hWnd = hWnd;
        SetProp(hWnd, BYSTAG_HORIZONTALLINE, (HANDLE)pHorizontalLine);
    }
    return pHorizontalLine;
}
void CHorizontalLine::Release()
{
    // delete
    delete this;
}
void CHorizontalLine::Notify(int nCode, int dwData, int dwData1/* = 0*/, int dwData2/* = 0*/)
{
    HWND hParent;
    hParent = GetParent(m_hWnd);
    if(hParent != NULL) {
        BYHORIZONTALLINE_NMHDR iii_nmhdr;
        iii_nmhdr.nmhdr.hwndFrom = m_hWnd;
        iii_nmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
        iii_nmhdr.nmhdr.code = nCode;
        iii_nmhdr.dwData = dwData;
        iii_nmhdr.dwData1 = dwData1;
        iii_nmhdr.dwData2 = dwData2;
        SendMessage(hParent, WM_NOTIFY, (WPARAM)iii_nmhdr.nmhdr.idFrom, (LPARAM)&iii_nmhdr);
    }
}
////////////////////////////////
// æ‹¦æˆªçª—口消息函数
LRESULT CALLBACK CHorizontalLine::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CHorizontalLine* pHorizontalLine = (CHorizontalLine *)GetProp(hWnd, BYSTAG_HORIZONTALLINE);
    if(pHorizontalLine == NULL && uMsg != WM_NCCREATE)
    {
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    // å¦‚æžœHook则响应消息
    ASSERT(hWnd);
    switch(uMsg)
    {
    case WM_NCCREATE:
        return OnNcCreate(hWnd, wParam, lParam);
    case WM_DESTROY:
        return pHorizontalLine->OnDestroy(wParam, lParam);
    case WM_PAINT:
        return pHorizontalLine->OnPaint(wParam, lParam);
    case WM_TIMER:
        return pHorizontalLine->OnTimer(wParam, lParam);
    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS;
    default:
        break;
    }
    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
///////////////////////////////
// WM_NCCREATE
// çª—口创建前的初始化工作
LRESULT CHorizontalLine::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    CHorizontalLine* pHorizontalLine = (CHorizontalLine *)GetProp(hWnd, BYSTAG_HORIZONTALLINE);
    ASSERT(pHorizontalLine == NULL);
    Hook(hWnd);
    return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
}
///////////////////////////////
// WM_DESTROY
LRESULT CHorizontalLine::OnDestroy(WPARAM wParam, LPARAM lParam)
{
    Release();
    return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
}
///////////////////////////////
// WM_TIMER
LRESULT CHorizontalLine::OnTimer(WPARAM wParam, LPARAM lParam)
{
    return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
}
///////////////////////////////
// WM_PAINT
LRESULT CHorizontalLine::OnPaint(WPARAM wParam, LPARAM lParam)
{
    HDC hDC, hMemDC;
    HBITMAP hBitmap;
    RECT rcClient;
    CString strText;
    HFONT hFont;
    HBRUSH hBrushBK;
    // BeginPaint
    PAINTSTRUCT ps;
    hDC = BeginPaint(m_hWnd, &ps);
    GetClientRect(m_hWnd, &rcClient);
    hMemDC = ::CreateCompatibleDC(hDC);
    hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right-rcClient.left,
        rcClient.bottom-rcClient.top);
    ::SelectObject(hMemDC, hBitmap);
    hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    ::SelectObject(hMemDC, hFont);
    // èƒŒæ™¯é¢œè‰²
    hBrushBK = CreateSolidBrush( m_crBkgnd );
    ::FillRect(hMemDC, &rcClient, hBrushBK);
    DeleteObject(hBrushBK);
    // ç”»çº¿
    HPEN hPen = CreatePen(PS_SOLID, 1, m_crLineColor);
    HPEN hOldPen = (HPEN)::SelectObject(hMemDC, hPen);
    ::MoveToEx(hMemDC, 0, 0, NULL);
    LineTo(hMemDC, rcClient.right, 0);
    ::SelectObject(hMemDC, hOldPen);
    // EndPaint
    ::BitBlt(hDC, 0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
        hMemDC, 0, 0, SRCCOPY);
    EndPaint(m_hWnd, &ps);
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
    return 1;
}
void CHorizontalLine::SetBkgndColor(COLORREF cr)
{
    m_crBkgnd = cr;
}
SourceCode/Bond/BondEq/HorizontalLine.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,86 @@
// HorizontalLine.h: interface for the CHorizontalLine class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_HORIZONTALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)
#define AFX_HORIZONTALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_
#pragma comment(lib, "Msimg32.lib")            // TransparentBlt
//====== HorizontalLine =====================================================
#ifndef NOHORIZONTALLINE
#ifdef _WIN32
#define BYHORIZONTALLINE_CLASSA       "BYHorizontalLine"
#define BYHORIZONTALLINE_CLASSW       L"BYHorizontalLine"
#ifdef UNICODE
#define  BYHORIZONTALLINE_CLASS       BYHORIZONTALLINE_CLASSW
#else
#define  BYHORIZONTALLINE_CLASS       BYHORIZONTALLINE_CLASSA
#endif
#else
#define BYHORIZONTALLINE_CLASS        "BYHorizontalLine"
#endif
#define BYSTAG_HORIZONTALLINE         _T("ISHORIZONTALLINE")
//====== WM_NOTIFY codes (NMHDR.code values) ==================================
#define BYHORIZONTALLINE_FIRST                 (0U-590U)       //
#define BYHORIZONTALLINE_LAST                 (0U-550U)
#define BYHORIZONTALLINE_                      (BYHORIZONTALLINE_FIRST - 1)
typedef struct tagBYHORIZONTALLINE_NMHDR
{
    NMHDR        nmhdr;
    DWORD        dwData;
    DWORD        dwData1;
    DWORD        dwData2;
} BYHORIZONTALLINE_NMHDR;
#endif
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CHorizontalLine
{
public:
    CHorizontalLine();
    virtual ~CHorizontalLine();
public:
    static BOOL RegisterWndClass();
    static CHorizontalLine* Hook(HWND hWnd);
    void Notify(int nCode, int dwData, int dwData1 = 0, int dwData2 = 0);
    void Release();
    void SetBkgndColor(COLORREF cr);
    static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    static LRESULT OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
    LRESULT OnDestroy(WPARAM wParam, LPARAM lParam);
    LRESULT OnTimer(WPARAM wParam, LPARAM lParam);
    LRESULT OnPaint(WPARAM wParam, LPARAM lParam);
private:
    HWND        m_hWnd;
    COLORREF m_crBkgnd;
    COLORREF m_crLineColor;
};
#endif // !defined(AFX_HORIZONTALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)
SourceCode/Bond/BondEq/Log.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,214 @@
#include "stdafx.h"
#include "Log.h"
static const char* pszLevel[] = {" [Debug] ", " [Info] ", " [Warn] ", " [Error] "};
CLog::CLog()
{
    m_nLevel = 0;
    m_nOutputTarget = OT_TRACE;
    m_bAutoAppendTime = TRUE;
    m_strEquipmentId = _T("Unknown");
    m_nDay = 0;
    m_funOnLog = nullptr;
    InitializeCriticalSection(&m_criticalSection);
}
CLog::~CLog()
{
    DeleteCriticalSection(&m_criticalSection);
}
CLog *CLog::GetLog(void)
{
    static CLog* pLog = NULL;
    if (pLog == NULL) {
        static CLog log;
        pLog = &log;
    }
    return pLog;
}
void CLog::SetOnLogCallback(ONLOG funOnLog)
{
    m_funOnLog = funOnLog;
}
void CLog::SetOutputTarget(int flag)
{
    m_nOutputTarget = flag;
}
void CLog::SetEquipmentId(const char* pszEquipmentId)
{
    m_strEquipmentId = pszEquipmentId;
}
void CLog::SetAutoAppendTimeString(BOOL bAutoAppendTime)
{
    m_bAutoAppendTime = bAutoAppendTime;
}
void CLog::Batch()
{
    if (m_file.m_hFile != CFile::hFileNull) {
        m_file.Close();
    }
}
BOOL CLog::BatchAndNew(int& nDay)
{
    Batch();
    if ( (m_nOutputTarget & OT_FILE) && m_file.m_hFile == CFile::hFileNull) {
        CString strFilepath;
        BOOL bRet = m_file.Open(MakeFilepathD(strFilepath, nDay), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::shareDenyWrite);
        if (bRet) {
            m_file.SeekToEnd();
        }
        return bRet;
    }
    return FALSE;
}
#define BUFFERSIZE        1024*10
void CLog::LogFormat(int nLevel, const char* pszTag, char* szMessage, ...)
{
    // æ£€æŸ¥æ—¥æœŸæ˜¯å¦æœ‰å˜åŒ–,有变化则结批
    Lock();
    _SYSTEMTIME sysTime;
    GetLocalTime(&sysTime);
    if(m_nDay != sysTime.wDay) {
        int nDay = 0;
        if (BatchAndNew(nDay)) {
            m_nDay = nDay;
        }
    }
    Unlock();
    if (nLevel < m_nLevel) {
        return;
    }
    char szFullMessage[BUFFERSIZE];
    char szFormatMessage[BUFFERSIZE];
    // format message
    va_list ap;
    va_start(ap, szMessage);
    _vsnprintf_s(szFormatMessage, BUFFERSIZE, szMessage, ap);
    va_end(ap);
    if (m_bAutoAppendTime) {
        CString strTime;
        strcpy_s(szFullMessage, BUFFERSIZE, (LPTSTR)(LPCTSTR)GetCurTime(strTime));
    }
    strcat_s(szFullMessage, BUFFERSIZE, pszLevel[nLevel]);
    strcat_s(szFullMessage, szFormatMessage);
    strcat_s(szFullMessage, BUFFERSIZE, "\n");
    if (m_nOutputTarget & OT_FILE) {
        Lock();
        if (m_file.m_hFile != CFile::hFileNull) {
            m_file.WriteString(szFullMessage);
        }
        Unlock();
    }
    if (m_nOutputTarget & OT_ODSTRING) {
        OutputDebugStringA(szFullMessage);
    }
    else if(m_nOutputTarget & OT_TRACE) {
        TRACE(szFormatMessage);
    }
    if (m_funOnLog != nullptr) {
        m_funOnLog(nLevel, szFullMessage);
    }
}
void CLog::Log(int nLevel, const char* pszTag, const char* szMessage)
{
    // æ£€æŸ¥æ—¥æœŸæ˜¯å¦æœ‰å˜åŒ–,有变化则结批
    Lock();
    _SYSTEMTIME sysTime;
    GetLocalTime(&sysTime);
    if (m_nDay != sysTime.wDay) {
        int nDay = 0;
        if (BatchAndNew(nDay)) {
            m_nDay = nDay;
        }
    }
    Unlock();
    if (nLevel < m_nLevel) {
        return;
    }
    CString strMsg;
    if (m_bAutoAppendTime) {
        CString strTime;
        GetCurTime(strTime);
        strMsg.Append(strTime);
    }
    strMsg.Append(pszTag);
    strMsg.Append(szMessage);
    strMsg.Append("\n");
    if (m_nOutputTarget & OT_FILE) {
        Lock();
        if (m_file.m_hFile != CFile::hFileNull) {
            m_file.WriteString(strMsg);
        }
        Unlock();
    }
    if (m_nOutputTarget & OT_ODSTRING) {
        OutputDebugStringA(strMsg);
    }
    else if (m_nOutputTarget & OT_TRACE) {
        TRACE(strMsg);
    }
    if (m_funOnLog != nullptr) {
        m_funOnLog(nLevel, strMsg);
    }
}
CString& CLog::GetCurTime(CString& strTime)
{
    _SYSTEMTIME sysTime;
    GetLocalTime(&sysTime);
    strTime.Format(_T("%d/%02d/%02d %02d:%02d:%02d.%03d"), sysTime.wYear, sysTime.wMonth, sysTime.wDay,
        sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds);
    return strTime;
}
CString& CLog::MakeFilepath(CString& strFilepath)
{
    _SYSTEMTIME sysTime;
    GetLocalTime(&sysTime);
    strFilepath.Format(_T("%s\\Log(%s)_%d_%02d_%02d.log"), (LPTSTR)(LPCTSTR)m_strLogsDir,
        (LPTSTR)(LPCTSTR)m_strEquipmentId,
        sysTime.wYear, sysTime.wMonth, sysTime.wDay);
    return strFilepath;
}
CString& CLog::MakeFilepathD(CString& strFilepath, int& day)
{
    _SYSTEMTIME sysTime;
    GetLocalTime(&sysTime);
    strFilepath.Format(_T("%s\\Log(%s)_%d_%02d_%02d.log"), (LPTSTR)(LPCTSTR)m_strLogsDir,
        (LPTSTR)(LPCTSTR)m_strEquipmentId,
        sysTime.wYear, sysTime.wMonth, sysTime.wDay);
    day = sysTime.wDay;
    return strFilepath;
}
void CLog::SetLogsDir(CString strDir)
{
    m_strLogsDir = strDir;
}
SourceCode/Bond/BondEq/Log.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
#pragma once
#include <functional>
#define LEVEL_DEBUG        0
#define LEVEL_INFO        1
#define LEVEL_WARN        2
#define LEVEL_ERROR        3
#define LOGD(msg, ...)        CLog::GetLog()->LogFormat(LEVEL_DEBUG, "", msg, __VA_ARGS__)
#define LOGI(msg, ...)        CLog::GetLog()->LogFormat(LEVEL_INFO, "", msg, __VA_ARGS__)
#define LOGW(msg, ...)        CLog::GetLog()->LogFormat(LEVEL_WARN, "", msg, __VA_ARGS__)
#define LOGE(msg, ...)        CLog::GetLog()->LogFormat(LEVEL_ERROR, "", msg, __VA_ARGS__)
#define OT_FILE            0x01
#define OT_ODSTRING        0x02
#define OT_TRACE        0x04
#define LOGBATHCH()                CLog::GetLog()->Batch()
#define LOGNEW()                CLog::GetLog()->BatchAndNew()
typedef std::function<void(int level, const char* pszMessage)> ONLOG;
class CLog
{
public:
    CLog();
    ~CLog();
public:
    void SetOnLogCallback(ONLOG funOnLog);
    static CLog *GetLog(void);
    void SetOutputTarget(int flag);
    void SetEquipmentId(const char* pszEquipmentId);
    static CString& GetCurTime(CString& strTime);
    CString& MakeFilepath(CString& strFilepath);
    CString& MakeFilepathD(CString& strFilepath, int& day);
    void LogFormat(int nLevel, const char* pszTag, char* szMessage, ...);
    void Log(int nLevel, const char* pszTag, const char* szMessage);
    void SetAutoAppendTimeString(BOOL bAutoAppendTime);
    void SetLogsDir(CString strDir);
    void Batch();
    BOOL BatchAndNew(int& nDay);
private:
    inline void Lock() { EnterCriticalSection(&m_criticalSection); }
    inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
private:
    ONLOG m_funOnLog;
    int m_nOutputTarget;
    int m_nLevel;
    BOOL m_bAutoAppendTime;
    CString m_strLogsDir;
    CString m_strEquipmentId;
    CStdioFile m_file;
    int m_nDay;                        // æŒ‰æ—¥ä¿å­˜ä¸€æ¡è®°å½•,比较此数字,以决定是否结批并创建新文件
    CRITICAL_SECTION m_criticalSection;
};
SourceCode/Bond/BondEq/LogEdit.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,87 @@
#include "stdafx.h"
#include "LogEdit.h"
#define MENU_ITEM_SEL_ALL        0x666
#define MENU_ITEM_COPY            0x667
#define MENU_ITEM_CLEAR            0x668
CLogEdit::CLogEdit()
{
    m_nMaxLineCount = 0xffff;
}
CLogEdit::~CLogEdit()
{
}
BEGIN_MESSAGE_MAP(CLogEdit, CEdit)
    ON_WM_CONTEXTMENU()
END_MESSAGE_MAP()
void CLogEdit::SetMaxLineCount(int line)
{
    m_nMaxLineCount = line;
}
void CLogEdit::OnContextMenu(CWnd* pWnd, CPoint point)
{
    HMENU hMenu = CreatePopupMenu();
    InsertMenu(hMenu, 0, MF_BYPOSITION, MENU_ITEM_SEL_ALL, "ȫѡ");
    InsertMenu(hMenu, 1, MF_BYPOSITION, MENU_ITEM_COPY, "复制");
    InsertMenu(hMenu, 2, MF_BYPOSITION | MF_SEPARATOR, NULL, NULL);
    InsertMenu(hMenu, 3, MF_BYPOSITION, MENU_ITEM_CLEAR, "全部清除");
    int cmd = ::TrackPopupMenu(hMenu,
        TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
        point.x, point.y + 2, 0, m_hWnd, NULL);
    DestroyMenu(hMenu);
    if (cmd == MENU_ITEM_SEL_ALL) {
        SetFocus();
        this->SetSel(0, -1);
    }
    else if (cmd == MENU_ITEM_COPY) {
        this->Copy();
    }
    else if (cmd == MENU_ITEM_CLEAR) {
        SetWindowText(_T(""));
    }
}
void CLogEdit::AppendText(const char* pszText)
{
    // èŽ·å–é€‰æ‹©èŒƒå›´ä»¥ä¾¿æ¢å¤
    int nStart, nEnd;
    GetSel(nStart, nEnd);
    // è¶…过指定行数则删除最前面的行
    int nLineCount = GetLineCount();
    while (nLineCount > m_nMaxLineCount) {
        int nLin1End = LineIndex(1);
        nStart -= nLin1End;
        if (nStart < 0) nStart = 0;
        nEnd -= nLin1End;
        if (nEnd < 0) nEnd = 0;
        SetSel(0, nLin1End);
        ReplaceSel(_T(""));
        nLineCount = GetLineCount();
    }
    // è¿½åŠ åˆ°æœ€åŽ
    int length = GetWindowTextLength();
    SetSel(length, length);
    ReplaceSel(pszText);
    PostMessage(WM_VSCROLL, SB_BOTTOM, 0);
    // æ¢å¤
    if (nStart == 0 && nEnd == 0) {
        nStart = GetWindowTextLength();
        nEnd = nStart;
    }
    SetSel(nStart, nEnd);
}
SourceCode/Bond/BondEq/LogEdit.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
#pragma once
#include "afxwin.h"
class CLogEdit :
    public CEdit
{
public:
    CLogEdit();
    ~CLogEdit();
public:
    void SetMaxLineCount(int line);
    void AppendText(const char* pszText);
private:
    int m_nMaxLineCount;
    DECLARE_MESSAGE_MAP()
    afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
};
SourceCode/Bond/BondEq/Model.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,357 @@
#include "stdafx.h"
#include "Common.h"
#include "Log.h"
#include "Model.h"
#include "Log.h"
#include "ToolUnits.h"
CModel* g_pModel = NULL;
void CALLBACK ModerTimerProc(HWND hWnd, UINT nMsg, UINT nTimerid, DWORD dwTime)
{
    if (g_pModel != NULL) {
        g_pModel->onTimer(nTimerid);
    }
}
CModel::CModel()
{
    m_pObservableEmitter = nullptr;
    m_pObservable = nullptr;
    m_pServo = nullptr;
    m_pEqBond1 = nullptr;
    m_nTimerID = 0;
}
CModel::~CModel()
{
}
IObservable* CModel::getObservable()
{
    return m_pObservable;
}
void CModel::setWorkDir(const char* pszWorkDir)
{
    m_strWorkDir = pszWorkDir;
}
int CModel::init()
{
    CString strIniFile;
    CString strUnitId;
    strIniFile.Format(_T("%s\\Configuration.ini"), (LPTSTR)(LPCTSTR)m_strWorkDir);
    m_configuration.setFilepath((LPTSTR)(LPCTSTR)strIniFile);
    m_configuration.getUnitId(strUnitId);
    /*
    char szUnitId[256], szDataDir[MAX_PATH];
    char szModeType[256];
    CString strIniFile;
    strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)m_strWorkDir);
    GetPrivateProfileString("Equipment", "UNITID", _T(""), szUnitId, 256, strIniFile);
    GetPrivateProfileString("Equipment", "ModelType", _T("GB2860"), szModeType, 256, strIniFile);
    GetPrivateProfileString("APP", "DataDir", _T(""), szDataDir, MAX_PATH, strIniFile);
    m_strDataDir = szDataDir;
    CToolUnits::createDir(szDataDir);
    */
    // Log
    CString strLogDir;
    strLogDir.Format(_T("%s\\Log"), (LPTSTR)(LPCTSTR)m_strWorkDir);
    ::CreateDirectory(strLogDir, NULL);
    CLog::GetLog()->SetOnLogCallback([&](int level, const char* pszMessage) -> void {
        notifyTextAndInt(RX_CODE_LOG, pszMessage, level);
    });
    CLog::GetLog()->SetAutoAppendTimeString(TRUE);
    CLog::GetLog()->SetOutputTarget(OT_FILE);
    CLog::GetLog()->SetLogsDir(strLogDir);
    CLog::GetLog()->SetEquipmentId((LPTSTR)(LPCTSTR)strUnitId);
    LOGI("\r\n\r\n~~~ Prog Start! ~~~");
    // åˆ›å»ºServo
    BEQ_CreateServo(m_pServo, "BLServo");
    ASSERT(m_pServo);
    BEQ::ServoListener listener;
    listener.onRemoteEqConnecting = [&](void* pServo, void* pRemoteEiuipment) -> void {
        BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment;
        char szBuffer[256];
        p->getName(szBuffer, 256);
        LOGI("<ServoListener>正在连接远程设备(%s)...", szBuffer);
    };
    listener.onRemoteEqConnected = [&](void* pServo, void* pRemoteEiuipment) -> void {
        BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment;
        char szBuffer[256];
        p->getName(szBuffer, 256);
        LOGI("<ServoListener>连接远程设备(%s)成功.", szBuffer);
        notifyPtr(RX_CODE_REMOTEEQ_STATE_CHANGED, pRemoteEiuipment);
    };
    listener.onRemoteEqConnectFailed = [&](void* pServo, void* pRemoteEiuipment, int errorCode) -> void {
        BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment;
        char szBuffer[256];
        p->getName(szBuffer, 256);
        LOGW("<ServoListener>连接远程设备(%s)失败.", szBuffer);
    };
    listener.onRemoteEqDisconnecting = [&](void* pServo, void* pRemoteEiuipment) -> void {
        BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment;
        char szBuffer[256];
        p->getName(szBuffer, 256);
        LOGI("<ServoListener>正在断开远程设备(%s).", szBuffer);
    };
    listener.onRemoteEqDisconnected = [&](void* pServo, void* pRemoteEiuipment) -> void {
        BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment;
        char szBuffer[256];
        p->getName(szBuffer, 256);
        LOGW("<ServoListener>远程设备(%s)连接断开.", szBuffer);
        notifyPtr(RX_CODE_REMOTEEQ_STATE_CHANGED, pRemoteEiuipment);
    };
    listener.onRemoteEqReadRawdata = [&](void* pServo, void* pRemoteEiuipment, const char* pszData, int len) -> void {
        BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment;
        char szBuffer[256];
        p->getName(szBuffer, 256);
        LOGD("<ServoListener>收到远程设备(%s)原始数据(%s).", szBuffer, std::string(pszData, len).c_str());
    };
    listener.onRemoteEqEventUpdate = [&](void* pServo, void* pRemoteEiuipment, void* pUnit, BEQ::REMOTE_EQ_EVENT eventCode) -> void {
        BEQ::IRemoteEquipment* p = (BEQ::IRemoteEquipment*)pRemoteEiuipment;
        char szBuffer[256];
        p->getName(szBuffer, 256);
        LOGD("<ServoListener>远程设备(%s)onRemoteEqEventUpdate.", szBuffer);
    };
    m_pServo->setListener(listener);
    m_pObservable = RX_AllocaObservable([&](IObservableEmitter* e) -> void {
        m_pObservableEmitter = e;            // ä¿å­˜å‘射器
    });
    m_nTimerID = (int)SetTimer(NULL, 1, 1000, (TIMERPROC)ModerTimerProc);
    g_pModel = this;
    return 0;
}
int CModel::createRemoteEqs()
{
    // ä»Žé…ç½®ä¸­è¯»å–远程机器配置
    CString strIp, strIniFile;
    UINT nPort, nDoorCount;
    strIniFile.Format(_T("%s\\Configuration.ini"), (LPTSTR)(LPCTSTR)m_strWorkDir);
    CConfiguration configuration((LPTSTR)(LPCTSTR)strIniFile);
    configuration.getBond1(strIp, nPort, nDoorCount);
    m_pServo->createRemoteEquipment(m_pEqBond1, (LPTSTR)(LPCTSTR)strIp, nPort);
    ASSERT(m_pEqBond1);
    m_pEqBond1->addUnit("UNITA", nDoorCount);
    m_pServo->connectRemoteEquipment(m_pEqBond1);
    return 0;
}
int CModel::term()
{
    CLog::GetLog()->SetOnLogCallback(nullptr);
    return 0;
}
CServo& CModel::getServo()
{
    return m_servo;
}
BEQ::IRemoteEquipment* CModel::getBond1()
{
    return m_pEqBond1;
}
int CModel::notify(int code)
{
    /* code */
    if (m_pObservableEmitter != NULL) {
        IAny* pAny = RX_AllocaAny();
        if (pAny != NULL) {
            pAny->addRef();
            pAny->setCode(code);
            m_pObservableEmitter->onNext(pAny);
            pAny->release();
        }
    }
    return 1;
}
int CModel::notifyPtr(int code, void* ptr/* = NULL*/)
{
    /* code */
    if (m_pObservableEmitter != NULL) {
        IAny* pAny = RX_AllocaAny();
        if (pAny != NULL) {
            pAny->addRef();
            pAny->setCode(code);
            pAny->setPtrValue("ptr", ptr);
            m_pObservableEmitter->onNext(pAny);
            pAny->release();
        }
    }
    return 1;
}
int CModel::notifyObj(int code, IRxObject* pObj)
{
    /* code */
    if (m_pObservableEmitter != NULL) {
        IAny* pAny = RX_AllocaAny();
        if (pAny != NULL) {
            pAny->addRef();
            pAny->setCode(code);
            pAny->setObject("obj", pObj);
            m_pObservableEmitter->onNext(pAny);
            pAny->release();
        }
    }
    return 1;
}
int CModel::notifyObjAndPtr(int code, IRxObject* pObj, void* ptr)
{
    /* code */
    if (m_pObservableEmitter != NULL) {
        IAny* pAny = RX_AllocaAny();
        if (pAny != NULL) {
            pAny->addRef();
            pAny->setCode(code);
            pAny->setObject("obj", pObj);
            pAny->setPtrValue("ptr", ptr);
            m_pObservableEmitter->onNext(pAny);
            pAny->release();
        }
    }
    return 1;
}
int CModel::notifyInt(int code, int exCode)
{
    if (m_pObservableEmitter != NULL) {
        IAny* pAny = RX_AllocaAny();
        if (pAny != NULL) {
            pAny->addRef();
            pAny->setCode(code);
            pAny->setIntValue("exCode", exCode);
            m_pObservableEmitter->onNext(pAny);
            pAny->release();
        }
    }
    return 0;
}
int CModel::notifyObjAndInt(int code, IRxObject* pObj1, IRxObject* pObj2, int exCode)
{
    if (m_pObservableEmitter != NULL) {
        IAny* pAny = RX_AllocaAny();
        if (pAny != NULL) {
            pAny->addRef();
            pAny->setCode(code);
            if (pObj1 != nullptr) pAny->setObject("obj", pObj1);
            if (pObj2 != nullptr) pAny->setObject("obj2", pObj2);
            pAny->setIntValue("exCode", exCode);
            m_pObservableEmitter->onNext(pAny);
            pAny->release();
        }
    }
    return 0;
}
int CModel::notifyText(int code, const char* pszText)
{
    if (m_pObservableEmitter != NULL) {
        IAny* pAny = RX_AllocaAny();
        if (pAny != NULL) {
            pAny->addRef();
            pAny->setCode(code);
            pAny->setStringValue("text", pszText);
            m_pObservableEmitter->onNext(pAny);
            pAny->release();
        }
    }
    return 0;
}
int CModel::notifyTextAndInt(int code, const char* pszText, int exCode)
{
    if (m_pObservableEmitter != NULL) {
        IAny* pAny = RX_AllocaAny();
        if (pAny != NULL) {
            pAny->addRef();
            pAny->setCode(code);
            pAny->setStringValue("text", pszText);
            pAny->setIntValue("exCode", exCode);
            m_pObservableEmitter->onNext(pAny);
            pAny->release();
        }
    }
    return 0;
}
int CModel::notifyPtrAndInt(int code, void* ptr1, void* ptr2, int exCode)
{
    if (m_pObservableEmitter != NULL) {
        IAny* pAny = RX_AllocaAny();
        if (pAny != NULL) {
            pAny->addRef();
            pAny->setCode(code);
            pAny->setPtrValue("ptr", ptr1);
            pAny->setPtrValue("ptr1", ptr1);
            pAny->setPtrValue("ptr2", ptr2);
            pAny->setIntValue("exCode", exCode);
            m_pObservableEmitter->onNext(pAny);
            pAny->release();
        }
    }
    return 0;
}
int CModel::notifyMesMsg(int code, int stream, int function, const char* pszText)
{
    if (m_pObservableEmitter != NULL) {
        IAny* pAny = RX_AllocaAny();
        if (pAny != NULL) {
            pAny->addRef();
            pAny->setCode(code);
            pAny->setIntValue("stream", stream);
            pAny->setIntValue("function", function);
            pAny->setStringValue("text", pszText);
            m_pObservableEmitter->onNext(pAny);
            pAny->release();
        }
    }
    return 0;
}
void CModel::onTimer(UINT nTimerid)
{
    ULONGLONG tick = GetTickCount64();
    int interval = m_configuration.getP2RemoteEqReconnectInterval() * 1000;
    if (m_pEqBond1 != nullptr) {
        if (!m_pEqBond1->isConnected()) {
            if (tick - m_pEqBond1->getConnectTick() > interval) {
                m_pEqBond1->connect();
            }
        }
    }
}
SourceCode/Bond/BondEq/Model.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
#pragma once
#include "Servo.h"
#include "Configuration.h"
class CModel
{
public:
    CModel();
    ~CModel();
public:
    IObservable* getObservable();
    void setWorkDir(const char* pszWorkDir);
    int init();
    int term();
    void onTimer(UINT nTimerid);
    int createRemoteEqs();
    CServo& getServo();
    BEQ::IRemoteEquipment* getBond1();
public:
    int notify(int code);
    int notifyPtr(int code, void* ptr = NULL);
    int notifyObj(int code, IRxObject* pObj);
    int notifyObjAndPtr(int code, IRxObject* pObj, void* ptr);
    int notifyObjAndInt(int code, IRxObject* pObj1, IRxObject* pObj2, int exCode);
    int notifyInt(int code, int exCode);
    int notifyText(int code, const char* pszText);
    int notifyPtrAndInt(int code, void* ptr1, void* ptr2, int exCode);
    int notifyTextAndInt(int code, const char* pszText, int exCode);
    int notifyMesMsg(int code, int stream, int function, const char* pszText);
public:
    CConfiguration m_configuration;
private:
    IObservable* m_pObservable;
    IObservableEmitter* m_pObservableEmitter;
    CString m_strWorkDir;
    CString m_strDataDir;
private:
    CServo m_servo;
    BEQ::IServo* m_pServo;
    BEQ::IRemoteEquipment* m_pEqBond1;
    int m_nTimerID;
};
SourceCode/Bond/BondEq/ReadMe.txt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
================================================================================
    MICROSOFT åŸºç¡€ç±»åº“ : BondServo é¡¹ç›®æ¦‚è¿°
===============================================================================
应用程序向导已为您创建了此 BondServo åº”用程序。此应用程序不仅演示 Microsoft åŸºç¡€ç±»çš„基本使用方法,还可作为您编写应用程序的起点。
本文件概要介绍组成 BondServo åº”用程序的每个文件的内容。
BondServo.vcxproj
    è¿™æ˜¯ä½¿ç”¨åº”用程序向导生成的 VC++ é¡¹ç›®çš„主项目文件,其中包含生成该文件的 Visual C++ çš„版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
BondServo.vcxproj.filters
    è¿™æ˜¯ä½¿ç”¨â€œåº”用程序向导”生成的 VC++ é¡¹ç›®ç­›é€‰å™¨æ–‡ä»¶ã€‚它包含有关项目文件与筛选器之间的关联信息。在 IDE ä¸­ï¼Œé€šè¿‡è¿™ç§å…³è”,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
BondServo.h
    è¿™æ˜¯åº”用程序的主头文件。
    å…¶ä¸­åŒ…括其他项目特定的标头(包括 Resource.h),并声明 CBondServoApp åº”用程序类。
BondServo.cpp
    è¿™æ˜¯åŒ…含应用程序类 CBondServoApp çš„主应用程序源文件。
BondServo.rc
    è¿™æ˜¯ç¨‹åºä½¿ç”¨çš„æ‰€æœ‰ Microsoft Windows èµ„源的列表。它包括 RES å­ç›®å½•中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ ä¸­è¿›è¡Œç¼–辑。项目资源包含在 2052 ä¸­ã€‚
res\BondServo.ico
    è¿™æ˜¯ç”¨ä½œåº”用程序图标的图标文件。此图标包括在主资源文件 BondServo.rc ä¸­ã€‚
res\BondServo.rc2
    æ­¤æ–‡ä»¶åŒ…含不在 Microsoft Visual C++ ä¸­è¿›è¡Œç¼–辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。
/////////////////////////////////////////////////////////////////////////////
应用程序向导创建一个对话框类:
BondServoDlg.h、BondServoDlg.cpp - å¯¹è¯æ¡†
    è¿™äº›æ–‡ä»¶åŒ…含 CBondServoDlg ç±»ã€‚此类定义应用程序的主对话框的行为。对话框模板包含在 BondServo.rc ä¸­ï¼Œè¯¥æ–‡ä»¶å¯ä»¥åœ¨ Microsoft Visual C++ ä¸­ç¼–辑。
/////////////////////////////////////////////////////////////////////////////
其他功能:
ActiveX æŽ§ä»¶
    è¯¥åº”用程序包含对使用 ActiveX æŽ§ä»¶çš„æ”¯æŒã€‚
/////////////////////////////////////////////////////////////////////////////
其他标准文件:
StdAfx.h, StdAfx.cpp
    è¿™äº›æ–‡ä»¶ç”¨äºŽç”Ÿæˆåä¸º BondServo.pch çš„预编译头 (PCH) æ–‡ä»¶å’Œåä¸º StdAfx.obj çš„预编译类型文件。
Resource.h
    è¿™æ˜¯æ ‡å‡†å¤´æ–‡ä»¶ï¼Œå¯ç”¨äºŽå®šä¹‰æ–°çš„资源 ID。Microsoft Visual C++ å°†è¯»å–并更新此文件。
BondServo.manifest
    Windows XP ä½¿ç”¨åº”用程序清单文件来描述特定版本的并行程序集的应用程序依赖项。加载程序使用这些信息来从程序集缓存中加载相应的程序集,并保护其不被应用程序访问。应用程序清单可能会包含在内,以作为与应用程序可执行文件安装在同一文件夹中的外部 .manifest æ–‡ä»¶è¿›è¡Œé‡æ–°åˆ†å‘,它还可能以资源的形式包含在可执行文件中。
/////////////////////////////////////////////////////////////////////////////
其他注释:
应用程序向导使用“TODO:”来指示应添加或自定义的源代码部分。
如果应用程序使用共享 DLL ä¸­çš„ MFC,您将需要重新分发 MFC DLL。如果应用程序所使用的语言与操作系统的区域设置不同,则还需要重新分发相应的本地化资源 mfc110XXX.DLL。
有关上述话题的更多信息,请参见 MSDN æ–‡æ¡£ä¸­æœ‰å…³é‡æ–°åˆ†å‘ Visual C++ åº”用程序的部分。
/////////////////////////////////////////////////////////////////////////////
SourceCode/Bond/BondEq/Resource.h
Binary files differ
SourceCode/Bond/BondEq/Servo.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
#include "stdafx.h"
#include "Servo.h"
CServo::CServo()
{
}
CServo::~CServo()
{
}
BOOL CServo::isRunning()
{
    return FALSE;
}
SourceCode/Bond/BondEq/Servo.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
#pragma once
class CServo
{
public:
    CServo();
    ~CServo();
public:
    BOOL isRunning();
};
SourceCode/Bond/BondEq/SetPage1.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
// SetPage1.cpp : å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "SetPage1.h"
#include "afxdialogex.h"
// CSetPage1 å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CSetPage1, CBaseSetPage)
CSetPage1::CSetPage1(CWnd* pParent /*=NULL*/)
    : CBaseSetPage(IDD_SET_PAGE1, pParent)
{
}
CSetPage1::~CSetPage1()
{
}
void CSetPage1::DoDataExchange(CDataExchange* pDX)
{
    CBaseSetPage::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CSetPage1, CBaseSetPage)
END_MESSAGE_MAP()
// CSetPage1 æ¶ˆæ¯å¤„理程序
BOOL CSetPage1::OnInitDialog()
{
    CBaseSetPage::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
SourceCode/Bond/BondEq/SetPage1.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
#pragma once
#include "BaseSetPage.h"
// CSetPage1 å¯¹è¯æ¡†
class CSetPage1 : public CBaseSetPage
{
    DECLARE_DYNAMIC(CSetPage1)
public:
    CSetPage1(CWnd* pParent = NULL);   // æ ‡å‡†æž„造函数
    virtual ~CSetPage1();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_SET_PAGE1 };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
};
SourceCode/Bond/BondEq/SetPage2.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,62 @@
// SetPage2.cpp : å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "SetPage2.h"
#include "afxdialogex.h"
// CSetPage2 å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CSetPage2, CBaseSetPage)
CSetPage2::CSetPage2(CWnd* pParent /*=NULL*/)
    : CBaseSetPage(IDD_SET_PAGE2, pParent)
{
}
CSetPage2::~CSetPage2()
{
}
void CSetPage2::DoDataExchange(CDataExchange* pDX)
{
    CBaseSetPage::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CSetPage2, CBaseSetPage)
    ON_EN_CHANGE(IDC_EDIT_REMOTEEQ_RECONNECT_INTERVAL, &CSetPage2::OnEnChangeEditRemoteeqReconnectInterval)
END_MESSAGE_MAP()
// CSetPage2 æ¶ˆæ¯å¤„理程序
BOOL CSetPage2::OnInitDialog()
{
    CBaseSetPage::OnInitDialog();
    // è¯»å–配置
    int nReconnectInterval = theApp.m_model.m_configuration.getP2RemoteEqReconnectInterval();
    SetDlgItemInt(IDC_EDIT_REMOTEEQ_RECONNECT_INTERVAL, nReconnectInterval);
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
void CSetPage2::OnApply()
{
    // ä¿å­˜é…ç½®
    int nReconnectInterval = GetDlgItemInt(IDC_EDIT_REMOTEEQ_RECONNECT_INTERVAL);
    theApp.m_model.m_configuration.setP2RemoteEqReconnectInterval(nReconnectInterval);
}
void CSetPage2::OnEnChangeEditRemoteeqReconnectInterval()
{
    OnModify();
}
SourceCode/Bond/BondEq/SetPage2.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
#pragma once
#include "BaseSetPage.h"
// CSetPage2 å¯¹è¯æ¡†
class CSetPage2 : public CBaseSetPage
{
    DECLARE_DYNAMIC(CSetPage2)
public:
    CSetPage2(CWnd* pParent = NULL);   // æ ‡å‡†æž„造函数
    virtual ~CSetPage2();
public:
    virtual void OnApply();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_SET_PAGE2 };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    afx_msg void OnEnChangeEditRemoteeqReconnectInterval();
};
SourceCode/Bond/BondEq/SettingsDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,191 @@
// SettingsDlg.cpp : å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "SettingsDlg.h"
#include "afxdialogex.h"
// CSettingsDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CSettingsDlg, CDialogEx)
CSettingsDlg::CSettingsDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_DIALOG_SETTINGS, pParent)
{
    m_crBkgnd = RGB(239, 244, 254);
    m_pTab = nullptr;
    m_bInit = FALSE;
}
CSettingsDlg::~CSettingsDlg()
{
}
void CSettingsDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CSettingsDlg, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_NOTIFY(HMVERTICALTAB_SEL_CHANGED, IDC_TAB1, &CSettingsDlg::OnTabSelChanged)
    ON_BN_CLICKED(IDC_BUTTON_APPLY, &CSettingsDlg::OnBnClickedButtonApply)
    ON_BN_CLICKED(IDOK, &CSettingsDlg::OnBnClickedOk)
    ON_MESSAGE(ID_MSG_PAGE_MODIFY, &CSettingsDlg::OnPageModify)
END_MESSAGE_MAP()
// CSettingsDlg æ¶ˆæ¯å¤„理程序
BOOL CSettingsDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    CSetPage1* pPage1 = new CSetPage1();
    pPage1->Create(IDD_SET_PAGE1, this);
    CSetPage2* pPage2 = new CSetPage2();
    pPage2->Create(IDD_SET_PAGE2, this);
    m_pTab = CHmVerticalTab::Hook(GetDlgItem(IDC_TAB1)->m_hWnd);
    m_pTab->SetPaddingTop(3);
    m_pTab->SetBkgndColor(RGB(235, 235, 243));
    m_pTab->AddItem(_T("常规设置"), pPage1);
    m_pTab->AddItem(_T("杀毒"), pPage2);
    m_pTab->AddItem(_T("实时防护"));
    m_pTab->AddItem(_T("清理加速"));
    m_pTab->AddItem(_T("漏洞修复"));
    ShowChildPage(0);
    Resize();
    m_bInit = TRUE;
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CSettingsDlg::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 CSettingsDlg::OnDestroy()
{
    CDialogEx::OnDestroy();
    for (unsigned int i = 0; i < 5; i++) {
        CBaseSetPage* pPage = (CBaseSetPage*)m_pTab->GetContext(i);
        if (pPage != nullptr) {
            pPage->DestroyWindow();
            delete pPage;
        }
    }
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
}
void CSettingsDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (nullptr == GetDlgItem(IDC_TAB1)) return;
    Resize();
}
void CSettingsDlg::Resize()
{
    CWnd* pItem;
    CRect rcClient, rcItem;
    int x, y;
    x = 1;
    GetClientRect(&rcClient);
    pItem = GetDlgItem(IDC_TAB1);
    pItem->GetClientRect(&rcItem);
    pItem->MoveWindow(x, 1, rcItem.Width(), rcClient.Height() - 2);
    x += rcItem.Width();
    x += 1;
    pItem = GetDlgItem(IDC_BUTTON_APPLY);
    pItem->GetWindowRect(&rcItem);
    ScreenToClient(&rcItem);
    y = rcItem.top - 12;
    for (unsigned int i = 0; i < 5; i++) {
        CBaseSetPage* pPage = (CBaseSetPage*)m_pTab->GetContext(i);
        if (pPage != nullptr) {
            pPage->MoveWindow(x, 1, rcClient.Width() - x - 1, y - 2);
        }
    }
}
void CSettingsDlg::OnTabSelChanged(NMHDR* nmhdr, LRESULT* result)
{
    HMVERTICALTAB_NMHDR* pNmhdrex = (HMVERTICALTAB_NMHDR*)nmhdr;
    ShowChildPage((unsigned int)pNmhdrex->dwData);
    *result = 0;
}
void CSettingsDlg::ShowChildPage(unsigned int index)
{
    ASSERT(0 <= index && index < 5);
    for (unsigned int i = 0; i < 5; i++) {
        CBaseSetPage* pPage = (CBaseSetPage*)m_pTab->GetContext(i);
        if (pPage != nullptr) {
            pPage->ShowWindow(i == index ? SW_SHOW : SW_HIDE);
        }
    }
}
void CSettingsDlg::OnBnClickedButtonApply()
{
    for (unsigned int i = 0; i < 5; i++) {
        CBaseSetPage* pPage = (CBaseSetPage*)m_pTab->GetContext(i);
        if (pPage != nullptr) {
            pPage->OnApply();
        }
    }
    GetDlgItem(IDC_BUTTON_APPLY)->EnableWindow(FALSE);
}
void CSettingsDlg::OnBnClickedOk()
{
    for (unsigned int i = 0; i < 5; i++) {
        CBaseSetPage* pPage = (CBaseSetPage*)m_pTab->GetContext(i);
        if (pPage != nullptr) {
            pPage->OnApply();
        }
    }
    CDialogEx::OnOK();
}
LRESULT CSettingsDlg::OnPageModify(WPARAM wParam, LPARAM lParam)
{
    if (m_bInit) {
        GetDlgItem(IDC_BUTTON_APPLY)->EnableWindow(TRUE);
    }
    return 0;
}
SourceCode/Bond/BondEq/SettingsDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
#pragma once
#include "HmVerticalTab.h"
#include "SetPage1.h"
#include "SetPage2.h"
// CSettingsDlg å¯¹è¯æ¡†
class CSettingsDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CSettingsDlg)
public:
    CSettingsDlg(CWnd* pParent = NULL);   // æ ‡å‡†æž„造函数
    virtual ~CSettingsDlg();
private:
    void Resize();
    void ShowChildPage(unsigned int index);
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    CHmVerticalTab* m_pTab;
    BOOL m_bInit;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_SETTINGS };
#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 OnTabSelChanged(NMHDR* nmhdr, LRESULT* result);
    afx_msg void OnBnClickedButtonApply();
    afx_msg void OnBnClickedOk();
    afx_msg    LRESULT OnPageModify(WPARAM wParam, LPARAM lParam);
};
SourceCode/Bond/BondEq/ToolUnits.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,147 @@
#include "stdafx.h"
#include "ToolUnits.h"
#include <chrono>
CToolUnits::CToolUnits()
{
}
CToolUnits::~CToolUnits()
{
}
std::string CToolUnits::timeToString(ULONGLONG time)
{
    ULONGLONG time1, time2;
    time1 = time / 1000000000;
    time2 = time % 1000000000;
    char buffer1[256], buffer[128];
    struct tm timeinfo;
    time_t t = time_t(time1);
    localtime_s(&timeinfo, &t);
    strftime(buffer, 128, "%Y-%m-%d %H:%M:%S", &timeinfo);
    sprintf_s(buffer1, 256, "%s.%lld", buffer, time2);
    return std::string(buffer1);
}
std::string CToolUnits::timeToString2(ULONGLONG time)
{
    ULONGLONG time1;
    time1 = time / 1000;
    char buffer[256];
    struct tm timeinfo;
    time_t t = time_t(time1);
    localtime_s(&timeinfo, &t);
    strftime(buffer, 128, "%Y-%m-%d %H:%M:%S", &timeinfo);
    return std::string(buffer);
}
std::string CToolUnits::timeToString3(ULONGLONG time)
{
    ULONGLONG time1;
    int ms;
    time1 = time / 1000;
    ms = time % 1000;
    char buffer1[256], buffer[128];
    struct tm timeinfo;
    time_t t = time_t(time1);
    localtime_s(&timeinfo, &t);
    strftime(buffer, 128, "%Y-%m-%d %H:%M:%S", &timeinfo);
    sprintf_s(buffer1, 256, "%s.%03d", buffer, ms);
    return std::string(buffer1);
}
ULONGLONG CToolUnits::stringToTime(const char* pszTime)
{
    struct tm tm;
    memset(&tm, 0, sizeof(tm));
    sscanf_s(pszTime, "%d-%d-%d %d:%d:%d",
        &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
        &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
    tm.tm_year -= 1900;
    tm.tm_mon--;
    return mktime(&tm) * 1000;
}
ULONGLONG CToolUnits::getTimestamp()
{
    auto now = std::chrono::system_clock::now();
    auto duration_in_milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
    uint64_t timestamp = duration_in_milliseconds.count();
    return timestamp;
}
void CToolUnits::createDir(const char* pszDir)
{
    CString strDir = pszDir;
    int lastIndex = 0;
    int index = strDir.Find(_T("\\"), lastIndex);
    while (index > 0) {
        CString strTempDir = strDir.Left(index);
        CreateDirectory(strTempDir, NULL);
        lastIndex = index + 1;
        index = strDir.Find(_T("\\"), lastIndex);
    }
    CreateDirectory(strDir, NULL);
}
CString& CToolUnits::floatToString1(float value, CString& strOut)
{
    strOut.Format(_T("%.1f"), value);
    return strOut;
}
CString& CToolUnits::floatToString3(float value, CString& strOut)
{
    strOut.Format(_T("%.3f"), value);
    return strOut;
}
BOOL CToolUnits::copyTextToClipboard(CWnd* pWnd, const CString& strText)
{
    if (OpenClipboard(pWnd->GetSafeHwnd())) {
        EmptyClipboard();
        HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (strText.GetLength() + 1) * sizeof(TCHAR));
        if (hglbCopy == NULL) {
            CloseClipboard();
            return FALSE;
        }
        LPTSTR lptstrCopy = (LPTSTR)GlobalLock(hglbCopy);
        strcpy_s(lptstrCopy, strText.GetLength()+1, strText);
        GlobalUnlock(hglbCopy);
        SetClipboardData(CF_TEXT, hglbCopy);
        CloseClipboard();
        GlobalFree(hglbCopy);
        return TRUE;
    }
    return FALSE;
}
std::string CToolUnits::getCurrentExePath() {
    char path[MAX_PATH];
    GetModuleFileName(NULL, path, MAX_PATH);
    std::string exePath(path);
    return exePath.substr(0, exePath.find_last_of("\\/"));
}
bool CToolUnits::isFile(const std::string& path) {
    DWORD attributes = GetFileAttributes(path.c_str());
    return (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY));
}
bool CToolUnits::isDirectory(const std::string& path) {
    DWORD attributes = GetFileAttributes(path.c_str());
    return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
}
SourceCode/Bond/BondEq/ToolUnits.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
#pragma once
#include <string>
class CToolUnits
{
public:
    CToolUnits();
    ~CToolUnits();
public:
    static std::string timeToString(ULONGLONG time);
    static std::string timeToString2(ULONGLONG time);
    static std::string timeToString3(ULONGLONG time);
    static ULONGLONG stringToTime(const char* pszTime);
    static CString& floatToString1(float value, CString& strOut);
    static CString& floatToString3(float value, CString& strOut);
    static ULONGLONG getTimestamp();
    static void createDir(const char* pszDir);
    static BOOL copyTextToClipboard(CWnd* pWnd, const CString& strText);
    static std::string getCurrentExePath();
    static bool isFile(const std::string& path);
    static bool isDirectory(const std::string& path);
};
SourceCode/Bond/BondEq/TopToolbar.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,189 @@
// TopToolbar.cpp : å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "TopToolbar.h"
#include "afxdialogex.h"
#include "Common.h"
// CTopToolbar å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CTopToolbar, CDialogEx)
CTopToolbar::CTopToolbar(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_TOP_TOOLBAR, pParent)
{
    m_crBkgnd = TOP_TOOLBAR_BACKGROUND;
    m_hbrBkgnd = nullptr;
}
CTopToolbar::~CTopToolbar()
{
}
void CTopToolbar::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_BUTTON_RUN, m_btnRun);
    DDX_Control(pDX, IDC_BUTTON_STOP, m_btnStop);
    DDX_Control(pDX, IDC_BUTTON_SETTINGS, m_btnSettings);
    DDX_Control(pDX, IDC_BUTTON_OPERATOR, m_btnOperator);
}
BEGIN_MESSAGE_MAP(CTopToolbar, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_OPERATOR, &CTopToolbar::OnButtonOperatorMenuClicked)
END_MESSAGE_MAP()
// CTopToolbar æ¶ˆæ¯å¤„理程序
BOOL CTopToolbar::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    InitBtn(m_btnRun, "Run_High_32.ico", "Run_Gray_32.ico");
    InitBtn(m_btnStop, "Stop_High_32.ico", "Stop_Gray_32.ico");
    InitBtn(m_btnSettings, "Settings_High_32.ico", "Settings_Gray_32.ico");
    InitBtn(m_btnOperator, "Operator_High_32.ico", "Operator_Gray_32.ico");
    HMENU hMenu = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCEA(IDR_MENU_OPEATOR));
    m_btnOperator.SetMenu(hMenu);
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CTopToolbar::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 CTopToolbar::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
        m_hbrBkgnd = nullptr;
    }
}
void CTopToolbar::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (GetDlgItem(IDC_BUTTON_RUN) == nullptr) return;
    Resize();
}
#define BTN_WIDTH        60
#define BTN_HEIGHT        30
void CTopToolbar::Resize()
{
    CWnd* pItem;
    CRect rcClient, rcItem;
    GetClientRect(&rcClient);
    int nBthHeight = (rcClient.Height() - 10);
    int x = 2, y = 3;
    pItem = GetDlgItem(IDC_BUTTON_RUN);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_BUTTON_STOP);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_TOOLBAR_LINE1);
    pItem->MoveWindow(x, y + 6, 2, nBthHeight - 12);
    x += 4;
    pItem = GetDlgItem(IDC_BUTTON_SETTINGS);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    x = rcClient.right - 5 - BTN_WIDTH - 20;
    pItem = GetDlgItem(IDC_BUTTON_OPERATOR);
    pItem->MoveWindow(x, y, BTN_WIDTH + 20, nBthHeight);
    CWnd* pLine = GetDlgItem(IDC_LINE1);
    pLine->MoveWindow(0, rcClient.bottom - 2, rcClient.Width(), 2);
}
void CTopToolbar::InitBtn(CBlButton& btn, const char* pszIcon1, const char* pszIcon2)
{
    CString strIcon1, strIcon2;
    HICON hIcon1, hIcon2;
    strIcon1.Format(_T("%s\\Res\\%s"), theApp.m_strAppDir, pszIcon1);
    strIcon2.Format(_T("%s\\Res\\%s"), theApp.m_strAppDir, pszIcon2);
    hIcon1 = (HICON)::LoadImage(AfxGetInstanceHandle(),
        strIcon1, IMAGE_ICON, 32, 32,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    hIcon2 = (HICON)::LoadImage(AfxGetInstanceHandle(),
        strIcon2, IMAGE_ICON, 32, 32,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    btn.SetBkgndColor(BS_NORMAL, TOP_TOOLBAR_BACKGROUND);
    btn.SetBkgndColor(BS_PRESS, RGB(185, 209, 234));
    btn.SetBkgndColor(BS_DISABLE, TOP_TOOLBAR_BACKGROUND);
    btn.SetFrameColor(BS_NORMAL, TOP_TOOLBAR_BACKGROUND);
    btn.SetFrameColor(BS_PRESS, RGB(185, 209, 234));
    btn.SetFrameColor(BS_HOVER, RGB(185, 209, 234));
    btn.SetFrameColor(BS_DISABLE, TOP_TOOLBAR_BACKGROUND);
    btn.SetIcon(hIcon1, hIcon2, 32);
}
CWnd* CTopToolbar::GetBtn(UINT nId)
{
    return GetDlgItem(nId);
}
void CTopToolbar::SetOperatorBtnText(const char* pszText)
{
    m_btnOperator.SetWindowText(pszText);
}
BOOL CTopToolbar::OnCommand(WPARAM wParam, LPARAM lParam)
{
    switch (LOWORD(wParam)) {
    case IDC_BUTTON_RUN:
    case IDC_BUTTON_STOP:
    case IDC_BUTTON_SETTINGS:
        GetParent()->SendMessage(ID_MSG_TOOLBAR_BTN_CLICKED, 0, LOWORD(wParam));
        break;
    }
    return CDialogEx::OnCommand(wParam, lParam);
}
void CTopToolbar::OnButtonOperatorMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
    BLBUTTON_NMHDR* pblbNmhdr = reinterpret_cast<BLBUTTON_NMHDR*>(pNMHDR);
    GetParent()->SendMessage(ID_MSG_TOOLBAR_BTN_CLICKED, (int)pblbNmhdr->dwData, IDC_BUTTON_OPERATOR);
    *pResult = 0;
}
SourceCode/Bond/BondEq/TopToolbar.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,54 @@
#pragma once
#include "BlButton.h"
#define ID_MSG_TOOLBAR_BTN_CLICKED        WM_USER + 20368
// CTopToolbar å¯¹è¯æ¡†
class CTopToolbar : public CDialogEx
{
    DECLARE_DYNAMIC(CTopToolbar)
public:
    CTopToolbar(CWnd* pParent = NULL);   // æ ‡å‡†æž„造函数
    virtual ~CTopToolbar();
public:
    CWnd* GetBtn(UINT nId);
    void SetOperatorBtnText(const char* pszText);
private:
    void Resize();
    void InitBtn(CBlButton& btn, const char* pszIcon1, const char* pszIcon2);
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
private:
    CBlButton m_btnRun;
    CBlButton m_btnStop;
    CBlButton m_btnSettings;
    CBlButton m_btnOperator;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_TOP_TOOLBAR };
#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);
    virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
    afx_msg void OnButtonOperatorMenuClicked(NMHDR* pNMHDR, LRESULT* pResult);
};
SourceCode/Bond/BondEq/VerticalLine.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,310 @@
// VerticalLine.cpp: implementation of the CVerticalLine class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "VerticalLine.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CVerticalLine::CVerticalLine()
{
    m_hWnd = NULL;
    m_crBkgnd = RGB(255, 255, 255);
    m_crLineColor = RGB(222, 222, 222);
    m_bEnableResize = FALSE;
}
CVerticalLine::~CVerticalLine()
{
}
BOOL CVerticalLine::RegisterWndClass()
{
    WNDCLASS wc;
    wc.lpszClassName = BYVERTICALLINE_CLASS;
    wc.hInstance = AfxGetInstanceHandle();
    wc.lpfnWndProc = WindowProc;
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = 0;
    wc.lpszMenuName = NULL;
    wc.hbrBackground = NULL;
    wc.style = CS_GLOBALCLASS|CS_DBLCLKS;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    // æ³¨å†Œè‡ªå®šä¹‰ç±»
    return (::RegisterClass(&wc) != 0);
}
CVerticalLine* CVerticalLine::Hook(HWND hWnd)
{
    CVerticalLine* pVerticalLine = (CVerticalLine*)GetProp(hWnd, BYSTAG_VERTICALLINE);
    if(pVerticalLine == NULL)
    {
        pVerticalLine = new CVerticalLine;
        pVerticalLine->m_hWnd = hWnd;
        SetProp(hWnd, BYSTAG_VERTICALLINE, (HANDLE)pVerticalLine);
    }
    return pVerticalLine;
}
void CVerticalLine::Release()
{
    // delete
    delete this;
}
void CVerticalLine::Notify(int nCode, int dwData, int dwData1/* = 0*/, int dwData2/* = 0*/)
{
    HWND hParent;
    hParent = GetParent(m_hWnd);
    if(hParent != NULL) {
        BYVERTICALLINE_NMHDR iii_nmhdr;
        iii_nmhdr.nmhdr.hwndFrom = m_hWnd;
        iii_nmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
        iii_nmhdr.nmhdr.code = nCode;
        iii_nmhdr.dwData = dwData;
        iii_nmhdr.dwData1 = dwData1;
        iii_nmhdr.dwData2 = dwData2;
        SendMessage(hParent, WM_NOTIFY, (WPARAM)iii_nmhdr.nmhdr.idFrom, (LPARAM)&iii_nmhdr);
    }
}
////////////////////////////////
// æ‹¦æˆªçª—口消息函数
LRESULT CALLBACK CVerticalLine::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CVerticalLine* pVerticalLine = (CVerticalLine *)GetProp(hWnd, BYSTAG_VERTICALLINE);
    if(pVerticalLine == NULL && uMsg != WM_NCCREATE)
    {
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    // å¦‚æžœHook则响应消息
    ASSERT(hWnd);
    switch(uMsg)
    {
    case WM_NCCREATE:
        return OnNcCreate(hWnd, wParam, lParam);
    case WM_DESTROY:
        return pVerticalLine->OnDestroy(wParam, lParam);
    case WM_PAINT:
        return pVerticalLine->OnPaint(wParam, lParam);
    case WM_TIMER:
        return pVerticalLine->OnTimer(wParam, lParam);
    case WM_SETCURSOR:
        return pVerticalLine->OnSetCursor(wParam, lParam);
    case WM_LBUTTONDOWN:
        return pVerticalLine->OnLButtonDown(wParam, lParam);
    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS;
    default:
        break;
    }
    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
///////////////////////////////
// WM_NCCREATE
// çª—口创建前的初始化工作
LRESULT CVerticalLine::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    CVerticalLine* pVerticalLine = (CVerticalLine *)GetProp(hWnd, BYSTAG_VERTICALLINE);
    ASSERT(pVerticalLine == NULL);
    Hook(hWnd);
    return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
}
///////////////////////////////
// WM_DESTROY
LRESULT CVerticalLine::OnDestroy(WPARAM wParam, LPARAM lParam)
{
    Release();
    return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
}
///////////////////////////////
// WM_TIMER
LRESULT CVerticalLine::OnTimer(WPARAM wParam, LPARAM lParam)
{
    return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
}
///////////////////////////////
// WM_SETCURSOR
LRESULT CVerticalLine::OnSetCursor(WPARAM wParam, LPARAM lParam)
{
    if(m_bEnableResize) {
        SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
        return TRUE;
    }
    return ::DefWindowProc(m_hWnd, WM_SETCURSOR, wParam, lParam);
}
/*
 * WM_LBUTTONDOWN
 * é¼ æ ‡å·¦é”®æŒ‰ä¸‹
 */
LRESULT CVerticalLine::OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
    if (!m_bEnableResize) {
        return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
    }
    POINT pt, ptNew;
    pt.x = LOWORD(lParam);
    pt.y = HIWORD(lParam);
    int nMoveX = 0;
    // æ•捉鼠标消息,检测是否拖动
    RECT rcParent, rcWindows;
    GetClientRect(m_hWnd, &rcWindows);
    ::ClientToScreen(m_hWnd, (LPPOINT)&rcWindows);
    ::ClientToScreen(m_hWnd, (LPPOINT)&rcWindows.right);
    GetClientRect(GetParent(m_hWnd), &rcParent);
    ::ClientToScreen(GetParent(m_hWnd), (LPPOINT)&rcParent);
    HDC hDC = GetDC(GetDesktopWindow());
    ::DrawFocusRect(hDC, &rcWindows);
    if (::GetCapture() == NULL) {
        SetCapture(m_hWnd);
        ASSERT(m_hWnd == GetCapture());
        AfxLockTempMaps();
        for (;;) {
            MSG msg;
            VERIFY(::GetMessage(&msg, NULL, 0, 0));
            if (GetCapture() != m_hWnd) break;
            switch (msg.message)
            {
            case WM_MOUSEMOVE:
                ptNew = msg.pt;
                if (ptNew.x < rcParent.left) ptNew.x = rcParent.left;
                ::DrawFocusRect(hDC, &rcWindows);
                rcWindows.left = ptNew.x - 3;
                rcWindows.right = ptNew.x + 3;
                ::DrawFocusRect(hDC, &rcWindows);
                ::ScreenToClient(m_hWnd, &ptNew);
                break;
            case WM_LBUTTONUP:
                ptNew = msg.pt;
                ::ScreenToClient(m_hWnd, &ptNew);
                nMoveX = ptNew.x - pt.x;
                goto ExitLoop;
            case WM_KEYDOWN:
                if (msg.wParam == VK_ESCAPE) {
                    goto ExitLoop;
                }
                break;
            default:
                DispatchMessage(&msg);
                break;
            }
        }
    ExitLoop:
        ::DrawFocusRect(hDC, &rcWindows);
        ReleaseDC(GetDesktopWindow(), hDC);
        ReleaseCapture();
        ::InvalidateRect(m_hWnd, NULL, TRUE);
        Notify((int)BYVERTICALLINE_MOVEX, nMoveX);
        AfxUnlockTempMaps(FALSE);
    }
    return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
}
///////////////////////////////
// WM_PAINT
LRESULT CVerticalLine::OnPaint(WPARAM wParam, LPARAM lParam)
{
    HDC hDC, hMemDC;
    HBITMAP hBitmap;
    RECT rcClient;
    CString strText;
    HFONT hFont;
    HBRUSH hBrushBK;
    // BeginPaint
    PAINTSTRUCT ps;
    hDC = BeginPaint(m_hWnd, &ps);
    GetClientRect(m_hWnd, &rcClient);
    hMemDC = ::CreateCompatibleDC(hDC);
    hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right-rcClient.left,
        rcClient.bottom-rcClient.top);
    ::SelectObject(hMemDC, hBitmap);
    hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    ::SelectObject(hMemDC, hFont);
    // èƒŒæ™¯é¢œè‰²
    hBrushBK = CreateSolidBrush( m_crBkgnd );
    ::FillRect(hMemDC, &rcClient, hBrushBK);
    DeleteObject(hBrushBK);
    // ç”»çº¿
    HPEN hPen = CreatePen(PS_SOLID, 1, m_crLineColor);
    HPEN hOldPen = (HPEN)::SelectObject(hMemDC, hPen);
    ::MoveToEx(hMemDC, rcClient.right-1, 0, NULL);
    LineTo(hMemDC, rcClient.right - 1, rcClient.bottom);
    ::SelectObject(hMemDC, hOldPen);
    // EndPaint
    ::BitBlt(hDC, 0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
        hMemDC, 0, 0, SRCCOPY);
    EndPaint(m_hWnd, &ps);
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
    return 1;
}
void CVerticalLine::SetBkgndColor(COLORREF cr)
{
    m_crBkgnd = cr;
}
void CVerticalLine::EnableResize()
{
    m_bEnableResize = TRUE;
}
void CVerticalLine::DisableResize()
{
    m_bEnableResize = FALSE;
}
SourceCode/Bond/BondEq/VerticalLine.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
// VerticalLine.h: interface for the CVerticalLine class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_VERTICALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)
#define AFX_VERTICALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_
#pragma comment(lib, "Msimg32.lib")            // TransparentBlt
//====== VerticalLine =====================================================
#ifndef NOVERTICALLINE
#ifdef _WIN32
#define BYVERTICALLINE_CLASSA       "BYVerticalLine"
#define BYVERTICALLINE_CLASSW       L"BYVerticalLine"
#ifdef UNICODE
#define  BYVERTICALLINE_CLASS       BYVERTICALLINE_CLASSW
#else
#define  BYVERTICALLINE_CLASS       BYVERTICALLINE_CLASSA
#endif
#else
#define BYVERTICALLINE_CLASS        "BYVerticalLine"
#endif
#define BYSTAG_VERTICALLINE         _T("ISVERTICALLINE")
//====== WM_NOTIFY codes (NMHDR.code values) ==================================
#define BYVERTICALLINE_FIRST             (0U-2330U)       //
#define BYVERTICALLINE_LAST                 (0U-2320U)
#define BYVERTICALLINE_MOVEX              (BYVERTICALLINE_FIRST - 1)
typedef struct tagBYVERTICALLINE_NMHDR
{
    NMHDR        nmhdr;
    DWORD        dwData;
    DWORD        dwData1;
    DWORD        dwData2;
} BYVERTICALLINE_NMHDR;
#endif
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CVerticalLine
{
public:
    CVerticalLine();
    virtual ~CVerticalLine();
public:
    void EnableResize();
    void DisableResize();
    static BOOL RegisterWndClass();
    static CVerticalLine* Hook(HWND hWnd);
    void Notify(int nCode, int dwData, int dwData1 = 0, int dwData2 = 0);
    void Release();
    void SetBkgndColor(COLORREF cr);
    static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    static LRESULT OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
    LRESULT OnDestroy(WPARAM wParam, LPARAM lParam);
    LRESULT OnTimer(WPARAM wParam, LPARAM lParam);
    LRESULT OnSetCursor(WPARAM wParam, LPARAM lParam);
    LRESULT OnPaint(WPARAM wParam, LPARAM lParam);
    LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam);
private:
    HWND        m_hWnd;
    COLORREF m_crBkgnd;
    COLORREF m_crLineColor;
private:
    BOOL m_bEnableResize;
};
#endif // !defined(AFX_VERTICALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)
SourceCode/Bond/BondEq/View/ChangePasswordDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,114 @@
// CChangePasswordDlg.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "afxdialogex.h"
#include "ChangePasswordDlg.h"
#include "UserManager.h"
// CChangePasswordDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CChangePasswordDlg, CDialogEx)
CChangePasswordDlg::CChangePasswordDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_CHANGE_PASSWORD, pParent)
{
}
CChangePasswordDlg::~CChangePasswordDlg()
{
}
bool CChangePasswordDlg::changeUserPassword(UserManager& userManager, const std::string& username, const std::string& newPassword)
{
    if (!userManager.changePassword(username, newPassword)) {
        AfxMessageBox(_T("修改用户密码失败。"));
        return false;
    }
    return true;
}
void CChangePasswordDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT_CHANGE_USERNAME, m_editUsername);
    DDX_Control(pDX, IDC_EDIT_CHANGE_CURRENT_PASSWORD, m_editCurrentPassword);
    DDX_Control(pDX, IDC_EDIT_CHANGE_NEW_PASSWORD, m_editNewPassword);
    DDX_Control(pDX, IDC_EDIT_CHANGE_CONFIRM_PASSWORD, m_editConfirmPassword);
}
BEGIN_MESSAGE_MAP(CChangePasswordDlg, CDialogEx)
    ON_BN_CLICKED(IDOK, &CChangePasswordDlg::OnBnClickedOk)
END_MESSAGE_MAP()
// CChangePasswordDlg æ¶ˆæ¯å¤„理程序
BOOL CChangePasswordDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // è®¾ç½®çª—口标题和初始值
    SetWindowText(_T("修改密码"));
    UserManager& userManager = UserManager::getInstance();
    if (userManager.isLoggedIn()) {
        m_editUsername.SetWindowText(userManager.getCurrentUser().c_str());
    }
    return TRUE;
}
void CChangePasswordDlg::OnBnClickedOk()
{
    CString username, currentPassword, newPassword, confirmPassword;
    m_editUsername.GetWindowText(username);
    m_editCurrentPassword.GetWindowText(currentPassword);
    m_editNewPassword.GetWindowText(newPassword);
    m_editConfirmPassword.GetWindowText(confirmPassword);
    if (username.IsEmpty() || currentPassword.IsEmpty() || newPassword.IsEmpty() || confirmPassword.IsEmpty()) {
        AfxMessageBox(_T("所有字段均为必填项。"));
        return;
    }
    if (newPassword.Compare(confirmPassword) != 0) {
        AfxMessageBox(_T("新密码与确认密码不匹配。"));
        return;
    }
#ifdef UNICODE
    std::string strUsername = CStringA(username);
    std::string strCurrentPassword = CStringA(currentPassword);
    std::string strNewPassword = CStringA(newPassword);
#else
    std::string strUsername = username;
    std::string strCurrentPassword = currentPassword;
    std::string strNewPassword = newPassword;
#endif
    UserManager& userManager = UserManager::getInstance();
    if (userManager.isLoggedIn() && strCurrentPassword.compare(userManager.getCurrentPass()) == 0) {
        if (changeUserPassword(userManager, strUsername, strNewPassword)) {
            EndDialog(IDOK);
        }
    }
    else {
        if (userManager.login(strUsername, strCurrentPassword)) {
            if (changeUserPassword(userManager, strUsername, strNewPassword)) {
                EndDialog(IDOK);
            }
            else {
                userManager.logout();
            }
        }
        else {
            AfxMessageBox(_T("当前用户名或密码输入错误。"));
        }
    }
}
SourceCode/Bond/BondEq/View/ChangePasswordDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
#pragma once
#include "afxdialogex.h"
#include <string>
class UserManager;
// CChangePasswordDlg å¯¹è¯æ¡†
class CChangePasswordDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CChangePasswordDlg)
public:
    CChangePasswordDlg(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CChangePasswordDlg();
private:
    bool changeUserPassword(UserManager& userManager, const std::string& username, const std::string& newPassword);
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_CHANGE_PASSWORD };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    virtual BOOL OnInitDialog();
    afx_msg void OnBnClickedOk();
    afx_msg void OnBnClickedCancel();
    DECLARE_MESSAGE_MAP()
private:
    CEdit m_editUsername;              // ç”¨æˆ·åè¾“入框
    CEdit m_editCurrentPassword;       // å½“前密码输入框
    CEdit m_editNewPassword;           // æ–°å¯†ç è¾“入框
    CEdit m_editConfirmPassword;       // ç¡®è®¤æ–°å¯†ç è¾“入框
};
SourceCode/Bond/BondEq/View/LoginDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,116 @@
// LoginDlg.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondServo.h"
#include "afxdialogex.h"
#include "LoginDlg.h"
#include "UserManager.h"
#include "ChangePasswordDlg.h"
// CLoginDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CLoginDlg, CDialogEx)
CLoginDlg::CLoginDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_LOGIN, pParent)
{
}
CLoginDlg::~CLoginDlg()
{
}
void CLoginDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT_USERNAME, m_editUsername);
    DDX_Control(pDX, IDC_EDIT_PASSWORD, m_editPassword);
    DDX_Control(pDX, IDC_COMBO_ROLE, m_comboRole);
    DDX_Control(pDX, IDC_CHECK_REMEMBER_PASSWORD, m_checkRememberPassword);
}
BEGIN_MESSAGE_MAP(CLoginDlg, CDialogEx)
    ON_BN_CLICKED(IDC_BUTTON_LOGIN, &CLoginDlg::OnBnClickedLogin)
    ON_STN_CLICKED(IDC_STATIC_CHANGE_PASSWORD, &CLoginDlg::OnBnClickedChangePassword)
END_MESSAGE_MAP()
// CLoginDlg æ¶ˆæ¯å¤„理程序
BOOL CLoginDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    // è®¾ç½®çª—口标题和初始值
    SetWindowText(_T("登录"));
    m_comboRole.AddString(_T("管理员"));
    m_comboRole.AddString(_T("工程师"));
    m_comboRole.AddString(_T("操作员"));
    m_comboRole.SetCurSel(0);
    // æ·»åŠ SS_NOTIFY样式
    CStatic* pStatic = (CStatic*)GetDlgItem(IDC_STATIC_CHANGE_PASSWORD);
    if (pStatic != nullptr) {
        pStatic->ModifyStyle(0, SS_NOTIFY);
    }
    UserManager& userManager = UserManager::getInstance();
    if (userManager.isLoggedIn()) {
        int nRole = (int)userManager.getCurrentUserRole();
        if (nRole <= m_comboRole.GetCount()) {
            m_comboRole.SetCurSel(nRole);
        }
        if (userManager.isRememberMe()) {
            m_checkRememberPassword.SetCheck(BST_CHECKED);
        }
        userManager.getCurrentUserRole();
        m_editUsername.SetWindowText(userManager.getCurrentUser().c_str());
        m_editPassword.SetWindowText(userManager.getCurrentPass().c_str());
    }
    return TRUE;
}
void CLoginDlg::OnBnClickedLogin()
{
    CString username, password, role;
    m_editUsername.GetWindowText(username);
    m_editPassword.GetWindowText(password);
    m_comboRole.GetLBText(m_comboRole.GetCurSel(), role);
    if (username.IsEmpty() || password.IsEmpty()) {
        AfxMessageBox(_T("请输入用户名和密码。"));
        return;
    }
#ifdef UNICODE
    std::string strUsername = CStringA(username);
    std::string strPassword = CStringA(password);
#else
    std::string strUsername = username;
    std::string strPassword = password;
#endif
    UserManager& userManager = UserManager::getInstance();
    if (!userManager.login(strUsername, strPassword, (m_checkRememberPassword.GetCheck() == BST_CHECKED))) {
        AfxMessageBox(_T("登录失败。"));
        return;
    }
    EndDialog(IDOK);
}
void CLoginDlg::OnBnClickedChangePassword()
{
    CChangePasswordDlg changePasswordDlg;
    changePasswordDlg.DoModal();
    if (changePasswordDlg.DoModal() == IDOK) {
        m_editPassword.SetWindowText("");
    }
}
SourceCode/Bond/BondEq/View/LoginDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
#pragma once
#include "afxdialogex.h"
// CLoginDlg å¯¹è¯æ¡†
class CLoginDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CLoginDlg)
public:
    CLoginDlg(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CLoginDlg();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_LOGIN };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    virtual BOOL OnInitDialog();
    afx_msg void OnBnClickedLogin();
    afx_msg void OnBnClickedChangePassword();
    DECLARE_MESSAGE_MAP()
private:
    CEdit m_editUsername;
    CEdit m_editPassword;
    CComboBox m_comboRole;
    CButton m_checkRememberPassword;
};
SourceCode/Bond/BondEq/res/BondServo.ico
SourceCode/Bond/BondEq/res/BondServo.rc2
Binary files differ
SourceCode/Bond/BondEq/res/application.exe.manifest
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity
         name="XP style manifest"
         processorArchitecture="amd64"
         version="1.0.0.0"
         type="win32"/>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity
                type="win32"
                name="Microsoft.Windows.Common-Controls"
                version="6.0.0.0"
                processorArchitecture="amd64"
                publicKeyToken="6595b64144ccf1df"
                language="*"
            />
        </dependentAssembly>
    </dependency>
</assembly>
SourceCode/Bond/BondEq/stdafx.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
// stdafx.cpp : åªåŒ…括标准包含文件的源文件
// BondServo.pch å°†ä½œä¸ºé¢„编译头
// stdafx.obj å°†åŒ…含预编译类型信息
#include "stdafx.h"
SourceCode/Bond/BondEq/stdafx.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,78 @@
// stdafx.h : æ ‡å‡†ç³»ç»ŸåŒ…含文件的包含文件,
// æˆ–是经常使用但不常更改的
// ç‰¹å®šäºŽé¡¹ç›®çš„包含文件
#pragma once
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN            // ä»Ž Windows å¤´ä¸­æŽ’除极少使用的资料
#endif
#include "targetver.h"
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // æŸäº› CString æž„造函数将是显式的
// å…³é—­ MFC å¯¹æŸäº›å¸¸è§ä½†ç»å¸¸å¯æ”¾å¿ƒå¿½ç•¥çš„警告消息的隐藏
#define _AFX_ALL_WARNINGS
#include <afxwin.h>         // MFC æ ¸å¿ƒç»„件和标准组件
#include <afxext.h>         // MFC æ‰©å±•
#include <afxdisp.h>        // MFC è‡ªåŠ¨åŒ–ç±»
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxdtctl.h>           // MFC å¯¹ Internet Explorer 4 å…¬å…±æŽ§ä»¶çš„æ”¯æŒ
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>             // MFC å¯¹ Windows å…¬å…±æŽ§ä»¶çš„æ”¯æŒ
#endif // _AFX_NO_AFXCMN_SUPPORT
#include <afxcontrolbars.h>     // åŠŸèƒ½åŒºå’ŒæŽ§ä»¶æ¡çš„ MFC æ”¯æŒ
#include "..\RxWindows1.0\include\RxWindowsLib.h"
#include "..\BEQLibrarySDK\include\BEQLib.h"
// æ•°æ®åº“模块
#include "..\DatabaseSDK\include\Database.h"
#include "..\DatabaseSDK\include\MySQLDatabase.h"
#include "..\DatabaseSDK\include\SQLiteDatabase.h"
#if defined(_WIN64)
    #if defined(_DEBUG)
        #pragma comment(lib, "..\\DatabaseSDK\\lib\\x64\\Debug\\DatabaseEx.lib")
    #else
        #pragma comment(lib, "..\\DatabaseSDK\\lib\\x64\\Release\\DatabaseEx.lib")
    #endif
#else
    #if defined(_DEBUG)
        #pragma comment(lib, "..\\DatabaseSDK\\lib\\Win32\\Debug\\DatabaseEx.lib")
    #else
        #pragma comment(lib, "..\\DatabaseSDK\\lib\\Win32\\Release\\DatabaseEx.lib")
    #endif
#endif
#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif
SourceCode/Bond/BondEq/targetver.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
#pragma once
// åŒ…括 SDKDDKVer.h å°†å®šä¹‰å¯ç”¨çš„æœ€é«˜ç‰ˆæœ¬çš„ Windows å¹³å°ã€‚
// å¦‚果要为以前的 Windows å¹³å°ç”Ÿæˆåº”用程序,请包括 WinSDKVer.h,并将
// å°† _WIN32_WINNT å®è®¾ç½®ä¸ºè¦æ”¯æŒçš„平台,然后再包括 SDKDDKVer.h。
#include <SDKDDKVer.h>
SourceCode/Bond/DatabaseSDK/include/Database.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
#ifndef DATABASE_H
#define DATABASE_H
#include <string>
#include <vector>
#ifdef BUILDING_DLL
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
namespace BL {
    class DLL_API Database {
    public:
        virtual ~Database() {}
        virtual bool connect(const std::string& connectionString, bool createIfNotExists = false) = 0;
        virtual void disconnect() = 0;
        virtual bool executeQuery(const std::string& query) = 0;
        virtual std::vector<std::vector<std::string>> fetchResults(const std::string& query) = 0;
    };
}
#endif // DATABASE_H
SourceCode/Bond/DatabaseSDK/include/MySQLDatabase.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
#ifndef MYSQL_DATABASE_H
#define MYSQL_DATABASE_H
#include "Database.h"
#include <string>
#include <vector>
namespace BL {
    class DLL_API MySQLDatabase : public Database {
    public:
        MySQLDatabase();
        virtual ~MySQLDatabase() override;
        bool connect(const std::string& connectionString, bool createIfNotExists = false) override;
        void disconnect() override;
        bool executeQuery(const std::string& query) override;
        std::vector<std::vector<std::string>> fetchResults(const std::string& query) override;
    private:
        class Impl;            // å‰å‘声明内部实现类
        Impl* m_impl;          // ä½¿ç”¨åŽŸå§‹æŒ‡é’ˆæŒ‡å‘å†…éƒ¨å®žçŽ°ç±»
    };
}
#endif // MYSQL_DATABASE_H
SourceCode/Bond/DatabaseSDK/include/SQLiteDatabase.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
#ifndef SQLITE_DATABASE_H
#define SQLITE_DATABASE_H
#include "Database.h"
#include <string>
#include <vector>
namespace BL {
    class DLL_API SQLiteDatabase : public Database {
    public:
        SQLiteDatabase();
        virtual ~SQLiteDatabase() override;
        bool connect(const std::string& connectionString, bool createIfNotExists = false) override;
        void disconnect() override;
        bool executeQuery(const std::string& query) override;
        std::vector<std::vector<std::string>> fetchResults(const std::string& query) override;
    private:
        class Impl;           // å£°æ˜Žå†…部实现类
        Impl* m_impl;         // æŒ‡å‘内部实现类的指针
    };
}
#endif // SQLITE_DATABASE_H
SourceCode/Bond/GangBond2860.sln
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BEQLibrary", "BEQLibrary\BEQLibrary.vcxproj", "{8421CE64-06F9-48F4-A3F3-ACFB683C94D4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BEQDemo", "BEQDemo\BEQDemo.vcxproj", "{E374F8A0-F864-49F4-AF5C-F751AAC5F133}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GangBond2860Emulator", "GangBond2860Emulator\GangBond2860Emulator.vcxproj", "{E0EC2761-ABDE-4F89-937C-0B147FE26628}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BondEq", "BondEq\BondEq.vcxproj", "{7864134E-C538-4C0F-AF24-215FFCCBBAB4}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|x64 = Debug|x64
        Debug|x86 = Debug|x86
        Release|x64 = Release|x64
        Release|x86 = Release|x86
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {8421CE64-06F9-48F4-A3F3-ACFB683C94D4}.Debug|x64.ActiveCfg = Debug|x64
        {8421CE64-06F9-48F4-A3F3-ACFB683C94D4}.Debug|x64.Build.0 = Debug|x64
        {8421CE64-06F9-48F4-A3F3-ACFB683C94D4}.Debug|x86.ActiveCfg = Debug|Win32
        {8421CE64-06F9-48F4-A3F3-ACFB683C94D4}.Debug|x86.Build.0 = Debug|Win32
        {8421CE64-06F9-48F4-A3F3-ACFB683C94D4}.Release|x64.ActiveCfg = Release|x64
        {8421CE64-06F9-48F4-A3F3-ACFB683C94D4}.Release|x64.Build.0 = Release|x64
        {8421CE64-06F9-48F4-A3F3-ACFB683C94D4}.Release|x86.ActiveCfg = Release|Win32
        {8421CE64-06F9-48F4-A3F3-ACFB683C94D4}.Release|x86.Build.0 = Release|Win32
        {E374F8A0-F864-49F4-AF5C-F751AAC5F133}.Debug|x64.ActiveCfg = Debug|x64
        {E374F8A0-F864-49F4-AF5C-F751AAC5F133}.Debug|x64.Build.0 = Debug|x64
        {E374F8A0-F864-49F4-AF5C-F751AAC5F133}.Debug|x86.ActiveCfg = Debug|Win32
        {E374F8A0-F864-49F4-AF5C-F751AAC5F133}.Debug|x86.Build.0 = Debug|Win32
        {E374F8A0-F864-49F4-AF5C-F751AAC5F133}.Release|x64.ActiveCfg = Release|x64
        {E374F8A0-F864-49F4-AF5C-F751AAC5F133}.Release|x64.Build.0 = Release|x64
        {E374F8A0-F864-49F4-AF5C-F751AAC5F133}.Release|x86.ActiveCfg = Release|Win32
        {E374F8A0-F864-49F4-AF5C-F751AAC5F133}.Release|x86.Build.0 = Release|Win32
        {E0EC2761-ABDE-4F89-937C-0B147FE26628}.Debug|x64.ActiveCfg = Debug|x64
        {E0EC2761-ABDE-4F89-937C-0B147FE26628}.Debug|x64.Build.0 = Debug|x64
        {E0EC2761-ABDE-4F89-937C-0B147FE26628}.Debug|x86.ActiveCfg = Debug|Win32
        {E0EC2761-ABDE-4F89-937C-0B147FE26628}.Debug|x86.Build.0 = Debug|Win32
        {E0EC2761-ABDE-4F89-937C-0B147FE26628}.Release|x64.ActiveCfg = Release|x64
        {E0EC2761-ABDE-4F89-937C-0B147FE26628}.Release|x64.Build.0 = Release|x64
        {E0EC2761-ABDE-4F89-937C-0B147FE26628}.Release|x86.ActiveCfg = Release|Win32
        {E0EC2761-ABDE-4F89-937C-0B147FE26628}.Release|x86.Build.0 = Release|Win32
        {7864134E-C538-4C0F-AF24-215FFCCBBAB4}.Debug|x64.ActiveCfg = Debug|x64
        {7864134E-C538-4C0F-AF24-215FFCCBBAB4}.Debug|x64.Build.0 = Debug|x64
        {7864134E-C538-4C0F-AF24-215FFCCBBAB4}.Debug|x86.ActiveCfg = Debug|Win32
        {7864134E-C538-4C0F-AF24-215FFCCBBAB4}.Debug|x86.Build.0 = Debug|Win32
        {7864134E-C538-4C0F-AF24-215FFCCBBAB4}.Release|x64.ActiveCfg = Release|x64
        {7864134E-C538-4C0F-AF24-215FFCCBBAB4}.Release|x64.Build.0 = Release|x64
        {7864134E-C538-4C0F-AF24-215FFCCBBAB4}.Release|x86.ActiveCfg = Release|Win32
        {7864134E-C538-4C0F-AF24-215FFCCBBAB4}.Release|x86.Build.0 = Release|Win32
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection
    GlobalSection(ExtensibilityGlobals) = postSolution
        SolutionGuid = {5E986E48-21B7-4EB6-97A1-49C49C727971}
    EndGlobalSection
EndGlobal
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,137 @@
// GangBond2860Emulator.cpp : å®šä¹‰åº”用程序的类行为。
//
#include "stdafx.h"
#include "GangBond2860Emulator.h"
#include "GangBond2860EmulatorDlg.h"
#include "HmTab.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define VERSION_NUMBER        1
#define VERSION_NAME        _T("1.0.2")
// CGangBond2860EmulatorApp
BEGIN_MESSAGE_MAP(CGangBond2860EmulatorApp, CWinApp)
    ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// CGangBond2860EmulatorApp æž„造
CGangBond2860EmulatorApp::CGangBond2860EmulatorApp()
{
    // æ”¯æŒé‡æ–°å¯åŠ¨ç®¡ç†å™¨
    m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
    // TODO: åœ¨æ­¤å¤„添加构造代码,
    // å°†æ‰€æœ‰é‡è¦çš„初始化放置在 InitInstance ä¸­
    // ç‰ˆæœ¬å·åŠç‰ˆæœ¬åç§°
    m_nVersionNumber = VERSION_NUMBER;
    m_strVersionName = VERSION_NAME;
}
// å”¯ä¸€çš„一个 CGangBond2860EmulatorApp å¯¹è±¡
CGangBond2860EmulatorApp theApp;
// CGangBond2860EmulatorApp åˆå§‹åŒ–
BOOL CGangBond2860EmulatorApp::InitInstance()
{
    // å¦‚果一个运行在 Windows XP ä¸Šçš„应用程序清单指定要
    // ä½¿ç”¨ ComCtl32.dll ç‰ˆæœ¬ 6 æˆ–更高版本来启用可视化方式,
    //则需要 InitCommonControlsEx()。  å¦åˆ™ï¼Œå°†æ— æ³•创建窗口。
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    // å°†å®ƒè®¾ç½®ä¸ºåŒ…括所有要在应用程序中使用的
    // å…¬å…±æŽ§ä»¶ç±»ã€‚
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);
    CWinApp::InitInstance();
    AfxEnableControlContainer();
    // åˆ›å»º shell ç®¡ç†å™¨ï¼Œä»¥é˜²å¯¹è¯æ¡†åŒ…含
    // ä»»ä½• shell æ ‘视图控件或 shell åˆ—表视图控件。
    CShellManager *pShellManager = new CShellManager;
    // æ¿€æ´»â€œWindows Native”视觉管理器,以便在 MFC æŽ§ä»¶ä¸­å¯ç”¨ä¸»é¢˜
    CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
    // æ ‡å‡†åˆå§‹åŒ–
    // å¦‚果未使用这些功能并希望减小
    // æœ€ç»ˆå¯æ‰§è¡Œæ–‡ä»¶çš„大小,则应移除下列
    // ä¸éœ€è¦çš„特定初始化例程
    // æ›´æ”¹ç”¨äºŽå­˜å‚¨è®¾ç½®çš„æ³¨å†Œè¡¨é¡¹
    // TODO: åº”适当修改该字符串,
    // ä¾‹å¦‚修改为公司或组织名
    SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
    // æœ¬ç¨‹åºæ–‡ä»¶ç›®å½•
    TCHAR sDrive[_MAX_DRIVE];
    TCHAR sDir[_MAX_DIR];
    TCHAR sFilename[_MAX_FNAME], sAppFilename[_MAX_FNAME];
    TCHAR sExt[_MAX_EXT];
    GetModuleFileName(AfxGetInstanceHandle(), sAppFilename, _MAX_FNAME);
    _tsplitpath_s(sAppFilename, sDrive, sDir, sFilename, sExt);
    m_strAppDir = CString(sDrive) + CString(sDir);
    m_strAppFile = CString(sFilename);
    // æŽ§ä»¶æ³¨å†Œ
    CHmTab::RegisterWndClass();
    // åˆå§‹åŒ–BEQ库
    BEQ_Initialize();
    CGangBond2860EmulatorDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
        // TODO: åœ¨æ­¤æ”¾ç½®å¤„理何时用
        //  â€œç¡®å®šâ€æ¥å…³é—­å¯¹è¯æ¡†çš„代码
    }
    else if (nResponse == IDCANCEL)
    {
        // TODO: åœ¨æ­¤æ”¾ç½®å¤„理何时用
        //  â€œå–消”来关闭对话框的代码
    }
    else if (nResponse == -1)
    {
        TRACE(traceAppMsg, 0, "警告: å¯¹è¯æ¡†åˆ›å»ºå¤±è´¥ï¼Œåº”用程序将意外终止。\n");
        TRACE(traceAppMsg, 0, "警告: å¦‚果您在对话框上使用 MFC æŽ§ä»¶ï¼Œåˆ™æ— æ³• #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
    }
    // åˆ é™¤ä¸Šé¢åˆ›å»ºçš„ shell ç®¡ç†å™¨ã€‚
    if (pShellManager != NULL)
    {
        delete pShellManager;
    }
    // ç”±äºŽå¯¹è¯æ¡†å·²å…³é—­ï¼Œæ‰€ä»¥å°†è¿”回 FALSE ä»¥ä¾¿é€€å‡ºåº”用程序,
    //  è€Œä¸æ˜¯å¯åŠ¨åº”ç”¨ç¨‹åºçš„æ¶ˆæ¯æ³µã€‚
    return FALSE;
}
int CGangBond2860EmulatorApp::ExitInstance()
{
    BEQ_Term();
    return CWinApp::ExitInstance();
}
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
// GangBond2860Emulator.h : PROJECT_NAME åº”用程序的主头文件
//
#pragma once
#ifndef __AFXWIN_H__
    #error "在包含此文件之前包含“stdafx.h”以生成 PCH æ–‡ä»¶"
#endif
#include "resource.h"        // ä¸»ç¬¦å·
#include "Model.h"
// CGangBond2860EmulatorApp:
// æœ‰å…³æ­¤ç±»çš„实现,请参阅 GangBond2860Emulator.cpp
//
class CGangBond2860EmulatorApp : public CWinApp
{
public:
    CGangBond2860EmulatorApp();
public:
    CString m_strAppDir;
    CString m_strAppFile;
    int m_nVersionNumber;
    CString m_strVersionName;
    CModel m_model;
// é‡å†™
public:
    virtual BOOL InitInstance();
// å®žçް
    DECLARE_MESSAGE_MAP()
    virtual int ExitInstance();
};
extern CGangBond2860EmulatorApp theApp;
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.rc
Binary files differ
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.vcxproj
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,236 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{E0EC2761-ABDE-4F89-937C-0B147FE26628}</ProjectGuid>
    <RootNamespace>GangBond2860Emulator</RootNamespace>
    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
    <Keyword>MFCProj</Keyword>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>MultiByte</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>MultiByte</CharacterSet>
    <UseOfMfc>Static</UseOfMfc>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="Shared">
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <ValidateAllParameters>true</ValidateAllParameters>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ResourceCompile>
      <Culture>0x0804</Culture>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="GangBond2860Emulator.h" />
    <ClInclude Include="GangBond2860EmulatorDlg.h" />
    <ClInclude Include="HmTab.h" />
    <ClInclude Include="Model.h" />
    <ClInclude Include="PageEquipment.h" />
    <ClInclude Include="PageUnit.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="stdafx.h" />
    <ClInclude Include="targetver.h" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="GangBond2860Emulator.cpp" />
    <ClCompile Include="GangBond2860EmulatorDlg.cpp" />
    <ClCompile Include="HmTab.cpp" />
    <ClCompile Include="Model.cpp" />
    <ClCompile Include="PageEquipment.cpp" />
    <ClCompile Include="PageUnit.cpp" />
    <ClCompile Include="stdafx.cpp">
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="GangBond2860Emulator.rc" />
  </ItemGroup>
  <ItemGroup>
    <None Include="res\GangBond2860Emulator.rc2" />
  </ItemGroup>
  <ItemGroup>
    <Image Include="res\GangBond2860Emulator.ico" />
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="res\application.exe.manifest" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
  <ProjectExtensions>
    <VisualStudio>
      <UserProperties RESOURCE_FILE="GangBond2860Emulator.rc" />
    </VisualStudio>
  </ProjectExtensions>
</Project>
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.vcxproj.filters
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="源文件">
      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
    </Filter>
    <Filter Include="头文件">
      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
    </Filter>
    <Filter Include="资源文件">
      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="GangBond2860Emulator.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="GangBond2860EmulatorDlg.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="stdafx.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="targetver.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Resource.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="HmTab.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="PageUnit.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="PageEquipment.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="Model.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="GangBond2860Emulator.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="GangBond2860EmulatorDlg.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="stdafx.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="HmTab.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="PageUnit.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="PageEquipment.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Model.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="GangBond2860Emulator.rc">
      <Filter>资源文件</Filter>
    </ResourceCompile>
  </ItemGroup>
  <ItemGroup>
    <None Include="res\GangBond2860Emulator.rc2">
      <Filter>资源文件</Filter>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Image Include="res\GangBond2860Emulator.ico">
      <Filter>资源文件</Filter>
    </Image>
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="res\application.exe.manifest" />
  </ItemGroup>
</Project>
SourceCode/Bond/GangBond2860Emulator/GangBond2860Emulator.vcxproj.user
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup />
</Project>
SourceCode/Bond/GangBond2860Emulator/GangBond2860EmulatorDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,274 @@
// GangBond2860EmulatorDlg.cpp : å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "GangBond2860Emulator.h"
#include "GangBond2860EmulatorDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// ç”¨äºŽåº”用程序“关于”菜单项的 CAboutDlg å¯¹è¯æ¡†
class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_ABOUTBOX };
#endif
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
// å®žçް
protected:
    DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CGangBond2860EmulatorDlg å¯¹è¯æ¡†
CGangBond2860EmulatorDlg::CGangBond2860EmulatorDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_GANGBOND2860EMULATOR_DIALOG, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_pTab = nullptr;
    m_crBkgnd = RGB(255, 255, 255);
    m_hbrBkgnd = nullptr;
    m_pPageEquipment = nullptr;
    m_pPageUnitA = nullptr;
    m_pPageUnitB = nullptr;
}
void CGangBond2860EmulatorDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CGangBond2860EmulatorDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_NOTIFY(BYHMTAB_SEL_CHANGED, IDC_HMTAB1, &CGangBond2860EmulatorDlg::OnTabSelChanged)
END_MESSAGE_MAP()
// CGangBond2860EmulatorDlg æ¶ˆæ¯å¤„理程序
BOOL CGangBond2860EmulatorDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // å°†â€œå…³äºŽ...”菜单项添加到系统菜单中。
    // IDM_ABOUTBOX å¿…须在系统命令范围内。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);
    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }
    // è®¾ç½®æ­¤å¯¹è¯æ¡†çš„图标。  å½“应用程序主窗口不是对话框时,框架将自动
    //  æ‰§è¡Œæ­¤æ“ä½œ
    SetIcon(m_hIcon, TRUE);            // è®¾ç½®å¤§å›¾æ ‡
    SetIcon(m_hIcon, FALSE);        // è®¾ç½®å°å›¾æ ‡
    // å­é¡µé¢
    m_pPageEquipment = new CPageEquipment();
    m_pPageEquipment->Create(IDD_PAGE_EQUIPMENT, this);
    m_pPageUnitA = new CPageUnit();
    m_pPageUnitA->Create(IDD_PAGE_UNIT, this);
    m_pPageUnitA->setName("UNITA");
    m_pPageUnitB = new CPageUnit();
    m_pPageUnitB->Create(IDD_PAGE_UNIT, this);
    m_pPageUnitB->setName("UNITB");
    // Tab
    m_pTab = CHmTab::Hook(GetDlgItem(IDC_HMTAB1)->m_hWnd);
    m_pTab->SetPaddingLeft(20);
    m_pTab->SetItemMarginLeft(18);
    m_pTab->SetBkgndColor(RGB(255, 255, 255));
    m_pTab->AddItem("机器信息", FALSE);
    m_pTab->AddItem("UNITA", FALSE);
    m_pTab->AddItem("UNITB", FALSE);
    m_pTab->SetCurSel(0);
    ShowChildPage(0);
    // ShowWindow(SW_MAXIMIZE);
    Resize();
    return TRUE;  // é™¤éžå°†ç„¦ç‚¹è®¾ç½®åˆ°æŽ§ä»¶ï¼Œå¦åˆ™è¿”回 TRUE
}
void CGangBond2860EmulatorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}
// å¦‚果向对话框添加最小化按钮,则需要下面的代码
//  æ¥ç»˜åˆ¶è¯¥å›¾æ ‡ã€‚  å¯¹äºŽä½¿ç”¨æ–‡æ¡£/视图模型的 MFC åº”用程序,
//  è¿™å°†ç”±æ¡†æž¶è‡ªåŠ¨å®Œæˆã€‚
void CGangBond2860EmulatorDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // ç”¨äºŽç»˜åˆ¶çš„设备上下文
        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
        // ä½¿å›¾æ ‡åœ¨å·¥ä½œåŒºçŸ©å½¢ä¸­å±…中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;
        // ç»˜åˆ¶å›¾æ ‡
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CGangBond2860EmulatorDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}
HBRUSH CGangBond2860EmulatorDlg::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 CGangBond2860EmulatorDlg::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_pPageEquipment != nullptr) {
        m_pPageEquipment->DestroyWindow();
        delete m_pPageEquipment;
        m_pPageEquipment = nullptr;
    }
    if (m_pPageUnitA != nullptr) {
        m_pPageUnitA->DestroyWindow();
        delete m_pPageUnitA;
        m_pPageUnitA = nullptr;
    }
    if (m_pPageUnitB != nullptr) {
        m_pPageUnitB->DestroyWindow();
        delete m_pPageUnitB;
        m_pPageUnitB = nullptr;
    }
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
}
void CGangBond2860EmulatorDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (GetDlgItem(IDC_HMTAB1) == nullptr) return;
    Resize();
}
void CGangBond2860EmulatorDlg::ShowChildPage(int index)
{
    ASSERT(0 <= index && index < 3);
    static CWnd* pPages[] = { m_pPageEquipment, m_pPageUnitA, m_pPageUnitB };
    for (int i = 0; i < 3; i++) {
        pPages[i]->ShowWindow(i == index ? SW_SHOW : SW_HIDE);
    }
}
void CGangBond2860EmulatorDlg::OnTabSelChanged(NMHDR* nmhdr, LRESULT* result)
{
    BYHMTAB_NMHDR* pNmhdrex = (BYHMTAB_NMHDR*)nmhdr;
    ShowChildPage((int)pNmhdrex->dwData);
    *result = 0;
}
void CGangBond2860EmulatorDlg::Resize()
{
    CRect rcClient, rcItem;
    GetClientRect(&rcClient);
    int x = 8;
    int y = 12;
    GetDlgItem(IDC_HMTAB1)->GetWindowRect(&rcItem);
    GetDlgItem(IDC_HMTAB1)->MoveWindow(x, y, rcClient.Width() - x * 2, rcItem.Height());
    y += rcItem.Height();
    y += 1;
    m_pPageEquipment->MoveWindow(x, y, rcClient.Width() - x * 2, rcClient.Height() - y);
    m_pPageUnitA->MoveWindow(x, y, rcClient.Width() - x * 2, rcClient.Height() - y);
    m_pPageUnitB->MoveWindow(x, y, rcClient.Width() - x * 2, rcClient.Height() - y);
}
SourceCode/Bond/GangBond2860Emulator/GangBond2860EmulatorDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
// GangBond2860EmulatorDlg.h : å¤´æ–‡ä»¶
//
#pragma once
#include "HmTab.h"
#include "PageEquipment.h"
#include "PageUnit.h"
// CGangBond2860EmulatorDlg å¯¹è¯æ¡†
class CGangBond2860EmulatorDlg : public CDialogEx
{
// æž„造
public:
    CGangBond2860EmulatorDlg(CWnd* pParent = NULL);    // æ ‡å‡†æž„造函数
private:
    void ShowChildPage(int index);
    void Resize();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    CHmTab* m_pTab;
    CPageEquipment* m_pPageEquipment;
    CPageUnit* m_pPageUnitA;
    CPageUnit* m_pPageUnitB;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_GANGBOND2860EMULATOR_DIALOG };
#endif
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
// å®žçް
protected:
    HICON m_hIcon;
    // ç”Ÿæˆçš„æ¶ˆæ¯æ˜ å°„函数
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    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 OnTabSelChanged(NMHDR* nmhdr, LRESULT* result);
};
SourceCode/Bond/GangBond2860Emulator/HmTab.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,529 @@
// HmTab.cpp: implementation of the CHmTab class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HmTab.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CHmTab::CHmTab()
{
    m_hWnd = NULL;
    m_crBkgnd = RGB(250, 250, 255);
    m_nPaddingLeft = 28;
    m_nPaddingBottom = 12;
    m_nItemMarginLeft = 8;
    m_crText[0] = RGB(88, 88, 88);
    m_crText[1] = RGB(18, 18, 18);
    m_pPressItem = nullptr;
    m_pHighItem = nullptr;
    LOGBRUSH lb;
    lb.lbColor = RGB(225, 127, 39);
    lb.lbHatch = 0;
    lb.lbStyle = BS_SOLID;
    DWORD iStyle = PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_SQUARE | PS_JOIN_MITER;
    m_hPenUnder[0] = ExtCreatePen(iStyle, 3, &lb, 0, NULL);
    lb.lbColor = RGB(225, 127, 39);
    m_hPenUnder[1] = ExtCreatePen(iStyle, 2, &lb, 0, NULL);
    lb.lbColor = RGB(223, 226, 230);
    m_hPenUnderWnd = ExtCreatePen(iStyle, 1, &lb, 0, NULL);
    m_nCurSel = 0;
}
CHmTab::~CHmTab()
{
    if (m_hPenUnder[0] != nullptr) {
        ::DeleteObject(m_hPenUnder[0]);
    }
    if (m_hPenUnder[1] != nullptr) {
        ::DeleteObject(m_hPenUnder[1]);
    }
    if (m_hPenUnderWnd != nullptr) {
        ::DeleteObject(m_hPenUnderWnd);
    }
}
BOOL CHmTab::RegisterWndClass()
{
    WNDCLASS wc;
    wc.lpszClassName = BYHMTAB_CLASS;
    wc.hInstance = AfxGetInstanceHandle();
    wc.lpfnWndProc = WindowProc;
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = 0;
    wc.lpszMenuName = NULL;
    wc.hbrBackground = NULL;
    wc.style = CS_GLOBALCLASS|CS_DBLCLKS;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    // æ³¨å†Œè‡ªå®šä¹‰ç±»
    return (::RegisterClass(&wc) != 0);
}
CHmTab* CHmTab::Hook(HWND hWnd)
{
    CHmTab* pHmTab = (CHmTab*)GetProp(hWnd, BYSTAG_HMTAB);
    if(pHmTab == NULL)
    {
        pHmTab = new CHmTab;
        pHmTab->m_hWnd = hWnd;
        SetProp(hWnd, BYSTAG_HMTAB, (HANDLE)pHmTab);
    }
    return pHmTab;
}
void CHmTab::Release()
{
    // delete
    delete this;
}
void CHmTab::SetPaddingLeft(int value)
{
    m_nPaddingLeft = value;
}
void CHmTab::SetItemMarginLeft(int value)
{
    m_nItemMarginLeft = value;
}
void CHmTab::SetTextColor(COLORREF color1, COLORREF color2)
{
    m_crText[0] = color1;
    m_crText[1] = color2;
    InvalidateRect(m_hWnd, NULL, TRUE);
}
int CHmTab::AddItem(const char* pszText,BOOL bUpdate/* = TRUE*/)
{
    HMTABITEM item;
    memset(&item, 0, sizeof(HMTABITEM));
    strcpy_s(item.szText, MHITEM_TEXT_MAX, pszText);
    m_items.push_back(item);
    if (bUpdate) {
        InvalidateRect(m_hWnd, NULL, TRUE);
    }
    return 0;
}
int CHmTab::DeleteItem(const char* pszText, BOOL bUpdate/* = TRUE*/)
{
    for (auto iter = m_items.begin(); iter != m_items.end(); iter++) {
        if (strcmp((*iter).szText, pszText) == 0) {
            m_items.erase(iter);
            break;
        }
    }
    if (bUpdate) {
        InvalidateRect(m_hWnd, NULL, TRUE);
    }
    return 0;
}
void CHmTab::Notify(int nCode, DWORD_PTR dwData, DWORD_PTR dwData1/* = 0*/, DWORD_PTR dwData2/* = 0*/)
{
    HWND hParent;
    hParent = GetParent(m_hWnd);
    if (hParent != NULL) {
        BYHMTAB_NMHDR iii_nmhdr;
        iii_nmhdr.nmhdr.hwndFrom = m_hWnd;
        iii_nmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
        iii_nmhdr.nmhdr.code = nCode;
        iii_nmhdr.dwData = dwData;
        iii_nmhdr.dwData1 = dwData1;
        iii_nmhdr.dwData2 = dwData2;
        SendMessage(hParent, WM_NOTIFY, (WPARAM)iii_nmhdr.nmhdr.idFrom, (LPARAM)&iii_nmhdr);
    }
}
////////////////////////////////
// æ‹¦æˆªçª—口消息函数
LRESULT CALLBACK CHmTab::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CHmTab* pHmTab = (CHmTab *)GetProp(hWnd, BYSTAG_HMTAB);
    if(pHmTab == NULL && uMsg != WM_NCCREATE)
    {
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    // å¦‚æžœHook则响应消息
    ASSERT(hWnd);
    switch(uMsg)
    {
    case WM_NCCREATE:
        return OnNcCreate(hWnd, wParam, lParam);
    case WM_DESTROY:
        return pHmTab->OnDestroy(wParam, lParam);
    case WM_PAINT:
        return pHmTab->OnPaint(wParam, lParam);
    case WM_TIMER:
        return pHmTab->OnTimer(wParam, lParam);
    case WM_MOUSEMOVE:
        return pHmTab->OnMouseMove(wParam, lParam);
    case WM_LBUTTONDOWN:
        return pHmTab->OnLButtonDown(wParam, lParam);
    case WM_SETCURSOR:
        return pHmTab->OnSetCursor(wParam, lParam);
    case WM_SIZE:
        return pHmTab->OnSize(wParam, lParam);
    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS;
    default:
        break;
    }
    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
///////////////////////////////
// WM_NCCREATE
// çª—口创建前的初始化工作
LRESULT CHmTab::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    CHmTab* pHmTab = (CHmTab *)GetProp(hWnd, BYSTAG_HMTAB);
    ASSERT(pHmTab == NULL);
    Hook(hWnd);
    return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
}
///////////////////////////////
// WM_DESTROY
LRESULT CHmTab::OnDestroy(WPARAM wParam, LPARAM lParam)
{
    Release();
    return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
}
///////////////////////////////
// WM_TIMER
LRESULT CHmTab::OnTimer(WPARAM wParam, LPARAM lParam)
{
    if (wParam == 1) {
        POINT pt;
        GetCursorPos(&pt);
        ::ScreenToClient(m_hWnd, &pt);
        HMTABITEM* pLastHighItem = m_pHighItem;
        HighTest(pt, m_pHighItem, nullptr);
        if (m_pHighItem != pLastHighItem) {
            ::InvalidateRect(m_hWnd, NULL, TRUE);
        }
        if (m_pHighItem == nullptr) {
            ::KillTimer(m_hWnd, 1);
        }
    }
    return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
}
///////////////////////////////
// WM_MOUSEMOVE
LRESULT CHmTab::OnMouseMove(WPARAM wParam, LPARAM lParam)
{
    POINT pt;
    pt.x = LOWORD(lParam);
    pt.y = HIWORD(lParam);
    HMTABITEM* pLastHighItem = m_pHighItem;
    int nHitCode = HighTest(pt, m_pHighItem, nullptr);
    if (m_pHighItem != pLastHighItem) {
        RECT rcClient;
        GetClientRect(m_hWnd, &rcClient);
        ::InvalidateRect(m_hWnd, &rcClient, TRUE);
    }
    if (m_pHighItem != NULL) {
        ::KillTimer(m_hWnd, 1);
        ::SetTimer(m_hWnd, 1, 100, NULL);
    }
    ::SetProp(m_hWnd, HMTAB_HITCODETEST, (HANDLE)(__int64)nHitCode);
    return ::DefWindowProc(m_hWnd, WM_MOUSEMOVE, wParam, lParam);
}
/*
 * WM_LBUTTONDOWN
 * é¼ æ ‡å·¦é”®æŒ‰ä¸‹
 */
LRESULT CHmTab::OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
    POINT pt, ptNew;
    pt.x = LOWORD(lParam);
    pt.y = HIWORD(lParam);
    BOOL bButtonUp = FALSE;
    int nClickIndex = -1;
    HighTest(pt, m_pPressItem, &nClickIndex);
    if (m_pPressItem != NULL) {
        m_pHighItem = NULL;
        ::InvalidateRect(m_hWnd, NULL, TRUE);
    }
    // æ•捉鼠标消息,检测是否拖动
    HMTABITEM* pPressItem = NULL;
    if (m_pPressItem != NULL) {
        ::KillTimer(m_hWnd, 1);
        if (::GetCapture() == NULL) {
            SetCapture(m_hWnd);
            ASSERT(m_hWnd == GetCapture());
            AfxLockTempMaps();
            for (;;)
            {
                MSG msg;
                VERIFY(::GetMessage(&msg, NULL, 0, 0));
                if (GetCapture() != m_hWnd) break;
                switch (msg.message)
                {
                case WM_MOUSEMOVE:
                    ptNew = msg.pt;
                    ::ScreenToClient(m_hWnd, &ptNew);
                    HighTest(ptNew, pPressItem, &nClickIndex);
                    if (pPressItem != m_pPressItem) {
                        m_pPressItem = nullptr;
                        ::InvalidateRect(m_hWnd, NULL, TRUE);
                    }
                    break;
                case WM_LBUTTONUP:
                    ptNew = msg.pt;
                    ::ScreenToClient(m_hWnd, &ptNew);
                    HighTest(ptNew, pPressItem, &nClickIndex);
                    if (m_pPressItem != nullptr && pPressItem == m_pPressItem) {
                        m_nCurSel = nClickIndex;
                        bButtonUp = TRUE;
                    }
                    goto ExitLoop;
                case WM_KEYDOWN:
                    if (msg.wParam == VK_ESCAPE) {
                        goto ExitLoop;
                    }
                    break;
                default:
                    DispatchMessage(&msg);
                    break;
                }
            }
        ExitLoop:
            m_pPressItem = NULL;
            ReleaseCapture();
            ::InvalidateRect(m_hWnd, NULL, TRUE);
            if (bButtonUp) {
                Notify((int)BYHMTAB_SEL_CHANGED, m_nCurSel);
            }
            AfxUnlockTempMaps(FALSE);
        }
    }
    return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
}
///////////////////////////////
// WM_SETCURSOR
LRESULT CHmTab::OnSetCursor(WPARAM wParam, LPARAM lParam)
{
    int nHitCode = (int)(__int64)GetProp(m_hWnd, HMTAB_HITCODETEST);
    switch (nHitCode)
    {
    case HMTAB_HT_NOWHERE:
    case HMTAB_HT_ITEM:
        SetCursor(::LoadCursor(NULL, IDC_ARROW));
        return TRUE;
    case HMTAB_HT_HIGT_ITEM:
        SetCursor(::LoadCursor(NULL, IDC_HAND));
        return TRUE;
    default:
        break;
    }
    return ::DefWindowProc(m_hWnd, WM_SETCURSOR, wParam, lParam);
}
/*
 * WM_SIZE
 */
LRESULT CHmTab::OnSize(WPARAM wParam, LPARAM lParam)
{
    ::InvalidateRect(m_hWnd, NULL, TRUE);
    return ::DefWindowProc(m_hWnd, WM_SIZE, wParam, lParam);
}
///////////////////////////////
// WM_PAINT
LRESULT CHmTab::OnPaint(WPARAM wParam, LPARAM lParam)
{
    HDC hDC, hMemDC;
    HBITMAP hBitmap;
    RECT rcClient;
    CString strText;
    HFONT hFont1, hFont2;
    HBRUSH hBrushBK;
    // BeginPaint
    PAINTSTRUCT ps;
    hDC = BeginPaint(m_hWnd, &ps);
    GetClientRect(m_hWnd, &rcClient);
    hMemDC = ::CreateCompatibleDC(hDC);
    hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left,
        rcClient.bottom - rcClient.top);
    ::SelectObject(hMemDC, hBitmap);
    ::SetBkMode(hMemDC, TRANSPARENT);
    HFONT hFontDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    CFont* pFont = CFont::FromHandle(hFontDefault);
    LOGFONT lf;
    pFont->GetLogFont(&lf);
    hFont1 = ::CreateFontIndirect(&lf);
    lf.lfHeight -= 5;
    hFont2 = ::CreateFontIndirect(&lf);
    // èƒŒæ™¯é¢œè‰²
    hBrushBK = CreateSolidBrush(m_crBkgnd);
    ::FillRect(hMemDC, &rcClient, hBrushBK);
    DeleteObject(hBrushBK);
    SelectObject(hMemDC, m_hPenUnderWnd);
    ::MoveToEx(hMemDC, rcClient.left, rcClient.bottom - 2, NULL);
    ::LineTo(hMemDC, rcClient.right, rcClient.bottom - 2);
    // ç»˜åˆ¶å­é¡¹
    SIZE sizeItem;
    RECT rcItem, rcText;
    rcItem.top = rcClient.top;
    rcItem.bottom = rcClient.bottom-1;
    rcItem.left = m_nPaddingLeft;
    int index = 0;
    for (int i = 0; i < m_items.size(); i++) {
        auto& item = m_items.at(i);
        ::SelectObject(hMemDC, i == m_nCurSel ? hFont2 : hFont1);
        ::SetTextColor(hMemDC, i == m_nCurSel ? m_crText[1] : m_crText[0]);
        ::GetTextExtentPoint32(hMemDC, item.szText, (int)strlen(item.szText), &sizeItem);
        rcItem.left += m_nItemMarginLeft;
        rcItem.right = rcItem.left + (int)sizeItem.cx;
        ::CopyRect(&rcText, &rcItem);
        rcText.bottom -= m_nPaddingBottom;
        ::DrawText(hMemDC, item.szText, (int)strlen(item.szText), &rcText,
            DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_END_ELLIPSIS);
        ::CopyRect(&item.rect, &rcItem);
        // ä¸‹åˆ’线?
        if (i == m_nCurSel || &item == m_pHighItem) {
            HPEN hOldPen = (HPEN)::SelectObject(hMemDC, i == m_nCurSel ? m_hPenUnder[0] : m_hPenUnder[1]);
            ::MoveToEx(hMemDC, item.rect.left, item.rect.bottom - 3, NULL);
            ::LineTo(hMemDC, item.rect.right, item.rect.bottom - 3);
            ::SelectObject(hMemDC, hOldPen);
        }
        index++;
        rcItem.left = rcItem.right;
    }
    ::DeleteObject(hFont1);
    ::DeleteObject(hFont2);
    // EndPaint
    ::BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
        hMemDC, 0, 0, SRCCOPY);
    EndPaint(m_hWnd, &ps);
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
    return 1;
}
void CHmTab::SetBkgndColor(COLORREF cr)
{
    m_crBkgnd = cr;
}
/*
 * æ£€æµ‹åæ ‡ç‚¹æ‰€åœ¨çš„项
 * è¿”回, TYGTLITEM
 */
int CHmTab::HighTest(POINT pt, OUT HMTABITEM*& pItem, int* pnIndex)
{
    // æ£€æµ‹æ˜¯å¦åœ¨æŸä¸ªå­é¡¹
    int nRet = HMTAB_HT_NOWHERE;
    pItem = NULL;
    for (int i = 0; i < m_items.size(); i++) {
        auto& item = m_items.at(i);
        if (::PtInRect(&item.rect, pt)) {
            pItem = &item;
            nRet = pItem == m_pHighItem ? HMTAB_HT_HIGT_ITEM : HMTAB_HT_ITEM;
            if (pnIndex != nullptr) *pnIndex = i;
            break;
        }
    }
    return nRet;
}
int CHmTab::GetCurSel()
{
    return m_nCurSel;
}
void CHmTab::SetCurSel(int index)
{
    if (0 <= index && index <= m_items.size()) {
        m_nCurSel = index;
        InvalidateRect(m_hWnd, NULL, TRUE);
    }
}
int CHmTab::GetItemCount()
{
    return (int)m_items.size();
}
在上述文件截断后对比
SourceCode/Bond/GangBond2860Emulator/HmTab.h SourceCode/Bond/GangBond2860Emulator/Model.cpp SourceCode/Bond/GangBond2860Emulator/Model.h SourceCode/Bond/GangBond2860Emulator/PageEquipment.cpp SourceCode/Bond/GangBond2860Emulator/PageEquipment.h SourceCode/Bond/GangBond2860Emulator/PageUnit.cpp SourceCode/Bond/GangBond2860Emulator/PageUnit.h SourceCode/Bond/GangBond2860Emulator/ReadMe.txt SourceCode/Bond/GangBond2860Emulator/Resource.h SourceCode/Bond/GangBond2860Emulator/res/GangBond2860Emulator.ico SourceCode/Bond/GangBond2860Emulator/res/GangBond2860Emulator.rc2 SourceCode/Bond/GangBond2860Emulator/res/application.exe.manifest SourceCode/Bond/GangBond2860Emulator/stdafx.cpp SourceCode/Bond/GangBond2860Emulator/stdafx.h SourceCode/Bond/GangBond2860Emulator/targetver.h SourceCode/Bond/RxWindows1.0/include/IAny.h SourceCode/Bond/RxWindows1.0/include/IObservable.h SourceCode/Bond/RxWindows1.0/include/IObservableEmitter.h SourceCode/Bond/RxWindows1.0/include/IObserver.h SourceCode/Bond/RxWindows1.0/include/IRxObject.h SourceCode/Bond/RxWindows1.0/include/IRxWindows.h SourceCode/Bond/RxWindows1.0/include/IThrowable.h SourceCode/Bond/RxWindows1.0/include/RxWindowsLib.h SourceCode/Bond/x64/Debug/AlarmList.txt SourceCode/Bond/x64/Debug/Config/BondServo.db SourceCode/Bond/x64/Debug/Res/Operator_Gray_32.ico SourceCode/Bond/x64/Debug/Res/Operator_High_32.ico SourceCode/Bond/x64/Debug/Res/Run_Gray_32.ico SourceCode/Bond/x64/Debug/Res/Run_High_32.ico SourceCode/Bond/x64/Debug/Res/Settings_Gray_32.ico SourceCode/Bond/x64/Debug/Res/Settings_High_32.ico SourceCode/Bond/x64/Debug/Res/Stop_Gray_32.ico SourceCode/Bond/x64/Debug/Res/Stop_High_32.ico SourceCode/Bond/x64/Debug/Res/arrow_down.ico SourceCode/Bond/x64/Debug/Res/arrow_right.ico SourceCode/Bond/x64/Debug/Res/indicator_check_24.ico SourceCode/Bond/x64/Debug/Res/indicator_check_28.ico SourceCode/Bond/x64/Debug/Res/indicator_check_32.ico SourceCode/Bond/x64/Debug/Res/indicator_check_32_dark.ico SourceCode/Bond/x64/Debug/Res/indicator_check_32_dark2.ico SourceCode/Bond/x64/Debug/Res/logcat_include.ico SourceCode/Bond/x64/Debug/Res/remote_eq_dark_32.ico SourceCode/Bond/x64/Debug/Res/remote_eq_light_32.ico SourceCode/Bond/x64/Debug/Res/small_close0.ico SourceCode/Bond/x64/Debug/Res/small_close1.ico SourceCode/Bond/x64/Debug/Res/small_close2.ico SourceCode/Bond/x64/Debug/Res/small_close3.ico SourceCode/Bond/x64/Release/AlarmList.txt SourceCode/Bond/x64/Release/Res/arrow_down.ico SourceCode/Bond/x64/Release/Res/arrow_right.ico SourceCode/Bond/x64/Release/Res/small_close0.ico SourceCode/Bond/x64/Release/Res/small_close1.ico SourceCode/Bond/x64/Release/Res/small_close2.ico SourceCode/Bond/x64/Release/Res/small_close3.ico SourceCode/Bond/x64/Release/configuration.ini