LAPTOP-SNT8I5JK\Boounion
2025-01-06 a3a9a6aeb574d21fb6e54b12b797b859662e5ad2
1.PLC独立模块,添加了工具条
已添加8个文件
已修改8个文件
1695 ■■■■■ 文件已修改
SourceCode/Bond/BoounionPLC/BlButton.cpp 499 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BlButton.h 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLC.cpp 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLC.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/Common.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/HorizontalLine.cpp 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/HorizontalLine.h 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/Resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/TopToolbar.cpp 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/TopToolbar.h 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/VerticalLine.cpp 310 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/VerticalLine.h 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BlButton.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,499 @@
#include "stdafx.h"
#include "BlButton.h"
#define BADGE_HIDE                  0
#define BADGE_DOT                   1
#define BADGE_NUMBER                2
#define BADGE_DOT_WIDTH             12
#define BADGE_NUMBER_WIDTH          20
CBlButton::CBlButton()
{
    m_nState = BS_NORMAL;
    m_crFrame[BS_NORMAL] = RGB(225, 225, 225);
    m_crFrame[BS_HOVER] = RGB(0, 120, 215);
    m_crFrame[BS_PRESS] = RGB(0, 84, 153);
    m_crFrame[BS_FOCUS] = RGB(0, 120, 215);
    m_crFrame[BS_DISABLE] = RGB(191, 191, 191);
    m_crBkgnd[BS_NORMAL] = RGB(225, 225, 225);
    m_crBkgnd[BS_HOVER] = RGB(229, 241, 251);
    m_crBkgnd[BS_PRESS] = RGB(204, 228, 247);
    m_crBkgnd[BS_FOCUS] = RGB(225, 225, 225);
    m_crBkgnd[BS_DISABLE] = RGB(204, 204, 204);
    m_crText[BS_NORMAL] = RGB(0, 0, 0);
    m_crText[BS_HOVER] = RGB(0, 0, 0);
    m_crText[BS_PRESS] = RGB(0, 0, 0);
    m_crText[BS_FOCUS] = RGB(0, 0, 0);
    m_crText[BS_DISABLE] = RGB(131, 131, 131);
    m_bHover = FALSE;
    m_bSelected = FALSE;
    m_bTracking = FALSE;
    memset(&m_badge, 0, sizeof(BADGE));
    m_nRoundWidth = 0;
    m_hMenu = nullptr;
    m_hIcon[0] = nullptr;
    m_hIcon[1] = nullptr;
    m_nIconWidth = 0;
    m_nFlashState = 0;
}
CBlButton::~CBlButton()
{
}
void CBlButton::SetFrameColor(int index, COLORREF color)
{
    if (BS_NORMAL <= index && index <= BS_DISABLE) {
        m_crFrame[index] = color;
    }
}
void CBlButton::SetFrameColor(COLORREF color)
{
    m_crFrame[BS_NORMAL] = color;
    m_crFrame[BS_HOVER] = color;
    m_crFrame[BS_PRESS] = color;
    m_crFrame[BS_FOCUS] = color;
    Invalidate();
}
void CBlButton::SetRoundWidth(int width)
{
    m_nRoundWidth = width;
}
void CBlButton::SetBkgndColor(int index, COLORREF color)
{
    if (BS_NORMAL <= index && index <= BS_DISABLE) {
        m_crBkgnd[index] = color;
    }
}
void CBlButton::SetTextColor(int index, COLORREF color)
{
    if (BS_NORMAL <= index && index <= BS_DISABLE) {
        m_crText[index] = color;
    }
}
void CBlButton::SetFaceColor(COLORREF color)
{
    m_crBkgnd[BS_NORMAL] = color;
    m_crBkgnd[BS_HOVER] = color;
    m_crBkgnd[BS_PRESS] = color;
    m_crBkgnd[BS_FOCUS] = color;
    Invalidate();
}
void CBlButton::SetTextColor(COLORREF color)
{
    m_crText[BS_NORMAL] = color;
    m_crText[BS_HOVER] = color;
    m_crText[BS_PRESS] = color;
    m_crText[BS_FOCUS] = color;
    Invalidate();
}
void CBlButton::SetBadgeNumber(int number)
{
    m_badge.badgeBackground = RGB(255, 0, 0);
    m_badge.badgeForeground = RGB(255, 255, 255);
    m_badge.type = number > 0 ? BADGE_NUMBER : BADGE_HIDE;
    m_badge.number = number;
    Invalidate();
}
void CBlButton::ShowDotBadge(BOOL bShow, COLORREF color)
{
    m_badge.badgeBackground = color;
    m_badge.type = bShow ? BADGE_DOT : BADGE_HIDE;
    Invalidate();
}
void CBlButton::SetBkgndBmp(const char* pszBmpFile)
{
    m_strBkgndBmp = pszBmpFile;
}
void CBlButton::SetMenu(HMENU hMenu)
{
    m_hMenu = hMenu;
}
void CBlButton::SetCurrentMenuItem(UINT nPosition)
{
    char szTxt[256];
    GetMenuString(::GetSubMenu(m_hMenu, 0), nPosition, szTxt, 256, MF_BYPOSITION);
    SetWindowText(szTxt);
}
HMENU CBlButton::GetMenu()
{
    return m_hMenu;
}
void CBlButton::SetIcon(HICON hIcon, HICON hIconGray, int width)
{
    m_hIcon[0] = hIcon;
    m_hIcon[1] = hIconGray;
    m_nIconWidth = width;
}
void CBlButton::Flash(int ms)
{
    m_nFlashState = 1;
    SetTimer(1, ms, nullptr);
}
void CBlButton::StopFlash()
{
    m_nFlashState = 0;
    KillTimer(1);
    Invalidate();
}
BOOL CBlButton::IsFlash()
{
    return m_nFlashState != 0;
}
void CBlButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    HDC hDC = lpDrawItemStruct->hDC;
    RECT rcClient;
    GetClientRect(&rcClient);
    // è¾¹æ¡†+背景
    int state = GetDrawState();
    if (m_nFlashState != 0) {
        if (state != BS_DISABLE) {
            state = m_nFlashState == 1 ? BS_NORMAL : BS_PRESS;
        }
    }
    HBRUSH hBrush = CreateSolidBrush(m_crBkgnd[state]);
    HPEN hPen = CreatePen(PS_SOLID, state == BS_FOCUS ? 2 : 1, m_crFrame[state]);
    HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
    HPEN hOldBrush = (HPEN)::SelectObject(hDC, hBrush);
    ::RoundRect(hDC, state == BS_FOCUS ? rcClient.left + 1 : rcClient.left,
        state == BS_FOCUS ? rcClient.top + 1 : rcClient.top, rcClient.right,
        rcClient.bottom, m_nRoundWidth, m_nRoundWidth);
    ::SelectObject(hDC, hOldPen);
    ::SelectObject(hDC, hOldBrush);
    ::DeleteObject(hBrush);
    ::DeleteObject(hPen);
    // è´´å›¾
    CustomBitBlt(hDC, &rcClient, m_strBkgndBmp, state, 5, 2, 2, 2, 2, RGB(255,0,255));
    // èŽ·å¾—æ–‡æœ¬
    char szText[64];
    int nTextLen = GetWindowText(szText, 64);
    // å›¾æ ‡
    RECT rcText = rcClient;
    HICON hIcon = this->IsWindowEnabled() ? m_hIcon[0] : m_hIcon[01];
    if (hIcon != nullptr) {
        int xIcon = (rcClient.right - rcClient.top - m_nIconWidth) / 2;
        if (m_hMenu != nullptr) xIcon -= 10;
        int yIcon = (rcClient.bottom - rcClient.top - m_nIconWidth) / 2;
        if (nTextLen != 0) {
            yIcon -= 8;
        }
        DrawIconEx(hDC, xIcon, yIcon,
            hIcon, m_nIconWidth, m_nIconWidth, 0, 0, DI_NORMAL);
        rcText.top = yIcon + m_nIconWidth + 2;
    }
    // æ–‡æœ¬
    HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    CFont* pFont = GetFont();
    if (pFont != nullptr) {
        hFont = (HFONT)pFont->GetSafeHandle();
    }
    ::SelectObject(hDC, hFont);
    ::SetBkMode(hDC, TRANSPARENT);
    ::SetTextColor(hDC, m_crText[state]);
    if ((BS_MULTILINE & GetStyle()) == BS_MULTILINE) {
        CRect rcBound;
        int height = DrawTextA(hDC, szText, (int)strlen(szText), &rcBound,  DT_CENTER | DT_CALCRECT | DT_EDITCONTROL);
        rcText.top = rcBound.top + (rcClient.bottom - rcClient.top - height) / 2;
        rcText.bottom = rcText.top + height;
        DrawTextA(hDC, szText, (int)strlen(szText), &rcText,  DT_CENTER | DT_EDITCONTROL);
    }
    else {
        if (m_hMenu != nullptr) {
            rcText.right -= (10);
        }
        DrawTextA(hDC, szText, (int)strlen(szText), &rcText, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    }
    // æ˜¯å¦æœ‰å°åœ†ç‚¹
    if (m_badge.type == BADGE_DOT) {
        Gdiplus::Graphics graphics(hDC);
        graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
        Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(m_badge.badgeBackground), GetGValue(m_badge.badgeBackground), GetBValue(m_badge.badgeBackground)));
        int x = rcClient.right - 8 - BADGE_DOT_WIDTH;
        int y = rcClient.top + 8;
        graphics.FillEllipse(&brush, x, y, BADGE_DOT_WIDTH, BADGE_DOT_WIDTH);
    }
    else if (m_badge.type == BADGE_NUMBER) {
        Gdiplus::Graphics graphics(hDC);
        graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
        Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(m_badge.badgeBackground), GetGValue(m_badge.badgeBackground), GetBValue(m_badge.badgeBackground)));
        int x = rcClient.right - 8 - BADGE_NUMBER_WIDTH;
        int y = rcClient.top + 8;
        graphics.FillEllipse(&brush, x, y, BADGE_NUMBER_WIDTH, BADGE_NUMBER_WIDTH);
        RECT rcBadge;
        rcBadge.left = x;
        rcBadge.right = rcBadge.left + BADGE_NUMBER_WIDTH;
        rcBadge.top = y;
        rcBadge.bottom = rcBadge.top + BADGE_NUMBER_WIDTH;
        ::SetTextColor(hDC, m_badge.badgeForeground);
        char szBuffer[32];
        sprintf_s(szBuffer, 32, "%d%s", min(m_badge.number, 9), m_badge.number > 9 ? "+" : "");
        DrawText(hDC, szBuffer, (int)strlen(szBuffer), &rcBadge, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    }
    // èœå•项小三角
    if (m_hMenu != nullptr) {
        HPEN hPenDrop = CreatePen(PS_SOLID, 1, m_crText[state]);
        HBRUSH hbrDrop = CreateSolidBrush(m_crText[state]);
        HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC, hbrDrop);
        HPEN hOldPen = (HPEN)::SelectObject(hDC, hPenDrop);
        POINT pt[3];
        pt[0].x = rcClient.right - 20;
        pt[0].y = rcClient.top + (rcClient.bottom - rcClient.top - 5) / 2;
        pt[1].x = pt[0].x + 10;
        pt[1].y = pt[0].y;
        pt[2].x = pt[0].x + (pt[1].x - pt[0].x) / 2;
        pt[2].y = pt[0].y + 5;
        ::Polygon(hDC, pt, 3);
        ::SelectObject(hDC, hOldBrush);
        ::SelectObject(hDC, hOldPen);
        ::DeleteObject(hBrush);
        ::DeleteObject(hPen);
    }
}
int CBlButton::GetDrawState()
{
    if (!IsWindowEnabled()) {
        return BS_DISABLE;
    }
    //if (GetFocus() == this) {
    //    return BS_FOCUS;
    //}
    return m_nState;
}
void CBlButton::PreSubclassWindow()
{
    m_bHover = false;
    m_bSelected = false;
    m_bTracking = FALSE;
    ModifyStyle(0, BS_OWNERDRAW);
    CButton::PreSubclassWindow();
}
BEGIN_MESSAGE_MAP(CBlButton, CButton)
    ON_WM_MOUSEMOVE()
    ON_WM_MOUSEHOVER()
    ON_WM_MOUSELEAVE()
    ON_WM_LBUTTONDOWN()
    ON_CONTROL_REFLECT_EX(BN_CLICKED, &CBlButton::OnBnClicked)
    ON_WM_LBUTTONUP()
    ON_WM_TIMER()
