chenluhua1980
2025-12-26 0275102b79ccf2c7fe1acf11117de8a89cca372f
1.生产总览页面框架实现;
已添加6个文件
已修改8个文件
1402 ■■■■■ 文件已修改
SourceCode/Bond/BondEq/AccordionWnd.cpp 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/AccordionWnd.cpp 787 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/AccordionWnd.h 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageProdOverview.cpp 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageProdOverview.h 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPanelProduction.cpp 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPanelProduction.h 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HmLabel.cpp 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HmLabel.h 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.cpp 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.filters 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/AccordionWnd.cpp
@@ -47,9 +47,16 @@
BOOL CAccordionWnd::RegisterWndClass()
{
    WNDCLASS wc;
    WNDCLASS wcExisting = {};
    HINSTANCE hInstance = AfxGetInstanceHandle();
    if (::GetClassInfo(hInstance, ACCORDIONWND_CLASS, &wcExisting) ||
        ::GetClassInfo(NULL, ACCORDIONWND_CLASS, &wcExisting)) {
        return TRUE;
    }
    WNDCLASS wc = {};
    wc.lpszClassName = ACCORDIONWND_CLASS;
    wc.hInstance = AfxGetInstanceHandle();
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WindowProc;
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = 0;
@@ -60,7 +67,10 @@
    wc.cbWndExtra = 0;
    // æ³¨å†Œè‡ªå®šä¹‰ç±»
    return (::RegisterClass(&wc) != 0);
    if (::RegisterClass(&wc) != 0) {
        return TRUE;
    }
    return (::GetLastError() == ERROR_CLASS_ALREADY_EXISTS);
}
CAccordionWnd * CAccordionWnd::FromHandle(HWND hWnd)
SourceCode/Bond/Servo/AccordionWnd.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,787 @@
#include "stdafx.h"
#include "AccordionWnd.h"
#define ITEM_HEIGHT                32
#define ITEM_SPACE                5
#define TIMER_ID_CHECKHOVER        1
#define EXPAND_ICON_WIDE        16
#define BORDER            5
#define SHADOWWIDE        5
CAccordionWnd::CAccordionWnd()
{
    m_hWnd = NULL;
    m_crFrame = GetSysColor(COLOR_WINDOWFRAME);
    m_crBkgnd = RGB(255, 255, 255);//GetSysColor(COLOR_BTNFACE); ;
    m_nPadding[PADDING_LEFT] = 5;
    m_nPadding[PADDING_TOP] = 5;
    m_nPadding[PADDING_RIGHT] = 5;
    m_nPadding[PADDING_BOTTOM] = 5;
    m_crItemBackground[0] = RGB(218, 218, 218);
    m_crItemBackground[1] = RGB(34, 177, 76);
    m_crItemFrame[0] = RGB(128, 128, 128);
    m_crItemFrame[1] = RGB(128, 128, 128);
    m_crItemText[0] = RGB(68, 84, 111);
    m_crItemText[1] = RGB(0, 0, 0);
    m_crSeparateLine = RGB(222, 222, 222);
    m_crHoverItemBackground = RGB(244, 245, 247);
    m_crHoverItemFrame = RGB(200, 222, 255);
    m_hIconExpand = NULL;
    m_hIconClose = NULL;
    m_nHoverItem = -1;
    m_nCheckHoverItem = -1;
    m_bShadow = FALSE;
    m_crShadowBkgnd = GetSysColor(COLOR_BTNFACE);
}
CAccordionWnd::~CAccordionWnd()
{
    for (size_t i = 0; i < m_vectorItems.size(); i++) {
        delete m_vectorItems[i];
    }
    m_vectorItems.clear();
}
BOOL CAccordionWnd::RegisterWndClass()
{
    WNDCLASS wcExisting = {};
    HINSTANCE hInstance = AfxGetInstanceHandle();
    if (::GetClassInfo(hInstance, ACCORDIONWND_CLASS, &wcExisting) ||
        ::GetClassInfo(NULL, ACCORDIONWND_CLASS, &wcExisting)) {
        return TRUE;
    }
    WNDCLASS wc = {};
    wc.lpszClassName = ACCORDIONWND_CLASS;
    wc.hInstance = hInstance;
    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;
    // æ³¨å†Œè‡ªå®šä¹‰ç±»
    if (::RegisterClass(&wc) != 0) {
        return TRUE;
    }
    return (::GetLastError() == ERROR_CLASS_ALREADY_EXISTS);
}
CAccordionWnd* CAccordionWnd::FromHandle(HWND hWnd)
{
    CAccordionWnd* pAccordionWnd = (CAccordionWnd*)::GetProp(hWnd, ACCORDIONWND_TAG);
    return pAccordionWnd;
}
CAccordionWnd* CAccordionWnd::Hook(HWND hWnd)
{
    CAccordionWnd* pAccordionWnd = (CAccordionWnd*)GetProp(hWnd, ACCORDIONWND_TAG);
    if (pAccordionWnd == NULL) {
        pAccordionWnd = new CAccordionWnd();
        pAccordionWnd->m_hWnd = hWnd;
        SetProp(hWnd, ACCORDIONWND_TAG, (HANDLE)pAccordionWnd);
    }
    return pAccordionWnd;
}
void CAccordionWnd::LoadExpandIcon(CString strExpandFile, CString strCloseFile)
{
    m_hIconExpand = (HICON)::LoadImage(AfxGetInstanceHandle(), strExpandFile, IMAGE_ICON, EXPAND_ICON_WIDE, EXPAND_ICON_WIDE,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    m_hIconClose = (HICON)::LoadImage(AfxGetInstanceHandle(), strCloseFile, IMAGE_ICON, EXPAND_ICON_WIDE, EXPAND_ICON_WIDE,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
}
void CAccordionWnd::Setpadding(int type, unsigned int nPadding)
{
    if (type >= PADDING_LEFT && PADDING_LEFT <= PADDING_BOTTOM) {
        m_nPadding[type] = nPadding;
    }
}
void CAccordionWnd::SetDefaultItemBackgroundColor(COLORREF crNormal, COLORREF crSel)
{
    m_crItemBackground[0] = crNormal;
    m_crItemBackground[1] = crSel;
}
void CAccordionWnd::SetDefaultItemFrameColor(COLORREF crNormal, COLORREF crSel)
{
    m_crItemFrame[0] = crNormal;
    m_crItemFrame[1] = crSel;
}
void CAccordionWnd::SetDefaultItemTextColor(COLORREF crNormal, COLORREF crSel)
{
    m_crItemText[0] = crNormal;
    m_crItemText[1] = crSel;
}
void CAccordionWnd::Init()
{
}
void CAccordionWnd::Release()
{
    // delete
    delete this;
}
/*
 * æ·»åŠ é¡¹ç›®
 * pszName -- åç§°
 * pWnd -- ç»‘定的窗口
 * nExpandHeight -- å±•开高度,如果为0则自动设置为窗口高
 */
void CAccordionWnd::AddItem(char* pszName, CWnd* pWnd, int nExpandHeight, BOOL bExpand/* = TRUE*/, BOOL bEnable/* = TRUE*/)
{
    ACCORDIONITEM* pItem = new ACCORDIONITEM;
    memset(pItem, 0, sizeof(ACCORDIONITEM));
    pItem->pWnd = pWnd;
    pItem->bExpand = bExpand;
    pItem->bEnable = bEnable;
    strcpy_s(pItem->text, sizeof(pItem->text), pszName);
    if (nExpandHeight == 0) {
        RECT rect;
        pWnd->GetWindowRect(&rect);
        pItem->nExpandHeight = rect.bottom - rect.top;
    }
    else if (nExpandHeight == -1) {
        pItem->nExpandHeight = -1;
    }
    else {
        pItem->nExpandHeight = nExpandHeight;
    }
    m_vectorItems.push_back(pItem);
    // é‡æ–°è°ƒæ•´ä¸ªå­çª—口的位置
    ResizeItemWnd();
}
void CAccordionWnd::ResizeItemWnd()
{
    RECT rcClient, rcItemClient;
    GetClientRect(m_hWnd, &rcClient);
    for (size_t i = 0; i < m_vectorItems.size(); i++) {
        ACCORDIONITEM* pItem = m_vectorItems.at(i);
        if (pItem->pWnd != NULL) {
            GetItemRect(rcClient, (UINT)i, &rcItemClient);
            rcItemClient.top += ITEM_HEIGHT;
            if (pItem->nExpandHeight == -1) {
                rcItemClient.bottom = rcClient.bottom;
            }
            else {
                rcItemClient.bottom = rcItemClient.top + pItem->nExpandHeight;
            }
            pItem->pWnd->MoveWindow(&rcItemClient);
            pItem->pWnd->ShowWindow(pItem->bExpand ? SW_SHOW : SW_HIDE);
        }
    }
}
BOOL CAccordionWnd::GetItemHeaderRect(RECT rcClient, unsigned int nIndex, LPRECT lpRect)
{
    RECT rcItem;
    if (!GetItemRect(rcClient, nIndex, &rcItem)) {
        return FALSE;
    }
    rcItem.bottom = rcItem.top + ITEM_HEIGHT;
    CopyRect(lpRect, &rcItem);
    return TRUE;
}
BOOL CAccordionWnd::GetItemRect(RECT rcClient, unsigned int nIndex, LPRECT lpRect)
{
    if (nIndex >= m_vectorItems.size()) {
        return FALSE;
    }
    RECT rcItemHeader;
    rcItemHeader.left = rcClient.left + m_nPadding[PADDING_LEFT];
    rcItemHeader.right = rcClient.right - m_nPadding[PADDING_RIGHT];
    rcItemHeader.top = rcClient.top + m_nPadding[PADDING_TOP];
    rcItemHeader.bottom = rcItemHeader.top + ITEM_HEIGHT;
    for (size_t i = 0; i < m_vectorItems.size(); i++) {
        ACCORDIONITEM* pItem = m_vectorItems.at(i);
        if (pItem->bExpand) {
            rcItemHeader.bottom += pItem->nExpandHeight;
        }
        if (i == nIndex) {
            break;;
        }
        rcItemHeader.top = rcItemHeader.bottom + ITEM_SPACE;
        rcItemHeader.bottom = rcItemHeader.top + ITEM_HEIGHT;
    }
    CopyRect(lpRect, &rcItemHeader);
    return TRUE;
}
int CAccordionWnd::HitTest(POINT pt, int& nHitTest)
{
    int nRet = -1;
    nHitTest = -1;
    RECT rcClient;
    GetClientRect(m_hWnd, &rcClient);
    if (PtInRect(&rcClient, pt)) {
        nRet = 1;
    }
    int nItemIndex = -1;
    RECT rcItemHeader;
    for (size_t i = 0; i < m_vectorItems.size(); i++) {
        GetItemHeaderRect(rcClient, (unsigned int)i, &rcItemHeader);
        if (PtInRect(&rcItemHeader, pt)) {
            nItemIndex = (unsigned int)i;
            break;
        }
    }
    if (nItemIndex != -1) {
        nRet = 2;
        nHitTest = nItemIndex;
    }
    return nRet;
}
BOOL CAccordionWnd::Togle(unsigned int nIndex)
{
    if (nIndex >= m_vectorItems.size()) {
        return FALSE;
    }
    ACCORDIONITEM* pItem = m_vectorItems[nIndex];
    pItem->bExpand = !pItem->bExpand;
    // é‡æ–°è°ƒæ•´ä¸ªå­çª—口的位置
    ResizeItemWnd();
    RECT rcClient;
    GetClientRect(m_hWnd, &rcClient);
    ::InvalidateRect(m_hWnd, &rcClient, TRUE);
    return TRUE;
}
void CAccordionWnd::Notify(int nCode, int dwData, int dwData1/* = 0*/, int dwData2/* = 0*/)
{
    HWND hParent;
    hParent = GetParent(m_hWnd);
    if (hParent != NULL) {
        ACCORDION_NMHDR accordionWndnmhdr;
        accordionWndnmhdr.nmhdr.hwndFrom = m_hWnd;
        accordionWndnmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
        accordionWndnmhdr.nmhdr.code = nCode;
        accordionWndnmhdr.dwData = dwData;
        accordionWndnmhdr.dwData1 = dwData1;
        accordionWndnmhdr.dwData2 = dwData2;
        SendMessage(hParent, WM_NOTIFY, (WPARAM)accordionWndnmhdr.nmhdr.idFrom, (LPARAM)&accordionWndnmhdr);
    }
}
/*
 * æ‹¦æˆªçª—口消息函数
 */
LRESULT CALLBACK CAccordionWnd::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CAccordionWnd* pAccordionWnd = (CAccordionWnd*)GetProp(hWnd, ACCORDIONWND_TAG);
    if (pAccordionWnd == NULL && uMsg != WM_NCCREATE)
    {
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    // å¦‚æžœHook则响应消息
    ASSERT(hWnd);
    switch (uMsg)
    {
    case WM_NCCREATE:
        return CAccordionWnd::OnNcCreate(hWnd, wParam, lParam);
    case WM_DESTROY:
        return pAccordionWnd->OnDestroy(wParam, lParam);
    case WM_NCCALCSIZE:
        return pAccordionWnd->OnNcCalcsize(wParam, lParam);
    case WM_NCPAINT:
        return pAccordionWnd->OnNcPaint(wParam, lParam);
    case WM_PAINT:
        return pAccordionWnd->OnPaint(wParam, lParam);
    case WM_TIMER:
        return pAccordionWnd->OnTimer(wParam, lParam);
    case WM_MOUSEMOVE:
        return pAccordionWnd->OnMouseMove(wParam, lParam);
    case WM_LBUTTONDOWN:
        return pAccordionWnd->OnLButtonDown(wParam, lParam);
    case WM_LBUTTONUP:
        return pAccordionWnd->OnLButtonUp(wParam, lParam);
    case WM_MOUSEWHEEL:
        return pAccordionWnd->OnMouseWheel(wParam, lParam);
    case WM_SIZE:
        return pAccordionWnd->OnSize(wParam, lParam);
    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS;
    default:
        break;
    }
    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
/*
 * WM_NCCREATE
 * çª—口创建前的初始化工作
 */
LRESULT CAccordionWnd::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    CAccordionWnd* pAccordionWnd = (CAccordionWnd*)GetProp(hWnd, ACCORDIONWND_TAG);
    ASSERT(pAccordionWnd == NULL);
    Hook(hWnd);
    return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
}
/*
 * WM_NCCALCSIZE
 */
LRESULT CAccordionWnd::OnNcCalcsize(WPARAM wParam, LPARAM lParam)
{
    if (!m_bShadow) {
        return ::DefWindowProc(m_hWnd, WM_NCCALCSIZE, wParam, lParam);
    }
    LPRECT lprcWnd = (LPRECT)lParam;
    lprcWnd->left += BORDER;
    lprcWnd->top += BORDER;
    lprcWnd->right -= (BORDER + SHADOWWIDE);
    lprcWnd->bottom -= (BORDER + SHADOWWIDE);
    return 0;
}
/*
 * WM_DESTROY
 * çª—口销毁时
 */
LRESULT CAccordionWnd::OnDestroy(WPARAM wParam, LPARAM lParam)
{
    Release();
    return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
}
/*
 * WM_TIMER
 */
LRESULT CAccordionWnd::OnTimer(WPARAM wParam, LPARAM lParam)
{
    int nTimerId = (int)wParam;
    if (m_nTimerId == nTimerId) {
        POINT pt;
        ::GetCursorPos(&pt);
        ::ScreenToClient(m_hWnd, &pt);
        int nRet, nHitTest;
        nRet = HitTest(pt, nHitTest);
        if (m_nCheckHoverItem != nHitTest) {
            KillTimer(m_hWnd, m_nTimerId);
            m_nHoverItem = nHitTest;
            m_nCheckHoverItem = nHitTest;
            RECT rcClient;
            GetClientRect(m_hWnd, &rcClient);
            ::InvalidateRect(m_hWnd, &rcClient, TRUE);
        }
    }
    return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
}
/*
 * WM_MOUSEMOVE
 * é¼ æ ‡ç§»åŠ¨æ—¶ï¼Œæ£€æµ‹é¼ æ ‡ä½ç½®å¹¶å›žè°ƒç»™ä¸»çª—å£
 */
LRESULT CAccordionWnd::OnMouseMove(WPARAM wParam, LPARAM lParam)
{
    POINT pt;
    pt.x = (int)LOWORD(lParam);
    pt.y = (int)HIWORD(lParam);
    int nRet, nHitTest;
    nRet = HitTest(pt, nHitTest);
    if (nRet == 2) {
        ACCORDIONITEM* pItem = m_vectorItems[nHitTest];
        if (pItem != NULL && pItem->bEnable) {
            ::SetCursor(LoadCursor(NULL, IDC_HAND));
        }
    }
    else {
        ::SetCursor(LoadCursor(NULL, IDC_ARROW));
    }
    int nLastItem = m_nHoverItem;
    if (m_nHoverItem != nHitTest) {
        m_nHoverItem = nHitTest;
        RECT rcClient, rcLastItemClient, rcCurItemClient;
        GetClientRect(m_hWnd, &rcClient);
        GetItemRect(rcClient, nLastItem, &rcLastItemClient);
        ::InvalidateRect(m_hWnd, &rcLastItemClient, nHitTest < 0);
        if (nHitTest >= 0) {
            ACCORDIONITEM* pItem = m_vectorItems.at(nHitTest);
            if (!pItem->bEnable) {
                m_nHoverItem = -1;
            }
            else {
                KillTimer(m_hWnd, m_nTimerId);
                m_nTimerId = SetTimer(m_hWnd, TIMER_ID_CHECKHOVER, 200, NULL);
                m_nCheckHoverItem = m_nHoverItem;
                GetItemRect(rcClient, m_nHoverItem, &rcCurItemClient);
                ::InvalidateRect(m_hWnd, &rcCurItemClient, TRUE);
            }
        }
    }
    return ::DefWindowProc(m_hWnd, WM_MOUSEMOVE, wParam, lParam);
}
/*
 * WM_LBUTTONDOWN
 * é¼ æ ‡å·¦é”®ä¸‹åŽ‹
 */
LRESULT CAccordionWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
    POINT pt;
    pt.x = (int)LOWORD(lParam);
    pt.y = (int)HIWORD(lParam);
    int nRet, nHitTest;
    nRet = HitTest(pt, nHitTest);
    if (nRet == 2) {
        ACCORDIONITEM* pItem = m_vectorItems[nHitTest];
        if (pItem != NULL && pItem->bEnable) {
            ::SetCursor(LoadCursor(NULL, IDC_HAND));
        }
    }
    else {
        ::SetCursor(LoadCursor(NULL, IDC_ARROW));
    }
    return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
}
/*
 * WM_LBUTTONUP
 * é¼ æ ‡å·¦é”®é‡Šæ”¾
 */
LRESULT CAccordionWnd::OnLButtonUp(WPARAM wParam, LPARAM lParam)
{
    POINT pt;
    pt.x = (int)LOWORD(lParam);
    pt.y = (int)HIWORD(lParam);
    int nRet, nHitTest;
    nRet = HitTest(pt, nHitTest);
    if (nRet == 2) {
        ACCORDIONITEM* pItem = m_vectorItems[nHitTest];
        if (pItem != NULL && pItem->bEnable) {
            ::SetCursor(LoadCursor(NULL, IDC_HAND));
            Togle(nHitTest);
        }
    }
    else {
        ::SetCursor(LoadCursor(NULL, IDC_ARROW));
    }
    return ::DefWindowProc(m_hWnd, WM_LBUTTONUP, wParam, lParam);
}
/*
 * WM_MOUSEWHEEL
 * é¼ æ ‡æ»šè½®æ»šåŠ¨æ—¶ï¼Œç¼©æ”¾å›¾åƒ
 */
LRESULT CAccordionWnd::OnMouseWheel(WPARAM wParam, LPARAM lParam)
{
    return ::DefWindowProc(m_hWnd, WM_MOUSEWHEEL, wParam, lParam);
}
/*
 * WM_NCPAINT
 */
LRESULT CAccordionWnd::OnNcPaint(WPARAM wParam, LPARAM lParam)
{
    LRESULT lRet = ::DefWindowProc(m_hWnd, WM_NCPAINT, wParam, lParam);
    // ç„¶åŽç”»è¾¹æ¡†
    long styleEx = GetWindowLong(m_hWnd, GWL_EXSTYLE);
    if ((styleEx & WS_EX_CLIENTEDGE) == WS_EX_CLIENTEDGE) {
        RECT rcWindow, rcClient;
        GetClientRect(m_hWnd, &rcClient);
        ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.left);
        ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.right);
        GetWindowRect(m_hWnd, &rcWindow);
        ::OffsetRect(&rcClient, -rcWindow.left, -rcWindow.top);
        ::OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
        HRGN hRgnWnd = CreateRectRgnIndirect(&rcWindow);
        HRGN hRgnClient = CreateRectRgnIndirect(&rcClient);
        HDC hDC = GetWindowDC(m_hWnd);
        ::SelectClipRgn(hDC, hRgnWnd);
        ::ExtSelectClipRgn(hDC, hRgnClient, RGN_DIFF);
        // æ²¡æœ‰é˜´å½±çš„边框
        if (!m_bShadow) {
            HBRUSH hBrushBK, hBrushFrame;
            hBrushBK = CreateSolidBrush(m_crBkgnd);
            ::FillRect(hDC, &rcWindow, hBrushBK);
            DeleteObject(hBrushBK);
            hBrushFrame = CreateSolidBrush(m_crFrame);
            ::FrameRect(hDC, &rcWindow, hBrushFrame);
            DeleteObject(hBrushFrame);
        }
        // æœ‰é˜´å½±çš„边框
        else {
            RECT rcFrame0, rcFrame1;
            rcFrame0.left = rcWindow.left + SHADOWWIDE;
            rcFrame0.top = rcWindow.top + SHADOWWIDE;
            rcFrame0.right = rcWindow.right;
            rcFrame0.bottom = rcWindow.bottom;
            rcFrame1.left = rcWindow.left;
            rcFrame1.top = rcWindow.top;
            rcFrame1.right = rcWindow.right - SHADOWWIDE;
            rcFrame1.bottom = rcWindow.bottom - SHADOWWIDE;
            // èƒŒæ™¯æ¡†å’Œå¯¹è¯æ¡†(父窗体)背景色一致
            HBRUSH hBrushBK, hBrushFrame;
            hBrushBK = CreateSolidBrush(m_crShadowBkgnd);
            ::FillRect(hDC, &rcWindow, hBrushBK);
            DeleteObject(hBrushBK);
            // é˜´å½±æ¡†
            BYTE r = GetRValue(m_crShadowBkgnd);
            BYTE g = GetGValue(m_crShadowBkgnd);
            BYTE b = GetBValue(m_crShadowBkgnd);
            BYTE rstep = (r - GetRValue(m_crFrame)) / SHADOWWIDE;
            BYTE gstep = (r - GetGValue(m_crFrame)) / SHADOWWIDE;
            BYTE bstep = (r - GetBValue(m_crFrame)) / SHADOWWIDE;
            for (int i = 0; i < SHADOWWIDE; i++) {
                hBrushBK = CreateSolidBrush(RGB(r - i * rstep, g - i * gstep, b - i * bstep));
                ::FillRect(hDC, &rcFrame0, hBrushBK);
                DeleteObject(hBrushBK);
                rcFrame0.bottom -= 1;
                rcFrame0.right -= 1;
            }
            // å‰æ™¯æ¡†
            hBrushBK = CreateSolidBrush(m_crBkgnd);
            ::FillRect(hDC, &rcFrame1, hBrushBK);
            DeleteObject(hBrushBK);
            hBrushFrame = CreateSolidBrush(m_crFrame);
            ::FrameRect(hDC, &rcFrame1, hBrushFrame);
            DeleteObject(hBrushFrame);
        }
        ::DeleteObject(hRgnWnd);
        ::DeleteObject(hRgnClient);
        ReleaseDC(m_hWnd, hDC);
    }
    return lRet;
}
/*
 * WM_PAINT
 */
