chenluhua1980
2025-11-13 23c351be52a0567ac089b28e8f534c3ebf08b9a9
1.机器状态图由单个指示修改为多个指示器,代表是否有物料;
已修改4个文件
331 ■■■■■ 文件已修改
SourceCode/Bond/Servo/CPageGraph2.cpp 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageGraph2.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/EqsGraphWnd.cpp 295 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/EqsGraphWnd.h 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -64,10 +64,8 @@
            if (RX_CODE_EQ_DATA_CHANGED == code) {
                // 通知设备状态
                SERVO::CEquipment* pEquipment = nullptr;
                if (pAny->getPtrValue("ptr", (void*&)pEquipment)) {
                    if (pEquipment != nullptr) {
                        m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, pEquipment->hasGlass());
                    }
                if (pAny->getPtrValue("ptr", (void*&)pEquipment) && pEquipment != nullptr) {
                    UpdateItemIndicators(pEquipment);
                }
            }
@@ -377,7 +375,20 @@
        m_pEqsGraphWnd->AddPin(pItem, OUTPIN, outPin->getName().c_str(), (DWORD_PTR)outPin);
    }
    m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, pEquipment->hasGlass());
    UpdateItemIndicators(pEquipment);
}
void CPageGraph2::UpdateItemIndicators(SERVO::CEquipment* pEquipment)
{
    for (int i = 0; i < SLOT_MAX; i++) {
        auto pSlot = pEquipment->getSlot(i);
        int state = 0;
        if (pSlot->isEnable()) {
            state = pSlot->getContext() != nullptr ? 1 : 2;
        }
        m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, state, i);
    }
}
void CPageGraph2::OnTimer(UINT_PTR nIDEvent)
SourceCode/Bond/Servo/CPageGraph2.h
@@ -16,6 +16,7 @@
private:
    void InitRxWindows();
    void AddEqToGraphWnd(SERVO::CEquipment* pEquipment);
    void UpdateItemIndicators(SERVO::CEquipment* pEquipment);
    void SaveEqsGraphData();
    void GetItemDataFormIni(const char* pszItemName, int& left, int& top);
SourceCode/Bond/Servo/EqsGraphWnd.cpp
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "EqsGraphWnd.h"
#include "ColorTransfer.h"
#include "MapPosWnd.h"
@@ -86,7 +86,7 @@
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    // 注册窗口类
    // 注册窗口类
    return (::RegisterClass(&wc) != 0);
}
@@ -235,7 +235,7 @@
}
/*
 * 计算磁力线位置
 * 计算磁力线位置
 */
void CEqsGraphWnd::CalculateMagneticLine(EQITEM* pItem, LPRECT lprcItemRect, int &hoz, int &ver)
{
@@ -243,7 +243,7 @@
    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) {
@@ -287,10 +287,10 @@
}
/*
 * 取得In Pin的区域
 * 取得In Pin的区域
 * pItem -- EQITEM
 * lpRect -- 得到的Rect
 * 返回是否成功
 * lpRect -- 得到的Rect
 * 返回是否成功
 */
BOOL CEqsGraphWnd::GetItemRect(EQITEM* pItem, LPRECT lpRect)
{
@@ -321,11 +321,11 @@
}
/*
 * 取得In Pin的区域
 * 取得In Pin的区域
 * pItem -- EQITEM
 * nPinIndex -- in pin索引
 * lpRect -- 得到的Rect
 * 返回是否成功
 * nPinIndex -- in pin索引
 * lpRect -- 得到的Rect
 * 返回是否成功
 */
BOOL CEqsGraphWnd::GetInPinRect(EQITEM* pItem, int nPinIndex, LPRECT lpRect)
{
@@ -345,11 +345,11 @@
}
/*
 * 取得Out Pin的区域
 * 取得Out Pin的区域
 * pItem -- EQITEM
 * nPinIndex -- in pin索引
 * lpRect -- 得到的Rect
 * 返回是否成功
 * nPinIndex -- in pin索引
 * lpRect -- 得到的Rect
 * 返回是否成功
 */