END_MESSAGE_MAP()
void CBlButton::OnMouseMove(UINT nFlags, CPoint point)
{
    if (!m_bTracking)
    {
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(tme);
        tme.dwFlags = TME_HOVER | TME_LEAVE;        // å‘送WM_MOUSEHOVER和WM_MOUSELEAVE
        tme.hwndTrack = m_hWnd;                        // æŒ‡å®šè¦è¿½è¸ªçš„窗口
        tme.dwHoverTime = 10;                        // é¼ æ ‡åœ¨æŒ‰é’®ä¸Šåœç•™è¶…过10ms,才认为状态为HOVER
        m_bTracking = _TrackMouseEvent(&tme);        // å¼€å¯Windows的WM_MOUSELEAVEWM_MOUSEHOVER事件支持
    }
    CButton::OnMouseMove(nFlags, point);
}
void CBlButton::OnMouseHover(UINT nFlags, CPoint point)
{
    m_bHover = true;
    m_nState = BS_HOVER;
    InvalidateRect(NULL);
    return;
    // CButton::OnMouseHover(nFlags, point);
}
void CBlButton::OnMouseLeave()
{
    m_bHover = false;
    m_bTracking = FALSE;    // è‹¥å·²ç»ç¦»å¼€ï¼Œåˆ™åœæ­¢è¿½è¸ª
    m_nState = BS_NORMAL;
    InvalidateRect(NULL);
    CButton::OnMouseLeave();
}
BOOL CBlButton::CustomBitBlt(HDC hDC, LPRECT lprc, CString& strBkgndBmp, int nFrame, int nAllFrame,
    int nB0, int nB1, int nB2, int nB3, COLORREF crTransparent)
{
    // è½½å…¥BMP
    HBITMAP hBmpTemp = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
        strBkgndBmp, IMAGE_BITMAP, 0, 0,
        LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
    if (hBmpTemp == NULL)
        return FALSE;
    HDC hDCTemp = ::CreateCompatibleDC(hDC);
    ::SelectObject(hDCTemp, hBmpTemp);
    BITMAP bitmap;
    ::GetObject(hBmpTemp, sizeof(BITMAP), &bitmap);
    int nFrameWidth = bitmap.bmWidth / nAllFrame;        // æ¯å¸§çš„宽
    int nFrameX = nFrameWidth*nFrame;                // æŒ‡å®šå¸§ç›¸ç´ èµ·ç‚¹
                                                    // å¦‚果角或边厚为0
    if (nB0 == 0 && nB1 == 0 &&
        nB2 == 0 && nB3 == 0) {
        ::TransparentBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top,
            hDCTemp, nFrameX, 0, nFrameWidth, bitmap.bmHeight, crTransparent);
        ::DeleteObject(hBmpTemp);
        ::DeleteDC(hDCTemp);
        return TRUE;
    }
    // å…¶å®ƒ
    int x = lprc->left + nB3;
    int y = lprc->top + nB0;
    ::TransparentBlt(hDC, x, y, lprc->right - lprc->left - (nB1 + nB3), lprc->bottom - lprc->top - (nB0 + nB2),
        hDCTemp, nFrameX + nB3, nB0, nFrameWidth - (nB1 + nB3), bitmap.bmHeight - (nB0 + nB2), crTransparent);
    x = lprc->left;
    y = lprc->top;
    ::TransparentBlt(hDC, x, y, nB3, nB0,
        hDCTemp, nFrameX + 0, 0, nB3, nB0, crTransparent);
    x += nB3;
    y = lprc->top;
    ::TransparentBlt(hDC, x, y, lprc->right - lprc->left - (nB1 + nB3), nB0,
        hDCTemp, nFrameX + nB3, 0, nFrameWidth - (nB1 + nB3), nB0, crTransparent);
    x = lprc->right - nB1;
    y = lprc->top;
    ::TransparentBlt(hDC, x, y, nB1, nB0,
        hDCTemp, nFrameX + nFrameWidth - nB1, 0, nB1, nB0, crTransparent);
    x = lprc->right - nB1;
    y = lprc->top + nB0;
    ::TransparentBlt(hDC, x, y, nB1, lprc->bottom - lprc->top - (nB0 + nB2),
        hDCTemp, nFrameX + nFrameWidth - nB1, nB0, nB1, bitmap.bmHeight - (nB0 + nB2), crTransparent);
    x = lprc->right - nB1;
    y = lprc->bottom - nB2;
    ::TransparentBlt(hDC, x, y, nB1, nB2,
        hDCTemp, nFrameX + nFrameWidth - nB1, bitmap.bmHeight - nB2, nB1, nB2, crTransparent);
    x = lprc->left + nB3;
    y = lprc->bottom - nB2;
    ::TransparentBlt(hDC, x, y, lprc->right - lprc->left - (nB1 + nB3), nB2,
        hDCTemp, nFrameX + nB3, bitmap.bmHeight - nB2, nFrameWidth - (nB1 + nB3), nB2, crTransparent);
    x = lprc->left;
    y = lprc->bottom - nB2;
    ::TransparentBlt(hDC, x, y, nB3, nB2,
        hDCTemp, nFrameX + 0, bitmap.bmHeight - nB2, nB3, nB2, crTransparent);
    x = lprc->left;
    y = lprc->top + nB0;
    ::TransparentBlt(hDC, x, y, nB3, lprc->bottom - lprc->top - (nB0 + nB2),
        hDCTemp, nFrameX + 0, nB0, nB3, bitmap.bmHeight - (nB0 + nB2), crTransparent);
    ::DeleteObject(hBmpTemp);
    ::DeleteDC(hDCTemp);
    return TRUE;
}
void CBlButton::OnLButtonDown(UINT nFlags, CPoint point)
{
    m_nState = BS_PRESS;
    CButton::OnLButtonDown(nFlags, point);
}
void CBlButton::OnLButtonUp(UINT nFlags, CPoint point)
{
    m_nState = BS_HOVER;
    CButton::OnLButtonUp(nFlags, point);
}
BOOL CBlButton::OnBnClicked()
{
    if (m_hMenu != NULL) {
        RECT rect;
        GetWindowRect(&rect);
        int cmd = ::TrackPopupMenu(::GetSubMenu(m_hMenu, 0),
            TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, rect.left, rect.bottom, 0, m_hWnd, NULL);
        if (cmd > 0) {
            int position = cmd - GetMenuItemID(::GetSubMenu(m_hMenu, 0), 0);
            Notify((int)BLBUTTON_MENU_ITEM_CLICKED, position);
        }
    }
    return FALSE;
}
void CBlButton::Notify(int nCode, DWORD_PTR dwData, DWORD_PTR dwData1/* = 0*/, DWORD_PTR dwData2/* = 0*/)
{
    CWnd* pParent;
    pParent = GetParent();
    if (pParent != nullptr) {
        BLBUTTON_NMHDR blbNmhdr;
        blbNmhdr.nmhdr.code = nCode;
        blbNmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
        blbNmhdr.nmhdr.hwndFrom = m_hWnd;
        blbNmhdr.dwData = dwData;
        blbNmhdr.dwData1 = dwData1;
        blbNmhdr.dwData2 = dwData2;
        pParent->SendMessage(WM_NOTIFY, (WPARAM)blbNmhdr.nmhdr.idFrom, (LPARAM)&blbNmhdr);
    }
}
void CBlButton::OnTimer(UINT_PTR nIDEvent)
{
    if (1 == nIDEvent) {
        m_nFlashState++;
        if (m_nFlashState > 2) m_nFlashState = 1;
        Invalidate();
    }
    CButton::OnTimer(nIDEvent);
}
SourceCode/Bond/BoounionPLC/BlButton.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
#pragma once
#include "afxwin.h"
#define BS_NORMAL        0
#define BS_HOVER        1
#define BS_PRESS        2
#define BS_FOCUS        3
#define BS_DISABLE        4
#define BLBUTTON_MENU_ITEM_CLICKED        0x1345
typedef struct tagBLBUTTON_NMHDR
{
    NMHDR        nmhdr;
    DWORD_PTR    dwData;
    DWORD_PTR    dwData1;
    DWORD_PTR    dwData2;
} BLBUTTON_NMHDR;
class CBlButton :
    public CButton
{
private:
    typedef struct tagBADGE
    {
        COLORREF badgeBackground;
        COLORREF badgeForeground;
        int type;                       /* 0: æ— ,不显示*/
        int number;
    } BADGE;
public:
    CBlButton();
    ~CBlButton();
public:
    void SetRoundWidth(int width);
    int GetDrawState();
    void SetFrameColor(int index, COLORREF color);
    void SetFrameColor(COLORREF color);
    void SetBkgndColor(int index, COLORREF color);
    void SetTextColor(int index, COLORREF color);
    void SetBkgndBmp(const char* pszBmpFile);
    void SetFaceColor(COLORREF color);
    void SetTextColor(COLORREF color);
    void SetBadgeNumber(int number);
    void ShowDotBadge(BOOL bShow, COLORREF color);
    void SetMenu(HMENU hMenu);
    void SetCurrentMenuItem(UINT nPosition);
    HMENU GetMenu();
    void SetIcon(HICON hIcon, HICON hIconGray, int width);
    void Flash(int ms);
    void StopFlash();
    BOOL IsFlash();
private:
    BOOL CustomBitBlt(HDC hDC, LPRECT lprc, CString& strBkgndBmp, int nFrame, int nAllFrame,
        int nB0, int nB1, int nB2, int nB3, COLORREF crTransparent);
    void CBlButton::Notify(int nCode, DWORD_PTR dwData, DWORD_PTR dwData1 = 0, DWORD_PTR dwData2 = 0);
private:
    bool m_bHover;            // æ‚¬åœ
    bool m_bSelected;        // æŒ‰ä¸‹
    BOOL m_bTracking;        // è·Ÿè¸ª
    int m_nState;
    int m_nRoundWidth;
private:
    COLORREF m_crFrame[5];    // è¾¹æ¡†é¢œè‰²
    COLORREF m_crBkgnd[5];    // èƒŒæ™¯é¢œè‰²
    COLORREF m_crText[5];    // æ–‡æœ¬é¢œè‰²
    CString m_strBkgndBmp;
private:
    BADGE m_badge;
    HMENU m_hMenu;
    HICON m_hIcon[2];
    int m_nIconWidth;
    int m_nFlashState;        // é—ªçƒçŠ¶æ€ï¼Œ0:不闪;1和2为闪烁切换中
public:
    virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
    virtual void PreSubclassWindow();
    DECLARE_MESSAGE_MAP()
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnMouseHover(UINT nFlags, CPoint point);
    afx_msg void OnMouseLeave();
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg BOOL OnBnClicked();
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
};
SourceCode/Bond/BoounionPLC/BoounionPLC.cpp
@@ -5,6 +5,9 @@
#include "stdafx.h"
#include "BoounionPLC.h"
#include "BoounionPLCDlg.h"
#include "HorizontalLine.h"
#include "VerticalLine.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -102,6 +105,11 @@
    }
    // æŽ§ä»¶æ³¨å†Œ
    CHorizontalLine::RegisterWndClass();
    CVerticalLine::RegisterWndClass();
    CBoounionPLCDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
