From 94e388265ca97ba07b102c295529fd40b04b419d Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期一, 26 五月 2025 15:26:09 +0800
Subject: [PATCH] 1.增加顶部工具条; 2.Robot cmd测试页面增加Robot命令的响应结果; 3.CMaster增加start, stop函数,准备编写调试逻辑;

---
 SourceCode/Bond/Servo/CPageGraph2.cpp           |   40 ----
 SourceCode/Bond/Servo/Servo.vcxproj             |    4 
 SourceCode/Bond/Servo/resource.h                |    0 
 SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp      |   71 ++++---
 SourceCode/Bond/Servo/Servo.cpp                 |    2 
 SourceCode/Bond/Servo/CEFEM.h                   |   30 +-
 SourceCode/Bond/Servo/CMaster.h                 |    2 
 SourceCode/Bond/Servo/Model.cpp                 |    5 
 SourceCode/Bond/Servo/ServoDlg.cpp              |   48 ++++
 SourceCode/Bond/Servo/CRobotCmdTestDlg.h        |    2 
 SourceCode/Bond/Servo/Servo.vcxproj.filters     |    4 
 SourceCode/Bond/x64/Debug/Res/robot_High_32.ico |    0 
 SourceCode/Bond/Servo/TopToolbar.h              |   58 +++++
 SourceCode/Bond/Servo/Model.h                   |    1 
 SourceCode/Bond/Servo/Servo.rc                  |    0 
 SourceCode/Bond/Servo/TopToolbar.cpp            |  218 +++++++++++++++++++++
 SourceCode/Bond/Servo/CEFEM.cpp                 |   60 +++---
 SourceCode/Bond/Servo/CMaster.cpp               |   12 +
 SourceCode/Bond/x64/Debug/Res/robot_Gray_32.ico |    0 
 SourceCode/Bond/Servo/Common.h                  |    2 
 SourceCode/Bond/Servo/ServoDlg.h                |    3 
 21 files changed, 444 insertions(+), 118 deletions(-)

diff --git a/SourceCode/Bond/Servo/CEFEM.cpp b/SourceCode/Bond/Servo/CEFEM.cpp
index 05e7074..3918098 100644
--- a/SourceCode/Bond/Servo/CEFEM.cpp
+++ b/SourceCode/Bond/Servo/CEFEM.cpp
@@ -126,15 +126,15 @@
 		return 0;
 	}
 
-	int CEFEM::SendHome(int seq)
+	int CEFEM::robotSendHome(int seq, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
 		cmd.rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot)