LRESULT CAccordionWnd::OnPaint(WPARAM wParam, LPARAM lParam)
{
    HDC hDC, hMemDC;
    HBITMAP hBitmap;
    RECT rcClient;
    CString strText;
    HFONT hFont;
    HBRUSH hBrushBK;
    // BeginPaint
    PAINTSTRUCT ps;
    hDC = BeginPaint(m_hWnd, &ps);
    GetClientRect(m_hWnd, &rcClient);
    hMemDC = ::CreateCompatibleDC(hDC);
    hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left,
        rcClient.bottom - rcClient.top);
    ::SelectObject(hMemDC, hBitmap);
    ::SetBkMode(hMemDC, TRANSPARENT);
    // èƒŒæ™¯é¢œè‰²
    hBrushBK = CreateSolidBrush(m_crBkgnd);
    ::FillRect(hMemDC, &rcClient, hBrushBK);
    DeleteObject(hBrushBK);
    // ç»˜å­é¡¹åˆ—表
    hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    ::SelectObject(hMemDC, hFont);
    HPEN hPenSeparate = ::CreatePen(PS_SOLID, 1, m_crSeparateLine);
    RECT rcItem, rcItemHeader;
    for (size_t i = 0; i < m_vectorItems.size(); i++) {
        ACCORDIONITEM* pItem = m_vectorItems[i];
        GetItemRect(rcClient, (UINT)i, &rcItem);
        GetItemHeaderRect(rcClient, (UINT)i, &rcItemHeader);
        // çƒ­ç‚¹é¡¹çš„背景色和边框
        if (m_nHoverItem == (int)i) {
            HBRUSH hbrItemHeaderBackground = CreateSolidBrush(m_crHoverItemBackground);
            HBRUSH hbrItemFrame = CreateSolidBrush(m_crHoverItemFrame);
            HRGN hRgn = CreateRoundRectRgn(rcItemHeader.left, rcItemHeader.top, rcItemHeader.right, rcItemHeader.bottom, 2, 2);
            ::FillRgn(hMemDC, hRgn, hbrItemHeaderBackground);
            ::FrameRgn(hMemDC, hRgn, hbrItemFrame, 1, 1);
            ::DeleteObject(hbrItemHeaderBackground);
            ::DeleteObject(hbrItemFrame);
            ::DeleteObject(hRgn);
        }
        // ç®­å¤´
        BOOL bDrawIcon = DrawIconEx(hMemDC, rcItemHeader.left + (ITEM_HEIGHT - EXPAND_ICON_WIDE) / 2, rcItemHeader.top + (ITEM_HEIGHT - EXPAND_ICON_WIDE) / 2,
            pItem->bExpand ? m_hIconExpand : m_hIconClose, EXPAND_ICON_WIDE, EXPAND_ICON_WIDE, 0, 0, DI_NORMAL);
        // æ–‡æœ¬
        ::SetTextColor(hMemDC, m_nHoverItem == (int)i ? m_crItemText[1] : m_crItemText[0]);
        RECT rcText;
        rcText.left = rcItemHeader.left + (bDrawIcon ? ITEM_HEIGHT : (ITEM_HEIGHT - EXPAND_ICON_WIDE) / 2);
        rcText.top = rcItemHeader.top;
        rcText.right = rcItemHeader.right;
        rcText.bottom = rcItemHeader.bottom;
        ::DrawText(hMemDC, pItem->text, (int)strlen(pItem->text), &rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
        // æ–‡æœ¬å³è¾¹åˆ†éš”线
        SIZE sizeText;
        GetTextExtentPoint32(hMemDC, pItem->text, (int)strlen(pItem->text), &sizeText);
        HPEN hOldPen = (HPEN)::SelectObject(hMemDC, hPenSeparate);
        MoveToEx(hMemDC, rcText.left + sizeText.cx + 10, rcItemHeader.top + (rcItemHeader.bottom - rcItemHeader.top - 1) / 2, NULL);
        LineTo(hMemDC, rcItemHeader.right - 10, rcItemHeader.top + (rcItemHeader.bottom - rcItemHeader.top - 1) / 2);
        ::SelectObject(hMemDC, hOldPen);
        rcItemHeader.top = rcItemHeader.bottom + ITEM_SPACE;
        rcItemHeader.bottom = rcItemHeader.top + ITEM_HEIGHT;
    }
    ::DeleteObject(hPenSeparate);
    // EndPaint
    ::BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
        hMemDC, 0, 0, SRCCOPY);
    EndPaint(m_hWnd, &ps);
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
    return 1;
}
/*
 * WM_SIZE
 */