SourceCode/Bond/BoounionPLC/BoounionPLC.rc
Binary files differ
SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj
@@ -189,6 +189,8 @@
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\BondEq\HorizontalLine.h" />
    <ClInclude Include="BlButton.h" />
    <ClInclude Include="BoounionPLC.h" />
    <ClInclude Include="BoounionPLCDlg.h" />
    <ClInclude Include="Common.h" />
@@ -198,8 +200,12 @@
    <ClInclude Include="Resource.h" />
    <ClInclude Include="stdafx.h" />
    <ClInclude Include="targetver.h" />
    <ClInclude Include="TopToolbar.h" />
    <ClInclude Include="VerticalLine.h" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="..\BondEq\HorizontalLine.cpp" />
    <ClCompile Include="BlButton.cpp" />
    <ClCompile Include="BoounionPLC.cpp" />
    <ClCompile Include="BoounionPLCDlg.cpp" />
    <ClCompile Include="Configuration.cpp" />
@@ -211,6 +217,8 @@
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
    </ClCompile>
    <ClCompile Include="TopToolbar.cpp" />
    <ClCompile Include="VerticalLine.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="BoounionPLC.rc" />
@@ -224,4 +232,9 @@
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
  <ProjectExtensions>
    <VisualStudio>
      <UserProperties RESOURCE_FILE="BoounionPLC.rc" />
    </VisualStudio>
  </ProjectExtensions>
