From a3a9a6aeb574d21fb6e54b12b797b859662e5ad2 Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期一, 06 一月 2025 18:01:35 +0800
Subject: [PATCH] 1.PLC独立模块,添加了工具条

---
 SourceCode/Bond/BoounionPLC/BoounionPLC.cpp             |    8 
 SourceCode/Bond/BoounionPLC/BoounionPLC.rc              |    0 
 SourceCode/Bond/BoounionPLC/HorizontalLine.h            |   87 +++
 SourceCode/Bond/BoounionPLC/VerticalLine.cpp            |  310 ++++++++++
 SourceCode/Bond/BoounionPLC/Common.h                    |    3 
 SourceCode/Bond/BoounionPLC/Resource.h                  |    0 
 SourceCode/Bond/BoounionPLC/TopToolbar.cpp              |  211 +++++++
 SourceCode/Bond/BoounionPLC/HorizontalLine.cpp          |  209 +++++++
 SourceCode/Bond/BoounionPLC/VerticalLine.h              |   94 +++
 SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp          |   70 ++
 SourceCode/Bond/BoounionPLC/BlButton.h                  |   94 +++
 SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h            |   16 
 SourceCode/Bond/BoounionPLC/TopToolbar.h                |   57 +
 SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters |   24 
 SourceCode/Bond/BoounionPLC/BlButton.cpp                |  499 +++++++++++++++++
 SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj         |   13 
 16 files changed, 1,694 insertions(+), 1 deletions(-)

diff --git a/SourceCode/Bond/BoounionPLC/BlButton.cpp b/SourceCode/Bond/BoounionPLC/BlButton.cpp
new file mode 100644
index 0000000..5eb7694
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/BlButton.cpp
@@ -0,0 +1,499 @@
+#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;
+	m_nFlashState = 0;
+}
+
+
+CBlButton::~CBlButton()
+{
+}
+
+void CBlButton::SetFrameColor(int index, COLORREF color)
+{
+	if (BS_NORMAL <= index && index <= BS_DISABLE) {
+		m_crFrame[index] = color;
+	}
+}
+
+void CBlButton::SetFrameColor(COLORREF color)
+{
+	m_crFrame[BS_NORMAL] = color;
+	m_crFrame[BS_HOVER] = color;
+	m_crFrame[BS_PRESS] = color;
+	m_crFrame[BS_FOCUS] = color;
+	Invalidate();
+}
+
+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::Flash(int ms)
+{
+	m_nFlashState = 1;
+	SetTimer(1, ms, nullptr);
+}
+
+void CBlButton::StopFlash()
+{
+	m_nFlashState = 0;
+	KillTimer(1);
+	Invalidate();
+}
+
+BOOL CBlButton::IsFlash()
+{
+	return m_nFlashState != 0;
+}
+
+void CBlButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
+{
+	HDC hDC = lpDrawItemStruct->hDC;
+	RECT rcClient;
+	GetClientRect(&rcClient);
+
+
+	// 边框+背景
+	int state = GetDrawState();
+	if (m_nFlashState != 0) {
+		if (state != BS_DISABLE) {
+			state = m_nFlashState == 1 ? BS_NORMAL : BS_PRESS;
+		}
+	}
+	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;
+	HICON hIcon = this->IsWindowEnabled() ? m_hIcon[0] : m_hIcon[01];
+	if (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,
+			hIcon, m_nIconWidth, m_nIconWidth, 0, 0, DI_NORMAL);
+		rcText.top = yIcon + m_nIconWidth + 2;
+	}
+
+
+	// 文本
+	HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+	CFont* pFont = GetFont();
+	if (pFont != nullptr) {
+		hFont = (HFONT)pFont->GetSafeHandle();
+	}
+
+
+	::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()
+	ON_WM_TIMER()
+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);
+	}
+}
+
+void CBlButton::OnTimer(UINT_PTR nIDEvent)
+{
+	if (1 == nIDEvent) {
+		m_nFlashState++;
+		if (m_nFlashState > 2) m_nFlashState = 1;
+		Invalidate();
+	}
+
+	CButton::OnTimer(nIDEvent);
+}
diff --git a/SourceCode/Bond/BoounionPLC/BlButton.h b/SourceCode/Bond/BoounionPLC/BlButton.h
new file mode 100644
index 0000000..7b9bcea
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/BlButton.h
@@ -0,0 +1,94 @@
+#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 SetFrameColor(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);
+	void Flash(int ms);
+	void StopFlash();
+	BOOL IsFlash();
+
+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;
+	int m_nFlashState;		// 闪烁状态,0:不闪;1和2为闪烁切换中
+
+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);
+	afx_msg void OnTimer(UINT_PTR nIDEvent);
+};
+
diff --git a/SourceCode/Bond/BoounionPLC/BoounionPLC.cpp b/SourceCode/Bond/BoounionPLC/BoounionPLC.cpp
index ea8cc72..b528c1f 100644
--- a/SourceCode/Bond/BoounionPLC/BoounionPLC.cpp
+++ b/SourceCode/Bond/BoounionPLC/BoounionPLC.cpp
@@ -5,6 +5,9 @@
 #include "stdafx.h"
 #include "BoounionPLC.h"
 #include "BoounionPLCDlg.h"