LRESULT CAccordionWnd::OnSize(WPARAM wParam, LPARAM lParam)
{
    LRESULT lRet = ::DefWindowProc(m_hWnd, WM_SIZE, wParam, lParam);
    ResizeItemWnd();
    return lRet;
}
/*
 * è®¾ç½®èƒŒæ™¯è‰²
 * color -- èƒŒæ™¯è‰²
 */
void CAccordionWnd::SetBkgndColor(COLORREF color)
{
    m_crBkgnd = color;
}
/*
 * è®¾ç½®é˜´å½±çš„背景色(即父窗口的背景)
 * color -- èƒŒæ™¯è‰²
 */
void CAccordionWnd::SetShadowBkgnd(COLORREF color)
{
    m_crShadowBkgnd = color;
}
/*
 * è®¾ç½®è¾¹æ¡†é¢œè‰²
 * color -- è¾¹æ¡†é¢œè‰²
 */
void CAccordionWnd::SetFrameColor(COLORREF color, BOOL bShadow/* = FALSE*/)
{
    m_crFrame = color;
    m_bShadow = bShadow;
    SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
SourceCode/Bond/Servo/AccordionWnd.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,131 @@
#pragma once
#include <functional>
#include <vector>
#ifndef ACCORDIONWND_TAG
#ifdef _WIN32
#define ACCORDIONWND_CLASSA        "AccordionWnd"
#define ACCORDIONWND_CLASSW        L"AccordionWnd"
#ifdef UNICODE
#define ACCORDIONWND_CLASS        ACCORDIONWND_CLASSW
#else
#define ACCORDIONWND_CLASS        ACCORDIONWND_CLASSA
#endif
#else
#define ACCORDIONWND_CLASS      "AccordionWnd"
#endif
#define ACCORDIONWND_TAG        _T("ACCORDIONWND_TAG")
#define ACCORDIONWND_FIRST        (0U-3590U)
#define ACCORDIONWND_LAST        (0U-5350U)
#define ACCORDIONWND_ONTOGLE    (ACCORDIONWND_FIRST - 1)
typedef struct tagACCORDION_NMHDR
{
    NMHDR        nmhdr;
    DWORD        dwData;
    DWORD        dwData1;
    DWORD        dwData2;
} ACCORDION_NMHDR;
typedef struct tagACCORDIONITEM
{
    unsigned int id;
    int nExpandHeight;
    COLORREF crBackground[2];
    COLORREF crFrame[2];
    COLORREF crText[2];
    char text[256];
    CWnd *pWnd;
    BOOL bExpand;
    BOOL bEnable;                // æ˜¯å¦å¯ä»¥ç‚¹å‡»å±•开和收起
} ACCORDIONITEM;
#endif
#define PADDING_LEFT        0
#define PADDING_TOP            1
#define PADDING_RIGHT        2
#define PADDING_BOTTOM        3
class CAccordionWnd
{
public:
    CAccordionWnd();
    ~CAccordionWnd();
public:
    static BOOL RegisterWndClass();
    static CAccordionWnd * FromHandle(HWND hWnd);
    void SetFrameColor(COLORREF color, BOOL bShadow = FALSE);
    void SetBkgndColor(COLORREF color);
    void SetShadowBkgnd(COLORREF color);
public:
    void LoadExpandIcon(CString strExpandFile, CString strCloseFile);
    void Setpadding(int type, unsigned int nPadding);
    void SetDefaultItemBackgroundColor(COLORREF crNormal, COLORREF crSel);
    void SetDefaultItemFrameColor(COLORREF crNormal, COLORREF crSel);
    void SetDefaultItemTextColor(COLORREF crNormal, COLORREF crSel);
    void AddItem(char *pszName, CWnd *pWnd, int nExpandHeight, BOOL bExpand = TRUE, BOOL bEnable = TRUE);
    BOOL Togle(unsigned int nIndex);
    int GetItemHeaderHeight();
    BOOL IsExpand(unsigned int nIndex);
private:
    void Init();
    void Notify(int nCode, int dwData, int dwData1 = 0, int dwData2 = 0);
    void Release();
    void ResizeItemWnd();
    static CAccordionWnd* Hook(HWND hWnd);
    static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    static LRESULT OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
    LRESULT OnDestroy(WPARAM wParam, LPARAM lParam);
    LRESULT OnTimer(WPARAM wParam, LPARAM lParam);
    LRESULT OnNcPaint(WPARAM wParam, LPARAM lParam);
    LRESULT OnNcCalcsize(WPARAM wParam, LPARAM lParam);
    LRESULT OnPaint(WPARAM wParam, LPARAM lParam);
    LRESULT OnMouseMove(WPARAM wParam, LPARAM lParam);
    LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam);
    LRESULT OnLButtonUp(WPARAM wParam, LPARAM lParam);
    LRESULT OnMouseWheel(WPARAM wParam, LPARAM lParam);
    LRESULT OnSize(WPARAM wParam, LPARAM lParam);
private:
    HWND        m_hWnd;
    COLORREF    m_crBkgnd;
    COLORREF    m_crFrame;
    HICON        m_hIconClose;
    HICON        m_hIconExpand;
    int            m_nHoverItem;
    int            m_nCheckHoverItem;
    BOOL        m_bShadow;                // é˜´å½±
    COLORREF    m_crShadowBkgnd;        // é˜´å½±èƒŒæ™¯è‰²(即父窗口的颜色)
private:
    unsigned int m_nPadding[4];
    COLORREF m_crItemBackground[2];
    COLORREF m_crItemFrame[2];
    COLORREF m_crItemText[2];
    COLORREF m_crSeparateLine;
    COLORREF m_crHoverItemBackground;
    COLORREF m_crHoverItemFrame;
    CString m_strExpandIconFilepath[2];
private:
    std::vector<ACCORDIONITEM *> m_vectorItems;
    int m_nTimerId;
private:
    int HitTest(POINT pt, int &nHitTest);
    BOOL GetItemHeaderRect(RECT rcClient, unsigned int nIndex, LPRECT lpRect);
    BOOL GetItemRect(RECT rcClient, unsigned int nIndex, LPRECT lpRect);
};
SourceCode/Bond/Servo/CPageProdOverview.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,140 @@
// CPageProOverview.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "Servo.h"
#include "CPageProdOverview.h"
#include "afxdialogex.h"
namespace
{
    constexpr UINT_PTR kTimerRefreshId = 2001;
    constexpr UINT kTimerRefreshIntervalMs = 5000;
}
IMPLEMENT_DYNAMIC(CPageProdOverview, CDialogEx)
CPageProdOverview::CPageProdOverview(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_PROD_OVERVIEW, pParent)
    , m_clrBackground(RGB(240, 240, 240))
{
}
CPageProdOverview::~CPageProdOverview()
{
}
void CPageProdOverview::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
void CPageProdOverview::SetBackgroundColor(COLORREF color)
{
    m_clrBackground = color;
    m_brushBackground.DeleteObject();
    m_brushBackground.CreateSolidBrush(m_clrBackground);
    if (::IsWindow(m_hWnd)) {
        Invalidate();
    }
}
BEGIN_MESSAGE_MAP(CPageProdOverview, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_WM_TIMER()
END_MESSAGE_MAP()
BOOL CPageProdOverview::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // ä½¿ç”¨è‡ªå®šä¹‰æ ‡ç­¾
    if (CWnd* pDay = GetDlgItem(IDC_PROD_DAY_OUTPUT)) {
        m_labelDayOut.SubclassWindow(pDay->GetSafeHwnd());
        m_labelDayOut.setFontSize(28);
        m_labelDayOut.setNoteTextColor(RGB(128, 128, 128));
        m_labelDayOut.setNote1(_T("白班产出"));
        m_labelDayOut.setBackground(m_clrBackground);
        m_labelDayOut.setForeground(RGB(18, 18, 18), TRUE);
    }
    if (CWnd* pNight = GetDlgItem(IDC_PROD_NIGHT_OUTPUT)) {
        m_labelNightOut.SubclassWindow(pNight->GetSafeHwnd());
        m_labelNightOut.setFontSize(28);
        m_labelNightOut.setNoteTextColor(RGB(128, 128, 128));
        m_labelNightOut.setNote1(_T("夜班产出"));
        m_labelNightOut.setBackground(m_clrBackground);
        m_labelNightOut.setForeground(RGB(18, 18, 18), TRUE);
    }
    if (CWnd* pDayTakt = GetDlgItem(IDC_PROD_DAY_TAKT)) {
        m_labelDayTakt.SubclassWindow(pDayTakt->GetSafeHwnd());
        m_labelDayTakt.setFontSize(28);
        m_labelDayTakt.setNoteTextColor(RGB(128, 128, 128));
        m_labelDayTakt.setNote1(_T("白班平均TT"));
        m_labelDayTakt.setBackground(m_clrBackground);
        m_labelDayTakt.setForeground(RGB(18, 18, 18), TRUE);
    }
    if (CWnd* pNightTakt = GetDlgItem(IDC_PROD_NIGHT_TAKT)) {
        m_labelNightTakt.SubclassWindow(pNightTakt->GetSafeHwnd());
        m_labelNightTakt.setFontSize(28);
        m_labelNightTakt.setNoteTextColor(RGB(128, 128, 128));
        m_labelNightTakt.setNote1(_T("夜班平均TT"));
        m_labelNightTakt.setBackground(m_clrBackground);
        m_labelNightTakt.setForeground(RGB(18, 18, 18), TRUE);
    }
    RefreshData();
    m_timerId = SetTimer(kTimerRefreshId, kTimerRefreshIntervalMs, nullptr);
    return TRUE;
}
HBRUSH CPageProdOverview::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    if (nCtlColor == CTLCOLOR_DLG || nCtlColor == CTLCOLOR_STATIC) {
        if (m_brushBackground.GetSafeHandle() == NULL) {
            m_brushBackground.CreateSolidBrush(m_clrBackground);
        }
        pDC->SetBkMode(TRANSPARENT);
        return (HBRUSH)m_brushBackground.GetSafeHandle();
    }
    return hbr;
}
void CPageProdOverview::OnDestroy()
{
    if (m_timerId != 0) {
        KillTimer(m_timerId);
        m_timerId = 0;
    }
    CDialogEx::OnDestroy();
}
void CPageProdOverview::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
}
void CPageProdOverview::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == kTimerRefreshId) {
        RefreshData();
    }
    CDialogEx::OnTimer(nIDEvent);
}
void CPageProdOverview::RefreshData()
{
    CString text;
    text.Format(_T("%d"), 123);
    m_labelDayOut.setText(text);
    text.Format(_T("%d"), 1235);
    m_labelNightOut.setText(text);
    m_labelDayTakt.setText(_T("1236"));
    m_labelNightTakt.setText(_T("1238"));
}
SourceCode/Bond/Servo/CPageProdOverview.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
#pragma once
#include <chrono>
#include "HmLabel.h"
// CPageProOverview å¯¹è¯æ¡†
class CPageProdOverview : public CDialogEx
{
    DECLARE_DYNAMIC(CPageProdOverview)
public:
    CPageProdOverview(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CPageProdOverview();
    void SetBackgroundColor(COLORREF color);
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnDestroy();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
private:
    void RefreshData();
private:
    COLORREF m_clrBackground{ RGB(240, 240, 240) };
    CBrush m_brushBackground;
    UINT_PTR m_timerId = 0;
    CHmLabel m_labelDayOut;
    CHmLabel m_labelNightOut;
    CHmLabel m_labelDayTakt;
    CHmLabel m_labelNightTakt;
};
SourceCode/Bond/Servo/CPanelProduction.cpp
@@ -22,6 +22,8 @@
    m_hPlaceholder = nullptr;
    m_bShiftSummaryValid = FALSE;
    m_pStatsThread = nullptr;
    m_pAccordionWnd = nullptr;
    m_pPageProdOverview = nullptr;
}
CPanelProduction::~CPanelProduction()
@@ -61,6 +63,25 @@
    pLine1->SetBkgndColor(RGB(225, 225, 225));
    pLine1->SetLineColor(RGB(198, 198, 198));
    pLine1->EnableResize();
    CString strExpandIcon, strCloseIcon;
    strExpandIcon.Format(_T("%s\\res\\arrow_down.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    strCloseIcon.Format(_T("%s\\res\\arrow_right.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    m_pAccordionWnd = CAccordionWnd::FromHandle(GetDlgItem(IDC_ACCORDION_WND1)->m_hWnd);
    m_pAccordionWnd->SetBkgndColor(m_crBkgnd);
    m_pAccordionWnd->SetFrameColor(RGB(220, 220, 200), TRUE);
    m_pAccordionWnd->Setpadding(PADDING_LEFT, 2);
    m_pAccordionWnd->Setpadding(PADDING_TOP, 2);
    m_pAccordionWnd->Setpadding(PADDING_RIGHT, 2);
    m_pAccordionWnd->Setpadding(PADDING_BOTTOM, 2);
    m_pAccordionWnd->LoadExpandIcon(strExpandIcon, strCloseIcon);
    m_pPageProdOverview = new CPageProdOverview();
    m_pPageProdOverview->SetBackgroundColor(m_crBkgnd);
    m_pPageProdOverview->Create(IDD_PROD_OVERVIEW, GetDlgItem(IDC_ACCORDION_WND1));
    m_pPageProdOverview->ShowWindow(SW_HIDE);
    m_pAccordionWnd->AddItem("生产总览", m_pPageProdOverview, 280, TRUE, TRUE);
    SetTimer(1, 1000 * 10, nullptr);
    StartStatsThread();
@@ -107,6 +128,9 @@
    GetClientRect(&rcClient);
    pItem = GetDlgItem(IDC_LINE1);
    pItem->MoveWindow(rcClient.right - 3, 0, 3, rcClient.Height());
    pItem = GetDlgItem(IDC_ACCORDION_WND1);
    pItem->MoveWindow(5, 5, rcClient.Width() - 10, rcClient.Height() - 10);
}
#define PRODUCTION_PANEL_MIN_WIDTH        88
SourceCode/Bond/Servo/CPanelProduction.h
@@ -1,8 +1,9 @@
#pragma once
#include "BlButton.h"
#include <afxmt.h>
#include "AccordionWnd.h"
#include "ProductionStats.h"
#include "CPageProdOverview.h"
// CPanelProduction dialog
class CPanelProduction : public CDialogEx
@@ -21,6 +22,7 @@
    int m_nPanelWidth;
    CBlButton m_btnClose;
    HWND m_hPlaceholder;
    CAccordionWnd* m_pAccordionWnd;
    // Production shift summary (updated by background thread)
    ProductionShiftSummary m_shiftSummary;
@@ -28,6 +30,7 @@
    CCriticalSection m_csShiftSummary;
    CWinThread* m_pStatsThread;
    CEvent m_evStopStats;
    CPageProdOverview* m_pPageProdOverview;
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
SourceCode/Bond/Servo/HmLabel.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,177 @@
#include "stdafx.h"
#include "HmLabel.h"
CHmLabel::CHmLabel()
{
    m_crFrame = RGB(128, 128, 128);
    m_crBackground = RGB(255, 0, 0);
    m_crForeground = RGB(255, 255, 255);
    m_hFont = NULL;
    m_hFontNote = NULL;
}
CHmLabel::~CHmLabel()
{
    if (m_hFont != NULL) {
        ::DeleteObject(m_hFont);
        m_hFont = NULL;
    }
    if (m_hFontNote != NULL) {
        ::DeleteObject(m_hFontNote);
        m_hFontNote = NULL;
    }
}
BEGIN_MESSAGE_MAP(CHmLabel, CStatic)
    ON_WM_PAINT()
    ON_WM_NCPAINT()
END_MESSAGE_MAP()
void CHmLabel::setText(CString strText)
{
    SetWindowText(strText);
    Invalidate();
}
void CHmLabel::setNote1(CString strNote1)
{
    m_strNote1 = strNote1;
}
void CHmLabel::setFontSize(int size)
{
    if (m_hFont != NULL) {
        ::DeleteObject(m_hFont);
        m_hFont = NULL;
    }
    m_hFont = CreateFont(size, 0, 0, 0, FW_MEDIUM,
        FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS,
        CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, _T("宋体"));
}
void CHmLabel::setNoteFontSize(int size)
{
    if (m_hFontNote != NULL) {
        ::DeleteObject(m_hFontNote);
        m_hFontNote = NULL;
    }
    m_hFontNote = CreateFont(size, 0, 0, 0, FW_MEDIUM,
        FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS,
        CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, _T("宋体"));
}
void CHmLabel::setNoteTextColor(COLORREF color, BOOL bInvalidate/* = FALSE*/)
{
    m_crNote = color;
    if (bInvalidate) Invalidate(TRUE);
}
void CHmLabel::setBackground(COLORREF color, BOOL bInvalidate/* = FALSE*/)
{
    m_crBackground = color;
    if (bInvalidate) Invalidate(TRUE);
}
void CHmLabel::setForeground(COLORREF color, BOOL bInvalidate/* = FALSE*/)
{
    m_crForeground = color;
    if (bInvalidate) Invalidate(TRUE);
}
void CHmLabel::OnPaint()
{
    CPaintDC dc(this); // device context for painting
                       // TODO: åœ¨æ­¤å¤„添加消息处理程序代码
                       // ä¸ä¸ºç»˜å›¾æ¶ˆæ¯è°ƒç”¨ CStatic::OnPaint()
    HDC hMemDC;
    HBITMAP hBitmap;
    RECT rcClient;
    CString strText;
    HBRUSH hBrushBK;
    GetClientRect(&rcClient);
    hMemDC = ::CreateCompatibleDC(dc.m_hDC);
    hBitmap = ::CreateCompatibleBitmap(dc.m_hDC, rcClient.right - rcClient.left,
        rcClient.bottom - rcClient.top);
    ::SelectObject(hMemDC, hBitmap);
    // èƒŒæ™¯é¢œè‰²
    hBrushBK = CreateSolidBrush(m_crBackground);
    ::FillRect(hMemDC, &rcClient, hBrushBK);
    DeleteObject(hBrushBK);
    // æ–‡å­—
    char szText[256];
    GetWindowText(szText, 256);
    RECT rcText = rcClient;
    SetBkMode(hMemDC, TRANSPARENT);
    SetTextColor(hMemDC, m_crForeground);
    ::SelectObject(hMemDC, m_hFont == NULL ? (HFONT)GetStockObject(DEFAULT_GUI_FONT) : m_hFont);
    ::DrawTextA(hMemDC, szText, (int)strlen(szText), &rcText, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    // Note1
    SetTextColor(hMemDC, m_crNote);
    ::SelectObject(hMemDC, m_hFontNote == NULL ? (HFONT)GetStockObject(DEFAULT_GUI_FONT) : m_hFontNote);
    ::DrawText(hMemDC, m_strNote1, m_strNote1.GetLength(), &rcClient, DT_CENTER | DT_BOTTOM | DT_SINGLELINE | DT_END_ELLIPSIS);
    // EndPaint
    ::BitBlt(dc.m_hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
        hMemDC, 0, 0, SRCCOPY);
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
}
void CHmLabel::OnNcPaint()
{
    // TODO: åœ¨æ­¤å¤„添加消息处理程序代码
    // ä¸ä¸ºç»˜å›¾æ¶ˆæ¯è°ƒç”¨ CStatic::OnNcPaint()
    long styleEx = GetWindowLong(m_hWnd, GWL_EXSTYLE);
    if ((styleEx & WS_EX_CLIENTEDGE) == WS_EX_CLIENTEDGE) {
        RECT rect, rcClient;
        GetClientRect(&rcClient);
        ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.left);
        ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.right);
        GetWindowRect(&rect);
        ::OffsetRect(&rcClient, -rect.left, -rect.top);
        rect.right -= rect.left;
        rect.bottom -= rect.top;
        rect.left = 0;
        rect.top = 0;
        HRGN hRgnWnd = CreateRectRgnIndirect(&rect);
        HRGN hRgnClient = CreateRectRgnIndirect(&rcClient);
        HBRUSH hBrushBK, hBrushFrame;
        HDC hDC = ::GetWindowDC(m_hWnd);
        ::SelectClipRgn(hDC, hRgnWnd);
        ::ExtSelectClipRgn(hDC, hRgnClient, RGN_DIFF);
        hBrushBK = CreateSolidBrush(m_crBackground);
        ::FillRect(hDC, &rect, hBrushBK);
        DeleteObject(hBrushBK);
        hBrushFrame = CreateSolidBrush(m_crFrame);
        ::FrameRect(hDC, &rect, hBrushFrame);
        ::DeleteObject(hRgnWnd);
        ::DeleteObject(hRgnClient);
        DeleteObject(hBrushFrame);
        ::ReleaseDC(m_hWnd, hDC);
    }
}
SourceCode/Bond/Servo/HmLabel.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
#pragma once
class CHmLabel : public CStatic
{
public:
    CHmLabel();
    ~CHmLabel();
public:
    void setText(CString strText);
    void setNote1(CString strNote1);
    void setFontSize(int size);
    void setNoteFontSize(int size);
    void setBackground(COLORREF color, BOOL bInvalidate = FALSE);
    void setForeground(COLORREF color, BOOL bInvalidate = FALSE);
    void setNoteTextColor(COLORREF color, BOOL bInvalidate = FALSE);
private:
    COLORREF m_crFrame;
    COLORREF m_crBackground;
    COLORREF m_crForeground;
    COLORREF m_crNote;
    HFONT m_hFont;
    HFONT m_hFontNote;
private:
    CString m_strNote1;
public:
    DECLARE_MESSAGE_MAP()
    afx_msg void OnPaint();
    afx_msg void OnNcPaint();
};
SourceCode/Bond/Servo/Servo.cpp
@@ -19,6 +19,7 @@
#include "CControlJobManagerDlg.h"
#include "ToolUnits.h"
#include "CUserManager2.h"
#include "AccordionWnd.h"
// å£°æ˜Žå…¨å±€å˜é‡ï¼Œç”¨äºŽç®¡ç† GDI+ åˆå§‹åŒ–
@@ -116,6 +117,7 @@
    CEqsGraphWnd::RegisterWndClass();
    CMapPosWnd::RegisterWndClass();
    CHmTab::RegisterWndClass();
    CAccordionWnd::RegisterWndClass();
    // åˆå§‹åŒ–Rx库