</Project>
SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters
@@ -45,6 +45,18 @@
    <ClInclude Include="Log.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="TopToolbar.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="BlButton.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="..\BondEq\HorizontalLine.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="VerticalLine.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="BoounionPLC.cpp">
@@ -65,6 +77,18 @@
    <ClCompile Include="Log.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="TopToolbar.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="BlButton.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="..\BondEq\HorizontalLine.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="VerticalLine.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="BoounionPLC.rc">
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp
@@ -53,6 +53,7 @@
    : CDialogEx(IDD_BOOUNIONPLC_DIALOG, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_pTopToolbar = nullptr;
}
void CBoounionPLCDlg::DoDataExchange(CDataExchange* pDX)
@@ -64,6 +65,9 @@
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
@@ -98,7 +102,20 @@
    SetIcon(m_hIcon, TRUE);            // è®¾ç½®å¤§å›¾æ ‡
    SetIcon(m_hIcon, FALSE);        // è®¾ç½®å°å›¾æ ‡
    // TODO: åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–ä»£ç 
    // toolbar
    m_pTopToolbar = new CTopToolbar();
    m_pTopToolbar->Create(IDD_TOP_TOOLBAR, this);
    m_pTopToolbar->ShowWindow(SW_SHOW);
    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
    m_pTopToolbar->GetBtn(IDC_BUTTON_ALARM)->EnableWindow(FALSE);
    HMENU hMenu = m_pTopToolbar->GetOperatorMenu();
    ASSERT(hMenu);
    ::EnableMenuItem(hMenu, ID_OPEATOR_SWITCH, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
    Resize();
    return TRUE;  // é™¤éžå°†ç„¦ç‚¹è®¾ç½®åˆ°æŽ§ä»¶ï¼Œå¦åˆ™è¿”回 TRUE
}
@@ -152,3 +169,54 @@
    return static_cast<HCURSOR>(m_hIcon);
}
void CBoounionPLCDlg::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_pTopToolbar != nullptr) {
        m_pTopToolbar->DestroyWindow();
        delete m_pTopToolbar;
        m_pTopToolbar = nullptr;
    }
}
void CBoounionPLCDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (m_pTopToolbar == nullptr || !::IsWindow(m_pTopToolbar->m_hWnd)) return;
    Resize();
}
#define TOOLBAR_HEIGHT        78
void CBoounionPLCDlg::Resize()
{
    CRect rcClient, rcItem;
    GetClientRect(&rcClient);
    int y = 0;
    m_pTopToolbar->MoveWindow(0, 0, rcClient.Width(), TOOLBAR_HEIGHT);
    y += TOOLBAR_HEIGHT;
    /*
    ASSERT(m_pPanelProject);
    int nPanelEquipmentWidth = m_pPanelProject->GetPanelWidth();
    m_pPanelProject->MoveWindow(0, y, nPanelEquipmentWidth, rcClient.bottom - y);
    int x = nPanelEquipmentWidth;
    m_pMainContainer->MoveWindow(x + 1, y, rcClient.Width() - x - 0, rcClient.bottom - y - 2);
    */
}
HBRUSH CBoounionPLCDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    // TODO:  åœ¨æ­¤æ›´æ”¹ DC çš„任何特性
    // TODO:  å¦‚果默认的不是所需画笔,则返回另一个画笔
    return hbr;
}
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h
@@ -3,6 +3,7 @@
//
#pragma once
#include "TopToolbar.h"
// CBoounionPLCDlg å¯¹è¯æ¡†
@@ -11,6 +12,17 @@
// æž„造
public:
    CBoounionPLCDlg(CWnd* pParent = NULL);    // æ ‡å‡†æž„造函数
