From 3628a707a38e1c590216c5983c9b97b9c742f86c Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期一, 24 三月 2025 09:01:42 +0800
Subject: [PATCH] Merge branch 'clh' into liuyang
---
SourceCode/Bond/Servo/EqsGraphWnd.cpp | 2400 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 2,400 insertions(+), 0 deletions(-)
diff --git a/SourceCode/Bond/Servo/EqsGraphWnd.cpp b/SourceCode/Bond/Servo/EqsGraphWnd.cpp
new file mode 100644
index 0000000..8b8d441
--- /dev/null
+++ b/SourceCode/Bond/Servo/EqsGraphWnd.cpp
@@ -0,0 +1,2400 @@
+#include "stdafx.h"
+#include "EqsGraphWnd.h"
+#include "ColorTransfer.h"
+#include "MapPosWnd.h"
+
+
+#define INPIN 1
+#define OUTPIN 2
+
+#define ITEM_CX_SMALL 150
+#define ITEM_CY_SMALL 90
+#define ITEM_CX_NORMAL 250
+#define ITEM_CY_NORMAL 150
+#define ITEM_CX_LARGE 400
+#define ITEM_CY_LARGE 240
+
+#define HT_NOWHERE 0x1
+#define HT_ITEM 0x2
+#define HT_PIN 0x4
+#define HT_LINE 0x8
+
+#define PINWIDTH 8
+#define PINHEIGHT 12
+
+#define TIMER_FLASH 1
+#define TIMER_ANIMATION_RECT 2
+
+#define MAPPOSSIZE 150
+#define MAPPOSWND_PADDING_RIGHT 12
+#define MAPPOSWND_ID 1001
+
+CEqsGraphWnd::CEqsGraphWnd()
+{
+ m_bUseGdiPlus = TRUE;
+ m_hWnd = NULL;
+ m_crFrame = GetSysColor(COLOR_WINDOWFRAME);
+ m_crBkgnd = RGB(255, 255, 255);
+ m_listener.onConnectPin = nullptr;
+ m_listener.onCheckConnectPin = nullptr;
+ m_listener.onDisconnectPin = nullptr;
+ m_listener.onDeleteEqItem = nullptr;
+ m_listener.onEqItemPosChanged = nullptr;
+ m_listener.onDblckEqItem = nullptr;
+ m_listener.onRclickEqItem = nullptr;
+ m_crItemBackground[0] = RGB(218, 218, 218);
+ m_crItemBackground[1] = RGB(193, 208, 227);
+ m_crItemFrame[0] = RGB(128, 128, 128);
+ m_crItemFrame[1] = RGB(147, 172, 206);
+ m_crItemNameText[0] = RGB(0, 0, 0);
+ m_crItemNameText[1] = RGB(0, 0, 0);
+ m_crItemIdText[0] = CColorTransfer::ApproximateColor(m_crItemNameText[0], -0.3f);
+ m_crItemIdText[1] = m_crItemIdText[0];
+ m_nCurSel = -1;
+ m_bMultiSelect = FALSE;
+ m_nItemRound = 0;
+ m_pCurItem = NULL;
+ m_pCurPin = NULL;
+ m_pSelLineOutPin = NULL;
+ m_crPinBkgnd[0] = RGB(218, 218, 218);
+ m_crPinBkgnd[1] = RGB(193, 0, 0);
+ m_crPinBkgnd[2] = RGB(193, 0, 0);
+ m_nStageCx = 4000;
+ m_nStageCy = 3000;
+ m_nOffsetX = 0;
+ m_nOffsetY = 0;
+ m_pFlashItem = NULL;
+ m_nFlashCount = 0;
+ m_hWndMapPos = NULL;
+ m_bEnableScroll = FALSE;
+ m_nMagneticLinHoz = 0;
+ m_nMagneticLinVer = 0;
+ m_hFontTitle = nullptr;
+
+}
+
+CEqsGraphWnd::~CEqsGraphWnd()
+{
+ ReleaseAllItems();
+}
+
+BOOL CEqsGraphWnd::RegisterWndClass()
+{
+ WNDCLASS wc;
+ wc.lpszClassName = EQSGRAPHWND_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);
+}
+
+CEqsGraphWnd* CEqsGraphWnd::FromHandle(HWND hWnd)
+{
+ CEqsGraphWnd* pEqsGraphWnd = (CEqsGraphWnd*)::GetProp(hWnd, EQSGRAPHWND_TAG);
+ return pEqsGraphWnd;
+}
+
+CEqsGraphWnd* CEqsGraphWnd::Hook(HWND hWnd)
+{
+ CEqsGraphWnd* pEqsGraphWnd = (CEqsGraphWnd*)GetProp(hWnd, EQSGRAPHWND_TAG);
+ if (pEqsGraphWnd == NULL) {
+ pEqsGraphWnd = new CEqsGraphWnd();
+ pEqsGraphWnd->m_hWnd = hWnd;
+
+ SetProp(hWnd, EQSGRAPHWND_TAG, (HANDLE)pEqsGraphWnd);
+ }
+
+
+ return pEqsGraphWnd;
+}
+
+void CEqsGraphWnd::InitFont()
+{
+ HDC hDC = GetDC(NULL);
+ HFONT hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
+
+ {
+ LOGFONT lf = { 0 };
+ ::GetObject(hFont, sizeof(LOGFONT), &lf);
+ m_hFontName = CreateFontIndirect(&lf);
+ }
+
+ {
+ LOGFONT lf = { 0 };
+ ::GetObject(hFont, sizeof(LOGFONT), &lf);
+
+ int nSize = int(-lf.lfHeight * 72.0 / GetDeviceCaps(hDC, LOGPIXELSY) + 0.5);
+ lf.lfHeight = MulDiv(0 - (nSize - 2), GetDeviceCaps(hDC, LOGPIXELSX), 72);
+ m_hFontId = CreateFontIndirect(&lf);
+ }
+
+ ::ReleaseDC(NULL, hDC);
+}
+
+void CEqsGraphWnd::SetItemRound(int nRound)
+{
+ m_nItemRound = nRound;
+}
+
+void CEqsGraphWnd::SetDefaultItemBackgroundColor(COLORREF crNormal, COLORREF crSel)
+{
+ m_crItemBackground[0] = crNormal;
+ m_crItemBackground[1] = crSel;
+}
+
+void CEqsGraphWnd::SetDefaultItemFrameColor(COLORREF crNormal, COLORREF crSel)
+{
+ m_crItemFrame[0] = crNormal;
+ m_crItemFrame[1] = crSel;
+}
+
+void CEqsGraphWnd::SetDefaultItemTextColor(COLORREF crNormal, COLORREF crSel)
+{
+ m_crItemNameText[0] = crNormal;
+ m_crItemNameText[1] = crSel;
+
+ m_crItemIdText[0] = CColorTransfer::ApproximateColor(m_crItemNameText[0], -0.3f);
+ m_crItemIdText[1] = CColorTransfer::ApproximateColor(m_crItemNameText[1], -0.3f);
+}
+
+void CEqsGraphWnd::EnableScroll(BOOL bEnable)
+{
+ m_bEnableScroll = bEnable;
+}
+
+void CEqsGraphWnd::EnableMultiSelect()
+{
+ m_bMultiSelect = TRUE;
+}
+
+void CEqsGraphWnd::Init()
+{
+ InitFont();
+ CalculateScollbar();
+
+ long style = GetWindowLong(m_hWnd, GWL_STYLE);
+ SetWindowLong(m_hWnd, GWL_STYLE, style | WS_CLIPCHILDREN);
+
+ // MapPosWnd
+ if (m_hWndMapPos == NULL) {
+ m_hWndMapPos = CreateWindowEx(0, MAPPOSWND_CLASS,
+ NULL, WS_CHILD | WS_VISIBLE,
+ 0, 0, 400, 400,
+ m_hWnd, (HMENU)MAPPOSWND_ID, NULL, NULL);
+
+ long styleex = GetWindowLong(m_hWndMapPos, GWL_EXSTYLE);
+ SetWindowLong(m_hWndMapPos, GWL_EXSTYLE, styleex | WS_EX_CLIENTEDGE);
+
+ CMapPosWnd *pMapPosWnd = CMapPosWnd::FromHandle(m_hWndMapPos);
+ pMapPosWnd->SetWndMaxSize(MAPPOSSIZE);
+ pMapPosWnd->SetStageSize(m_nStageCx, m_nStageCy, TRUE);
+ }
+}
+
+void CEqsGraphWnd::CalculateMapPos()
+{
+ CRect rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::OffsetRect(&rcClient, m_nOffsetX, m_nOffsetY);
+ CMapPosWnd *pMapPosWnd = CMapPosWnd::FromHandle(m_hWndMapPos);
+ pMapPosWnd->SetViewPort(&rcClient, TRUE);
+}
+
+void CEqsGraphWnd::CalculateScollbar()
+{
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+
+ // vert scroll
+ if(m_bEnableScroll) {
+ SCROLLINFO scrinffo;
+ scrinffo.cbSize = sizeof(SCROLLINFO);
+ scrinffo.fMask = SIF_ALL;
+ scrinffo.nMax = m_nStageCy;
+ scrinffo.nMin = 0;
+ scrinffo.nPos = m_nOffsetY;
+ scrinffo.nTrackPos = 0;
+ scrinffo.nPage = rcClient.bottom - rcClient.top;
+ SetScrollInfo(m_hWnd, SB_VERT, &scrinffo, TRUE);
+ }
+
+ // horz scroll
+ if (m_bEnableScroll) {
+ SCROLLINFO scrinffo;
+ scrinffo.cbSize = sizeof(SCROLLINFO);
+ scrinffo.fMask = SIF_ALL;
+ scrinffo.nMax = m_nStageCx;
+ scrinffo.nMin = 0;
+ scrinffo.nPos = m_nOffsetX;
+ scrinffo.nTrackPos = 0;
+ scrinffo.nPage = rcClient.right - rcClient.left;
+ SetScrollInfo(m_hWnd, SB_HORZ, &scrinffo, TRUE);
+ }
+}
+
+/*
+ * 计算磁力线位置
+ */
+void CEqsGraphWnd::CalculateMagneticLine(EQITEM* pItem, LPRECT lprcItemRect, int &hoz, int &ver)
+{
+ hoz = 0;
+ ver = 0;
+#define MAGNETIC_DIS 10
+
+ // 检测是否接近或对齐
+ for (int i = 0; i < m_arItem.GetSize(); i++) {
+ EQITEM *pTemp = (EQITEM*)m_arItem.GetAt(i);
+ if (pTemp != pItem) {
+ if (abs(lprcItemRect->left - pTemp->rect.left) < MAGNETIC_DIS) {
+ ver = pTemp->rect.left;
+ break;
+ }
+ else if (abs(lprcItemRect->right - pTemp->rect.right) < MAGNETIC_DIS) {
+ ver = pTemp->rect.right - (lprcItemRect->right- lprcItemRect->left);
+ break;
+ }
+ }
+ }
+
+ for (int i = 0; i < m_arItem.GetSize(); i++) {
+ EQITEM* pTemp = (EQITEM*)m_arItem.GetAt(i);
+ if (pTemp != pItem) {
+ if (abs(lprcItemRect->top - pTemp->rect.top) < MAGNETIC_DIS) {
+ hoz = pTemp->rect.top;
+ break;
+ }
+ else if (abs(lprcItemRect->bottom - pTemp->rect.bottom) < MAGNETIC_DIS) {
+ hoz = pTemp->rect.bottom - (lprcItemRect->bottom - lprcItemRect->top);
+ break;
+ }
+ }
+ }
+}
+
+
+void CEqsGraphWnd::Release()
+{
+ ::DeleteObject(m_hFontName);
+ ::DeleteObject(m_hFontId);
+ if (m_hFontTitle != nullptr) {
+ ::DeleteObject(m_hFontTitle);
+ }
+
+ // delete
+ delete this;
+}
+
+/*
+ * 取得In Pin的区域
+ * pItem -- EQITEM
+ * lpRect -- 得到的Rect
+ * 返回是否成功
+ */
+BOOL CEqsGraphWnd::GetItemRect(EQITEM* pItem, LPRECT lpRect)
+{
+ ASSERT(pItem);
+ if (pItem == m_pAnimationItem) {
+ lpRect->left = (int)(m_rcAnimation.left - m_nOffsetX);
+ lpRect->top = (int)(m_rcAnimation.top - m_nOffsetY);
+ lpRect->right = (int)(m_rcAnimation.right - m_nOffsetX);
+ lpRect->bottom = (int)(m_rcAnimation.bottom - m_nOffsetY);
+ }
+ else {
+ lpRect->left = (int)(pItem->rect.left - m_nOffsetX);
+ lpRect->top = (int)(pItem->rect.top - m_nOffsetY);
+ lpRect->right = (int)(pItem->rect.right - m_nOffsetX);
+ lpRect->bottom = (int)(pItem->rect.bottom - m_nOffsetY);
+ }
+
+ return TRUE;
+}
+
+BOOL CEqsGraphWnd::GetItemWarperRect(EQITEM* pItem, LPRECT lpRect)
+{
+ CopyRect(lpRect, &pItem->rect);
+ lpRect->left -= PINWIDTH;
+ lpRect->right += PINWIDTH;
+
+ return TRUE;
+}
+
+/*
+ * 取得In Pin的区域
+ * pItem -- EQITEM
+ * nPinIndex -- in pin索引
+ * lpRect -- 得到的Rect
+ * 返回是否成功
+ */
+BOOL CEqsGraphWnd::GetInPinRect(EQITEM* pItem, int nPinIndex, LPRECT lpRect)
+{
+ CPtrArray * pPins = (CPtrArray *)pItem->pInPins;
+ if (nPinIndex >= pPins->GetSize()) {
+ return FALSE;
+ }
+
+ int nBottomMargin = pPins->GetCount() >= 4 ? 8 : 0;
+ int nSpace = ((pItem->rect.bottom - nBottomMargin - pItem->rect.top) - (int)pPins->GetSize() * PINHEIGHT) / (pPins->GetSize() + 1);
+ lpRect->right = pItem->rect.left+1 - m_nOffsetX;
+ lpRect->left = lpRect->right - PINWIDTH;
+ lpRect->bottom = pItem->rect.top + (nSpace + PINHEIGHT) * (nPinIndex+1) - m_nOffsetY;
+ lpRect->top = lpRect->bottom - PINHEIGHT;
+
+ return TRUE;
+}
+
+/*
+ * 取得Out Pin的区域
+ * pItem -- EQITEM
+ * nPinIndex -- in pin索引
+ * lpRect -- 得到的Rect
+ * 返回是否成功
+ */
+BOOL CEqsGraphWnd::GetOutPinRect(EQITEM* pItem, int nPinIndex, LPRECT lpRect)
+{
+ CPtrArray * pPins = (CPtrArray *)pItem->pOutPins;
+ if (nPinIndex >= pPins->GetSize()) {
+ return FALSE;
+ }
+
+ int nSpace = ((pItem->rect.bottom - pItem->rect.top) - (int)pPins->GetSize() * PINHEIGHT) / (pPins->GetSize() + 1);
+ lpRect->left = pItem->rect.right-1 - m_nOffsetX;
+ lpRect->right = lpRect->left + PINWIDTH;
+ lpRect->bottom = pItem->rect.top + (nSpace + PINHEIGHT) * (nPinIndex + 1) - m_nOffsetY;
+ lpRect->top = lpRect->bottom - PINHEIGHT;
+
+ return TRUE;
+}
+
+/*
+ * 取得Pin的Point
+ * pItem -- EQITEM
+ * nPinIndex -- in pin索引
+ * lpRect -- 得到的Rect
+ * 返回是否成功
+ */
+BOOL CEqsGraphWnd::GetPinPoint(PIN *pPin, LPPOINT lpPoint)
+{
+ ASSERT(pPin);
+ ASSERT(pPin->pItem);
+ CPtrArray * pPins;
+ RECT rcPin;
+
+ // in pin?
+ pPins = (CPtrArray *)pPin->pItem->pInPins;
+ for(int i=0; i<pPins->GetCount(); i++) {
+ if (pPins->GetAt(i) == pPin) {
+ if (GetInPinRect(pPin->pItem, i, &rcPin)) {
+ lpPoint->x = rcPin.left + (rcPin.right - rcPin.left) / 2;
+ lpPoint->y = rcPin.top + (rcPin.bottom - rcPin.top) / 2;
+ return TRUE;
+ }
+ }
+ }
+
+ // out pin?
+ pPins = (CPtrArray *)pPin->pItem->pOutPins;
+ for (int i = 0; i<pPins->GetCount(); i++) {
+ if (pPins->GetAt(i) == pPin) {
+ if (GetOutPinRect(pPin->pItem, i, &rcPin)) {
+ lpPoint->x = rcPin.left + (rcPin.right - rcPin.left) / 2;
+ lpPoint->y = rcPin.top + (rcPin.bottom - rcPin.top) / 2;
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+void CEqsGraphWnd::ReleaseItem(EQITEM* pItem)
+{
+ ASSERT(pItem);
+
+ CPtrArray *pArray = (CPtrArray *)pItem->pInPins;
+ for (int j = 0; j < pArray->GetSize(); j++) {
+ PIN *pPin = (PIN *)pArray->GetAt(j);
+ if (pPin->pConnectedPin != NULL) {
+ pPin->pConnectedPin->pConnectedPin = NULL;
+ }
+ delete pPin;
+ }
+ delete pArray;
+
+ pArray = (CPtrArray *)pItem->pOutPins;
+ for (int j = 0; j < pArray->GetSize(); j++) {
+ PIN *pPin = (PIN *)pArray->GetAt(j);
+ if (pPin->pConnectedPin != NULL) {
+ pPin->pConnectedPin->pConnectedPin = NULL;
+ }
+ delete pPin;
+ }
+ delete pArray;
+
+ delete pItem;
+}
+
+void CEqsGraphWnd::ReleaseAllItems()
+{
+ for (int i = 0; i < m_arItem.GetCount(); i++) {
+ ReleaseItem((EQITEM*)m_arItem.GetAt(i));
+ }
+ m_arItem.RemoveAll();
+}
+
+int CEqsGraphWnd::GetPinState(PIN *pPin)
+{
+ if (pPin == m_pCurPin) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * 清空PIN连接线缓存点,以便重新计算和绘制
+ */
+void CEqsGraphWnd::ClearConnectedLinePoint(EQITEM*& pItem)
+{
+ ASSERT(pItem);
+
+ CPtrArray *pPins;
+ PIN *pPin;
+
+ pPins = (CPtrArray *)pItem->pInPins;
+ for (int j = 0; j < pPins->GetSize(); j++) {
+ pPin = (PIN *)pPins->GetAt(j);
+ if (pPin->pConnectedPin != NULL) {
+ pPin->pConnectedPin->nLinePtCount = 0;
+ }
+ }
+
+ pPins = (CPtrArray *)pItem->pOutPins;
+ for (int j = 0; j < pPins->GetSize(); j++) {
+ pPin = (PIN *)pPins->GetAt(j);
+ pPin->nLinePtCount = 0;
+ }
+}
+
+void CEqsGraphWnd::SetOnListener(EqsGraphListener& listener)
+{
+ m_listener.onConnectPin = listener.onConnectPin;
+ m_listener.onCheckConnectPin = listener.onCheckConnectPin;
+ m_listener.onDisconnectPin = listener.onDisconnectPin;
+ m_listener.onDeleteEqItem = listener.onDeleteEqItem;
+ m_listener.onEqItemPosChanged = listener.onEqItemPosChanged;
+ m_listener.onDblckEqItem = listener.onDblckEqItem;
+ m_listener.onRclickEqItem = listener.onRclickEqItem;
+}
+
+BOOL CEqsGraphWnd::SetCurSel(int nSel)
+{
+ if (!(nSel == -1 || nSel < m_arItem.GetCount())) {
+ return FALSE;
+ }
+
+
+ m_nCurSel = nSel;
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+
+ return TRUE;
+}
+
+BOOL CEqsGraphWnd::SetCurSel(CString strItemName)
+{
+ int nIndex = -1;
+ for (int i = 0; i < m_arItem.GetCount(); i++) {
+ EQITEM* pItem = (EQITEM*)m_arItem.GetAt(i);
+ if (strItemName.Compare(pItem->text) == 0) {
+ nIndex = i;
+ break;
+ }
+ }
+
+ if (nIndex == -1) {
+ return FALSE;
+ }
+
+ m_nCurSel = nIndex;
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+
+ return TRUE;
+}
+
+BOOL CEqsGraphWnd::SetCurSel(DWORD_PTR pData)
+{
+ int nIndex = -1;
+ for (int i = 0; i < m_arItem.GetCount(); i++) {
+ EQITEM* pItem = (EQITEM*)m_arItem.GetAt(i);
+ if (pItem->pData == pData) {
+ nIndex = i;
+ break;
+ }
+ }
+
+ if (nIndex == -1) {
+ return FALSE;
+ }
+
+ m_nCurSel = nIndex;
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+
+ return TRUE;
+}
+
+/*
+ * nType: ITEM_SMALL, ITEM_NORMAL or ITEM_LARGE
+ */
+EQITEM* CEqsGraphWnd::AddItem(int id, CString strText, DWORD_PTR dwData, int nType/* = ITEM_NORMAL*/)
+{
+ // 需要计算一个新位置,不然全部重叠在一起
+ int x, y;
+ x = (m_arItem.GetCount() % 4) * 218;
+ y = (m_arItem.GetCount() / 4) * 168;
+
+
+ EQITEM* pItem = new EQITEM;
+ memset(pItem, 0, sizeof(EQITEM));
+ pItem->id = id;
+ pItem->nShowType = nType;
+ pItem->rect.left = x + 20 + m_nOffsetX;
+ pItem->rect.top = y + 50 + m_nOffsetY;
+ if (pItem->nShowType == ITEM_SMALL) {
+ pItem->rect.right = pItem->rect.left + ITEM_CX_SMALL;
+ pItem->rect.bottom = pItem->rect.top + ITEM_CY_SMALL;
+ }
+ else if(pItem->nShowType == ITEM_LARGE){
+ pItem->rect.right = pItem->rect.left + ITEM_CX_LARGE;
+ pItem->rect.bottom = pItem->rect.top + ITEM_CY_LARGE;
+ }
+ else {
+ pItem->rect.right = pItem->rect.left + ITEM_CX_NORMAL;
+ pItem->rect.bottom = pItem->rect.top + ITEM_CY_NORMAL;
+ }
+
+ pItem->pData = dwData;
+ pItem->pInPins = (DWORD_PTR)new CPtrArray();
+ pItem->pOutPins = (DWORD_PTR)new CPtrArray();
+
+ int len = min(63, strText.GetLength());
+ memcpy(pItem->text, (LPTSTR)(LPCTSTR)strText, len);
+ pItem->text[len] = '\0';
+ m_arItem.Add(pItem);
+
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+
+ return pItem;
+}
+
+void CEqsGraphWnd::RemoveItem(EQITEM* pItem)
+{
+ BOOL bChanged = FALSE;
+ if (m_listener.onDeleteEqItem != NULL) {
+ if (m_listener.onDeleteEqItem(m_pCurItem)) {
+ bChanged = DeleteItem(m_pCurItem) >= 0;
+ }
+ }
+
+
+ if (bChanged) {
+ if (pItem == m_pCurItem) {
+ m_pCurItem = NULL;
+ }
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ }
+}
+
+void CEqsGraphWnd::SetItemText(EQITEM* pItem, CString strText)
+{
+ int len = min(63, strText.GetLength());
+ memcpy(pItem->text, (LPTSTR)(LPCTSTR)strText, len);
+ pItem->text[len] = '\0';
+
+ ::InvalidateRect(m_hWnd, &pItem->rect, TRUE);
+}
+
+void CEqsGraphWnd::SetItemType(EQITEM* pItem, int nType)
+{
+ pItem->nShowType = nType;
+ if (pItem->nShowType == ITEM_SMALL) {
+ pItem->rect.right = pItem->rect.left + ITEM_CX_SMALL;
+ pItem->rect.bottom = pItem->rect.top + ITEM_CY_SMALL;
+ }
+ else if (pItem->nShowType == ITEM_LARGE) {
+ pItem->rect.right = pItem->rect.left + ITEM_CX_LARGE;
+ pItem->rect.bottom = pItem->rect.top + ITEM_CY_LARGE;
+ }
+ else {
+ pItem->rect.right = pItem->rect.left + ITEM_CX_NORMAL;
+ pItem->rect.bottom = pItem->rect.top + ITEM_CY_NORMAL;
+ }
+
+ ::InvalidateRect(m_hWnd, &pItem->rect, TRUE);
+}
+
+void CEqsGraphWnd::SetItemPos(EQITEM* pItem, int x, int y)
+{
+ ASSERT(pItem);
+ pItem->rect.left = x;
+ pItem->rect.top = y;
+ if (pItem->nShowType == ITEM_SMALL) {
+ pItem->rect.right = pItem->rect.left + ITEM_CX_SMALL;
+ pItem->rect.bottom = pItem->rect.top + ITEM_CY_SMALL;
+ }
+ else if (pItem->nShowType == ITEM_LARGE) {
+ pItem->rect.right = pItem->rect.left + ITEM_CX_LARGE;
+ pItem->rect.bottom = pItem->rect.top + ITEM_CY_LARGE;
+ }
+ else {
+ pItem->rect.right = pItem->rect.left + ITEM_CX_NORMAL;
+ pItem->rect.bottom = pItem->rect.top + ITEM_CY_NORMAL;
+ }
+
+ ::InvalidateRect(m_hWnd, &pItem->rect, TRUE);
+}
+
+PIN * CEqsGraphWnd::AddPin(EQITEM* pItem, int nType, CString strName, DWORD_PTR dwData)
+{
+ ASSERT(pItem);
+ ASSERT(nType == INPIN || nType == OUTPIN);
+ ASSERT(pItem->pInPins);
+ ASSERT(pItem->pOutPins);
+
+
+
+ PIN *pPin = new PIN;
+ memset(pPin, 0, sizeof(PIN));
+ pPin->pItem = pItem;
+ pPin->nIndex = nType == INPIN ? ((CPtrArray *)pItem->pInPins)->GetSize() : ((CPtrArray *)pItem->pOutPins)->GetSize();
+ pPin->nType = nType;
+ pPin->pData = dwData;
+
+ int len = MIN(sizeof(pPin->text), strName.GetLength());
+ memcpy(pPin->text, (LPTSTR)(LPCTSTR)strName, len);
+ pPin->text[len] = '\0';
+
+ CPtrArray *pArray = NULL;
+ if (nType == INPIN) {
+ pArray = (CPtrArray *)pItem->pInPins;
+ }
+ else {
+ pArray = (CPtrArray *)pItem->pOutPins;
+ }
+
+ ASSERT(pItem->pOutPins);
+ pArray->Add(pPin);
+
+ return pPin;
+}
+
+EQITEM* CEqsGraphWnd::GetItem(DWORD_PTR dwData)
+{
+ for (int i = 0; i < m_arItem.GetCount(); i++) {
+ EQITEM* pItem = (EQITEM*)m_arItem.GetAt(i);
+ if (pItem->pData == dwData) {
+ return pItem;
+ }
+ }
+
+ return NULL;
+}
+
+PIN * CEqsGraphWnd::GetPin(DWORD_PTR dwItemData, DWORD_PTR dwPinData)
+{
+ EQITEM* pItem = GetItem(dwItemData);
+ if (pItem != NULL) {
+ CPtrArray *pArray = (CPtrArray *)pItem->pInPins;
+ for (int i = 0; i < pArray->GetCount(); i++) {
+ PIN *pPin = (PIN *)pArray->GetAt(i);
+ if (pPin->pData == dwPinData) {
+ return pPin;
+ }
+ }
+
+ pArray = (CPtrArray *)pItem->pOutPins;
+ for (int i = 0; i < pArray->GetCount(); i++) {
+ PIN *pPin = (PIN *)pArray->GetAt(i);
+ if (pPin->pData == dwPinData) {
+ return pPin;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+int CEqsGraphWnd::ConnectPin(DWORD_PTR dwItem1Data, DWORD_PTR dwPin1Data, DWORD_PTR dwItem2Data, DWORD_PTR dwPin2Data)
+{
+ PIN *pPin1, *pPin2;
+
+ pPin1 = GetPin(dwItem1Data, dwPin1Data);
+ if (pPin1 == NULL) {
+ return -1;
+ }
+
+ pPin2 = GetPin(dwItem2Data, dwPin2Data);
+ if (pPin2 == NULL) {
+ return -2;
+ }
+
+ pPin1->pConnectedPin = pPin2;
+ pPin2->pConnectedPin = pPin1;
+
+ return 0;
+}
+
+// 删除Item, 如果pin有连接,注意先断开
+int CEqsGraphWnd::DeleteItem(EQITEM* pItem)
+{
+ for (int i = 0; i < m_arItem.GetSize(); i++) {
+ if (pItem == (EQITEM*)m_arItem.GetAt(i)) {
+ m_arItem.RemoveAt(i);
+ ReleaseItem(pItem);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+void CEqsGraphWnd::DeleteAllItems()
+{
+ ReleaseAllItems();
+
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+}
+
+void CEqsGraphWnd::SetCurrentItem(EQITEM* pItem)
+{
+ if (m_pCurItem != NULL) {
+ m_pCurItem->bHighlight = FALSE;
+ }
+
+ m_pCurItem = pItem;
+ if (m_pCurItem != NULL) {
+ m_pCurItem->bHighlight = TRUE;
+ }
+
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+}
+
+/*
+ * 设置子项的选中状态
+ */
+void CEqsGraphWnd::SetItemSelectState(int nIndex, BOOL bSelect)
+{
+ if (nIndex >= m_arItem.GetCount()) {
+ return;
+ }
+
+ EQITEM *pItem = (EQITEM*)m_arItem.GetAt(nIndex);
+ pItem->bHighlight = bSelect;
+
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+}
+
+void CEqsGraphWnd::Notify(int nCode, int dwData, int dwData1/* = 0*/, int dwData2/* = 0*/)
+{
+ HWND hParent;
+ hParent = GetParent(m_hWnd);
+ if (hParent != NULL) {
+ EQSGRAPHWND_NMHDR nmhdr;
+ nmhdr.nmhdr.hwndFrom = m_hWnd;
+ nmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
+ nmhdr.nmhdr.code = nCode;
+ nmhdr.dwData = dwData;
+ nmhdr.dwData1 = dwData1;
+ nmhdr.dwData2 = dwData2;
+ SendMessage(hParent, WM_NOTIFY, (WPARAM)nmhdr.nmhdr.idFrom, (LPARAM)&nmhdr);
+ }
+}
+
+/*
+ * 检测坐标点所在的项
+ * 返回项类型, 如HT_ITEM, HT_PIN, HT_LINE
+ * pItem - 所在的EQITEM
+ * pPin --所在的pin, 如果在连线上,表示所属pin, out pin;
+ */
+int CEqsGraphWnd::HighTest(POINT pt, OUT EQITEM*& pItem, OUT PIN *& pPin)
+{
+ // 检测是否在某个子项
+ int nRet = HT_NOWHERE;
+ pItem = NULL;
+ pPin = NULL;
+ RECT rcItem;
+ for (int i = m_arItem.GetSize() - 1; i >= 0 ; i--) {
+ EQITEM *pTempItem = (EQITEM*)m_arItem.GetAt(i);
+ GetItemRect(pTempItem, &rcItem);
+ if (::PtInRect(&rcItem, pt)) {
+ // 在Item
+ pItem = pTempItem;
+ nRet = HT_ITEM;
+ break;
+ }
+ else {
+ RECT rcPin;
+ CPtrArray * pPins = (CPtrArray *)pTempItem->pInPins;
+ for (int j = 0; j < pPins->GetSize(); j++) {
+ if (GetInPinRect(pTempItem, j, &rcPin) && ::PtInRect(&rcPin, pt)) {
+ // 在in pin上
+ pPin = (PIN *)pPins->GetAt(j);
+ pItem = pTempItem;
+ nRet = HT_PIN;
+ break;
+ }
+ }
+
+ if (nRet == HT_NOWHERE) {
+ pPins = (CPtrArray *)pTempItem->pOutPins;
+ for (int j = 0; j < pPins->GetSize(); j++) {
+ if (GetOutPinRect(pTempItem, j, &rcPin) && ::PtInRect(&rcPin, pt)) {
+ // 在out pin
+ pPin = (PIN *)pPins->GetAt(j);
+ pItem = pTempItem;
+ nRet = HT_PIN;
+ break;
+ }
+ else {
+ // 是否在pin连接线上,即判断点是否在线上
+ // 点到直线的距离公式(先通过p1,p2用两点式求出直线的表达式,再套距离公式);abs()为取绝对值函数,sqrt()为开根号函数
+ PIN *pTempPin = (PIN *)pPins->GetAt(j);
+ if (pTempPin->pConnectedPin != NULL && pTempPin->nLinePtCount > 1) {
+ for (int i = 0; i < pTempPin->nLinePtCount - 1; i++) {
+ double distance = PointToSegDist(pt.x + m_nOffsetX, pt.y + m_nOffsetY,
+ pTempPin->ptConnectedLine[i].x, pTempPin->ptConnectedLine[i].y,
+ pTempPin->ptConnectedLine[i+1].x, pTempPin->ptConnectedLine[i+1].y);
+ if (distance < 5.0) {
+ nRet = HT_LINE;
+ pPin = pTempPin;
+ break;
+ }
+ }
+
+ if (nRet == HT_LINE) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (nRet != HT_NOWHERE) {
+ break;
+ }
+ }
+ }
+
+
+ return nRet;
+}
+
+/*
+ * 绘制虚线框,代表正在拖动的item
+ */
+void CEqsGraphWnd::DrawDropItemRectangle(LPRECT lpRect1, LPRECT lpRect2)
+{
+ HDC hDC = GetDC(m_hWnd);
+ HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
+ HPEN hPen = CreatePen(PS_DASH, 1, RGB(0, 0, 0));
+ int oldRop = SetROP2(hDC, R2_NOTXORPEN);
+ HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC, hBrush);
+ HBRUSH hOldPen = (HBRUSH)::SelectObject(hDC, hPen);
+
+ if (lpRect1 != NULL) {
+ ::Rectangle(hDC, lpRect1->left, lpRect1->top, lpRect1->right, lpRect1->bottom);
+ }
+
+ if (lpRect2 != NULL) {
+ ::Rectangle(hDC, lpRect2->left, lpRect2->top, lpRect2->right, lpRect2->bottom);
+ }
+
+ ::SetROP2(hDC, oldRop);
+ ::SelectObject(hDC, hOldBrush);
+ ::SelectObject(hDC, hPen);
+ ::DeleteObject(hBrush);
+ ::DeleteObject(hOldPen);
+ ::ReleaseDC(m_hWnd, hDC);
+}
+
+/*
+ * 绘制磁吸线
+ */
+void CEqsGraphWnd::DrawMagneticLine(LPRECT lprcClient, int nHozLine1, int nHozLine2, int nVerLine1, int nVerLine2)
+{
+ HDC hDC = GetDC(m_hWnd);
+ HPEN hPen = CreatePen(PS_DASH, 1, RGB(64, 64, 64));
+ int oldRop = SetROP2(hDC, R2_NOTXORPEN);
+ HBRUSH hOldPen = (HBRUSH)::SelectObject(hDC, hPen);
+
+ if (nHozLine1) {
+ ::MoveToEx(hDC, 1, nHozLine1, NULL);
+ ::LineTo(hDC, lprcClient->right-1, nHozLine1);
+ }
+ if (nHozLine2) {
+ ::MoveToEx(hDC, 1, nHozLine2, NULL);
+ ::LineTo(hDC, lprcClient->right - 1, nHozLine2);
+ }
+
+ if (nVerLine1) {
+ ::MoveToEx(hDC, nVerLine1, 1, NULL);
+ ::LineTo(hDC, nVerLine1, lprcClient->bottom - 1);
+ }
+ if (nVerLine2) {
+ ::MoveToEx(hDC, nVerLine2, 1, NULL);
+ ::LineTo(hDC, nVerLine2, lprcClient->bottom - 1);
+ }
+
+ ::SetROP2(hDC, oldRop);
+ ::SelectObject(hDC, hPen);
+ ::DeleteObject(hOldPen);
+ ::ReleaseDC(m_hWnd, hDC);
+}
+
+/*
+ * 缓制Pin连接线
+ * pBrush -- 画刷
+ * pPen - 画笔
+ * lpPt1, lpPt2 -- Pin脚的位置
+ * lpRect1, lpRect2 -- 两个Item的Rect
+ */
+void CEqsGraphWnd::DrawPinConnectedLine(Gdiplus::Graphics *pGraphics, Gdiplus::Brush *pBrush, Gdiplus::Pen *pPen, LPPOINT lpPt1, LPPOINT lpPt2,
+ LPRECT lpRect1, LPRECT lpRect2, PIN *pOwnerPin)
+{
+ // 如果没有缓存线条的POINT,则先计算并缓存
+ ASSERT(pOwnerPin);
+
+ int nPinCount = ((CPtrArray*)pOwnerPin->pItem->pOutPins)->GetSize();
+ int nArrowLen = 8;
+ int nStartMinX = 8;
+ int nMargin = 12;
+ int x1, x2, y1;
+
+ if (pOwnerPin->nLinePtCount == 0) { // 第一个点的最小折线长
+ ::OffsetRect(lpRect1, +m_nOffsetX, +m_nOffsetY);
+ ::OffsetRect(lpRect2, +m_nOffsetX, +m_nOffsetY);
+ lpPt1->x += m_nOffsetX; // 消除偏移
+ lpPt1->y += m_nOffsetY;
+ lpPt2->x += m_nOffsetX;
+ lpPt2->y += m_nOffsetY;
+ int nMinX = 10 + nMargin * nPinCount + nArrowLen;
+ int xEnd = lpPt2->x - 5;
+ x1 = lpPt1->x + 10 + pOwnerPin->nIndex * nMargin;
+ if (lpPt2->x - lpPt1->x > nMinX) {
+ pOwnerPin->ptConnectedLine[0].x = lpPt1->x;
+ pOwnerPin->ptConnectedLine[0].y = lpPt1->y;
+ pOwnerPin->ptConnectedLine[1].x = x1;
+ pOwnerPin->ptConnectedLine[1].y = lpPt1->y;
+ pOwnerPin->ptConnectedLine[2].x = x1;
+ pOwnerPin->ptConnectedLine[2].y = lpPt2->y;
+ pOwnerPin->ptConnectedLine[3].x = xEnd;
+ pOwnerPin->ptConnectedLine[3].y = lpPt2->y;
+ pOwnerPin->nLinePtCount = 4;
+ }
+ else if (lpRect1 != NULL && lpRect2 != NULL) {
+ if (lpRect2->top - lpRect1->bottom > 20 || lpRect1->top - lpRect2->bottom > 20) {
+ if (lpRect2->top - lpRect1->bottom > 20) {
+ y1 = lpRect1->bottom + 10 + pOwnerPin->nIndex * nMargin;
+ x2 = min(lpPt2->x - nArrowLen, x1) - (nPinCount - pOwnerPin->nIndex) * nMargin;
+ }
+ else {
+ y1 = lpRect1->top - 10 - pOwnerPin->nIndex * nMargin;
+ x2 = min(lpPt2->x - nArrowLen, x1) - (nPinCount - pOwnerPin->nIndex) * nMargin;
+ }
+ pOwnerPin->ptConnectedLine[0].x = lpPt1->x;
+ pOwnerPin->ptConnectedLine[0].y = lpPt1->y;
+ pOwnerPin->ptConnectedLine[1].x = x1;
+ pOwnerPin->ptConnectedLine[1].y = lpPt1->y;
+ pOwnerPin->ptConnectedLine[2].x = x1;
+ pOwnerPin->ptConnectedLine[2].y = y1;
+ pOwnerPin->ptConnectedLine[3].x = x2;
+ pOwnerPin->ptConnectedLine[3].y = y1;
+ pOwnerPin->ptConnectedLine[4].x = x2;
+ pOwnerPin->ptConnectedLine[4].y = lpPt2->y;
+ pOwnerPin->ptConnectedLine[5].x = xEnd;
+ pOwnerPin->ptConnectedLine[5].y = lpPt2->y;
+ pOwnerPin->nLinePtCount = 6;
+ }
+ else {
+ x2 = min(lpRect1->left, lpRect2->left) - 30;
+ y1 = max(lpRect1->bottom, lpRect2->bottom) + 30;
+ pOwnerPin->ptConnectedLine[0].x = lpPt1->x;
+ pOwnerPin->ptConnectedLine[0].y = lpPt1->y;
+ pOwnerPin->ptConnectedLine[1].x = x1;
+ pOwnerPin->ptConnectedLine[1].y = lpPt1->y;
+ pOwnerPin->ptConnectedLine[2].x = x1;
+ pOwnerPin->ptConnectedLine[2].y = y1;
+ pOwnerPin->ptConnectedLine[3].x = x2;
+ pOwnerPin->ptConnectedLine[3].y = y1;
+ pOwnerPin->ptConnectedLine[4].x = x2;
+ pOwnerPin->ptConnectedLine[4].y = lpPt2->y;
+ pOwnerPin->ptConnectedLine[5].x = xEnd;
+ pOwnerPin->ptConnectedLine[5].y = lpPt2->y;
+ pOwnerPin->nLinePtCount = 6;
+ }
+ }
+ }
+
+ if (pOwnerPin->nLinePtCount >= 2) {
+ for (int i = 0; i < pOwnerPin->nLinePtCount - 1; i++) {
+ pGraphics->DrawLine(pPen, pOwnerPin->ptConnectedLine[i].x - m_nOffsetX, pOwnerPin->ptConnectedLine[i].y - m_nOffsetY,
+ pOwnerPin->ptConnectedLine[i + 1].x - m_nOffsetX, pOwnerPin->ptConnectedLine[i + 1].y - m_nOffsetY);
+ }
+
+ DrawArrow(pGraphics, pBrush, pPen, pOwnerPin->ptConnectedLine[pOwnerPin->nLinePtCount-1].x - m_nOffsetX,
+ pOwnerPin->ptConnectedLine[pOwnerPin->nLinePtCount-1].y - m_nOffsetY, nArrowLen);
+ }
+}
+
+void CEqsGraphWnd::DrawArrow(Gdiplus::Graphics *pGraphics, Gdiplus::Brush* pBrush, Gdiplus::Pen *pPen,
+ int x, int y, int nArrowLen)
+{
+ Gdiplus::Point pt[4];
+ pt[0].X = x;
+ pt[0].Y = y;
+ pt[1].X = x - nArrowLen;
+ pt[1].Y = y - 3;
+ pt[2].X = pt[1].X;
+ pt[2].Y = y + 3;
+ pt[3].X = x;
+ pt[3].Y = y;
+ pGraphics->FillPolygon(pBrush, pt, 4);
+ pGraphics->DrawPolygon(pPen, pt, 4);
+}
+
+void CEqsGraphWnd::DrawPinWillConnectLine(COLORREF color, LPPOINT lpPt1, LPPOINT lpPt2)
+{
+ HDC hDC = GetDC(m_hWnd);
+
+ HPEN hPen = CreatePen(PS_SOLID, 2, color);
+ int oldRop = SetROP2(hDC, R2_NOTXORPEN);
+ HBRUSH hOldPen = (HBRUSH)::SelectObject(hDC, hPen);
+
+ if (lpPt1 != NULL && lpPt2 != NULL) {
+ ::MoveToEx(hDC, lpPt1->x, lpPt1->y, NULL);
+ ::LineTo(hDC, lpPt2->x, lpPt2->y);
+ }
+
+ ::SetROP2(hDC, oldRop);
+ ::SelectObject(hDC, hPen);
+ ::DeleteObject(hOldPen);
+ ::ReleaseDC(m_hWnd, hDC);
+}
+
+/*
+ * WindowProc,窗口过程
+ */
+LRESULT CALLBACK CEqsGraphWnd::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ CEqsGraphWnd* pEqsGraphWnd = (CEqsGraphWnd*)GetProp(hWnd, EQSGRAPHWND_TAG);
+ if (pEqsGraphWnd == NULL && uMsg != WM_NCCREATE)
+ {
+ return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
+ }
+
+
+ // 处理窗口消息
+ ASSERT(hWnd);
+ switch (uMsg)
+ {
+ case WM_NCCREATE:
+ return CEqsGraphWnd::OnNcCreate(hWnd, wParam, lParam);
+
+ case WM_DESTROY:
+ return pEqsGraphWnd->OnDestroy(wParam, lParam);
+
+ case WM_NCPAINT:
+ return pEqsGraphWnd->OnNcPaint(wParam, lParam);
+
+ case WM_PAINT:
+ return pEqsGraphWnd->OnPaint(wParam, lParam);
+
+ case WM_TIMER:
+ return pEqsGraphWnd->OnTimer(wParam, lParam);
+
+ case WM_MOUSEMOVE:
+ return pEqsGraphWnd->OnMouseMove(wParam, lParam);
+
+ case WM_LBUTTONDOWN:
+ return pEqsGraphWnd->OnLButtonDown(wParam, lParam);
+
+ case WM_RBUTTONDOWN:
+ return pEqsGraphWnd->OnRButtonDown(wParam, lParam);
+
+ case WM_LBUTTONDBLCLK:
+ return pEqsGraphWnd->OnLButtonDblclk(wParam, lParam);
+
+ case WM_MOUSEWHEEL:
+ return pEqsGraphWnd->OnMouseWheel(wParam, lParam);
+
+ case WM_MOUSEHWHEEL:
+ return pEqsGraphWnd->OnMouseHWheel(wParam, lParam);
+
+ case WM_KEYDOWN:
+ return pEqsGraphWnd->OnKeyDown(wParam, lParam);
+
+ case WM_SIZE:
+ return pEqsGraphWnd->OnSize(wParam, lParam);
+
+ case WM_VSCROLL:
+ return pEqsGraphWnd->OnVScroll(wParam, lParam);
+
+ case WM_HSCROLL:
+ return pEqsGraphWnd->OnHScroll(wParam, lParam);
+
+ case WM_NOTIFY:
+ return pEqsGraphWnd->OnNitify(wParam, lParam);
+
+ case WM_GETDLGCODE:
+ return DLGC_WANTALLKEYS;
+
+ default:
+ break;
+ }
+
+ return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+/*
+ * WM_NCCREATE
+ * 窗口创建
+ */
+LRESULT CEqsGraphWnd::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+ CEqsGraphWnd* pEqsGraphWnd = (CEqsGraphWnd*)GetProp(hWnd,EQSGRAPHWND_TAG);
+ ASSERT(pEqsGraphWnd == NULL);
+
+ Hook(hWnd)->Init();
+ return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
+}
+
+/*
+ * WM_DESTROY
+ * 窗口销毁
+ */
+LRESULT CEqsGraphWnd::OnDestroy(WPARAM wParam, LPARAM lParam)
+{
+ Release();
+ return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
+}
+
+
+/*
+ * WM_TIMER
+ */
+LRESULT CEqsGraphWnd::OnTimer(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam == TIMER_FLASH) {
+ if (m_pFlashItem != NULL && m_nFlashCount > 0) {
+ m_nFlashCount--;
+ m_pFlashItem->nFlashFlag = (m_nFlashCount % 2);
+
+ RECT rcItem;
+ GetItemWarperRect(m_pFlashItem, &rcItem);
+ InvalidateRect(m_hWnd, &rcItem, TRUE);
+ }
+ else {
+ m_pFlashItem = NULL;
+ m_nFlashCount = 0;
+ }
+ }
+ else if (TIMER_ANIMATION_RECT == wParam) {
+ if (m_pAnimationItem != NULL) {
+ if (m_nAninationStep > 0) {
+ m_nAninationStep--;
+
+ m_rcAnimation.left += m_rcAninationStep.left;
+ m_rcAnimation.right += m_rcAninationStep.right;
+ m_rcAnimation.top += m_rcAninationStep.top;
+ m_rcAnimation.bottom += m_rcAninationStep.bottom;
+
+ RECT rcItem;
+ GetItemWarperRect(m_pAnimationItem, &rcItem);
+ InvalidateRect(m_hWnd, &rcItem, TRUE);
+ }
+ else {
+ KillTimer(m_hWnd, TIMER_ANIMATION_RECT);
+ RECT rcItem;
+ GetItemWarperRect(m_pAnimationItem, &rcItem);
+ InvalidateRect(m_hWnd, &rcItem, TRUE);
+ m_pAnimationItem = NULL;
+ }
+ }
+ else {
+ KillTimer(m_hWnd, TIMER_ANIMATION_RECT);
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ InvalidateRect(m_hWnd, &rcClient, TRUE);
+ }
+ }
+
+ return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
+}
+
+/*
+ * WM_MOUSEMOVE
+ * 鼠标滚动
+ */
+LRESULT CEqsGraphWnd::OnMouseMove(WPARAM wParam, LPARAM lParam)
+{
+ return ::DefWindowProc(m_hWnd, WM_MOUSEMOVE, wParam, lParam);
+}
+
+/*
+ * WM_LBUTTONDOWN
+ * 鼠标左键按下
+ */
+LRESULT CEqsGraphWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam)
+{
+ POINT pt, ptNew;
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+
+ RECT rcClient, rcItem, rcNewItem, rcLast;
+ GetClientRect(m_hWnd, &rcClient);
+ rcLast = {0, 0, 0, 0};
+ int nMaxOffsetX = m_nStageCx - (rcClient.right - rcClient.left);
+ int nMaxOffsetY = m_nStageCy - (rcClient.bottom - rcClient.top);
+ int nLastHozLine = 0;
+ int nLastVerLine = 0;
+
+
+ // 检测点击坐标是否在某一子项上,如是,则高亮显示
+ EQITEM* pLastItem = m_pCurItem;
+ PIN *pLastPin = m_pCurPin;
+ PIN *pLastSelLineOutPin = m_pSelLineOutPin;
+ BOOL bChanged = FALSE;
+ EQITEM* pHitItem = NULL;
+ PIN *pHitPin = NULL;
+ PIN *pPin2 = NULL;
+ int nRet = HighTest(pt, pHitItem, pHitPin);
+ if (pHitItem != m_pCurItem || nRet != HT_ITEM) {
+ if (m_pCurItem != NULL) {
+ m_pCurItem->bHighlight = FALSE;
+ }
+ m_pCurItem = NULL;
+ }
+
+ if (pHitPin != m_pCurPin || nRet != HT_PIN) {
+ if (m_pCurPin != NULL) {
+ m_pCurPin->bHighlight = FALSE;
+ }
+ m_pCurPin = NULL;
+ }
+
+ if (pHitPin != m_pSelLineOutPin || nRet != HT_LINE) {
+ m_pSelLineOutPin = NULL;
+ }
+
+ if (nRet == HT_ITEM) {
+ m_pCurItem = pHitItem;
+ m_pCurItem->bHighlight = TRUE;
+ }
+ else if (nRet == HT_PIN) {
+ m_pCurPin = pHitPin;
+ m_pCurPin->bHighlight = TRUE;
+ }
+ else if (nRet == HT_LINE) {
+ m_pSelLineOutPin = pHitPin;
+ }
+
+
+ bChanged = pLastItem != m_pCurItem || pLastPin != m_pCurPin || pLastSelLineOutPin != m_pSelLineOutPin;
+
+
+ // 刷新
+ SetFocus(m_hWnd);
+ if (bChanged) {
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ }
+
+
+ // 捕捉鼠标消息,检测是否拖动
+ if (nRet == HT_ITEM && m_pCurItem != NULL) {
+ GetItemRect(m_pCurItem, &rcItem);
+
+ 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);
+ rcNewItem.left = rcItem.left + (ptNew.x - pt.x);
+ rcNewItem.right = rcItem.right + (ptNew.x - pt.x);
+ rcNewItem.top = rcItem.top + (ptNew.y - pt.y);
+ rcNewItem.bottom = rcItem.bottom + (ptNew.y - pt.y);
+ CalculateMagneticLine(m_pCurItem, &rcNewItem, m_nMagneticLinHoz, m_nMagneticLinVer);
+ DrawDropItemRectangle(&rcNewItem, &rcLast);
+ DrawMagneticLine(&rcClient, m_nMagneticLinHoz, nLastHozLine, m_nMagneticLinVer, nLastVerLine);
+ nLastHozLine = m_nMagneticLinHoz;
+ nLastVerLine = m_nMagneticLinVer;
+ CopyRect(&rcLast, &rcNewItem);
+ break;
+
+ case WM_LBUTTONUP:
+ ptNew = msg.pt;
+ ::ScreenToClient(m_hWnd, &ptNew);
+ m_pCurItem->rect.left = m_nMagneticLinVer > 0 ? m_nMagneticLinVer : (rcItem.left + (ptNew.x - pt.x) + m_nOffsetX);
+ m_pCurItem->rect.right = m_pCurItem->rect.left + (rcItem.right - rcItem.left);
+ m_pCurItem->rect.top = m_nMagneticLinHoz > 0 ? m_nMagneticLinHoz : (rcItem.top + (ptNew.y - pt.y) + m_nOffsetY);
+ m_pCurItem->rect.bottom = m_pCurItem->rect.top + (rcItem.bottom - rcItem.top);
+ if (m_pCurItem->rect.left != rcItem.left || m_pCurItem->rect.top != rcItem.top) {
+ if (m_listener.onEqItemPosChanged != nullptr) {
+ m_listener.onEqItemPosChanged(m_pCurItem, m_pCurItem->rect.left, m_pCurItem->rect.top);
+ }
+ }
+ DrawDropItemRectangle(NULL, &rcLast);
+ ReleaseCapture();
+
+ ClearConnectedLinePoint(m_pCurItem);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ goto ExitLoop;
+
+ case WM_KEYDOWN:
+ if (msg.wParam != VK_ESCAPE)
+ break;
+
+ default:
+ DispatchMessage(&msg);
+ break;
+ }
+ }
+
+ ReleaseCapture();
+ ExitLoop:
+ m_nMagneticLinHoz = 0;
+ m_nMagneticLinVer = 0;
+ AfxUnlockTempMaps(FALSE);
+ }
+ }
+
+
+ // 捕捉鼠标消息,检测是否连接引脚
+ else if (nRet == HT_PIN && m_pCurPin != NULL) {
+ if (::GetCapture() == NULL) {
+ BOOL bLast = FALSE;
+ bool bCanConnect;
+ POINT ptPin, ptLast;
+ COLORREF lineColor;
+ GetPinPoint(m_pCurPin, &ptPin);
+ ptLast.x = ptPin.x;
+ ptLast.y = ptPin.y;
+
+ 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);
+
+ // 擦除上一次
+ if (bLast) {
+ DrawPinWillConnectLine(lineColor, &ptPin, &ptLast);
+ }
+
+ // 检测是否可以连接
+ bCanConnect = false;
+ nRet = HighTest(ptNew, pHitItem, pHitPin);
+ if (nRet == HT_PIN) {
+ if (m_listener.onCheckConnectPin != nullptr) {
+ bCanConnect = m_listener.onCheckConnectPin(m_pCurPin, pHitPin);
+ }
+ }
+ if (bCanConnect) {
+ lineColor = RGB(0, 255, 0);
+ DrawPinWillConnectLine(lineColor, &ptPin, &ptNew);
+ }
+ else {
+ lineColor = RGB(0, 0, 0);
+ DrawPinWillConnectLine(lineColor, &ptPin, &ptNew);
+ }
+
+ ptLast.x = ptNew.x;
+ ptLast.y = ptNew.y;
+ bLast = TRUE;
+ break;
+
+ case WM_LBUTTONUP:
+ ptNew = msg.pt;
+ ::ScreenToClient(m_hWnd, &ptNew);
+
+ // 擦除上一次
+ if (bLast) {
+ DrawPinWillConnectLine(lineColor, &ptPin, &ptLast);
+ }
+
+ // 检测是否可以连接
+ bCanConnect = false;
+ nRet = HighTest(ptNew, pHitItem, pHitPin);
+ if (nRet == HT_PIN) {
+ if (m_listener.onConnectPin != nullptr) {
+ bCanConnect = m_listener.onConnectPin(m_pCurPin, pHitPin);
+ }
+ }
+ if (bCanConnect) {
+ m_pCurPin->pConnectedPin = pHitPin;
+ pHitPin->pConnectedPin = m_pCurPin;
+ }
+ bLast = FALSE;
+
+ ReleaseCapture();
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ goto ExitLoop2;
+
+ case WM_KEYDOWN:
+ if (msg.wParam != VK_ESCAPE)
+ break;
+
+ default:
+ DispatchMessage(&msg);
+ break;
+ }
+ }
+
+ ReleaseCapture();
+ ExitLoop2:
+ AfxUnlockTempMaps(FALSE);
+ }
+ }
+
+
+ // 检测鼠标消息,检测是否移动画布
+ else if (nRet == HT_NOWHERE) {
+ if (::GetCapture() == NULL) {
+ int nLastOffsetX = m_nOffsetX;
+ int nLastOffsetY = m_nOffsetY;
+
+ POINT ptStart;
+ ptStart.x = pt.x;
+ ptStart.y = pt.y;
+
+ SetCursor(LoadCursor(NULL, IDC_SIZEALL));
+ 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);
+ m_nOffsetX = min(nMaxOffsetX, max(0, nLastOffsetX - (ptNew.x - ptStart.x)));
+ m_nOffsetY = min(nMaxOffsetY, max(0, nLastOffsetY - (ptNew.y - ptStart.y)));
+ CalculateScollbar();
+ CalculateMapPos();
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ break;
+
+ case WM_LBUTTONUP:
+ ptNew = msg.pt;
+ ::ScreenToClient(m_hWnd, &ptNew);
+
+ ReleaseCapture();
+ CalculateScollbar();
+ CalculateMapPos();
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ goto ExitLoop3;
+
+ case WM_KEYDOWN:
+ if (msg.wParam != VK_ESCAPE)
+ break;
+
+ default:
+ DispatchMessage(&msg);
+ break;
+ }
+ }
+
+ ReleaseCapture();
+ ExitLoop3:
+ AfxUnlockTempMaps(FALSE);
+ }
+ }
+
+
+ return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
+}
+
+/*
+ * WM_LBUTTONDBLCLK
+ * 鼠标左键双击
+ */
+LRESULT CEqsGraphWnd::OnLButtonDblclk(WPARAM wParam, LPARAM lParam)
+{
+ POINT pt;
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+
+ RECT rcClient, rcLast;
+ GetClientRect(m_hWnd, &rcClient);
+ rcLast = { 0, 0, 0, 0 };
+
+ // 检测点击坐标是否在某一子项上,如是,则高亮显示
+ EQITEM* pLastItem = m_pCurItem;
+ BOOL bChanged = FALSE;
+ EQITEM* pHitItem = NULL;
+ PIN *pHitPin = NULL;
+ int nRet = HighTest(pt, pHitItem, pHitPin);
+ if ( nRet == HT_ITEM) {
+ m_pCurItem = pHitItem;
+ m_pCurItem->bHighlight = FALSE;
+ if (m_listener.onDblckEqItem != nullptr) {
+ m_listener.onDblckEqItem(pHitItem);
+ }
+ }
+
+
+ return ::DefWindowProc(m_hWnd, WM_LBUTTONDBLCLK, wParam, lParam);
+}
+
+/*
+ * WM_MOUSEWHEEL
+ * 鼠标滚动
+ */
+LRESULT CEqsGraphWnd::OnMouseWheel(WPARAM wParam, LPARAM lParam)
+{
+ short zDelta;
+ UINT nFlags;
+ CPoint pt;
+
+ nFlags = LOWORD(wParam);
+ zDelta = (short)HIWORD(wParam);
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+
+
+ CRect rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ m_nOffsetY -= zDelta;
+ m_nOffsetY = max(0, min(m_nOffsetY, m_nStageCy - rcClient.Height()));
+ CalculateScollbar();
+ CalculateMapPos();
+
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ return ::DefWindowProc(m_hWnd, WM_MOUSEWHEEL, wParam, lParam);
+}
+
+/*
+* WM_MOUSEHWHEEL
+* 鼠标滚动
+*/
+LRESULT CEqsGraphWnd::OnMouseHWheel(WPARAM wParam, LPARAM lParam)
+{
+ short zDelta;
+ UINT nFlags;
+ CPoint pt;
+
+ nFlags = LOWORD(wParam);
+ zDelta = (short)HIWORD(wParam);
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+
+
+ CRect rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ m_nOffsetX += zDelta;
+ m_nOffsetX = max(0, min(m_nOffsetX, m_nStageCx - rcClient.Width()));
+ CalculateScollbar();
+ CalculateMapPos();
+
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ return ::DefWindowProc(m_hWnd, WM_MOUSEHWHEEL, wParam, lParam);
+}
+
+/*
+ * WM_RBUTTONDOWN
+ * 鼠标左键按下
+ */
+LRESULT CEqsGraphWnd::OnRButtonDown(WPARAM wParam, LPARAM lParam)
+{
+ POINT pt, ptNew;
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+
+ RECT rcClient, rcItem, rcLast;
+ GetClientRect(m_hWnd, &rcClient);
+ rcLast = { 0, 0, 0, 0 };
+
+ // 检测点击坐标是否在某一子项上,如是,则高亮显示
+ EQITEM* pLastItem = m_pCurItem;
+ PIN *pLastPin = m_pCurPin;
+ PIN *pLastSelLineOutPin = m_pSelLineOutPin;
+ BOOL bChanged = FALSE;
+ EQITEM* pHitItem = NULL;
+ PIN *pHitPin = NULL;
+ PIN *pPin2 = NULL;
+ int nRet = HighTest(pt, pHitItem, pHitPin);
+ if (pHitItem != m_pCurItem || nRet != HT_ITEM) {
+ if (m_pCurItem != NULL) {
+ m_pCurItem->bHighlight = FALSE;
+ }
+ m_pCurItem = NULL;
+ }
+
+ if (pHitPin != m_pCurPin || nRet != HT_PIN) {
+ if (m_pCurPin != NULL) {
+ m_pCurPin->bHighlight = FALSE;
+ }
+ m_pCurPin = NULL;
+ }
+
+ if (pHitPin != m_pSelLineOutPin || nRet != HT_LINE) {
+ m_pSelLineOutPin = NULL;
+ }
+
+ if (nRet == HT_ITEM) {
+ m_pCurItem = pHitItem;
+ m_pCurItem->bHighlight = TRUE;
+ }
+ else if (nRet == HT_PIN) {
+ m_pCurPin = pHitPin;
+ m_pCurPin->bHighlight = TRUE;
+ }
+ else if (nRet == HT_LINE) {
+ m_pSelLineOutPin = pHitPin;
+ }
+
+
+ bChanged = pLastItem != m_pCurItem || pLastPin != m_pCurPin || pLastSelLineOutPin != m_pSelLineOutPin;
+
+
+ // 刷新
+ SetFocus(m_hWnd);
+ if (bChanged) {
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ }
+
+
+ // 捕捉鼠标消息,检测是否拖动
+ if (nRet == HT_ITEM && m_pCurItem != NULL) {
+ CopyRect(&rcItem, &m_pCurItem->rect);
+
+ 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:
+ break;
+
+ case WM_RBUTTONUP:
+ ptNew = msg.pt;
+ ::ScreenToClient(m_hWnd, &ptNew);
+ nRet = HighTest(ptNew, pHitItem, pHitPin);
+ ReleaseCapture();
+ if (m_listener.onRclickEqItem != NULL) {
+ m_listener.onRclickEqItem(pHitItem);
+ }
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ goto ExitLoop;
+
+ case WM_KEYDOWN:
+ if (msg.wParam != VK_ESCAPE)
+ break;
+
+ default:
+ DispatchMessage(&msg);
+ break;
+ }
+ }
+
+ ReleaseCapture();
+ ExitLoop:
+ AfxUnlockTempMaps(FALSE);
+ }
+ }
+
+
+ return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
+}
+
+/*
+ * WM_KEYDOWN
+ * 键盘消息,按下按键
+ */
+LRESULT CEqsGraphWnd::OnKeyDown(WPARAM wParam, LPARAM lParam)
+{
+ BOOL bChanged = FALSE;
+ if (wParam == VK_DELETE) {
+ // 如果当前选择为线,则断开连接
+ if (m_pSelLineOutPin != NULL) {
+ if (m_listener.onDisconnectPin != nullptr) {
+ if (m_listener.onDisconnectPin(m_pSelLineOutPin)) {
+ m_pSelLineOutPin->pConnectedPin->pConnectedPin = NULL;
+ m_pSelLineOutPin->pConnectedPin = NULL;
+ m_pSelLineOutPin = NULL;
+ bChanged = TRUE;
+ }
+ }
+ }
+ else if (m_pCurItem != NULL) {
+ if (m_listener.onDeleteEqItem != NULL) {
+ if (m_listener.onDeleteEqItem(m_pCurItem)) {
+ bChanged = DeleteItem(m_pCurItem) >= 0;
+ }
+ }
+ }
+ }
+
+
+ if (bChanged) {
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ }
+
+ return ::DefWindowProc(m_hWnd, WM_KEYDOWN, wParam, lParam);
+}
+
+/*
+ * WM_NCPAINT
+ */
+LRESULT CEqsGraphWnd::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 rect, rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.left);
+ ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.right);
+ GetWindowRect(m_hWnd, &rect);
+ rcClient.right = rect.right - 1;
+ rcClient.bottom = rect.bottom - 1;
+ ::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);
+
+ hBrushFrame = CreateSolidBrush(m_crFrame);
+ ::FrameRect(hDC, &rect, hBrushFrame);
+
+ ::DeleteObject(hRgnWnd);
+ ::DeleteObject(hRgnClient);
+ DeleteObject(hBrushFrame);
+ ::ReleaseDC(m_hWnd, hDC);
+ }
+
+ return lRet;
+}
+
+/*
+ * WM_PAINT
+ */
+LRESULT CEqsGraphWnd::OnPaint(WPARAM wParam, LPARAM lParam)
+{
+ HDC hDC, hMemDC;
+ HBITMAP hBitmap;
+ RECT rcClient;
+ CString strText;
+ 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);
+
+
+ // 背景颜色
+ hBrushBK = CreateSolidBrush(m_crBkgnd);
+ ::FillRect(hMemDC, &rcClient, hBrushBK);
+ DeleteObject(hBrushBK);
+
+
+ // 标题
+ if (m_hFontTitle == nullptr) {
+ LOGFONT lf;
+ HFONT hFontDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+ ::GetObject(hFontDefault, sizeof(LOGFONT), &lf);
+ lf.lfHeight -= 6;
+ lf.lfWeight = FW_SEMIBOLD;
+ m_hFontTitle = CreateFontIndirect(&lf);
+ }
+
+ {
+ char szTitle[256];
+ GetWindowText(m_hWnd, szTitle, 256);
+ RECT rcTitle;
+ rcTitle.left = rcClient.left + 5;
+ rcTitle.top = rcClient.top + 12;
+ rcTitle.bottom = rcClient.bottom - 5;
+ rcTitle.right = rcClient.right - 5;
+ ::SelectObject(hMemDC, m_hFontTitle);
+ ::DrawText(hMemDC, szTitle, (int)strlen(szTitle), &rcTitle, DT_LEFT | DT_TOP);
+ }
+
+
+ // 绘制子项
+ HBRUSH hbrItemBackground[2];
+ HBRUSH hbrItemFrame[2];
+ HBRUSH hbrPinBackground[3];
+ hbrItemBackground[0] = CreateSolidBrush(m_crItemBackground[0]);
+ hbrItemBackground[1] = CreateSolidBrush(m_crItemBackground[1]);
+ hbrItemFrame[0] = CreateSolidBrush(m_crItemFrame[0]);
+ hbrItemFrame[1] = CreateSolidBrush(m_crItemFrame[1]);
+ for (int i = 0; i < 3; i++) {
+ hbrPinBackground[i] = CreateSolidBrush(m_crPinBkgnd[i]);
+ }
+
+
+ // gdi+
+ Gdiplus::Graphics graphics(hMemDC);
+ Gdiplus::Pen pen1(Gdiplus::Color(255, 64, 64, 64), 2);
+ Gdiplus::Pen pen2(Gdiplus::Color(255, 255, 127, 39), 2);
+ Gdiplus::SolidBrush brush1(Gdiplus::Color(255, 64, 64, 64));
+ if (m_bUseGdiPlus) {
+ graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
+ }
+
+
+ SetBkMode(hMemDC, TRANSPARENT);
+ {
+ RECT rcItem;
+ int nPinState;
+ int nItemCount = (int)m_arItem.GetCount();
+ for (int i = 0; i < nItemCount; i++) {
+ EQITEM* pItem = (EQITEM*)m_arItem.GetAt(i);
+ if (pItem->nFlashFlag == 1) {
+ continue;
+ }
+ GetItemRect(pItem, &rcItem);
+
+
+ // 子项背景和边框
+ if (m_nItemRound == 0) {
+ ::FillRect(hMemDC, &rcItem, pItem->bHighlight ? hbrItemBackground[1] : hbrItemBackground[0]);
+ ::FrameRect(hMemDC, &rcItem, pItem->bHighlight ? hbrItemFrame[1] : hbrItemFrame[0]);
+ }
+ else {
+ HRGN hRgn = CreateRoundRectRgn(rcItem.left, rcItem.top, rcItem.right, rcItem.bottom, m_nItemRound, m_nItemRound);
+ ::FillRgn(hMemDC, hRgn, pItem->bHighlight ? hbrItemBackground[1] : hbrItemBackground[0]);
+ ::FrameRgn(hMemDC, hRgn, pItem->bHighlight ? hbrItemFrame[1] : hbrItemFrame[0], 1, 1);
+ ::DeleteObject(hRgn);
+ }
+
+
+ // name和id
+ HFONT hFontOld = (HFONT)::SelectObject(hMemDC, m_hFontName);
+ ::SetTextColor(hMemDC, pItem->bHighlight ? m_crItemNameText[1] : m_crItemNameText[0]);
+ ::DrawText(hMemDC, pItem->text, (int)strlen(pItem->text), &rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
+
+ if (pItem->nShowType != ITEM_SMALL) {
+ RECT rcId = rcItem;
+ rcId.left += 5;
+ rcId.bottom -= 5;
+ CString strId;
+ strId.Format(_T("ID:%d"), pItem->id);
+ ::SelectObject(hMemDC, m_hFontId);
+ ::SetTextColor(hMemDC, pItem->bHighlight ? m_crItemIdText[1] : m_crItemIdText[0]);
+ ::DrawText(hMemDC, strId, (int)strId.GetLength(), &rcId, DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_END_ELLIPSIS);
+ }
+
+
+ // 动画效果不绘pin
+ if (m_pAnimationItem == pItem) {
+ continue;
+ }
+
+
+ // 绘制pin
+ RECT rcPin, rcPin2, rcPinText;
+ CPtrArray *pPins;
+ rcPinText.left = rcItem.left + 8;
+ rcPinText.right = rcItem.right - 8;
+
+
+ // in pins
+ PIN *pPin = NULL;
+ pPins = (CPtrArray *)pItem->pInPins;
+ for (int j = 0; j < pPins->GetSize(); j++) {
+ if (GetInPinRect(pItem, j, &rcPin)) {
+ pPin = (PIN *)pPins->GetAt(j);
+ ::FrameRect(hMemDC, &rcPin, pItem->bHighlight ? hbrItemFrame[1] : hbrItemFrame[0]);
+
+ rcPin2.left = rcPin.left + 1;
+ rcPin2.right = rcPin.right;
+ rcPin2.top = rcPin.top + 1;
+ rcPin2.bottom = rcPin.bottom - 1;
+ nPinState = GetPinState(pPin);
+ ::FillRect(hMemDC, &rcPin2, nPinState == 0 ? (pItem->bHighlight ? hbrItemBackground[1] : hbrItemBackground[0]) : hbrPinBackground[nPinState]);
+
+ if (pItem->nShowType != ITEM_SMALL) {
+ rcPinText.top = rcPin.top - 12;
+ rcPinText.bottom = rcPin.bottom + 12;
+ ::SetTextColor(hMemDC, pItem->bHighlight ? m_crItemIdText[1] : m_crItemIdText[0]);
+ ::DrawText(hMemDC, pPin->text, (int)strlen(pPin->text), &rcPinText, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
+ }
+ }
+ }
+
+
+ // out pins
+ pPins = (CPtrArray *)pItem->pOutPins;
+ for (int j = 0; j < pPins->GetSize(); j++) {
+ pPin = (PIN *)pPins->GetAt(j);
+ if (GetOutPinRect(pItem, j, &rcPin)) {
+ ::FrameRect(hMemDC, &rcPin, pItem->bHighlight ? hbrItemFrame[1] : hbrItemFrame[0]);
+
+ rcPin2.left = rcPin.left;
+ rcPin2.right = rcPin.right - 1;
+ rcPin2.top = rcPin.top + 1;
+ rcPin2.bottom = rcPin.bottom - 1;
+ nPinState = GetPinState(pPin);
+ ::FillRect(hMemDC, &rcPin2, nPinState == 0 ? (pItem->bHighlight ? hbrItemBackground[1] : hbrItemBackground[0]) : hbrPinBackground[nPinState]);
+
+ if (pItem->nShowType != ITEM_SMALL) {
+ rcPinText.top = rcPin.top - 12;
+ rcPinText.bottom = rcPin.bottom + 12;
+ ::SetTextColor(hMemDC, pItem->bHighlight ? m_crItemIdText[1] : m_crItemIdText[0]);
+ ::DrawText(hMemDC, pPin->text, (int)strlen(pPin->text), &rcPinText, DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
+ }
+ }
+ }
+
+ ::DeleteObject(hbrItemFrame);
+ ::SelectObject(hMemDC, hFontOld);
+ }
+
+
+ // 绘制连接线,保存线条在最后绘制
+ for (int i = 0; i < nItemCount; i++) {
+ EQITEM *pItem = (EQITEM*)m_arItem.GetAt(i);
+ if (pItem->nFlashFlag == 1) {
+ continue;
+ }
+
+ PIN *pPin = NULL;
+ CPtrArray *pPins;
+
+ // out pins边线
+ RECT rcItem1, rcItem2;
+ pPins = (CPtrArray *)pItem->pOutPins;
+ for (int j = 0; j < pPins->GetSize(); j++) {
+ pPin = (PIN *)pPins->GetAt(j);
+ if (pPin->pConnectedPin != NULL) {
+ POINT pt1, pt2;
+ if (GetPinPoint(pPin, &pt1) && GetPinPoint(pPin->pConnectedPin, &pt2)) {
+ GetItemRect(pItem, &rcItem1);
+ GetItemRect(pPin->pConnectedPin->pItem, &rcItem2);
+ DrawPinConnectedLine(&graphics, &brush1, pPin == m_pSelLineOutPin ? &pen2 : &pen1,
+ &pt1, &pt2, &rcItem1, &rcItem2, pPin);
+ }
+ }
+ }
+ }
+
+
+ for (int i = 0; i < 3; i++) {
+ ::DeleteObject(hbrPinBackground[i]);
+ }
+ ::DeleteObject(hbrItemBackground[0]);
+ ::DeleteObject(hbrItemBackground[1]);
+ ::DeleteObject(hbrItemFrame[0]);
+ ::DeleteObject(hbrItemFrame[1]);
+ }
+
+
+
+
+ // 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 CEqsGraphWnd::OnSize(WPARAM wParam, LPARAM lParam)
+{
+ LRESULT lRet = ::DefWindowProc(m_hWnd, WM_SIZE, wParam, lParam);
+
+ CalculateScollbar();
+
+ if (m_hWndMapPos != NULL) {
+ CalculateMapPos();
+
+ CRect rcItem, rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ GetWindowRect(m_hWndMapPos,& rcItem);
+
+ ::MoveWindow(m_hWndMapPos, rcClient.right- rcItem.Width() - MAPPOSWND_PADDING_RIGHT,
+ MAPPOSWND_PADDING_RIGHT, rcItem.Width(), rcItem.Height(), TRUE);
+ }
+
+ return lRet;
+}
+
+/*
+ * WM_VSCROLL
+ */
+LRESULT CEqsGraphWnd::OnVScroll(WPARAM wParam, LPARAM lParam)
+{
+ int nSBCode = LOWORD(wParam);
+ int nPos = HIWORD(wParam);
+
+ SCROLLINFO info = { 0 };
+ info.cbSize = sizeof(SCROLLINFO);
+ info.fMask = SIF_ALL;
+ GetScrollInfo(m_hWnd, SB_VERT, &info);
+
+ int nMaxPos = info.nMax - info.nPage;
+ int inc = 10;
+
+ switch (nSBCode)
+ {
+ case SB_BOTTOM:
+ if (info.nPos < nMaxPos) {
+ // ScrollWindow(m_hWnd, 0, -1 * inc*(iMaxPos - info.nPos), NULL, NULL);
+ info.nPos = nMaxPos;
+ }
+ break;
+
+ case SB_TOP:
+ if (info.nPos > info.nMin) {
+ // ScrollWindow(m_hWnd, 0, inc*(info.nPos - info.nMin), NULL, NULL);
+ info.nPos = info.nMin;
+ }
+ break;
+
+ case SB_LINEUP:
+ if (info.nPos > info.nMin) {
+ //ScrollWindow(m_hWnd, 0, inc, NULL, NULL);
+ info.nPos -= 1;
+ }
+ break;
+
+ case SB_LINEDOWN:
+ if (info.nPos < nMaxPos) {
+ // ScrollWindow(m_hWnd, 0, -1 * inc, NULL, NULL);
+ info.nPos += 1;
+ }
+ break;
+
+ case SB_PAGEUP:
+ if (info.nPos - 100 >= info.nMin) {
+ //ScrollWindow(m_hWnd, 0, 100 * inc, NULL, NULL);
+ info.nPos -= 100;
+ }
+ else {
+ if (info.nPos <= 0) {
+ // ScrollWindow(m_hWnd, 0, 0, NULL, NULL);
+ }
+ else {
+ // ScrollWindow(m_hWnd, 0, info.nPos, NULL, NULL);
+ }
+ info.nPos = info.nMin;
+ }
+ break;
+
+ case SB_PAGEDOWN:
+ if (info.nPos + 100 <= nMaxPos) {
+ // ScrollWindow(m_hWnd, 0, -100*inc, NULL, NULL);
+ info.nPos += 100;
+ }
+ else {
+ // ScrollWindow(m_hWnd, 0, (info.nPos - iMaxPos) * inc, NULL, NULL);
+ info.nPos = nMaxPos;
+ }
+ break;
+
+ case SB_ENDSCROLL:
+ break;
+
+ case SB_THUMBPOSITION:
+ break;
+
+ case SB_THUMBTRACK:
+ // ScrollWindow(m_hWnd, 0, inc * (info.nPos - nPos), NULL, NULL);
+ info.nPos = nPos;
+ break;
+ default:
+ break;
+ }
+
+ m_nOffsetY = info.nPos;
+ SetScrollInfo(m_hWnd, SB_VERT, &info, TRUE);
+ CalculateMapPos();
+
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+
+ LRESULT lRet = ::DefWindowProc(m_hWnd, WM_VSCROLL, wParam, lParam);
+ return lRet;
+}
+
+/*
+ * WM_HSCROLL
+ */
+LRESULT CEqsGraphWnd::OnHScroll(WPARAM wParam, LPARAM lParam)
+{
+ int nSBCode = LOWORD(wParam);
+ int nPos = HIWORD(wParam);
+
+ SCROLLINFO info = { 0 };
+ info.cbSize = sizeof(SCROLLINFO);
+ info.fMask = SIF_ALL;
+ GetScrollInfo(m_hWnd, SB_HORZ, &info);
+
+ int nMaxPos = info.nMax - info.nPage;
+ int inc = 10;
+
+ switch (nSBCode)
+ {
+ case SB_RIGHT:
+ if (info.nPos < nMaxPos) {
+ // ScrollWindow(m_hWnd, 0, -1 * inc*(iMaxPos - info.nPos), NULL, NULL);
+ info.nPos = nMaxPos;
+ }
+ break;
+
+ case SB_LEFT:
+ if (info.nPos > info.nMin) {
+ // ScrollWindow(m_hWnd, 0, inc*(info.nPos - info.nMin), NULL, NULL);
+ info.nPos = info.nMin;
+ }
+ break;
+
+ case SB_LINELEFT:
+ if (info.nPos > info.nMin) {
+ //ScrollWindow(m_hWnd, 0, inc, NULL, NULL);
+ info.nPos -= 1;
+ }
+ break;
+
+ case SB_LINERIGHT:
+ if (info.nPos < nMaxPos) {
+ // ScrollWindow(m_hWnd, 0, -1 * inc, NULL, NULL);
+ info.nPos += 1;
+ }
+ break;
+
+ case SB_PAGELEFT:
+ if (info.nPos - 100 >= info.nMin) {
+ //ScrollWindow(m_hWnd, 0, 100 * inc, NULL, NULL);
+ info.nPos -= 100;
+ }
+ else {
+ if (info.nPos <= 0) {
+ // ScrollWindow(m_hWnd, 0, 0, NULL, NULL);
+ }
+ else {
+ // ScrollWindow(m_hWnd, 0, info.nPos, NULL, NULL);
+ }
+ info.nPos = info.nMin;
+ }
+ break;
+
+ case SB_PAGERIGHT:
+ if (info.nPos + 100 <= nMaxPos) {
+ // ScrollWindow(m_hWnd, 0, -100*inc, NULL, NULL);
+ info.nPos += 100;
+ }
+ else {
+ // ScrollWindow(m_hWnd, 0, (info.nPos - iMaxPos) * inc, NULL, NULL);
+ info.nPos = nMaxPos;
+ }
+ break;
+
+ case SB_ENDSCROLL:
+ break;
+
+ case SB_THUMBPOSITION:
+ break;
+
+ case SB_THUMBTRACK:
+ // ScrollWindow(m_hWnd, 0, inc * (info.nPos - nPos), NULL, NULL);
+ info.nPos = nPos;
+ break;
+ default:
+ break;
+ }
+
+ m_nOffsetX = info.nPos;
+ SetScrollInfo(m_hWnd, SB_HORZ, &info, TRUE);
+ CalculateMapPos();
+
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+
+ LRESULT lRet = ::DefWindowProc(m_hWnd, WM_HSCROLL, wParam, lParam);
+ return lRet;
+}
+
+/*
+ * WM_NOTIFY
+ */
+LRESULT CEqsGraphWnd::OnNitify(WPARAM wParam, LPARAM lParam)
+{
+ LRESULT lRet = ::DefWindowProc(m_hWnd, WM_NOTIFY, wParam, lParam);
+
+ NMHDR *pNmhdr = (NMHDR *)lParam;
+ if (pNmhdr->idFrom == MAPPOSWND_ID) {
+ MAPPOSWND_NMHDR *pNmhdr2 = (MAPPOSWND_NMHDR *)lParam;
+ m_nOffsetX = pNmhdr2->dwData;
+ m_nOffsetY = pNmhdr2->dwData1;
+ CalculateScollbar();
+ CalculateMapPos();
+
+ RECT rcClient;
+ GetClientRect(m_hWnd, &rcClient);
+ ::InvalidateRect(m_hWnd, &rcClient, TRUE);
+ }
+
+ return lRet;
+}
+
+
+/*
+ * 设置背景颜色
+ * color -- 背景色
+ */
+void CEqsGraphWnd::SetBkgndColor(COLORREF color)
+{
+ m_crBkgnd = color;
+}
+
+/*
+ * 边框颜色
+ * color -- 边框色
+ */
+void CEqsGraphWnd::SetFrameColor(COLORREF color)
+{
+ m_crFrame = color;
+}
+
+void CEqsGraphWnd::FlashItem(EQITEM *pItem)
+{
+ if (m_pFlashItem != NULL) {
+ KillTimer(m_hWnd, TIMER_FLASH);
+ }
+
+ m_nFlashCount = 5;
+ m_pFlashItem = pItem;
+ SetTimer(m_hWnd, TIMER_FLASH, 100, NULL);
+}
+
+void CEqsGraphWnd::AnimationItem(EQITEM* pItem)
+{
+ if (m_pAnimationItem != NULL) {
+ KillTimer(m_hWnd, TIMER_ANIMATION_RECT);
+ }
+
+
+ m_pAnimationItem = NULL;
+ KillTimer(m_hWnd, TIMER_ANIMATION_RECT);
+
+ UINT uElpase = 50;
+ m_nAninationDuration = 200;
+ m_nAninationStep = m_nAninationDuration / uElpase;
+ m_pAnimationItem = pItem;
+ m_rcAnimation.left = pItem->rect.left + (pItem->rect.right - pItem->rect.left) / 2.0f;
+ m_rcAnimation.right = m_rcAnimation.left;
+ m_rcAnimation.top = pItem->rect.top + (pItem->rect.bottom - pItem->rect.top) / 2.0f;
+ m_rcAnimation.bottom = m_rcAnimation.top;
+ m_rcAninationStep.left = (pItem->rect.left - m_rcAnimation.left) / (float)m_nAninationStep;
+ m_rcAninationStep.right = (pItem->rect.right - m_rcAnimation.right) / (float)m_nAninationStep;
+ m_rcAninationStep.top = (pItem->rect.top - m_rcAnimation.top) / (float)m_nAninationStep;
+ m_rcAninationStep.bottom = (pItem->rect.bottom - m_rcAnimation.bottom) / (float)m_nAninationStep;
+
+ SetTimer(m_hWnd, TIMER_ANIMATION_RECT, uElpase, NULL);
+}
+
+double CEqsGraphWnd::PointToSegDist(double x, double y, double x1, double y1, double x2, double y2)
+{
+ double cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
+ if (cross <= 0) return sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
+
+ double d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
+ if (cross >= d2) return sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
+
+ double r = cross / d2;
+ double px = x1 + (x2 - x1) * r;
+ double py = y1 + (y2 - y1) * r;
+ return sqrt((x - px) * (x - px) + (py - y) * (py - y));
+}
+
--
Gitblit v1.9.3