+#include "HorizontalLine.h"
+#include "VerticalLine.h"
+
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -102,6 +105,11 @@
 	}
 
 
+	// 控件注册
+	CHorizontalLine::RegisterWndClass();
+	CVerticalLine::RegisterWndClass();
+
+	
 	CBoounionPLCDlg dlg;
 	m_pMainWnd = &dlg;
 	INT_PTR nResponse = dlg.DoModal();
diff --git a/SourceCode/Bond/BoounionPLC/BoounionPLC.rc b/SourceCode/Bond/BoounionPLC/BoounionPLC.rc
index 90b8244..0a1c8d5 100644
--- a/SourceCode/Bond/BoounionPLC/BoounionPLC.rc
+++ b/SourceCode/Bond/BoounionPLC/BoounionPLC.rc
Binary files differ
diff --git a/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj b/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj
index 5fb4565..fa0be85 100644
--- a/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj
+++ b/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj
@@ -189,6 +189,8 @@
     <Text Include="ReadMe.txt" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\BondEq\HorizontalLine.h" />
+    <ClInclude Include="BlButton.h" />
     <ClInclude Include="BoounionPLC.h" />
     <ClInclude Include="BoounionPLCDlg.h" />
     <ClInclude Include="Common.h" />
@@ -198,8 +200,12 @@
     <ClInclude Include="Resource.h" />
     <ClInclude Include="stdafx.h" />
     <ClInclude Include="targetver.h" />
+    <ClInclude Include="TopToolbar.h" />
+    <ClInclude Include="VerticalLine.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\BondEq\HorizontalLine.cpp" />
+    <ClCompile Include="BlButton.cpp" />
     <ClCompile Include="BoounionPLC.cpp" />
     <ClCompile Include="BoounionPLCDlg.cpp" />
     <ClCompile Include="Configuration.cpp" />
@@ -211,6 +217,8 @@
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
     </ClCompile>
+    <ClCompile Include="TopToolbar.cpp" />
+    <ClCompile Include="VerticalLine.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="BoounionPLC.rc" />
@@ -224,4 +232,9 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
+  <ProjectExtensions>
+    <VisualStudio>
+      <UserProperties RESOURCE_FILE="BoounionPLC.rc" />
+    </VisualStudio>
+  </ProjectExtensions>
 </Project>
\ No newline at end of file
diff --git a/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters b/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters
index deb74ad..36108b3 100644
--- a/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters
+++ b/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters
@@ -45,6 +45,18 @@
     <ClInclude Include="Log.h">
       <Filter>澶存枃浠�</Filter>
     </ClInclude>
+    <ClInclude Include="TopToolbar.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="BlButton.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="..\BondEq\HorizontalLine.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="VerticalLine.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="BoounionPLC.cpp">
@@ -65,6 +77,18 @@
     <ClCompile Include="Log.cpp">
       <Filter>婧愭枃浠�</Filter>
     </ClCompile>
+    <ClCompile Include="TopToolbar.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="BlButton.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="..\BondEq\HorizontalLine.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="VerticalLine.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="BoounionPLC.rc">
diff --git a/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp b/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp
index f2d77ba..a7524f9 100644
--- a/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp
+++ b/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp
@@ -53,6 +53,7 @@
 	: CDialogEx(IDD_BOOUNIONPLC_DIALOG, pParent)
 {
 	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+	m_pTopToolbar = nullptr;
 }
 
 void CBoounionPLCDlg::DoDataExchange(CDataExchange* pDX)
@@ -64,6 +65,9 @@
 	ON_WM_SYSCOMMAND()
 	ON_WM_PAINT()
 	ON_WM_QUERYDRAGICON()
+	ON_WM_DESTROY()
+	ON_WM_SIZE()
+	ON_WM_CTLCOLOR()
 END_MESSAGE_MAP()
 
 
@@ -98,7 +102,20 @@
 	SetIcon(m_hIcon, TRUE);			// 设置大图标
 	SetIcon(m_hIcon, FALSE);		// 设置小图标
 
-	// TODO: 在此添加额外的初始化代码
+
+	// 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);
+	
+
+	Resize();
+
 
 	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
 }
@@ -152,3 +169,54 @@
 	return static_cast<HCURSOR>(m_hIcon);
 }
 