private:
    void Resize();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    IObserver* m_pObserver;
    CTopToolbar* m_pTopToolbar;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
@@ -31,4 +43,8 @@
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnDestroy();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};
SourceCode/Bond/BoounionPLC/Common.h
@@ -4,3 +4,6 @@
/* Rx Code */
#define RX_CODE_TEST                    0
#define RX_CODE_LOG                        1000
/* å®šåˆ¶é¢œè‰² */
#define TOP_TOOLBAR_BACKGROUND            RGB(240, 240, 240)
SourceCode/Bond/BoounionPLC/HorizontalLine.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,209 @@
// HorizontalLine.cpp: implementation of the CHorizontalLine class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HorizontalLine.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CHorizontalLine::CHorizontalLine()
{
    m_hWnd = NULL;
    m_crBkgnd = RGB(255, 255, 255);
    m_crLineColor = RGB(222, 222, 222);
}
CHorizontalLine::~CHorizontalLine()
{
}
BOOL CHorizontalLine::RegisterWndClass()
{
    WNDCLASS wc;
    wc.lpszClassName = BYHORIZONTALLINE_CLASS;
    wc.hInstance = AfxGetInstanceHandle();
    wc.lpfnWndProc = WindowProc;
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = 0;
    wc.lpszMenuName = NULL;
    wc.hbrBackground = NULL;
    wc.style = CS_GLOBALCLASS|CS_DBLCLKS;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    // æ³¨å†Œè‡ªå®šä¹‰ç±»
    return (::RegisterClass(&wc) != 0);
}
CHorizontalLine* CHorizontalLine::Hook(HWND hWnd)
{
    CHorizontalLine* pHorizontalLine = (CHorizontalLine*)GetProp(hWnd, BYSTAG_HORIZONTALLINE);
    if(pHorizontalLine == NULL)
    {
        pHorizontalLine = new CHorizontalLine;
        pHorizontalLine->m_hWnd = hWnd;
        SetProp(hWnd, BYSTAG_HORIZONTALLINE, (HANDLE)pHorizontalLine);
    }
    return pHorizontalLine;
}
void CHorizontalLine::Release()
{
    // delete
    delete this;
}
void CHorizontalLine::Notify(int nCode, int dwData, int dwData1/* = 0*/, int dwData2/* = 0*/)
{
    HWND hParent;
    hParent = GetParent(m_hWnd);
    if(hParent != NULL) {
        BYHORIZONTALLINE_NMHDR iii_nmhdr;
        iii_nmhdr.nmhdr.hwndFrom = m_hWnd;
        iii_nmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
        iii_nmhdr.nmhdr.code = nCode;
        iii_nmhdr.dwData = dwData;
        iii_nmhdr.dwData1 = dwData1;
        iii_nmhdr.dwData2 = dwData2;
        SendMessage(hParent, WM_NOTIFY, (WPARAM)iii_nmhdr.nmhdr.idFrom, (LPARAM)&iii_nmhdr);
    }
}
////////////////////////////////
// æ‹¦æˆªçª—口消息函数
LRESULT CALLBACK CHorizontalLine::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CHorizontalLine* pHorizontalLine = (CHorizontalLine *)GetProp(hWnd, BYSTAG_HORIZONTALLINE);
    if(pHorizontalLine == NULL && uMsg != WM_NCCREATE)
    {
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    // å¦‚æžœHook则响应消息
    ASSERT(hWnd);
    switch(uMsg)
    {
    case WM_NCCREATE:
        return OnNcCreate(hWnd, wParam, lParam);
    case WM_DESTROY:
        return pHorizontalLine->OnDestroy(wParam, lParam);
    case WM_PAINT:
        return pHorizontalLine->OnPaint(wParam, lParam);
    case WM_TIMER:
        return pHorizontalLine->OnTimer(wParam, lParam);
    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS;
    default:
        break;
    }
    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
///////////////////////////////
// WM_NCCREATE
// çª—口创建前的初始化工作
LRESULT CHorizontalLine::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    CHorizontalLine* pHorizontalLine = (CHorizontalLine *)GetProp(hWnd, BYSTAG_HORIZONTALLINE);
    ASSERT(pHorizontalLine == NULL);
    Hook(hWnd);
    return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
}
///////////////////////////////
// WM_DESTROY
LRESULT CHorizontalLine::OnDestroy(WPARAM wParam, LPARAM lParam)
{
    Release();
    return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
}
///////////////////////////////
// WM_TIMER
LRESULT CHorizontalLine::OnTimer(WPARAM wParam, LPARAM lParam)
{
    return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
}
///////////////////////////////
// WM_PAINT
LRESULT CHorizontalLine::OnPaint(WPARAM wParam, LPARAM lParam)
{
    HDC hDC, hMemDC;
    HBITMAP hBitmap;
    RECT rcClient;
    CString strText;
    HFONT hFont;
    HBRUSH hBrushBK;
    // BeginPaint
    PAINTSTRUCT ps;
    hDC = BeginPaint(m_hWnd, &ps);
    GetClientRect(m_hWnd, &rcClient);
    hMemDC = ::CreateCompatibleDC(hDC);
    hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right-rcClient.left,
        rcClient.bottom-rcClient.top);
    ::SelectObject(hMemDC, hBitmap);
    hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    ::SelectObject(hMemDC, hFont);
    // èƒŒæ™¯é¢œè‰²
    hBrushBK = CreateSolidBrush( m_crBkgnd );
    ::FillRect(hMemDC, &rcClient, hBrushBK);
    DeleteObject(hBrushBK);
    // ç”»çº¿
    HPEN hPen = CreatePen(PS_SOLID, 1, m_crLineColor);
    HPEN hOldPen = (HPEN)::SelectObject(hMemDC, hPen);
    ::MoveToEx(hMemDC, 0, 0, NULL);
    LineTo(hMemDC, rcClient.right, 0);
    ::SelectObject(hMemDC, hOldPen);
    // EndPaint
    ::BitBlt(hDC, 0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
        hMemDC, 0, 0, SRCCOPY);
    EndPaint(m_hWnd, &ps);
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
    return 1;
}
void CHorizontalLine::SetBkgndColor(COLORREF cr)
{
    m_crBkgnd = cr;
}
void CHorizontalLine::SetLineColor(COLORREF cr)
{
    m_crLineColor = cr;
}
SourceCode/Bond/BoounionPLC/HorizontalLine.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,87 @@
// HorizontalLine.h: interface for the CHorizontalLine class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_HORIZONTALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)
#define AFX_HORIZONTALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_
#pragma comment(lib, "Msimg32.lib")            // TransparentBlt
//====== HorizontalLine =====================================================
#ifndef NOHORIZONTALLINE
#ifdef _WIN32
#define BYHORIZONTALLINE_CLASSA       "BYHorizontalLine"
#define BYHORIZONTALLINE_CLASSW       L"BYHorizontalLine"
#ifdef UNICODE
#define  BYHORIZONTALLINE_CLASS       BYHORIZONTALLINE_CLASSW
#else
#define  BYHORIZONTALLINE_CLASS       BYHORIZONTALLINE_CLASSA
#endif
#else
#define BYHORIZONTALLINE_CLASS        "BYHorizontalLine"
#endif
#define BYSTAG_HORIZONTALLINE         _T("ISHORIZONTALLINE")
//====== WM_NOTIFY codes (NMHDR.code values) ==================================
#define BYHORIZONTALLINE_FIRST                 (0U-590U)       //
#define BYHORIZONTALLINE_LAST                 (0U-550U)
#define BYHORIZONTALLINE_                      (BYHORIZONTALLINE_FIRST - 1)
typedef struct tagBYHORIZONTALLINE_NMHDR
{
    NMHDR        nmhdr;
    DWORD        dwData;
    DWORD        dwData1;
    DWORD        dwData2;
} BYHORIZONTALLINE_NMHDR;
#endif
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CHorizontalLine
{
public:
    CHorizontalLine();
    virtual ~CHorizontalLine();
public:
    static BOOL RegisterWndClass();
    static CHorizontalLine* Hook(HWND hWnd);
    void Notify(int nCode, int dwData, int dwData1 = 0, int dwData2 = 0);
    void Release();
    void SetBkgndColor(COLORREF cr);
    void SetLineColor(COLORREF cr);
    static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    static LRESULT OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
    LRESULT OnDestroy(WPARAM wParam, LPARAM lParam);
    LRESULT OnTimer(WPARAM wParam, LPARAM lParam);
    LRESULT OnPaint(WPARAM wParam, LPARAM lParam);
private:
    HWND        m_hWnd;
    COLORREF m_crBkgnd;
    COLORREF m_crLineColor;
};
#endif // !defined(AFX_HORIZONTALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)
SourceCode/Bond/BoounionPLC/Resource.h
Binary files differ
SourceCode/Bond/BoounionPLC/TopToolbar.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,211 @@
// TopToolbar.cpp : å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BoounionPLC.h"
#include "TopToolbar.h"
#include "afxdialogex.h"
#include "Common.h"
// CTopToolbar å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CTopToolbar, CDialogEx)
CTopToolbar::CTopToolbar(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_TOP_TOOLBAR, pParent)
{
    m_crBkgnd = TOP_TOOLBAR_BACKGROUND;
    m_hbrBkgnd = nullptr;
}
CTopToolbar::~CTopToolbar()
{
}
void CTopToolbar::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_BUTTON_RUN, m_btnRun);
    DDX_Control(pDX, IDC_BUTTON_STOP, m_btnStop);
    DDX_Control(pDX, IDC_BUTTON_ALARM, m_btnAlarm);
    DDX_Control(pDX, IDC_BUTTON_SETTINGS, m_btnSettings);
    DDX_Control(pDX, IDC_BUTTON_OPERATOR, m_btnOperator);
}
BEGIN_MESSAGE_MAP(CTopToolbar, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_OPERATOR, &CTopToolbar::OnButtonOperatorMenuClicked)
END_MESSAGE_MAP()
// CTopToolbar æ¶ˆæ¯å¤„理程序
BOOL CTopToolbar::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    InitBtn(m_btnRun, "Run_High_32.ico", "Run_Gray_32.ico");
    InitBtn(m_btnStop, "Stop_High_32.ico", "Stop_Gray_32.ico");
    InitBtn(m_btnAlarm, "Alarm_o_32.ico", "Alarm_gray_32.ico");
    InitBtn(m_btnSettings, "Settings_High_32.ico", "Settings_Gray_32.ico");
    InitBtn(m_btnOperator, "Operator_High_32.ico", "Operator_Gray_32.ico");
    HMENU hMenu = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCEA(IDR_MENU_OPEATOR));
    m_btnOperator.SetMenu(hMenu);
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CTopToolbar::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    if (nCtlColor == CTLCOLOR_STATIC) {
        pDC->SetBkColor(m_crBkgnd);
    }
    if (m_hbrBkgnd == nullptr) {
        m_hbrBkgnd = CreateSolidBrush(m_crBkgnd);
    }
    return m_hbrBkgnd;
}
void CTopToolbar::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
        m_hbrBkgnd = nullptr;
    }
}
void CTopToolbar::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (GetDlgItem(IDC_BUTTON_RUN) == nullptr) return;
    Resize();
}
#define BTN_WIDTH        60
#define BTN_HEIGHT        30
void CTopToolbar::Resize()
{
    CWnd* pItem;
    CRect rcClient, rcItem;
    GetClientRect(&rcClient);
    int nBthHeight = (rcClient.Height() - 10);
    int x = 2, y = 3;
    pItem = GetDlgItem(IDC_BUTTON_RUN);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_BUTTON_STOP);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_BUTTON_ALARM);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_TOOLBAR_LINE1);
    pItem->MoveWindow(x, y + 6, 2, nBthHeight - 12);
    x += 4;
    pItem = GetDlgItem(IDC_BUTTON_SETTINGS);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    x = rcClient.right - 5 - BTN_WIDTH - 20;
    pItem = GetDlgItem(IDC_BUTTON_OPERATOR);
    pItem->MoveWindow(x, y, BTN_WIDTH + 20, nBthHeight);
    CWnd* pLine = GetDlgItem(IDC_LINE1);
    pLine->MoveWindow(0, rcClient.bottom - 2, rcClient.Width(), 2);
}
void CTopToolbar::InitBtn(CBlButton& btn, const char* pszIcon1, const char* pszIcon2)
{
    CString strIcon1, strIcon2;
    HICON hIcon1, hIcon2;
    strIcon1.Format(_T("%s\\Res\\%s"), theApp.m_strAppDir, pszIcon1);
    strIcon2.Format(_T("%s\\Res\\%s"), theApp.m_strAppDir, pszIcon2);
    hIcon1 = (HICON)::LoadImage(AfxGetInstanceHandle(),
        strIcon1, IMAGE_ICON, 32, 32,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    hIcon2 = (HICON)::LoadImage(AfxGetInstanceHandle(),
        strIcon2, IMAGE_ICON, 32, 32,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    btn.SetBkgndColor(BS_NORMAL, TOP_TOOLBAR_BACKGROUND);
    btn.SetBkgndColor(BS_PRESS, RGB(185, 209, 234));
    btn.SetBkgndColor(BS_DISABLE, TOP_TOOLBAR_BACKGROUND);
    btn.SetFrameColor(BS_NORMAL, TOP_TOOLBAR_BACKGROUND);
    btn.SetFrameColor(BS_PRESS, RGB(185, 209, 234));
    btn.SetFrameColor(BS_HOVER, RGB(185, 209, 234));
    btn.SetFrameColor(BS_DISABLE, TOP_TOOLBAR_BACKGROUND);
    btn.SetIcon(hIcon1, hIcon2, 32);
}
CWnd* CTopToolbar::GetBtn(UINT nId)
{
    return GetDlgItem(nId);
}
void CTopToolbar::SetOperatorBtnText(const char* pszText)
{
    m_btnOperator.SetWindowText(pszText);
}
BOOL CTopToolbar::OnCommand(WPARAM wParam, LPARAM lParam)
{
    switch (LOWORD(wParam)) {
    case IDC_BUTTON_RUN:
    case IDC_BUTTON_STOP:
    case IDC_BUTTON_ALARM:
    case IDC_BUTTON_SETTINGS:
        GetParent()->SendMessage(ID_MSG_TOOLBAR_BTN_CLICKED, 0, LOWORD(wParam));
        break;
    }
    return CDialogEx::OnCommand(wParam, lParam);
}
void CTopToolbar::OnButtonOperatorMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
    BLBUTTON_NMHDR* pblbNmhdr = reinterpret_cast<BLBUTTON_NMHDR*>(pNMHDR);
    GetParent()->SendMessage(ID_MSG_TOOLBAR_BTN_CLICKED, (int)pblbNmhdr->dwData, IDC_BUTTON_OPERATOR);
    *pResult = 0;
}
HMENU CTopToolbar::GetOperatorMenu()
{
    return m_btnOperator.GetMenu();
}
BOOL CTopToolbar::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) {
        return TRUE;
    }
    return CDialogEx::PreTranslateMessage(pMsg);
}
SourceCode/Bond/BoounionPLC/TopToolbar.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
#pragma once
#include "BlButton.h"
#define ID_MSG_TOOLBAR_BTN_CLICKED        WM_USER + 20368
// CTopToolbar å¯¹è¯æ¡†
class CTopToolbar : public CDialogEx
{
    DECLARE_DYNAMIC(CTopToolbar)
public:
    CTopToolbar(CWnd* pParent = NULL);   // æ ‡å‡†æž„造函数
    virtual ~CTopToolbar();
public:
    CWnd* GetBtn(UINT nId);
    void SetOperatorBtnText(const char* pszText);
    HMENU GetOperatorMenu();
private:
    void Resize();
    void InitBtn(CBlButton& btn, const char* pszIcon1, const char* pszIcon2);
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
private:
    CBlButton m_btnRun;
    CBlButton m_btnStop;
    CBlButton m_btnAlarm;
    CBlButton m_btnSettings;
    CBlButton m_btnOperator;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_TOP_TOOLBAR };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnDestroy();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
    afx_msg void OnButtonOperatorMenuClicked(NMHDR* pNMHDR, LRESULT* pResult);
    virtual BOOL PreTranslateMessage(MSG* pMsg);
};
SourceCode/Bond/BoounionPLC/VerticalLine.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,310 @@
// VerticalLine.cpp: implementation of the CVerticalLine class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "VerticalLine.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CVerticalLine::CVerticalLine()
{
    m_hWnd = NULL;
    m_crBkgnd = RGB(255, 255, 255);
    m_crLineColor = RGB(222, 222, 222);
    m_bEnableResize = FALSE;
}
CVerticalLine::~CVerticalLine()
{
}
BOOL CVerticalLine::RegisterWndClass()
{
    WNDCLASS wc;
    wc.lpszClassName = BYVERTICALLINE_CLASS;
    wc.hInstance = AfxGetInstanceHandle();
    wc.lpfnWndProc = WindowProc;
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = 0;
    wc.lpszMenuName = NULL;
    wc.hbrBackground = NULL;
    wc.style = CS_GLOBALCLASS|CS_DBLCLKS;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    // æ³¨å†Œè‡ªå®šä¹‰ç±»
    return (::RegisterClass(&wc) != 0);
}
CVerticalLine* CVerticalLine::Hook(HWND hWnd)
{
    CVerticalLine* pVerticalLine = (CVerticalLine*)GetProp(hWnd, BYSTAG_VERTICALLINE);
    if(pVerticalLine == NULL)
    {
        pVerticalLine = new CVerticalLine;
        pVerticalLine->m_hWnd = hWnd;
        SetProp(hWnd, BYSTAG_VERTICALLINE, (HANDLE)pVerticalLine);
    }
    return pVerticalLine;
}
void CVerticalLine::Release()
{
    // delete
    delete this;
}
void CVerticalLine::Notify(int nCode, int dwData, int dwData1/* = 0*/, int dwData2/* = 0*/)
{
    HWND hParent;
    hParent = GetParent(m_hWnd);
    if(hParent != NULL) {
        BYVERTICALLINE_NMHDR iii_nmhdr;
        iii_nmhdr.nmhdr.hwndFrom = m_hWnd;
        iii_nmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
        iii_nmhdr.nmhdr.code = nCode;
        iii_nmhdr.dwData = dwData;
        iii_nmhdr.dwData1 = dwData1;
        iii_nmhdr.dwData2 = dwData2;
        SendMessage(hParent, WM_NOTIFY, (WPARAM)iii_nmhdr.nmhdr.idFrom, (LPARAM)&iii_nmhdr);
    }
}
////////////////////////////////
// æ‹¦æˆªçª—口消息函数
LRESULT CALLBACK CVerticalLine::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CVerticalLine* pVerticalLine = (CVerticalLine *)GetProp(hWnd, BYSTAG_VERTICALLINE);
    if(pVerticalLine == NULL && uMsg != WM_NCCREATE)
    {
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    // å¦‚æžœHook则响应消息
    ASSERT(hWnd);
    switch(uMsg)
    {
    case WM_NCCREATE:
        return OnNcCreate(hWnd, wParam, lParam);
    case WM_DESTROY:
        return pVerticalLine->OnDestroy(wParam, lParam);
    case WM_PAINT:
        return pVerticalLine->OnPaint(wParam, lParam);
    case WM_TIMER:
        return pVerticalLine->OnTimer(wParam, lParam);
    case WM_SETCURSOR:
        return pVerticalLine->OnSetCursor(wParam, lParam);
    case WM_LBUTTONDOWN:
        return pVerticalLine->OnLButtonDown(wParam, lParam);
    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS;
    default:
        break;
    }
    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
///////////////////////////////
// WM_NCCREATE
// çª—口创建前的初始化工作
LRESULT CVerticalLine::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    CVerticalLine* pVerticalLine = (CVerticalLine *)GetProp(hWnd, BYSTAG_VERTICALLINE);
    ASSERT(pVerticalLine == NULL);
    Hook(hWnd);
    return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
}
///////////////////////////////
// WM_DESTROY
LRESULT CVerticalLine::OnDestroy(WPARAM wParam, LPARAM lParam)
{
    Release();
    return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
}
///////////////////////////////
// WM_TIMER
LRESULT CVerticalLine::OnTimer(WPARAM wParam, LPARAM lParam)
{
    return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
}
///////////////////////////////
// WM_SETCURSOR
LRESULT CVerticalLine::OnSetCursor(WPARAM wParam, LPARAM lParam)
{
    if(m_bEnableResize) {
        SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
        return TRUE;
    }
    return ::DefWindowProc(m_hWnd, WM_SETCURSOR, wParam, lParam);
}
/*
 * WM_LBUTTONDOWN
 * é¼ æ ‡å·¦é”®æŒ‰ä¸‹
 */