SourceCode/Bond/Servo/Servo.rc
@@ -812,8 +812,18 @@
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    LTEXT           "Test",IDC_STATIC,95,67,15,8
    CONTROL         "Custom1",IDC_LINE1,"BYVerticalLine",WS_TABSTOP,286,7,18,240
    CONTROL         "Custom1",IDC_ACCORDION_WND1,"AccordionWnd",WS_TABSTOP,7,7,271,240
END
IDD_PROD_OVERVIEW DIALOGEX 0, 0, 271, 159
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    CTEXT           "0",IDC_PROD_DAY_OUTPUT,16,12,68,45,SS_CENTERIMAGE
    CTEXT           "0",IDC_PROD_NIGHT_OUTPUT,126,12,68,45,SS_CENTERIMAGE
    CTEXT           "-",IDC_PROD_DAY_TAKT,16,82,68,45,SS_CENTERIMAGE
    CTEXT           "-",IDC_PROD_NIGHT_TAKT,126,82,68,45,SS_CENTERIMAGE
END
@@ -1253,6 +1263,14 @@
        TOPMARGIN, 7
        BOTTOMMARGIN, 247
    END
    IDD_PROD_OVERVIEW, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 264
        TOPMARGIN, 7
        BOTTOMMARGIN, 152
    END