BOOL CEqsGraphWnd::GetOutPinRect(EQITEM* pItem, int nPinIndex, LPRECT lpRect)
{
@@ -368,11 +368,11 @@
}
/*
 * 取得Pin的Point
 * 取得Pin的Point
 * pItem -- EQITEM
 * nPinIndex -- in pin索引
 * lpRect -- 得到的Rect
 * 返回是否成功
 * nPinIndex -- in pin索引
 * lpRect -- 得到的Rect
 * 返回是否成功
 */
BOOL CEqsGraphWnd::GetPinPoint(PIN *pPin, LPPOINT lpPoint)
{
@@ -453,7 +453,7 @@
}
/*
 * 清空PIN连接线缓存点,以便重新计算和绘制
 * 清空PIN连接线缓存点,以便重新计算和绘制
 */
void CEqsGraphWnd::ClearConnectedLinePoint(EQITEM*& pItem)
{
@@ -555,7 +555,7 @@
 */
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;
@@ -755,7 +755,7 @@
    return 0;
}
// 删除Item, 如果pin有连接,注意先断开
// 删除Item, 如果pin有连接,注意先断开
int CEqsGraphWnd::DeleteItem(EQITEM* pItem)
{
    for (int i = 0; i < m_arItem.GetSize(); i++) {
@@ -795,7 +795,7 @@
}
/*
 * 设置子项的选中状态
 * 设置子项的选中状态
 */
void CEqsGraphWnd::SetItemSelectState(int nIndex, BOOL bSelect)
{
@@ -828,14 +828,14 @@
}
/*
 * 检测坐标点所在的项
 * 返回项类型, 如HT_ITEM, HT_PIN, HT_LINE
 * pItem - 所在的EQITEM
 * pPin --所在的pin, 如果在连线上,表示所属pin, out pin;
 * 检测坐标点所在的项
 * 返回项类型, 如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;
@@ -844,7 +844,7 @@
        EQITEM *pTempItem = (EQITEM*)m_arItem.GetAt(i);
        GetItemRect(pTempItem, &rcItem);
        if (::PtInRect(&rcItem, pt)) {
            // 在Item
            // 在Item
            pItem = pTempItem;
            nRet = HT_ITEM;
            break;
@@ -854,7 +854,7 @@
            CPtrArray * pPins = (CPtrArray *)pTempItem->pInPins;
            for (int j = 0; j < pPins->GetSize(); j++) {
                if (GetInPinRect(pTempItem, j, &rcPin) && ::PtInRect(&rcPin, pt)) {
                    // 在in pin上
                    // 在in pin上
                    pPin = (PIN *)pPins->GetAt(j);
                    pItem = pTempItem;
                    nRet = HT_PIN;
@@ -866,15 +866,15 @@
                pPins = (CPtrArray *)pTempItem->pOutPins;
                for (int j = 0; j < pPins->GetSize(); j++) {
                    if (GetOutPinRect(pTempItem, j, &rcPin) && ::PtInRect(&rcPin, pt)) {
                        // 在out pin
                        // 在out pin
                        pPin = (PIN *)pPins->GetAt(j);
                        pItem = pTempItem;
                        nRet = HT_PIN;
                        break;
                    }
                    else {
                        // 是否在pin连接线上,即判断点是否在线上
                        // 点到直线的距离公式(先通过p1,p2用两点式求出直线的表达式,再套距离公式);abs()为取绝对值函数,sqrt()为开根号函数
                        // 是否在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++) {
@@ -907,7 +907,7 @@
}
/*
 * 绘制虚线框,代表正在拖动的item
 * 绘制虚线框,代表正在拖动的item
 */
void CEqsGraphWnd::DrawDropItemRectangle(LPRECT lpRect1, LPRECT lpRect2)
{
@@ -935,7 +935,7 @@
}
/*
 * 绘制磁吸线
 * 绘制磁吸线
 */
void CEqsGraphWnd::DrawMagneticLine(LPRECT lprcClient, int nHozLine1, int nHozLine2, int nVerLine1, int nVerLine2)
{
@@ -969,16 +969,16 @@
}
/*
 * 缓制Pin连接线
 * pBrush -- 画刷
 * pPen - 画笔
 * lpPt1, lpPt2 -- Pin脚的位置
 * lpRect1, lpRect2 -- 两个Item的Rect
 * 缓制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,则先计算并缓存
    // 如果没有缓存线条的POINT,则先计算并缓存
    ASSERT(pOwnerPin);
    int nPinCount = ((CPtrArray*)pOwnerPin->pItem->pOutPins)->GetSize();
@@ -987,10 +987,10 @@
    int nMargin = 12;
    int x1, x2, y1;
    if (pOwnerPin->nLinePtCount == 0) {                        // 第一个点的最小折线长
    if (pOwnerPin->nLinePtCount == 0) {                        // 第一个点的最小折线长
        ::OffsetRect(lpRect1, +m_nOffsetX, +m_nOffsetY);
        ::OffsetRect(lpRect2, +m_nOffsetX, +m_nOffsetY);
        lpPt1->x += m_nOffsetX;                // 消除偏移
        lpPt1->x += m_nOffsetX;                // 消除偏移
        lpPt1->y += m_nOffsetY;
        lpPt2->x += m_nOffsetX;
        lpPt2->y += m_nOffsetY;
@@ -1099,7 +1099,7 @@
}
/*
 * WindowProc,窗口过程
 * WindowProc,窗口过程
 */
LRESULT CALLBACK CEqsGraphWnd::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
@@ -1110,7 +1110,7 @@
    }
    // 处理窗口消息
    // 处理窗口消息
    ASSERT(hWnd);
    switch (uMsg)
    {
@@ -1174,7 +1174,7 @@
/*
 * WM_NCCREATE
 * 窗口创建
 * 窗口创建
 */
LRESULT CEqsGraphWnd::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
@@ -1187,7 +1187,7 @@
/*
 * WM_DESTROY
 * 窗口销毁
 * 窗口销毁
 */
LRESULT CEqsGraphWnd::OnDestroy(WPARAM wParam, LPARAM lParam)
{
@@ -1250,7 +1250,7 @@
/*
 * WM_MOUSEMOVE
 * 鼠标滚动
 * 鼠标滚动
 */
LRESULT CEqsGraphWnd::OnMouseMove(WPARAM wParam, LPARAM lParam)
{
@@ -1259,7 +1259,7 @@
/*
 * WM_LBUTTONDOWN
 * 鼠标左键按下
 * 鼠标左键按下
 */
LRESULT CEqsGraphWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
@@ -1276,7 +1276,7 @@
    int nLastVerLine = 0;
    // 检测点击坐标是否在某一子项上,如是,则高亮显示
    // 检测点击坐标是否在某一子项上,如是,则高亮显示
    EQITEM* pLastItem = m_pCurItem;
    PIN *pLastPin = m_pCurPin;
    PIN *pLastSelLineOutPin = m_pSelLineOutPin;
@@ -1323,14 +1323,14 @@
    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);
@@ -1400,7 +1400,7 @@
    }
    // 捕捉鼠标消息,检测是否连接引脚
    // 捕捉鼠标消息,检测是否连接引脚
    else if (nRet == HT_PIN && m_pCurPin != NULL) {
        if (::GetCapture() == NULL) {
            BOOL bLast = FALSE;
@@ -1427,12 +1427,12 @@
                    ptNew = msg.pt;
                    ::ScreenToClient(m_hWnd, &ptNew);
                    // 擦除上一次
                    // 擦除上一次
                    if (bLast) {
                        DrawPinWillConnectLine(lineColor, &ptPin, &ptLast);
                    }
                    // 检测是否可以连接
                    // 检测是否可以连接
                    bCanConnect = false;
                    nRet = HighTest(ptNew, pHitItem, pHitPin);
                    if (nRet == HT_PIN) {
@@ -1458,12 +1458,12 @@
                    ptNew = msg.pt;
                    ::ScreenToClient(m_hWnd, &ptNew);
                    // 擦除上一次
                    // 擦除上一次
                    if (bLast) {
                        DrawPinWillConnectLine(lineColor, &ptPin, &ptLast);
                    }
                    // 检测是否可以连接
                    // 检测是否可以连接
                    bCanConnect = false;
                    nRet = HighTest(ptNew, pHitItem, pHitPin);
                    if (nRet == HT_PIN) {
@@ -1498,7 +1498,7 @@
    }
    
    // 检测鼠标消息,检测是否移动画布
    // 检测鼠标消息,检测是否移动画布
    else if (nRet == HT_NOWHERE) {
        if (::GetCapture() == NULL) {
            int nLastOffsetX = m_nOffsetX;
@@ -1569,7 +1569,7 @@
/*
 * WM_LBUTTONDBLCLK
 * 鼠标左键双击
 * 鼠标左键双击
 */
LRESULT CEqsGraphWnd::OnLButtonDblclk(WPARAM wParam, LPARAM lParam)
{
@@ -1581,7 +1581,7 @@
    GetClientRect(m_hWnd, &rcClient);
    rcLast = { 0, 0, 0, 0 };
    // 检测点击坐标是否在某一子项上,如是,则高亮显示
    // 检测点击坐标是否在某一子项上,如是,则高亮显示
    EQITEM* pLastItem = m_pCurItem;
    BOOL bChanged = FALSE;
    EQITEM* pHitItem = NULL;
@@ -1601,7 +1601,7 @@
/*
 * WM_MOUSEWHEEL
 * 鼠标滚动
 * 鼠标滚动
 */
LRESULT CEqsGraphWnd::OnMouseWheel(WPARAM wParam, LPARAM lParam)
{
@@ -1628,7 +1628,7 @@
/*
* WM_MOUSEHWHEEL
* 鼠标滚动
* 鼠标滚动
*/
LRESULT CEqsGraphWnd::OnMouseHWheel(WPARAM wParam, LPARAM lParam)
{
@@ -1655,7 +1655,7 @@
/*
 * WM_RBUTTONDOWN
 * 鼠标左键按下
 * 鼠标左键按下
 */
LRESULT CEqsGraphWnd::OnRButtonDown(WPARAM wParam, LPARAM lParam)
{
@@ -1667,7 +1667,7 @@
    GetClientRect(m_hWnd, &rcClient);
    rcLast = { 0, 0, 0, 0 };
    // 检测点击坐标是否在某一子项上,如是,则高亮显示
    // 检测点击坐标是否在某一子项上,如是,则高亮显示
    EQITEM* pLastItem = m_pCurItem;
    PIN *pLastPin = m_pCurPin;
    PIN *pLastSelLineOutPin = m_pSelLineOutPin;
@@ -1710,14 +1710,14 @@
    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);
@@ -1770,13 +1770,13 @@
/*
 * 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)) {
@@ -1866,7 +1866,6 @@
    CString strText;
    HBRUSH hBrushBK;
    // BeginPaint
    PAINTSTRUCT ps;
    hDC = BeginPaint(m_hWnd, &ps);
@@ -1877,14 +1876,12 @@
        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);
@@ -1894,8 +1891,9 @@
        m_hFontTitle = CreateFontIndirect(&lf);
    }
    // 绘制标题文本
    {
        char szTitle[256];
        char szTitle[256] = { 0 };
        GetWindowText(m_hWnd, szTitle, 256);
        RECT rcTitle;
        rcTitle.left = rcClient.left + 5;
@@ -1906,21 +1904,23 @@
        ::DrawText(hMemDC, szTitle, (int)strlen(szTitle), &rcTitle, DT_LEFT | DT_TOP);
    }
    // 绘制子项
    // 绘制子项
    HBRUSH hbrItemBackground[2];
    HBRUSH hbrItemFrame[2];
    HBRUSH hbrPinBackground[3];
    HBRUSH hbrIndicator;
    HBRUSH hbrIndicatorGray;
    hbrItemBackground[0] = CreateSolidBrush(m_crItemBackground[0]);
    hbrItemBackground[1] = CreateSolidBrush(m_crItemBackground[1]);
    hbrItemFrame[0] = CreateSolidBrush(m_crItemFrame[0]);
    hbrItemFrame[1] = CreateSolidBrush(m_crItemFrame[1]);
    hbrIndicator = CreateSolidBrush(RGB(34, 177, 76));
    hbrIndicator = CreateSolidBrush(RGB(34, 177, 76));    // 绿色
    hbrIndicatorGray = CreateSolidBrush(RGB(192, 192, 192));  // 灰色
    for (int i = 0; i < 3; i++) {
        hbrPinBackground[i] = CreateSolidBrush(m_crPinBkgnd[i]);
    }
    // gdi+
    Gdiplus::Graphics graphics(hMemDC);
@@ -1931,21 +1931,22 @@
        graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
    }
    SetBkMode(hMemDC, TRANSPARENT);
    {
        RECT rcItem;
        int nPinState;
        int nItemCount = (int)m_arItem.GetCount();
        // 先画 item、文本、pin 和指示灯
        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]);
@@ -1957,27 +1958,42 @@
                ::DeleteObject(hRgn);
            }
            // name和id
            // name
            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);
            ::DrawText(hMemDC, pItem->text, (int)strlen(pItem->text), &rcItem,
                DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
            // 添加一个小绿点指示器
            if(pItem->bShowIndicator[0]){
            // 多个指示灯:左上角,按 4 列 × 2 行排列
            const int indicatorSize = 10;
            const int indicatorMargin = 3;
            const int indicatorsPerRow = 4;
            for (int k = 0; k < EQITEM_INDICATOR_COUNT; ++k) {
                BYTE indicatorState = pItem->nIndicatorState[k];
                if (indicatorState == INDICATOR_STATE_HIDDEN) {
                    continue;
                }
                int row = k / indicatorsPerRow;
                int col = k % indicatorsPerRow;
                RECT rcIndicator;
                rcIndicator.left = rcItem.left + 5;
                rcIndicator.top = rcItem.top + 5;
                rcIndicator.right = rcIndicator.left + 12;
                rcIndicator.bottom = rcIndicator.top + 12;
                HRGN hRgn = CreateRoundRectRgn(rcIndicator.left, rcIndicator.top, rcIndicator.right, rcIndicator.bottom, 2, 2);
                ::FillRgn(hMemDC, hRgn, hbrIndicator);
                ::FrameRgn(hMemDC, hRgn, hbrItemFrame[0], 1, 1);
                ::DeleteObject(hRgn);
                rcIndicator.left = rcItem.left + 5 + col * (indicatorSize + indicatorMargin);
                rcIndicator.top = rcItem.top + 5 + row * (indicatorSize + indicatorMargin);
                rcIndicator.right = rcIndicator.left + indicatorSize;
                rcIndicator.bottom = rcIndicator.top + indicatorSize;
                // 画高亮/灰色方块
                RECT rcInner = rcIndicator;
                ::InflateRect(&rcInner, -1, -1);
                ::FillRect(hMemDC, &rcInner, indicatorState == INDICATOR_STATE_HIGHLIGHT
                    ? hbrIndicator : hbrIndicatorGray);
                ::FrameRect(hMemDC, &rcIndicator, hbrItemFrame[0]);
            }
            // ID 文本(非小号 item)
            if (pItem->nShowType != ITEM_SMALL) {
                RECT rcId = rcItem;
                rcId.left += 5;
@@ -1986,29 +2002,28 @@
                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);
                ::DrawText(hMemDC, strId, (int)strId.GetLength(), &rcId,
                    DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_END_ELLIPSIS);
            }
            // 动画效果不绘pin
            // 动画效果时不绘制 pin
            if (m_pAnimationItem == pItem) {
                ::SelectObject(hMemDC, hFontOld);
                continue;
            }
            // 绘制pin
            // 绘制 pin
            RECT rcPin, rcPin2, rcPinText;
            CPtrArray *pPins;
            CPtrArray* pPins;
            rcPinText.left = rcItem.left + 8;
            rcPinText.right = rcItem.right - 8;
            // in pins
            PIN *pPin = NULL;
            pPins = (CPtrArray *)pItem->pInPins;
            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);
                    pPin = (PIN*)pPins->GetAt(j);
                    ::FrameRect(hMemDC, &rcPin, pItem->bHighlight ? hbrItemFrame[1] : hbrItemFrame[0]);
                    rcPin2.left = rcPin.left + 1;
@@ -2016,22 +2031,25 @@
                    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]);
                    ::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);
                        ::DrawText(hMemDC, pPin->text, (int)strlen(pPin->text), &rcPinText,
                            DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
                    }
                }
            }
            // out pins
            pPins = (CPtrArray *)pItem->pOutPins;
            pPins = (CPtrArray*)pItem->pOutPins;
            for (int j = 0; j < pPins->GetSize(); j++) {
                pPin = (PIN *)pPins->GetAt(j);
                pPin = (PIN*)pPins->GetAt(j);
                if (GetOutPinRect(pItem, j, &rcPin)) {
                    ::FrameRect(hMemDC, &rcPin, pItem->bHighlight ? hbrItemFrame[1] : hbrItemFrame[0]);
@@ -2040,50 +2058,53 @@
                    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]);
                    ::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);
                        ::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);
            EQITEM* pItem = (EQITEM*)m_arItem.GetAt(i);
            if (pItem->nFlashFlag == 1) {
                continue;
            }
            PIN *pPin = NULL;
            CPtrArray *pPins;
            // out pins边线
            PIN* pPin = NULL;
            CPtrArray* pPins;
            RECT rcItem1, rcItem2;
            pPins = (CPtrArray *)pItem->pOutPins;
            // out pins 边线
            pPins = (CPtrArray*)pItem->pOutPins;
            for (int j = 0; j < pPins->GetSize(); j++) {
                pPin = (PIN *)pPins->GetAt(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,
                        DrawPinConnectedLine(&graphics, &brush1,
                            pPin == m_pSelLineOutPin ? &pen2 : &pen1,
                            &pt1, &pt2, &rcItem1, &rcItem2, pPin);
                    }
                }
            }
        }
        // 删除 brush
        for (int i = 0; i < 3; i++) {
            ::DeleteObject(hbrPinBackground[i]);
        }
@@ -2091,11 +2112,9 @@
        ::DeleteObject(hbrItemBackground[1]);
        ::DeleteObject(hbrItemFrame[0]);
        ::DeleteObject(hbrItemFrame[1]);
        ::DeleteObject(hbrIndicator);
        ::DeleteObject(hbrIndicator);
        ::DeleteObject(hbrIndicatorGray);
    }
    // EndPaint
    ::BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
@@ -2104,9 +2123,9 @@
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
    return 1;
}
/*
 * WM_SIZE
@@ -2354,8 +2373,8 @@
/*
 * 设置背景颜色
 * color -- 背景色
 * 设置背景颜色
 * color -- 背景色
 */
void CEqsGraphWnd::SetBkgndColor(COLORREF color)
{
@@ -2363,8 +2382,8 @@
}
/*
 * 边框颜色
 * color -- 边框色
 * 边框颜色
 * color -- 边框色
 */
void CEqsGraphWnd::SetFrameColor(COLORREF color)
{
@@ -2408,11 +2427,15 @@
    SetTimer(m_hWnd, TIMER_ANIMATION_RECT, uElpase, NULL);
}
void CEqsGraphWnd::ShowItemIndicator(DWORD_PTR dwItemData, BOOL bShow)
void CEqsGraphWnd::ShowItemIndicator(DWORD_PTR dwItemData, int state, int nIndex)
{
    if (nIndex < 0 || nIndex >= EQITEM_INDICATOR_COUNT) {
        return;
    }
    EQITEM* pItem = GetItem(dwItemData);
    if (pItem != nullptr) {
        pItem->bShowIndicator[0] = bShow;
        pItem->nIndicatorState[nIndex] = (BYTE)state;
        ::InvalidateRect(m_hWnd, nullptr, TRUE);
    }
}
SourceCode/Bond/Servo/EqsGraphWnd.h
@@ -35,6 +35,16 @@
#define MAX(X,Y) (((X)>(Y))?(X):(Y))
#endif
#define EQITEM_INDICATOR_COUNT        8
enum EIndicatorState
{
    INDICATOR_STATE_HIDDEN = 0,
    INDICATOR_STATE_HIGHLIGHT = 1,
    INDICATOR_STATE_GRAY = 2,
};
typedef struct tagEQSGRAPHWND_NMHDR
{
    NMHDR        nmhdr;
@@ -54,7 +64,7 @@
    DWORD_PTR pInPins;
    DWORD_PTR pOutPins;
    int nFlashFlag;
    BOOL bShowIndicator[2];
    BYTE nIndicatorState[EQITEM_INDICATOR_COUNT]; // 0=隐藏, 1=高亮, 2=灰色
} EQITEM;
typedef struct tagPIN
@@ -144,7 +154,7 @@
    void SetItemPos(EQITEM* pItem, int x, int y);
    void FlashItem(EQITEM* pItem);
    void AnimationItem(EQITEM*pItem);
    void ShowItemIndicator(DWORD_PTR dwItemData, BOOL bShow);
    void ShowItemIndicator(DWORD_PTR dwItemData, int state, int nIndex = 0);
private:
    void Init();