LRESULT CVerticalLine::OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
    if (!m_bEnableResize) {
        return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
    }
    POINT pt, ptNew;
    pt.x = LOWORD(lParam);
    pt.y = HIWORD(lParam);
    int nMoveX = 0;
    // æ•捉鼠标消息,检测是否拖动
    RECT rcParent, rcWindows;
    GetClientRect(m_hWnd, &rcWindows);
    ::ClientToScreen(m_hWnd, (LPPOINT)&rcWindows);
    ::ClientToScreen(m_hWnd, (LPPOINT)&rcWindows.right);
    GetClientRect(GetParent(m_hWnd), &rcParent);
    ::ClientToScreen(GetParent(m_hWnd), (LPPOINT)&rcParent);
    HDC hDC = GetDC(GetDesktopWindow());
    ::DrawFocusRect(hDC, &rcWindows);
    if (::GetCapture() == NULL) {
        SetCapture(m_hWnd);
        ASSERT(m_hWnd == GetCapture());
        AfxLockTempMaps();
        for (;;) {
            MSG msg;
            VERIFY(::GetMessage(&msg, NULL, 0, 0));
            if (GetCapture() != m_hWnd) break;
            switch (msg.message)
            {
            case WM_MOUSEMOVE:
                ptNew = msg.pt;
                if (ptNew.x < rcParent.left) ptNew.x = rcParent.left;
                ::DrawFocusRect(hDC, &rcWindows);
                rcWindows.left = ptNew.x - 3;
                rcWindows.right = ptNew.x + 3;
                ::DrawFocusRect(hDC, &rcWindows);
                ::ScreenToClient(m_hWnd, &ptNew);
                break;
            case WM_LBUTTONUP:
                ptNew = msg.pt;
                ::ScreenToClient(m_hWnd, &ptNew);
                nMoveX = ptNew.x - pt.x;
                goto ExitLoop;
            case WM_KEYDOWN:
                if (msg.wParam == VK_ESCAPE) {
                    goto ExitLoop;
                }
                break;
            default:
                DispatchMessage(&msg);
                break;
            }
        }
    ExitLoop:
        ::DrawFocusRect(hDC, &rcWindows);
        ReleaseDC(GetDesktopWindow(), hDC);
        ReleaseCapture();
        ::InvalidateRect(m_hWnd, NULL, TRUE);
        Notify((int)BYVERTICALLINE_MOVEX, nMoveX);
        AfxUnlockTempMaps(FALSE);
    }
    return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
}
///////////////////////////////
// WM_PAINT
LRESULT CVerticalLine::OnPaint(WPARAM wParam, LPARAM lParam)
{
    HDC hDC, hMemDC;
    HBITMAP hBitmap;
    RECT rcClient;
    CString strText;
    HFONT hFont;
    HBRUSH hBrushBK;
    // BeginPaint
    PAINTSTRUCT ps;
    hDC = BeginPaint(m_hWnd, &ps);
    GetClientRect(m_hWnd, &rcClient);
    hMemDC = ::CreateCompatibleDC(hDC);
    hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right-rcClient.left,
        rcClient.bottom-rcClient.top);
    ::SelectObject(hMemDC, hBitmap);
    hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    ::SelectObject(hMemDC, hFont);
    // èƒŒæ™¯é¢œè‰²
    hBrushBK = CreateSolidBrush( m_crBkgnd );
    ::FillRect(hMemDC, &rcClient, hBrushBK);
    DeleteObject(hBrushBK);
    // ç”»çº¿
    HPEN hPen = CreatePen(PS_SOLID, 1, m_crLineColor);
    HPEN hOldPen = (HPEN)::SelectObject(hMemDC, hPen);
    ::MoveToEx(hMemDC, rcClient.right-1, 0, NULL);
    LineTo(hMemDC, rcClient.right - 1, rcClient.bottom);
    ::SelectObject(hMemDC, hOldPen);
    // EndPaint
    ::BitBlt(hDC, 0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
        hMemDC, 0, 0, SRCCOPY);
    EndPaint(m_hWnd, &ps);
    ::DeleteObject(hBitmap);
    ::DeleteDC(hMemDC);
    return 1;
}
void CVerticalLine::SetBkgndColor(COLORREF cr)
{
    m_crBkgnd = cr;
}
void CVerticalLine::EnableResize()
{
    m_bEnableResize = TRUE;
}
void CVerticalLine::DisableResize()
{
    m_bEnableResize = FALSE;
}
SourceCode/Bond/BoounionPLC/VerticalLine.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
// VerticalLine.h: interface for the CVerticalLine class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_VERTICALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)
#define AFX_VERTICALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_
#pragma comment(lib, "Msimg32.lib")            // TransparentBlt
//====== VerticalLine =====================================================
#ifndef NOVERTICALLINE
#ifdef _WIN32
#define BYVERTICALLINE_CLASSA       "BYVerticalLine"
#define BYVERTICALLINE_CLASSW       L"BYVerticalLine"
#ifdef UNICODE
#define  BYVERTICALLINE_CLASS       BYVERTICALLINE_CLASSW
#else
#define  BYVERTICALLINE_CLASS       BYVERTICALLINE_CLASSA
#endif
#else
#define BYVERTICALLINE_CLASS        "BYVerticalLine"
#endif
#define BYSTAG_VERTICALLINE         _T("ISVERTICALLINE")
//====== WM_NOTIFY codes (NMHDR.code values) ==================================
#define BYVERTICALLINE_FIRST             (0U-2330U)       //
#define BYVERTICALLINE_LAST                 (0U-2320U)
#define BYVERTICALLINE_MOVEX              (BYVERTICALLINE_FIRST - 1)
typedef struct tagBYVERTICALLINE_NMHDR
{
    NMHDR        nmhdr;
    DWORD        dwData;
    DWORD        dwData1;
    DWORD        dwData2;
} BYVERTICALLINE_NMHDR;
#endif
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CVerticalLine
{
public:
    CVerticalLine();
    virtual ~CVerticalLine();
public:
    void EnableResize();
    void DisableResize();
    static BOOL RegisterWndClass();
    static CVerticalLine* Hook(HWND hWnd);
    void Notify(int nCode, int dwData, int dwData1 = 0, int dwData2 = 0);
    void Release();
    void SetBkgndColor(COLORREF cr);
    static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    static LRESULT OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
    LRESULT OnDestroy(WPARAM wParam, LPARAM lParam);
    LRESULT OnTimer(WPARAM wParam, LPARAM lParam);
    LRESULT OnSetCursor(WPARAM wParam, LPARAM lParam);
    LRESULT OnPaint(WPARAM wParam, LPARAM lParam);
    LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam);
private:
    HWND        m_hWnd;
    COLORREF m_crBkgnd;
    COLORREF m_crLineColor;
private:
    BOOL m_bEnableResize;
};
#endif // !defined(AFX_VERTICALLINE_H__FBB8916A_DE77_4EA3_9C21_E51E6B06194C__INCLUDED_)