+	int CEFEM::robotSendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -144,10 +144,10 @@
 		cmd.getSlotNo = static_cast<short>(fromSlot);
 		cmd.putPosition = static_cast<short>(toPos);
 		cmd.putSlotNo = static_cast<short>(toSlot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendMoveToGet(int seq, int armNo, int pos, int slot)
+	int CEFEM::robotSendMoveToGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -156,10 +156,10 @@
 		cmd.getPosition = static_cast<short>(pos);
 		cmd.getSlotNo = static_cast<short>(slot);
 		cmd.subCmd = 1;
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendMoveToPut(int seq, int armNo, int pos, int slot)
+	int CEFEM::robotSendMoveToPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -168,10 +168,10 @@
 		cmd.putPosition = static_cast<short>(pos);
 		cmd.putSlotNo = static_cast<short>(slot);
 		cmd.subCmd = 2;
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendGet(int seq, int armNo, int pos, int slot)
+	int CEFEM::robotSendGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -179,10 +179,10 @@
 		cmd.armNo = static_cast<short>(armNo);
 		cmd.getPosition = static_cast<short>(pos);
 		cmd.getSlotNo = static_cast<short>(slot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendPut(int seq, int armNo, int pos, int slot)
+	int CEFEM::robotSendPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -190,10 +190,10 @@
 		cmd.armNo = static_cast<short>(armNo);
 		cmd.putPosition = static_cast<short>(pos);
 		cmd.putSlotNo = static_cast<short>(slot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendExchange(int seq, int armNo, int pos, int getSlot, int putSlot)
+	int CEFEM::robotSendExchange(int seq, int armNo, int pos, int getSlot, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -203,18 +203,18 @@
 		cmd.putPosition = static_cast<short>(pos);
 		cmd.getSlotNo = static_cast<short>(getSlot);
 		cmd.putSlotNo = static_cast<short>(putSlot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendCommandClear(int seq)
+	int CEFEM::robotSendCommandClear(int seq, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
 		cmd.rcmd = static_cast<short>(SERVO::RCMD::Command_Clear);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendBatchGet(int seq, int getPos, int getSlot)
+	int CEFEM::robotSendBatchGet(int seq, int getPos, int getSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -222,10 +222,10 @@
 		cmd.armNo = ARM_ALL;
 		cmd.getPosition = static_cast<short>(getPos);
 		cmd.getSlotNo = static_cast<short>(getSlot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendBatchPut(int seq, int putPos, int putSlot)
+	int CEFEM::robotSendBatchPut(int seq, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -233,10 +233,10 @@
 		cmd.armNo = ARM_ALL;
 		cmd.putPosition = static_cast<short>(putPos);
 		cmd.putSlotNo = static_cast<short>(putSlot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot)
+	int CEFEM::robotSendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmds[2] = {};
 
@@ -252,10 +252,10 @@
 		cmds[1].sequenceNo = static_cast<short>(seq + 1);
 		cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
 
-		return robotCmds(cmds, 2);
+		return robotCmds(cmds, 2, onWritedBlock);
 	}
 
-	int CEFEM::SendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot)
+	int CEFEM::robotSendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmds[2] = {};
 
@@ -271,10 +271,10 @@
 		cmds[1].sequenceNo = static_cast<short>(seq + 1);
 		cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
 
-		return robotCmds(cmds, 2);
+		return robotCmds(cmds, 2, onWritedBlock);
 	}
 
-	int CEFEM::SendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot)
+	int CEFEM::robotSendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmds[2] = {};
 
@@ -291,10 +291,10 @@
 		cmds[1].sequenceNo = static_cast<short>(seq + 1);
 		cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
 
-		return robotCmds(cmds, 2);
+		return robotCmds(cmds, 2, onWritedBlock);
 	}
 
-	int CEFEM::SendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot)
+	int CEFEM::robotSendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmds[2] = {};
 
@@ -310,10 +310,10 @@
 		cmds[1].putPosition = static_cast<short>(putPos);
 		cmds[1].putSlotNo = static_cast<short>(putSlot);
 
-		return robotCmds(cmds, 2);
+		return robotCmds(cmds, 2, onWritedBlock);
 	}
 
-	int CEFEM::SendPutAndHome(int seq, int armNo, int putPos, int putSlot)
+	int CEFEM::robotSendPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmds[2] = {};
 
@@ -328,7 +328,7 @@
 		cmds[1].sequenceNo = static_cast<short>(seq + 1);
 		cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
 
-		return robotCmds(cmds, 2);
+		return robotCmds(cmds, 2, onWritedBlock);
 	}
 
 	void CEFEM::init()
diff --git a/SourceCode/Bond/Servo/CEFEM.h b/SourceCode/Bond/Servo/CEFEM.h
index d8a4e1b..997f22d 100644
--- a/SourceCode/Bond/Servo/CEFEM.h
+++ b/SourceCode/Bond/Servo/CEFEM.h
@@ -41,21 +41,21 @@
         int robotCmds(ROBOT_CMD_PARAM* robotCmdParam, unsigned int count, ONWRITED onWritedBlock = nullptr);
 
         // 快捷封装
-        int SendHome(int seq);
-        int SendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot);
-        int SendMoveToGet(int seq, int armNo, int pos, int slot);
-        int SendMoveToPut(int seq, int armNo, int pos, int slot);
-        int SendGet(int seq, int armNo, int pos, int slot);
-        int SendPut(int seq, int armNo, int pos, int slot);
-        int SendExchange(int seq, int armNo, int pos, int getSlot, int putSlot);
-        int SendCommandClear(int seq);
-        int SendBatchGet(int seq, int getPos, int getSlot);
-        int SendBatchPut(int seq, int putPos, int putSlot);
-        int SendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot);
-        int SendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot);
-        int SendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot);
-        int SendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot);
-        int SendPutAndHome(int seq, int armNo, int putPos, int putSlot);
+        int robotSendHome(int seq, ONWRITED onWritedBlock = nullptr);
+        int robotSendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendMoveToGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
+        int robotSendMoveToPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
+        int robotSendGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
+        int robotSendPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
+        int robotSendExchange(int seq, int armNo, int pos, int getSlot, int putSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendCommandClear(int seq, ONWRITED onWritedBlock = nullptr);
+        int robotSendBatchGet(int seq, int getPos, int getSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendBatchPut(int seq, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
 
     private:
         CLoadPort* m_pPort[4];
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index e148025..79e3277 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -188,6 +188,18 @@
 		return 0;
 	}
 
+	int CMaster::start()
+	{
+		AfxMessageBox("start");
+		return 0;
+	}
+
+	int CMaster::stop()
+	{
+		AfxMessageBox("stop");
+		return 0;
+	}
+
 	unsigned CMaster::ReadBitsProc()
 	{
 		while (1) {
diff --git a/SourceCode/Bond/Servo/CMaster.h b/SourceCode/Bond/Servo/CMaster.h
index fbd76cf..2a0286b 100644
--- a/SourceCode/Bond/Servo/CMaster.h
+++ b/SourceCode/Bond/Servo/CMaster.h
@@ -40,6 +40,8 @@
         void setListener(MasterListener listener);
         int init();
         int term();
+        int start();
+        int stop();
         unsigned ReadBitsProc();
         void onTimer(UINT nTimerid);
         std::list<CEquipment*>& getEquipmentList();
diff --git a/SourceCode/Bond/Servo/CPageGraph2.cpp b/SourceCode/Bond/Servo/CPageGraph2.cpp
index 7e4811e..7f3da57 100644
--- a/SourceCode/Bond/Servo/CPageGraph2.cpp
+++ b/SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -13,8 +13,6 @@
 #include "CPagePortStatus.h"
 #include "CPageCassetteCtrlCmd.h"
 #include "CJobDataB.h"
-#include "CRobotCmdContainerDlg.h"
-#include "CRobotCmdTestDlg.h"
 
 
 // CPageGraph2 瀵硅瘽妗�
@@ -254,44 +252,6 @@
 		}
 		else if (nCmd == ID_EQSGRAPHITEM_TEST4) {
 			SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
-
-			/* 娴嬭瘯 RobotCMD */
-			if (pEquipment->getID() == EQ_ID_EFEM) {
-				SERVO::CEFEM* pEFEM = (SERVO::CEFEM*)pEquipment;
-
-				//SERVO::ROBOT_CMD_PARAM cmds[4];
-				//cmds[0].sequenceNo = 1;
-				//cmds[0].rcmd = (short)SERVO::RCMD::Move;
-				//cmds[0].armNo = 1;
-				//cmds[0].getPosition = 1;
-				//cmds[0].putPosition = 2;
-				//cmds[0].getSlotNo = 3;
-				//cmds[0].putSlotNo = 4;
-				//cmds[0].subCmd = 5;
-				//cmds[1].sequenceNo = 2;
-				//cmds[1].rcmd = (short)SERVO::RCMD::Transfer;
-				//cmds[1].armNo = 2;
-				//cmds[1].getPosition = 6;
-				//cmds[1].putPosition = 7;
-				//cmds[1].getSlotNo = 8;
-				//cmds[1].putSlotNo = 9;
-				//cmds[1].subCmd = 10;
-				//pEFEM->robotCmds(cmds, 2);
-
-				//CRobotCmdContainerDlg dlg;
-				//if (dlg.DoModal() == IDOK) {
-				//	std::vector<SERVO::ROBOT_CMD_PARAM>& cmds = dlg.GetResultCmds();
-				//	if (!cmds.empty()) {
-				//		pEFEM->robotCmds(cmds.data(), (int)cmds.size());
-				//	}
-				//}
-
-				CRobotCmdTestDlg dlg;
-				dlg.SetEFEM(pEFEM);
-				dlg.DoModal();
-			}
-
-
 
 
 			// 娴嬭瘯涓嬪彂Cim Message
diff --git a/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp b/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
index 0a41147..ea62463 100644
--- a/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
+++ b/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
@@ -127,64 +127,64 @@
 
 	// 蹇嵎鍛戒护鎵ц鏄犲皠琛�
 	m_mapCmdExec = {
-		{_T("SendHome"), [this](int seq, int, int, int, int, int) {
-			return m_pEFEM->SendHome(seq);
+		{_T("SendHome"), [this](int seq, int, int, int, int, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendHome(seq, onWritedBlock);
 		}},
 
-		{_T("SendTransfer"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
-			return m_pEFEM->SendTransfer(seq, armNo, getPos, putPos, getSlot, putSlot);
+		{_T("SendTransfer"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendTransfer(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
 		}},
 
-		{_T("SendMoveToGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
-			return m_pEFEM->SendMoveToGet(seq, armNo, pos, slot);
+		{_T("SendMoveToGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendMoveToGet(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendMoveToPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
-			return m_pEFEM->SendMoveToPut(seq, armNo, pos, slot);
+		{_T("SendMoveToPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendMoveToPut(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
-			return m_pEFEM->SendGet(seq, armNo, pos, slot);
+		{_T("SendGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendGet(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
-			return m_pEFEM->SendPut(seq, armNo, pos, slot);
+		{_T("SendPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendPut(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendExchange"), [this](int seq, int armNo, int pos, int, int getSlot, int putSlot) {
-			return m_pEFEM->SendExchange(seq, armNo, pos, getSlot, putSlot);
+		{_T("SendExchange"), [this](int seq, int armNo, int pos, int, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendExchange(seq, armNo, pos, getSlot, putSlot, onWritedBlock);
 		}},
 
-		{_T("SendCommandClear"), [this](int seq, int, int, int, int, int) {
-			return m_pEFEM->SendCommandClear(seq);
+		{_T("SendCommandClear"), [this](int seq, int, int, int, int, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendCommandClear(seq, onWritedBlock);
 		}},
 
-		{_T("SendBatchGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
-			return m_pEFEM->SendBatchGet(seq, pos, slot);
+		{_T("SendBatchGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendBatchGet(seq, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendBatchPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
-			return m_pEFEM->SendBatchPut(seq, pos, slot);
+		{_T("SendBatchPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendBatchPut(seq, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendMoveToGetAndHome"), [this](int seq, int armNo, int pos, int, int slot, int) {
-			return m_pEFEM->SendMoveToGetAndHome(seq, armNo, pos, slot);
+		{_T("SendMoveToGetAndHome"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendMoveToGetAndHome(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendMoveToPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot) {
-			return m_pEFEM->SendMoveToPutAndHome(seq, armNo, pos, slot);
+		{_T("SendMoveToPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendMoveToPutAndHome(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendTransferAndHome"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
-			return m_pEFEM->SendTransferAndHome(seq, armNo, getPos, putPos, getSlot, putSlot);
+		{_T("SendTransferAndHome"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendTransferAndHome(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
 		}},
 
-		{_T("SendGetAndPut"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
-			return m_pEFEM->SendGetAndPut(seq, armNo, getPos, putPos, getSlot, putSlot);
+		{_T("SendGetAndPut"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendGetAndPut(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
 		}},
 
-		{_T("SendPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot) {
-			return m_pEFEM->SendPutAndHome(seq, armNo, pos, slot);
+		{_T("SendPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendPutAndHome(seq, armNo, pos, slot, onWritedBlock);
 		}}
 	};
 
@@ -333,7 +333,16 @@
 	// 鏌ユ壘鍑芥暟骞舵墽琛�
 	auto it = m_mapCmdExec.find(cmdName);
 	if (it != m_mapCmdExec.end() && nullptr != m_pEFEM) {
-		int ret = it->second(1, armNo, getPos, getSlot, putPos, putSlot);
+		int ret = it->second(1, armNo, getPos, getSlot, putPos, putSlot, [&](int code) -> int {
+			if (code == WOK) {
+				AppendLogLineRichStyled(_T("宸叉敹鍒癛obot鍥炲簲锛�"), LOG_COLOR_SUCCESS);
+			}
+			else {
+				AppendLogLineRichStyled(_T("鏈敹鍒癛obot鍥炲簲锛�"), LOG_COLOR_ERROR);
+			}
+
+			return 0;
+			});
 
 		CString log;
 		if (ret == 0) {
diff --git a/SourceCode/Bond/Servo/CRobotCmdTestDlg.h b/SourceCode/Bond/Servo/CRobotCmdTestDlg.h
index 065ee0a..c605e58 100644
--- a/SourceCode/Bond/Servo/CRobotCmdTestDlg.h
+++ b/SourceCode/Bond/Servo/CRobotCmdTestDlg.h
@@ -3,7 +3,7 @@
 #include <afxrich.h>
 
 // 瀹氫箟鍛戒护鍑芥暟鎸囬拡绫诲瀷锛坰eq, armNo, getPos, getSlot, putPos, putSlot锛�
-using CmdFunc = std::function<int(int, int, int, int, int, int)>;
+using CmdFunc = std::function<int(int, int, int, int, int, int, SERVO::ONWRITED onWritedBlock)>;
 
 // 杈撳叆鎺т欢鐘舵��
 struct QuickCmdFieldMask {
diff --git a/SourceCode/Bond/Servo/Common.h b/SourceCode/Bond/Servo/Common.h
index 7d09612..5915999 100644
--- a/SourceCode/Bond/Servo/Common.h
+++ b/SourceCode/Bond/Servo/Common.h
@@ -37,7 +37,7 @@
 #define CR_MSGBOX_BKGND						RGB(7, 71, 166)
 #define CR_MSGBOX_TITLE						RGB(200, 216, 246)
 #define CR_MSGBOX_MESSAGE					RGB(200, 216, 246)
-
+#define TOP_TOOLBAR_BACKGROUND				RGB(240, 240, 240)	
 
 /* LOG BTN */
 #define BTN_LOG_FRAME_NORMAL			RGB(88, 88, 88)
diff --git a/SourceCode/Bond/Servo/Model.cpp b/SourceCode/Bond/Servo/Model.cpp
index 14e2af9..959277e 100644
--- a/SourceCode/Bond/Servo/Model.cpp
+++ b/SourceCode/Bond/Servo/Model.cpp
@@ -29,6 +29,11 @@
 	return m_pObservable;
 }
 
+SERVO::CMaster& CModel::getMaster()
+{
+	return m_master;
+}
+
 void CModel::setWorkDir(const char* pszWorkDir)
 {
 	m_strWorkDir = pszWorkDir;
diff --git a/SourceCode/Bond/Servo/Model.h b/SourceCode/Bond/Servo/Model.h
index a4985ed..a9e5369 100644
--- a/SourceCode/Bond/Servo/Model.h
+++ b/SourceCode/Bond/Servo/Model.h
@@ -12,6 +12,7 @@
 
 public:
 	IObservable* getObservable();
+	SERVO::CMaster& getMaster();
 	void setWorkDir(const char* pszWorkDir);
 	int init();
 	int term();
diff --git a/SourceCode/Bond/Servo/Servo.cpp b/SourceCode/Bond/Servo/Servo.cpp
index 3b5e1c5..bd81237 100644
--- a/SourceCode/Bond/Servo/Servo.cpp
+++ b/SourceCode/Bond/Servo/Servo.cpp
@@ -10,6 +10,7 @@
 #include "SECSRuntimeManager.h"
 #include "ProductionLogManager.h"
 #include "VerticalLine.h"
+#include "HorizontalLine.h"
 #include "EqsGraphWnd.h"
 #include "MapPosWnd.h"
 #include "HmTab.h"
@@ -99,6 +100,7 @@
 	// 注册控件
 	CServoGraph::RegisterWndClass();
 	CVerticalLine::RegisterWndClass();
+	CHorizontalLine::RegisterWndClass();
 	CEqsGraphWnd::RegisterWndClass();
 	CMapPosWnd::RegisterWndClass();
 	CHmTab::RegisterWndClass();
diff --git a/SourceCode/Bond/Servo/Servo.rc b/SourceCode/Bond/Servo/Servo.rc
index 7bdf825..45c8ff9 100644
--- a/SourceCode/Bond/Servo/Servo.rc
+++ b/SourceCode/Bond/Servo/Servo.rc
Binary files differ
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj b/SourceCode/Bond/Servo/Servo.vcxproj
index 8fac7f2..599c92c 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj
+++ b/SourceCode/Bond/Servo/Servo.vcxproj
@@ -204,6 +204,7 @@
     <ClInclude Include="CRobotCmdTestDlg.h" />
     <ClInclude Include="CPagePortStatus.h" />
     <ClInclude Include="CPortStatusReport.h" />
+    <ClInclude Include="HorizontalLine.h" />
     <ClInclude Include="JobSlotGrid.h" />
     <ClInclude Include="MsgDlg.h" />
     <ClInclude Include="PageRecipe.h" />
@@ -302,6 +303,7 @@
     <ClInclude Include="targetver.h" />
     <ClInclude Include="TerminalDisplayDlg.h" />
     <ClInclude Include="ToolUnits.h" />
+    <ClInclude Include="TopToolbar.h" />
     <ClInclude Include="VerticalLine.h" />
   </ItemGroup>
   <ItemGroup>
@@ -311,6 +313,7 @@
     <ClCompile Include="CRobotCmdTestDlg.cpp" />
     <ClCompile Include="CPagePortStatus.cpp" />
     <ClCompile Include="CPortStatusReport.cpp" />
+    <ClCompile Include="HorizontalLine.cpp" />
     <ClCompile Include="JobSlotGrid.cpp" />
     <ClCompile Include="MsgDlg.cpp" />
     <ClCompile Include="PageRecipe.cpp" />
@@ -410,6 +413,7 @@
     </ClCompile>
     <ClCompile Include="TerminalDisplayDlg.cpp" />
     <ClCompile Include="ToolUnits.cpp" />
+    <ClCompile Include="TopToolbar.cpp" />
     <ClCompile Include="VerticalLine.cpp" />
   </ItemGroup>
   <ItemGroup>
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.filters b/SourceCode/Bond/Servo/Servo.vcxproj.filters
index 68273f0..6e77b3f 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.filters
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -112,6 +112,8 @@
     <ClCompile Include="MsgDlg.cpp" />
     <ClCompile Include="CPagePortStatus.cpp" />
     <ClCompile Include="JobSlotGrid.cpp" />
+    <ClCompile Include="TopToolbar.cpp" />
+    <ClCompile Include="HorizontalLine.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="AlarmManager.h" />
@@ -223,6 +225,8 @@
     <ClInclude Include="CPagePortStatus.h" />
     <ClInclude Include="ServoCommo.h" />
     <ClInclude Include="JobSlotGrid.h" />
+    <ClInclude Include="TopToolbar.h" />
+    <ClInclude Include="HorizontalLine.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Servo.rc" />
diff --git a/SourceCode/Bond/Servo/ServoDlg.cpp b/SourceCode/Bond/Servo/ServoDlg.cpp
index af02e73..cb8666e 100644
--- a/SourceCode/Bond/Servo/ServoDlg.cpp
+++ b/SourceCode/Bond/Servo/ServoDlg.cpp
@@ -13,6 +13,8 @@
 #include <thread>
 #include <cmath>
 #include "HmTab.h"
+#include "CRobotCmdContainerDlg.h"
+#include "CRobotCmdTestDlg.h"
 
 
 #ifdef _DEBUG
@@ -76,6 +78,7 @@
 	m_pPageAlarm = nullptr;
 	m_pPageLog = nullptr;
 	m_pPageRecipe = nullptr;
+	m_pTopToolbar = nullptr;
 }
 
 void CServoDlg::DoDataExchange(CDataExchange* pDX)
@@ -110,6 +113,7 @@
 	ON_WM_TIMER()
 	ON_MESSAGE(ID_MSG_PANEL_RESIZE, OnPanelResize)
 	ON_NOTIFY(BYHMTAB_SEL_CHANGED, IDC_TAB1, &CServoDlg::OnTabSelChanged)
+	ON_MESSAGE(ID_MSG_TOOLBAR_BTN_CLICKED, &CServoDlg::OnToolbarBtnClicked)
 END_MESSAGE_MAP()
 
 
@@ -209,6 +213,17 @@
 	menu.LoadMenu(IDR_MENU_APP);
 	SetMenu(&menu);
 
+
+	// 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_pTopToolbar->GetBtn(IDC_BUTTON_ALARM)->EnableWindow(FALSE);
+	HMENU hMenu = m_pTopToolbar->GetOperatorMenu();
+	ASSERT(hMenu);
+	::EnableMenuItem(hMenu, ID_OPEATOR_SWITCH, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+	
 
 	// Tab
 	m_pPageGraph1 = new CPageGraph1();
@@ -491,6 +506,12 @@
 	CDialogEx::OnDestroy();
 
 
+	if (m_pTopToolbar != nullptr) {
+		m_pTopToolbar->DestroyWindow();
+		delete m_pTopToolbar;
+		m_pTopToolbar = nullptr;
+	}
+
 	if (m_pTerminalDisplayDlg != nullptr) {
 		m_pTerminalDisplayDlg->DestroyWindow();
 		delete m_pTerminalDisplayDlg;
@@ -570,6 +591,7 @@
 	Invalidate();
 }
 
+#define TOOLBAR_HEIGHT		78
 void CServoDlg::Resize()
 {
 	CRect rcClient, rcItem;
@@ -579,6 +601,9 @@
 
 	x = 0;
 	y = 0;
+	m_pTopToolbar->MoveWindow(0, 0, rcClient.Width(), TOOLBAR_HEIGHT);
+	y += TOOLBAR_HEIGHT;
+
 	int nPanelWidth = 0;
 	if (m_pPanelMaster != nullptr) {
 		nPanelWidth = m_pPanelMaster->getPanelWidth();
@@ -675,4 +700,27 @@
 	for (int i = 0; i < 5; i++) {
 		pPages[i]->ShowWindow(i == index ? SW_SHOW : SW_HIDE);
 	}
+}
+
+LRESULT CServoDlg::OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam)
+{
+	int id = (int)lParam;
+	if (id == IDC_BUTTON_RUN) {
+		theApp.m_model.getMaster().start();
+		m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
+		m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(TRUE);
+
+	}
+	else if (id == IDC_BUTTON_STOP) {
+		theApp.m_model.getMaster().stop();
+		m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
+		m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
+	}
+	else if (id == IDC_BUTTON_ROBOT) {
+		SERVO::CEFEM* pEFEM = (SERVO::CEFEM*)theApp.m_model.getMaster().getEquipment(EQ_ID_EFEM);
+		CRobotCmdTestDlg dlg;
+		dlg.SetEFEM(pEFEM);
+		dlg.DoModal();
+	}
+	return 0;
 }
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/ServoDlg.h b/SourceCode/Bond/Servo/ServoDlg.h
index f78d8c5..b38bd30 100644
--- a/SourceCode/Bond/Servo/ServoDlg.h
+++ b/SourceCode/Bond/Servo/ServoDlg.h
@@ -13,6 +13,7 @@
 #include "CPanelAttributes.h"
 #include "CPageGraph1.h"
 #include "CPageGraph2.h"
+#include "TopToolbar.h"
 
 
 // CServoDlg 对话框
@@ -56,6 +57,7 @@
 	HICON m_hIcon;
 	COLORREF m_crBkgnd;
 	HBRUSH m_hbrBkgnd;
+	CTopToolbar* m_pTopToolbar;
 	CPanelMaster* m_pPanelMaster;
 	CPanelEquipment* m_pPanelEquipment;
 	CPanelAttributes* m_pPanelAttributes;
@@ -90,4 +92,5 @@
 	afx_msg void OnTimer(UINT_PTR nIDEvent);
 	afx_msg LRESULT OnPanelResize(WPARAM wParam, LPARAM lParam);
 	afx_msg void OnTabSelChanged(NMHDR* nmhdr, LRESULT* result);
+	LRESULT OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam);
 };
diff --git a/SourceCode/Bond/Servo/TopToolbar.cpp b/SourceCode/Bond/Servo/TopToolbar.cpp
new file mode 100644
index 0000000..32c9d8a
--- /dev/null
+++ b/SourceCode/Bond/Servo/TopToolbar.cpp
@@ -0,0 +1,218 @@
+// TopToolbar.cpp : 实现文件
+//
+
+#include "stdafx.h"
+#include "Servo.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_ALARM, m_btnAlarm);
+	DDX_Control(pDX, IDC_BUTTON_SETTINGS, m_btnSettings);
+	DDX_Control(pDX, IDC_BUTTON_ROBOT, m_btnRobot);
+	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_btnAlarm, "Alarm_o_32.ico", "Alarm_gray_32.ico");
+	InitBtn(m_btnSettings, "Settings_High_32.ico", "Settings_Gray_32.ico");
+	InitBtn(m_btnRobot, "Robot_High_32.ico", "Robot_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_BUTTON_ALARM);
+	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;
+
+	pItem = GetDlgItem(IDC_BUTTON_ROBOT);
+	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_ALARM:
+	case IDC_BUTTON_SETTINGS:
+	case IDC_BUTTON_ROBOT:
+		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;
+}
+
+HMENU CTopToolbar::GetOperatorMenu()
+{
+	return m_btnOperator.GetMenu();
+}
+
+BOOL CTopToolbar::PreTranslateMessage(MSG* pMsg)
+{
+	if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) {
+		return TRUE;
+	}
+
+	return CDialogEx::PreTranslateMessage(pMsg);
+}
diff --git a/SourceCode/Bond/Servo/TopToolbar.h b/SourceCode/Bond/Servo/TopToolbar.h
new file mode 100644
index 0000000..b65ad85
--- /dev/null
+++ b/SourceCode/Bond/Servo/TopToolbar.h
@@ -0,0 +1,58 @@
+#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);
+	HMENU GetOperatorMenu();
+
+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_btnAlarm;
+	CBlButton m_btnSettings;
+	CBlButton m_btnRobot;
+	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);
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+};
diff --git a/SourceCode/Bond/Servo/resource.h b/SourceCode/Bond/Servo/resource.h
index 3b75c47..8707561 100644
--- a/SourceCode/Bond/Servo/resource.h
+++ b/SourceCode/Bond/Servo/resource.h
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Res/robot_Gray_32.ico b/SourceCode/Bond/x64/Debug/Res/robot_Gray_32.ico
new file mode 100644
index 0000000..a65dbdc
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Res/robot_Gray_32.ico
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Res/robot_High_32.ico b/SourceCode/Bond/x64/Debug/Res/robot_High_32.ico
new file mode 100644
index 0000000..7c56fac
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Res/robot_High_32.ico
Binary files differ

--
Gitblit v1.9.3