END
#endif    // APSTUDIO_INVOKED
@@ -1507,6 +1525,11 @@
    0
END
IDD_PROD_OVERVIEW AFX_DIALOG_LAYOUT
BEGIN
    0
END
/////////////////////////////////////////////////////////////////////////////
//
SourceCode/Bond/Servo/Servo.vcxproj
@@ -222,6 +222,7 @@
    <ClInclude Include="..\jsoncpp\include\json\value.h" />
    <ClInclude Include="..\jsoncpp\include\json\writer.h" />
    <ClInclude Include="..\jsoncpp\lib_json\json_batchallocator.h" />
    <ClInclude Include="AccordionWnd.h" />
    <ClInclude Include="CBaseDlg.h" />
    <ClInclude Include="CCarrierSlotGrid.h" />
    <ClInclude Include="CCarrierSlotSelector.h" />
@@ -243,9 +244,11 @@
    <ClInclude Include="CPageCollectionEvent.h" />
    <ClInclude Include="CPageGlassList.h" />
    <ClInclude Include="CPageLinkSignal.h" />
    <ClInclude Include="CPageProdOverview.h" />
    <ClInclude Include="CPageReport.h" />
    <ClInclude Include="CPageVarialbles.h" />
    <ClInclude Include="CPanelProduction.h" />
    <ClInclude Include="HmLabel.h" />
    <ClInclude Include="ProductionStats.h" />
    <ClInclude Include="CParam.h" />
    <ClInclude Include="CCjPage1.h" />