+
+void CBoounionPLCDlg::OnDestroy()
+{
+	CDialogEx::OnDestroy();
+
+	if (m_pTopToolbar != nullptr) {
+		m_pTopToolbar->DestroyWindow();
+		delete m_pTopToolbar;
+		m_pTopToolbar = nullptr;
+	}
+}
+
+
+void CBoounionPLCDlg::OnSize(UINT nType, int cx, int cy)
+{
+	CDialogEx::OnSize(nType, cx, cy);
+	if (m_pTopToolbar == nullptr || !::IsWindow(m_pTopToolbar->m_hWnd)) return;
+
+	Resize();
+}
+
+#define TOOLBAR_HEIGHT		78
+void CBoounionPLCDlg::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);
+	*/
+}
+
+
+HBRUSH CBoounionPLCDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+{
+	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
+
+	// TODO:  在此更改 DC 的任何特性
+
+	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
+	return hbr;
+}
diff --git a/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h b/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h
index 76cf545..e2a2da9 100644
--- a/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h
+++ b/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h
@@ -3,6 +3,7 @@
 //
 
 #pragma once
+#include "TopToolbar.h"
 
 
 // CBoounionPLCDlg 对话框
@@ -11,6 +12,17 @@
 // 构造
 public:
 	CBoounionPLCDlg(CWnd* pParent = NULL);	// 标准构造函数
+
+private:
+	void Resize();
+
+
+private:
+	COLORREF m_crBkgnd;
+	HBRUSH m_hbrBkgnd;
+	IObserver* m_pObserver;
+	CTopToolbar* m_pTopToolbar;
+
 
 // 对话框数据
 #ifdef AFX_DESIGN_TIME
@@ -31,4 +43,8 @@
 	afx_msg void OnPaint();
 	afx_msg HCURSOR OnQueryDragIcon();
 	DECLARE_MESSAGE_MAP()
+public:
+	afx_msg void OnDestroy();
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
 };
diff --git a/SourceCode/Bond/BoounionPLC/Common.h b/SourceCode/Bond/BoounionPLC/Common.h
index 4f5420d..861ec49 100644
--- a/SourceCode/Bond/BoounionPLC/Common.h
+++ b/SourceCode/Bond/BoounionPLC/Common.h
@@ -4,3 +4,6 @@
 /* Rx Code */
 #define RX_CODE_TEST					0
 #define RX_CODE_LOG						1000
+
+/* 定制颜色 */
+#define TOP_TOOLBAR_BACKGROUND			RGB(240, 240, 240)	
diff --git a/SourceCode/Bond/BoounionPLC/HorizontalLine.cpp b/SourceCode/Bond/BoounionPLC/HorizontalLine.cpp
new file mode 100644
index 0000000..fc48b76
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/HorizontalLine.cpp
@@ -0,0 +1,209 @@
+// 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;
+}
+
+void CHorizontalLine::SetLineColor(COLORREF cr)
+{
+	m_crLineColor = cr;
+}
+
+
diff --git a/SourceCode/Bond/BoounionPLC/HorizontalLine.h b/SourceCode/Bond/BoounionPLC/HorizontalLine.h
new file mode 100644
index 0000000..f5b3647
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/HorizontalLine.h
@@ -0,0 +1,87 @@
+// 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);
+	void SetLineColor(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_)
diff --git a/SourceCode/Bond/BoounionPLC/Resource.h b/SourceCode/Bond/BoounionPLC/Resource.h
index ef4556f..1315a8c 100644
--- a/SourceCode/Bond/BoounionPLC/Resource.h
+++ b/SourceCode/Bond/BoounionPLC/Resource.h
Binary files differ
diff --git a/SourceCode/Bond/BoounionPLC/TopToolbar.cpp b/SourceCode/Bond/BoounionPLC/TopToolbar.cpp
new file mode 100644
index 0000000..56f41a9
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/TopToolbar.cpp
@@ -0,0 +1,211 @@
+// TopToolbar.cpp : 实现文件
+//
+
+#include "stdafx.h"
+#include "BoounionPLC.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_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_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;
+
+	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:
+		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/BoounionPLC/TopToolbar.h b/SourceCode/Bond/BoounionPLC/TopToolbar.h
new file mode 100644
index 0000000..1228bbb
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/TopToolbar.h
@@ -0,0 +1,57 @@
+#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_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/BoounionPLC/VerticalLine.cpp b/SourceCode/Bond/BoounionPLC/VerticalLine.cpp
new file mode 100644
index 0000000..440eb14
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/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;
+}
+
diff --git a/SourceCode/Bond/BoounionPLC/VerticalLine.h b/SourceCode/Bond/BoounionPLC/VerticalLine.h
new file mode 100644
index 0000000..9f22766
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/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_)

--
Gitblit v1.9.3