@@ -445,6 +448,7 @@
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
    </ClCompile>
    <ClCompile Include="AccordionWnd.cpp" />
    <ClCompile Include="CBaseDlg.cpp" />
    <ClCompile Include="CCarrierSlotGrid.cpp" />
    <ClCompile Include="CCarrierSlotSelector.cpp" />
@@ -466,10 +470,12 @@
    <ClCompile Include="CPageCollectionEvent.cpp" />
    <ClCompile Include="CPageGlassList.cpp" />
    <ClCompile Include="CPageLinkSignal.cpp" />
    <ClCompile Include="CPageProdOverview.cpp" />
    <ClCompile Include="CPageReport.cpp" />
    <ClCompile Include="CPageVarialbles.cpp" />
    <ClCompile Include="ConfigurationProduction.cpp" />
    <ClCompile Include="CPanelProduction.cpp" />
    <ClCompile Include="HmLabel.cpp" />
    <ClCompile Include="ProductionStats.cpp" />
    <ClCompile Include="CParam.cpp" />
    <ClCompile Include="CCjPage1.cpp" />
@@ -662,4 +668,4 @@
    <Error Condition="!Exists('..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
    <Error Condition="!Exists('..\packages\Microsoft.Windows.ImplementationLibrary.1.0.240803.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.ImplementationLibrary.1.0.240803.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
  </Target>
</Project>
</Project>
SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -239,6 +239,9 @@
    <ClCompile Include="ConfigurationProduction.cpp" />
    <ClCompile Include="CPanelProduction.cpp" />
    <ClCompile Include="ProductionStats.cpp" />
    <ClCompile Include="AccordionWnd.cpp" />
    <ClCompile Include="CPageProdOverview.cpp" />
    <ClCompile Include="HmLabel.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AlarmManager.h" />
@@ -520,6 +523,9 @@
    <ClInclude Include="CEventEditDlg.h" />
    <ClInclude Include="CReportEditDlg.h" />
    <ClInclude Include="CPanelProduction.h" />
    <ClInclude Include="AccordionWnd.h" />
    <ClInclude Include="CPageProdOverview.h" />
    <ClInclude Include="HmLabel.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Servo.rc" />
@@ -563,4 +569,4 @@
      <UniqueIdentifier>{885738f6-3122-4bb9-8308-46b7f692fb13}</UniqueIdentifier>
    </Filter>
  </ItemGroup>
</Project>
</Project>
SourceCode/Bond/Servo/resource.h
@@ -61,7 +61,7 @@
#define IDD_CJ_PAGE3                    180
#define IDD_DIALOG_USER_MANAGER2        181
#define IDD_DIALOG_USER_EDIT2           182
#define IDD_DIALOG1                     184
#define IDD_PROD_OVERVIEW                183
#define IDD_DIALOG_USERX_LOG            184
#define IDD_DIALOG_VARIABLE_EDIT2       186
#define IDD_DIALOG_REPORT_EDIT          187
@@ -323,6 +323,11 @@
#define IDC_EDIT_EVT_NAME               1244
#define IDC_EDIT_EVT_DESC               1245
#define IDC_LIST_EVT_RPTS               1246
#define IDC_ACCORDION_WND1              1247
#define IDC_PROD_DAY_OUTPUT                1248
#define IDC_PROD_NIGHT_OUTPUT            1249
#define IDC_PROD_DAY_TAKT                1250
#define IDC_PROD_NIGHT_TAKT                1251
#define ID_MENU_HELP_ABOUT              32771
#define ID_MENU_FILE_EXIT               32772
#define ID_MENU_FILE_SECSTEST           32773
@@ -362,7 +367,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        191
#define _APS_NEXT_COMMAND_VALUE         32804
#define _APS_NEXT_CONTROL_VALUE         1247
#define _APS_NEXT_CONTROL_VALUE         1252
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif