LAPTOP-SNT8I5JK\Boounion
2025-03-03 bf55b2f3083cbfdeb83611b2fa2dd552bf5b0775
1.开始处理Step属性值;
2.增加左侧master面板;
已添加16个文件
已修改22个文件
2332 ■■■■■ 文件已修改
SourceCode/Bond/Servo/AlarmDlg.cpp 415 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/AlarmDlg.h 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ApredTreeCtrl2.cpp 379 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ApredTreeCtrl2.h 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CAttribute.cpp 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CAttribute.h 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CAttributeVector.cpp 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CAttributeVector.h 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqAlarmStep.cpp 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqAlarmStep.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqModeStep.cpp 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqModeStep.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqProcessStep.cpp 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqProcessStep.h 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqStatusStep.cpp 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqStatusStep.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.cpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPanelMaster.cpp 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPanelMaster.h 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CStep.cpp 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CStep.h 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Common.h 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HorizontalLine.cpp 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HorizontalLine.h 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.cpp 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.filters 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.cpp 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.h 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoGraph.cpp 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoGraph.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/VerticalLine.cpp 316 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/VerticalLine.h 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/AlarmDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,415 @@
// AlarmDlg.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "Servo.h"
#include "afxdialogex.h"
#include "AlarmDlg.h"
#include "AlarmManager.h"
#include "Common.h"
#define PAGE_SIZE                        10
#define PAGE_BACKGROUND_COLOR            RGB(252, 252, 255)
// CAlarmDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CAlarmDlg, CDialogEx)
CAlarmDlg::CAlarmDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_ALARM, pParent)
{
    m_crBkgnd = PAGE_BACKGROUND_COLOR;
    m_hbrBkgnd = nullptr;
    m_pObserver = nullptr;
    m_strEqName = "";
    m_strKeyword = "";
    m_nCurPage = 0;
    m_nTotalPages = 0;
    m_nDateTimeFlag = 0;
    memset(m_szTimeStart, 0, sizeof(m_szTimeStart));
    memset(m_szTimeEnd, 0, sizeof(m_szTimeEnd));
    m_szTimeStart[0] = '\0';
    m_szTimeEnd[0] = '\0';
}
CAlarmDlg::~CAlarmDlg()
{
}
void CAlarmDlg::InitRxWindow()
{
    /* code */
    // è®¢é˜…数据
    IRxWindows* pRxWindows = RX_GetRxWindows();
    pRxWindows->enableLog(5);
    if (m_pObserver == NULL) {
        m_pObserver = pRxWindows->allocObserver([&](IAny* pAny) -> void {
            // onNext
            pAny->addRef();
            int code = pAny->getCode();
            if (RX_CODE_STEP_EVENT_READDATA == code) {
                LOGI("<CAlarmDlg> Accept RX_CODE_STEP_EVENT_READDATA successfully!");
                // é€šçŸ¥è®¾å¤‡çŠ¶æ€
                SERVO::CEqAlarmStep* pStep = nullptr;
                if (pAny->getPtrValue("ptr", (void*&)pStep)) {
                    if (pStep != nullptr) {
                        // èŽ·å– AlarmManager å•例
                        AlarmManager& alarmManager = AlarmManager::getInstance();
                        // ä»Ž pStep èŽ·å–éœ€è¦çš„å‚æ•°ï¼Œå‡è®¾è¿™äº›å€¼æ˜¯ä»Ž pStep ä¸­èŽ·å–çš„
                        std::string id = std::to_string(pStep->getAlarmId());
                        std::string deviceName = std::to_string(pStep->getUnitId());
                        std::string description = "pStep->getText()";
                        std::string startTime = "2025-02-25 10:00";
                        std::string endTime = "2025-02-25 12:00";
                        // æ’入列表控件
                        CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM);
                        if (pListCtrl != nullptr) {
                            InsertAlarmData(pListCtrl, id.c_str(), deviceName.c_str(), description.c_str(), startTime.c_str(), endTime.c_str());
                        }
                    }
                }
            }
        pAny->release();
        }, [&]() -> void {
            // onComplete
        }, [&](IThrowable* pThrowable) -> void {
            // onErrorm
            pThrowable->printf();
        });
        theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
            ->subscribe(m_pObserver);
    }
}
void CAlarmDlg::Resize()
{
    CWnd* pItem;
    CRect rcClient;
    GetClientRect(&rcClient);
    pItem = GetDlgItem(IDC_LIST_ALARM);
    pItem->MoveWindow(12, 52, rcClient.Width() - 24, rcClient.Height() - 64);
}
void CAlarmDlg::LoadAlarms()
{
    // åˆ·æ–°åŽ†å²æŠ¥è­¦æ•°æ®
    m_nCurPage = 1;
    UpdatePageData();
}
void CAlarmDlg::UpdatePageData()
{
    // æ ¹æ®è¿‡æ»¤æ¡ä»¶åŠ è½½æ•°æ®ï¼Œæä¾›æè¿°å’Œæ—¶é—´èŒƒå›´æŸ¥è¯¢
    auto vecData = AlarmManager::getInstance().getFilteredAlarms("", m_strEqName, m_strKeyword, m_szTimeStart, m_szTimeEnd, m_nCurPage, PAGE_SIZE);
    // å¡«å……数据到控件
    CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM);
    FillDataToListCtrl(pListCtrl, vecData);
    // æ›´æ–°åˆ†é¡µæŽ§ä»¶ï¼ˆé¡µæ•°å’ŒæŒ‰é’®ï¼‰
    UpdatePageControls();
}
void CAlarmDlg::UpdatePageControls()
{
    // æ›´æ–°åˆ†é¡µä¿¡æ¯
    CString strPage;
    strPage.Format(_T("第 %d é¡µ"), m_nCurPage);
    SetDlgItemText(IDC_LABEL_PAGE_NUMBER, strPage);
    // å¯ç”¨/禁用翻页按钮
    GetDlgItem(IDC_BUTTON_PREV_PAGE)->EnableWindow(m_nCurPage > 1);
    GetDlgItem(IDC_BUTTON_NEXT_PAGE)->EnableWindow(m_nCurPage < m_nTotalPages);
}
void CAlarmDlg::FillDataToListCtrl(CListCtrl* pListCtrl, const std::vector<std::vector<std::string>>& vecData)
{
    // æ¸…空当前CListCtrl中的所有项
    pListCtrl->DeleteAllItems();
    // éåŽ†æ•°æ®å¹¶æ’å…¥åˆ°CListCtrl中
    for (const auto& item : vecData) {
        int nItem = pListCtrl->InsertItem(pListCtrl->GetItemCount(), _T(""));    // æ’入新行
        pListCtrl->SetItemText(nItem, 1, item[0].c_str());                        // è®¾ç½®ç¬¬ä¸€åˆ—的文本(ID)
        pListCtrl->SetItemText(nItem, 2, item[1].c_str());                        // è®¾ç½®ç¬¬äºŒåˆ—的文本(设备名称)
        pListCtrl->SetItemText(nItem, 3, item[2].c_str());                        // è®¾ç½®ç¬¬ä¸‰åˆ—的文本(描述)
        pListCtrl->SetItemText(nItem, 4, item[3].c_str());                        // è®¾ç½®ç¬¬å››åˆ—的文本(开始时间)
        pListCtrl->SetItemText(nItem, 5, item[4].c_str());                        // è®¾ç½®ç¬¬å››åˆ—的文本(解除时间)
    }
}
void CAlarmDlg::InsertAlarmData(CListCtrl* pListCtrl, const CString& alarmId, const CString& deviceName, const CString& description, const CString& startTime, const CString& endTime)
{
    int nRowCount = pListCtrl->GetItemCount();
    if (nRowCount >= PAGE_SIZE) {
        pListCtrl->DeleteItem(nRowCount - 1);
    }
    int nNewItem = pListCtrl->InsertItem(0, _T(""));
    pListCtrl->SetItemText(nNewItem, 1, alarmId);       // è­¦å‘ŠID
    pListCtrl->SetItemText(nNewItem, 2, deviceName);    // è®¾å¤‡åç§°
    pListCtrl->SetItemText(nNewItem, 3, description);   // æè¿°
    pListCtrl->SetItemText(nNewItem, 4, startTime);     // å‘生时间
    pListCtrl->SetItemText(nNewItem, 5, endTime);       // è§£é™¤æ—¶é—´
}
void CAlarmDlg::DoDataExchange(CDataExchange* pDX)
{
    DDX_Control(pDX, IDC_DATETIMEPICKER_START, m_dateTimeStart);
    DDX_Control(pDX, IDC_DATETIMEPICKER_END, m_dateTimeEnd);
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAlarmDlg, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_CBN_SELCHANGE(IDC_COMBO_DATETIME, &CAlarmDlg::OnCbnSelchangeComboDatetime)
    ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CAlarmDlg::OnBnClickedButtonSearch)
    ON_BN_CLICKED(IDC_BUTTON_EXPORT, &CAlarmDlg::OnBnClickedButtonExport)
    ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CAlarmDlg::OnBnClickedButtonPrevPage)
    ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CAlarmDlg::OnBnClickedButtonNextPage)
END_MESSAGE_MAP()
// CAlarmDlg æ¶ˆæ¯å¤„理程序
BOOL CAlarmDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    InitRxWindow();
    // ä¸‹æ‹‰æ¡†æŽ§ä»¶
    CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
    pComboBox->AddString(_T("不限"));
    pComboBox->AddString(_T("今天"));
    pComboBox->AddString(_T("七天内"));
    pComboBox->AddString(_T("本月"));
    pComboBox->AddString(_T("今年"));
    pComboBox->AddString(_T("自定义"));
    pComboBox->SetCurSel(0);
    // æ—¥æœŸæŽ§ä»¶
    m_dateTimeStart.EnableWindow(FALSE);
    m_dateTimeEnd.EnableWindow(FALSE);
    // æŠ¥è¡¨æŽ§ä»¶
    CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM);
    DWORD dwStyle = pListCtrl->GetExtendedStyle();
    dwStyle |= LVS_EX_FULLROWSELECT;
    dwStyle |= LVS_EX_GRIDLINES;
    pListCtrl->SetExtendedStyle(dwStyle);
    HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1);
    ListView_SetImageList(pListCtrl->GetSafeHwnd(), imageList, LVSIL_SMALL);
    pListCtrl->InsertColumn(0, _T(""), LVCFMT_RIGHT, 0);
    pListCtrl->InsertColumn(1, _T("警告ID"), LVCFMT_LEFT, 50);
    pListCtrl->InsertColumn(2, _T("设备名称"), LVCFMT_LEFT, 120);
    pListCtrl->InsertColumn(3, _T("描述"), LVCFMT_LEFT, 280);
    pListCtrl->InsertColumn(4, _T("发生时间"), LVCFMT_LEFT, 180);
    pListCtrl->InsertColumn(5, _T("解除时间"), LVCFMT_LEFT, 180);
    // è®¡ç®—总页数
    int totalRecords = AlarmManager::getInstance().getTotalAlarmCount("", m_strEqName, m_strKeyword, m_szTimeStart, m_szTimeEnd);
    m_nTotalPages = (totalRecords + PAGE_SIZE - 1) / PAGE_SIZE;
    m_nCurPage = 1;
    Resize();
    LoadAlarms();
    return TRUE;  // return TRUE unless you set the focus to a control
    // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
BOOL CAlarmDlg::DestroyWindow()
{
    return CDialogEx::DestroyWindow();
}
HBRUSH CAlarmDlg::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 CAlarmDlg::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
    if (m_pObserver != NULL) {
        m_pObserver->unsubscribe();
        m_pObserver = NULL;
    }
}
void CAlarmDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (GetDlgItem(IDC_LIST_ALARM) == nullptr) return;
    Resize();
}
void CAlarmDlg::OnCbnSelchangeComboDatetime()
{
    CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
    int nIndex = pComboBox->GetCurSel();
    int nCount = pComboBox->GetCount();
    m_dateTimeStart.EnableWindow(nIndex == nCount - 1);
    m_dateTimeEnd.EnableWindow(nIndex == nCount - 1);
}
void CAlarmDlg::OnBnClickedButtonSearch()
{
    // èŽ·å–å…³é”®å­—
    CString cstrKeyword;
    GetDlgItemText(IDC_EDIT_KEYWORD, cstrKeyword);
    m_strKeyword = CT2A(cstrKeyword);
    // èŽ·å–æ—¥æœŸ
    CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
    m_nDateTimeFlag = pComboBox->GetCurSel();
    if (m_nDateTimeFlag == 0) {
        memset(m_szTimeStart, 0, sizeof(m_szTimeStart));
        memset(m_szTimeEnd, 0, sizeof(m_szTimeEnd));
        m_szTimeStart[0] = '\0';
        m_szTimeEnd[0] = '\0';
    }
    else {
        CTime time = CTime::GetCurrentTime();
        if (m_nDateTimeFlag == 1) {
            // ä»Šå¤©
            sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", time.GetYear(), time.GetMonth(), time.GetDay());
            sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
        }
        else if (m_nDateTimeFlag == 2) {
            // 7天内
            CTime time2 = time - CTimeSpan(7, 0, 0, 0);
            sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", time2.GetYear(), time2.GetMonth(), time2.GetDay());
            sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
        }
        else if (m_nDateTimeFlag == 3) {
            // æœ¬æœˆ
            sprintf_s(m_szTimeStart, 64, "%d-%02d-01 00:00:00", time.GetYear(), time.GetMonth());
            sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
        }
        else if (m_nDateTimeFlag == 4) {
            // ä»Šå¹´
            sprintf_s(m_szTimeStart, 64, "%d-01-01 00:00:00", time.GetYear());
            sprintf_s(m_szTimeEnd, 64, "%d-12-31 23:59:59", time.GetYear());
        }
        else if (m_nDateTimeFlag == 5) {
            // è‡ªå®šä¹‰
            SYSTEMTIME t1, t2;
            m_dateTimeStart.GetTime(&t1);
            m_dateTimeEnd.GetTime(&t2);
            sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d %02d:%02d:%02d",
                t1.wYear, t1.wMonth, t1.wDay, t1.wHour, t1.wMinute, t1.wSecond);
            sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d %02d:%02d:%02d",
                t2.wYear, t2.wMonth, t2.wDay, t2.wHour, t2.wMinute, t2.wSecond);
        }
    }
    // è®¡ç®—总页数
    int totalRecords = AlarmManager::getInstance().getTotalAlarmCount("", m_strEqName, m_strKeyword, m_szTimeStart, m_szTimeEnd);
    m_nTotalPages = (totalRecords + PAGE_SIZE - 1) / PAGE_SIZE;
    m_nCurPage = 1;
    UpdatePageData();  // è°ƒç”¨åˆ†é¡µæ›´æ–°å‡½æ•°
}
void CAlarmDlg::OnBnClickedButtonExport()
{
    CFileDialog fileDialog(FALSE, "csv", "", OFN_HIDEREADONLY, "csv.files(*.csv)|*.csv||");
    if (fileDialog.DoModal() != IDOK) {
        return;
    }
    CStdioFile file;
    if (!file.Open(fileDialog.GetPathName(), CFile::modeCreate | CFile::modeWrite)) {
        AfxMessageBox("创建文件失败!");
    }
    int nSubItemCount = 0;
    CString strSubItem, strHeader, strRow;
    char szItem[256];
    HDITEM hdItem[35];
    for (int i = 0; i < 35; i++) {
        hdItem[i].pszText = szItem;
        hdItem[i].cchTextMax = 256;
        hdItem[i].mask = HDI_TEXT | HDI_WIDTH;
    }
    // å…ˆè¯»è¡¨å¤´
    CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM);
    CHeaderCtrl* pHeader = pListCtrl->GetHeaderCtrl();
    nSubItemCount = pHeader->GetItemCount();
    ASSERT(nSubItemCount <= 35);
    for (int i = 0; i < pHeader->GetItemCount(); i++) {
        pHeader->GetItem(i, &hdItem[i]);
        if (hdItem[i].cxy > 0) {
            if (!strHeader.IsEmpty()) {
                strHeader.Append(",");
            }
            strHeader.Append(CString(hdItem[i].pszText));
        }
    }
    strHeader.Append("\n");
    file.WriteString(strHeader);
    // å†™è¡¨æ ¼å†…容
    int count = pListCtrl->GetItemCount();
    for (int i = 0; i < count; i++) {
        strRow.Empty();
        for (int j = 0; j < nSubItemCount; j++) {
            if (hdItem[j].cxy > 0) {
                if (!strRow.IsEmpty()) {
                    strRow.Append(",");
                }
                CString strTemp = pListCtrl->GetItemText(i, j);
                strTemp.Replace("* ", "");
                strRow.Append(strTemp);
            }
        }
        strRow.Append("\n");
        file.WriteString(strRow);
    }
    file.Close();
}
void CAlarmDlg::OnBnClickedButtonPrevPage()
{
    // ç‚¹å‡»ä¸Šä¸€é¡µ
    m_nCurPage--;
    UpdatePageData();  // è°ƒç”¨åˆ†é¡µæ›´æ–°å‡½æ•°
}
void CAlarmDlg::OnBnClickedButtonNextPage()
{
    // ç‚¹å‡»ä¸‹ä¸€é¡µ
    m_nCurPage++;
    UpdatePageData();  // è°ƒç”¨åˆ†é¡µæ›´æ–°å‡½æ•°
}
SourceCode/Bond/Servo/AlarmDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,65 @@
#pragma once
#include "afxdialogex.h"
#include <vector>
#include <string>
// CAlarmDlg å¯¹è¯æ¡†
class CAlarmDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CAlarmDlg)
public:
    CAlarmDlg(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CAlarmDlg();
private:
    void InitRxWindow();
    void Resize();
    void LoadAlarms();
    void UpdatePageData();
    void UpdatePageControls();
    void FillDataToListCtrl(CListCtrl* pListCtrl, const std::vector<std::vector<std::string>>& vecData);
    void InsertAlarmData(CListCtrl* pListCtrl, const CString& alarmId, const CString& deviceName, const CString& description, const CString& startTime, const CString& endTime);
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    IObserver* m_pObserver;
    // å…³é”®å­—
    std::string m_strEqName;
    std::string m_strKeyword;
    // é¡µç 
    int m_nCurPage;
    int m_nTotalPages;
    // æ—¥æœŸ
    int m_nDateTimeFlag;
    char m_szTimeStart[64];
    char m_szTimeEnd[64];
    // æŽ§ä»¶
    CDateTimeCtrl m_dateTimeStart;
    CDateTimeCtrl m_dateTimeEnd;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_ALARM };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    virtual BOOL OnInitDialog();
    virtual BOOL DestroyWindow();
    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 OnCbnSelchangeComboDatetime();
    afx_msg void OnBnClickedButtonSearch();
    afx_msg void OnBnClickedButtonExport();
    afx_msg void OnBnClickedButtonPrevPage();
    afx_msg void OnBnClickedButtonNextPage();
    DECLARE_MESSAGE_MAP()
};
SourceCode/Bond/Servo/ApredTreeCtrl2.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,379 @@
#include "stdafx.h"
#include "ApredTreeCtrl2.h"
#define ROFFSET 7
#define WIDE    10
#define WIDE2    5
#define EXPANDED_WIDE    8
#define BADGE_HIDE                  0
#define BADGE_DOT                   1
#define BADGE_NUMBER                2
#define BADGE_DOT_WIDTH             12
#define BADGE_NUMBER_WIDTH          20
IMPLEMENT_DYNAMIC(CApredTreeCtrl2, CTreeCtrl)
CApredTreeCtrl2::CApredTreeCtrl2()
{
    m_hBrushItem[0] = NULL;
    m_hBrushItem[1] = NULL;
    m_hBrushItem[2] = NULL;
    m_crItemBk[0] = GetSysColor(COLOR_WINDOW);
    m_crItemBk[1] = GetSysColor(COLOR_HIGHLIGHT);
    m_crItemBk[2] = RGB(204, 206, 219);
    m_crItemBtn[0] = RGB(30, 30, 30);
    m_crItemBtn[1] = RGB(255, 255, 255);
    m_crItemBtn[2] = RGB(255, 255, 255);
}
CApredTreeCtrl2::~CApredTreeCtrl2()
{
    if (m_hBrushItem[0] != NULL) {
        ::DeleteObject(m_hBrushItem[0]);
    }
    if (m_hBrushItem[1] != NULL) {
        ::DeleteObject(m_hBrushItem[1]);
    }
    if (m_hBrushItem[2] != NULL) {
        ::DeleteObject(m_hBrushItem[2]);
    }
}
BEGIN_MESSAGE_MAP(CApredTreeCtrl2, CTreeCtrl)
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CApredTreeCtrl2::OnNMCustomdraw)
END_MESSAGE_MAP()
void CApredTreeCtrl2::OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
    LPNMTVCUSTOMDRAW lpnmcd = (LPNMTVCUSTOMDRAW)pNMCD;
    HTREEITEM hItem;
    UINT unt;
    *pResult = 0;
    switch (lpnmcd->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT:
        *pResult = CDRF_NOTIFYITEMDRAW;
        m_items.clear();
        break;
    case CDDS_ITEMPREPAINT:
        m_items[(HTREEITEM)lpnmcd->nmcd.dwItemSpec] = lpnmcd->iLevel;
        hItem = (HTREEITEM)lpnmcd->nmcd.dwItemSpec;
        if (hItem != NULL) {
            if ( (GetItemState(hItem, TVIS_SELECTED) & TVIS_SELECTED)== TVIS_SELECTED) {
                if (GetFocus() != this) {
                    lpnmcd->clrTextBk = RGB(204, 206, 219);
                }
            }
        }
        *pResult = CDRF_NEWFONT | CDRF_NOTIFYPOSTPAINT;   // è®¢é˜…绘制结束通知
        break;
    case CDDS_ITEMPOSTPAINT: // é¡¹ç»˜åˆ¶ç»“束通知
        unt = GetIndent();
        hItem = (HTREEITEM)lpnmcd->nmcd.dwItemSpec;
        auto iter = m_items.find(hItem);
        if (iter != m_items.end()) {
            CRect button_rect = pNMCD->rc;
            button_rect.right = button_rect.left + unt + 5;
            int off = unt * iter->second;
            button_rect.OffsetRect(off, 0);
            DrawItemButton(hItem, pNMCD->hdc, &button_rect);
            // æ˜¯å¦æœ‰å°åœ†ç‚¹
            CRect rcItem = pNMCD->rc;
            Gdiplus::Graphics graphics(pNMCD->hdc);
            graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
            if (m_badges.find(hItem) != m_badges.end()) {
                BADGE& badge = m_badges[hItem];
                if (badge.type == BADGE_DOT) {
                    Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(badge.badgeBackground), GetGValue(badge.badgeBackground), GetBValue(badge.badgeBackground)));
                    int x = rcItem.right - 18 - BADGE_DOT_WIDTH;
                    int y = rcItem.top + (rcItem.Height() - BADGE_DOT_WIDTH) / 2;
                    graphics.FillEllipse(&brush, x, y, BADGE_DOT_WIDTH, BADGE_DOT_WIDTH);
                }
                else if (badge.type == BADGE_NUMBER) {
                    Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(badge.badgeBackground), GetGValue(badge.badgeBackground), GetBValue(badge.badgeBackground)));
                    int x = rcItem.right - 18 - BADGE_NUMBER_WIDTH;
                    int y = rcItem.top + (rcItem.Height() - BADGE_NUMBER_WIDTH) / 2;
                    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(pNMCD->hdc, badge.badgeForeground);
                    char szBuffer[32];
                    sprintf_s(szBuffer, 32, "%d%s", min(badge.number, 9), badge.number > 9 ? "+" : "");
                    DrawText(pNMCD->hdc, szBuffer, (int)strlen(szBuffer), &rcBadge, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
                }
            }
            *pResult = CDRF_SKIPDEFAULT;
        }
        break;
    }
}
void CApredTreeCtrl2::DrawItemButton(HTREEITEM hItem, HDC hDC, CRect* pRect)
{
    if (!ItemHasChildren(hItem)) {
        return;
    }
    // æŒ‰é’®è¦åˆ·ä¸€ä¸‹
    ::FillRect(hDC, pRect, GetItemBkBrush(hItem));
    if ((GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED) == TVIS_EXPANDED) {
        int nBottomOffset = (pRect->Height() - EXPANDED_WIDE) / 2;
        POINT pt[3];
        pt[0].x = pRect->right - ROFFSET - EXPANDED_WIDE;
        pt[0].y = pRect->bottom - nBottomOffset;
        pt[1].x = pRect->right - ROFFSET;
        pt[1].y = pRect->bottom - nBottomOffset;
        pt[2].x = pRect->right - ROFFSET;
        pt[2].y = pRect->bottom - nBottomOffset - EXPANDED_WIDE;
        HBRUSH hBrush = GetItemBtnBrush(hItem);
        HPEN hPen = GetItemBtnPen(hItem);
        HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC, hBrush);
        HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
        ::Polygon(hDC, pt, 3);
        ::SelectObject(hDC, hOldBrush);
        ::SelectObject(hDC, hOldPen);
        ::DeleteObject(hBrush);
        ::DeleteObject(hPen);
    }
    else {
        int nBottomOffset = (pRect->Height() - WIDE) / 2;
        POINT pt[3];
        pt[0].x = pRect->right - ROFFSET - WIDE2;
        pt[0].y = pRect->bottom - nBottomOffset - WIDE;
        pt[1].x = pRect->right - ROFFSET - WIDE2;
        pt[1].y = pRect->bottom - nBottomOffset;
        pt[2].x = pRect->right - ROFFSET;
        pt[2].y = pRect->bottom - nBottomOffset - WIDE2;
        HBRUSH hBrush = GetItemBtnBrush(hItem);
        HPEN hPen = GetItemBtnPen(hItem);
        HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC, hBrush);
        HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
        ::Polygon(hDC, pt, 3);
        ::SelectObject(hDC, hOldBrush);
        ::SelectObject(hDC, hOldPen);
        ::DeleteObject(hBrush);
        ::DeleteObject(hPen);
    }
}
COLORREF CApredTreeCtrl2::SetBkColor(COLORREF crColor)
{
    if (m_hBrushItem[0] != NULL) {
        ::DeleteObject(m_hBrushItem[0]);
    }
    m_hBrushItem[0] = CreateSolidBrush(crColor);
    return CTreeCtrl::SetBkColor(crColor);
}
int CApredTreeCtrl2::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CTreeCtrl::OnCreate(lpCreateStruct) == -1)
        return -1;
    m_crItemBk[0] = GetBkColor();
    m_crItemBk[1] = GetSysColor(COLOR_HIGHLIGHT);
    m_hBrushItem[0] = CreateSolidBrush(m_crItemBk[0]);
    m_hBrushItem[1] = CreateSolidBrush(m_crItemBk[1]);
    m_hBrushItem[2] = CreateSolidBrush(m_crItemBk[2]);
    return 0;
}
HBRUSH CApredTreeCtrl2::GetItemBkBrush(HTREEITEM hItem)
{
    BOOL bSelected = (GetItemState(hItem, TVIS_SELECTED) & TVIS_SELECTED) == TVIS_SELECTED;
    BOOL bHilited = (GetItemState(hItem, TVIS_DROPHILITED) & TVIS_DROPHILITED) == TVIS_DROPHILITED;;
    HTREEITEM hClickedItem = GetDropHilightItem();
    if (bHilited) {
        return m_hBrushItem[1];
    }
    if (!bSelected) {
        return m_hBrushItem[0];
    }
    if (GetFocus() == this) {
        if (hClickedItem == NULL) {
            return m_hBrushItem[1];
        }
        else {
            return m_hBrushItem[0];
        }
    }
    return m_hBrushItem[2];
}
HBRUSH CApredTreeCtrl2::GetItemBtnBrush(HTREEITEM hItem)
{
    BOOL bExpanded = (GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED) == TVIS_EXPANDED;
    BOOL bSelected = (GetItemState(hItem, TVIS_SELECTED) & TVIS_SELECTED) == TVIS_SELECTED;
    BOOL bHilited = (GetItemState(hItem, TVIS_DROPHILITED) & TVIS_DROPHILITED) == TVIS_DROPHILITED;;
    HTREEITEM hClickedItem = GetDropHilightItem();
    // å±•开时实心三角
    if (bExpanded) {
        if (bHilited) {
            return CreateSolidBrush(m_crItemBtn[1]);
        }
        if (!bSelected) {
            return CreateSolidBrush(m_crItemBtn[0]);
        }
        if (GetFocus() == this && hClickedItem == NULL) {
            return CreateSolidBrush(m_crItemBtn[1]);
        }
        return CreateSolidBrush(m_crItemBtn[0]);
    }
    else {
        // æ”¶èµ·æ—¶ç©ºå¿ƒä¸‰è§’
        if (bHilited) {
            return CreateSolidBrush(m_crItemBk[1]);
        }
        if (!bSelected) {
            return CreateSolidBrush(m_crItemBk[0]);
        }
        if (GetFocus() == this && hClickedItem == NULL) {
            return CreateSolidBrush(m_crItemBk[1]);
        }
        return CreateSolidBrush(m_crItemBk[2]);
    }
}
HPEN CApredTreeCtrl2::GetItemBtnPen(HTREEITEM hItem)
{
    BOOL bExpanded = (GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED) == TVIS_EXPANDED;
    BOOL bSelected = (GetItemState(hItem, TVIS_SELECTED) & TVIS_SELECTED) == TVIS_SELECTED;
    BOOL bHilited = (GetItemState(hItem, TVIS_DROPHILITED) & TVIS_DROPHILITED) == TVIS_DROPHILITED;;
    HTREEITEM hClickedItem = GetDropHilightItem();
    // å±•开时实心三角
    if (bExpanded) {
        if (bHilited) {
            return CreatePen(PS_SOLID, 1, m_crItemBtn[1]);
        }
        if (!bSelected) {
            return CreatePen(PS_SOLID, 1, m_crItemBtn[0]);
        }
        if (GetFocus() == this && hClickedItem == NULL) {
            return CreatePen(PS_SOLID, 1, m_crItemBtn[1]);
        }
        return CreatePen(PS_SOLID, 1, m_crItemBtn[0]);
    }
    else {
        // æ”¶èµ·æ—¶ç©ºå¿ƒä¸‰è§’
        if (bHilited) {
            return CreatePen(PS_SOLID, 1, m_crItemBtn[1]);
        }
        if (!bSelected) {
            return CreatePen(PS_SOLID, 1, m_crItemBtn[0]);
        }
        if (GetFocus() == this && hClickedItem == NULL) {
            return CreatePen(PS_SOLID, 1, m_crItemBtn[1]);
        }
        return CreatePen(PS_SOLID, 1, m_crItemBtn[0]);
    }
}
void CApredTreeCtrl2::PreSubclassWindow()
{
    m_crItemBk[0] = GetBkColor();
    m_crItemBk[1] = GetSysColor(COLOR_HIGHLIGHT);
    m_hBrushItem[0] = CreateSolidBrush(m_crItemBk[0]);
    m_hBrushItem[1] = CreateSolidBrush(m_crItemBk[1]);
    m_hBrushItem[2] = CreateSolidBrush(m_crItemBk[2]);
    CTreeCtrl::PreSubclassWindow();
}
void CApredTreeCtrl2::SetItemBadge(HTREEITEM hItem, COLORREF badgeBackground, COLORREF badgeForeground)
{
    if (m_badges.find(hItem) == m_badges.end()) {
        BADGE badge;
        badge.badgeBackground = badgeBackground;
        badge.badgeForeground = badgeForeground;
        badge.type = BADGE_HIDE;
        m_badges[hItem] = badge;
    }
    else {
        BADGE& badge = m_badges[hItem];
        badge.badgeBackground = badgeBackground;
        badge.badgeForeground = badgeForeground;
        badge.type = BADGE_HIDE;
    }
}
void CApredTreeCtrl2::ShowItemBadgeNumber(HTREEITEM hItem, int number)
{
    if (m_badges.find(hItem) == m_badges.end()) {
        return;
    }
    BADGE& badge = m_badges[hItem];
    badge.type = BADGE_NUMBER;
    badge.number = number;
    InvalidateRect(NULL, TRUE);
}
void CApredTreeCtrl2::ShowItemBadgeDotMode(HTREEITEM hItem)
{
    if (m_badges.find(hItem) == m_badges.end()) {
        return;
    }
    BADGE& badge = m_badges[hItem];
    if (badge.type != BADGE_DOT) {
        badge.type = BADGE_DOT;
        InvalidateRect(NULL, TRUE);
    }
}
void CApredTreeCtrl2::HideItemBadge(HTREEITEM hItem)
{
    if (m_badges.find(hItem) == m_badges.end()) {
        return;
    }
    BADGE& badge = m_badges[hItem];
    if (badge.type != BADGE_HIDE) {
        badge.type = BADGE_HIDE;
        InvalidateRect(NULL, TRUE);
    }
}
SourceCode/Bond/Servo/ApredTreeCtrl2.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
#pragma once
#include <afxcmn.h>
#include <map>
class CApredTreeCtrl2 :
    public CTreeCtrl
{
public:
    typedef struct tagBADGE
    {
        HTREEITEM hTreeItem;
        COLORREF badgeBackground;
        COLORREF badgeForeground;
        int type;                       /* 0: æ— ,不显示*/
        int number;
    } BADGE;
    DECLARE_DYNAMIC(CApredTreeCtrl2)
public:
    CApredTreeCtrl2();
    virtual ~CApredTreeCtrl2();
public:
    virtual COLORREF SetBkColor(COLORREF crColor);
    void SetItemBadge(HTREEITEM hItem, COLORREF badgeBackground, COLORREF badgeForeground);
    void ShowItemBadgeNumber(HTREEITEM hItem, int number);
    void ShowItemBadgeDotMode(HTREEITEM hItem);
    void HideItemBadge(HTREEITEM hItem);
private:
    HBRUSH GetItemBkBrush(HTREEITEM hItem);
    HBRUSH GetItemBtnBrush(HTREEITEM hItem);
    HPEN GetItemBtnPen(HTREEITEM hItem);
    void DrawItemButton(HTREEITEM hItem, HDC hDC, CRect* pRect);
private:
    std::map<HTREEITEM, BADGE> m_badges;
    std::map<HTREEITEM, int> m_items;
    HBRUSH m_hBrushItem[3];
    COLORREF m_crItemBk[3];
    COLORREF m_crItemBtn[3];
public:
    DECLARE_MESSAGE_MAP()
    afx_msg void OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    virtual void PreSubclassWindow();
};
SourceCode/Bond/Servo/CAttribute.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
#include "stdafx.h"
#include "CAttribute.h"
namespace SERVO {
    CAttribute::CAttribute()
    {
    }
    CAttribute::CAttribute(const char* pszName, const char* pszValue, const char* pszDescription)
    {
        m_strName = pszName;
        m_strValue = pszValue;
        m_strDescription = pszDescription;
    }
    CAttribute::~CAttribute()
    {
    }
}
SourceCode/Bond/Servo/CAttribute.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
#pragma once
namespace SERVO {
    class CAttribute
    {
    public:
        CAttribute();
        CAttribute(const char* pszName, const char* pszValue, const char* pszDescription);
        ~CAttribute();
    private:
        std::string m_strName;
        std::string m_strValue;
        std::string m_strDescription;
    };
}
SourceCode/Bond/Servo/CAttributeVector.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
#include "stdafx.h"
#include "CAttributeVector.h"
namespace SERVO {
    CAttributeVector::CAttributeVector()
    {
    }
    CAttributeVector::~CAttributeVector()
    {
    }
    void CAttributeVector::addAttribute(CAttribute* pAttribute)
    {
        m_attributes.push_back(pAttribute);
    }
    unsigned int CAttributeVector::size()
    {
        return m_attributes.size();
    }
    void CAttributeVector::clear()
    {
        for (auto item : m_attributes) {
            delete item;
        }
        m_attributes.clear();
    }
    bool CAttributeVector::empty()
    {
        return m_attributes.empty();
    }
    CAttribute* CAttributeVector::getAttribute(unsigned int index)
    {
        ASSERT(index < m_attributes.size());
        return m_attributes[index];
    }
}
SourceCode/Bond/Servo/CAttributeVector.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
#pragma once
#include <vector>
#include "CAttribute.h"
namespace SERVO {
    class CAttributeVector
    {
    public:
        CAttributeVector();
        ~CAttributeVector();
    public:
        void addAttribute(CAttribute* pAttribute);
        void clear();
        unsigned int size();
        bool empty();
        CAttribute* getAttribute(unsigned int index);
    private:
        std::vector<CAttribute*> m_attributes;
    };
}
SourceCode/Bond/Servo/CEqAlarmStep.cpp
@@ -20,6 +20,26 @@
    }
    void CEqAlarmStep::getAttributeVector(CAttributeVector& attrubutes)
    {
        CStep::getAttributeVector(attrubutes);
        attrubutes.addAttribute(new CAttribute("Alarm State",
            std::to_string(m_nAlarmState).c_str(), ""));
        attrubutes.addAttribute(new CAttribute("Unit ID",
            std::to_string(m_nUnitId).c_str(), ""));
        attrubutes.addAttribute(new CAttribute("Alarm Level",
            std::to_string(m_nAlarmLevel).c_str(), ""));
        attrubutes.addAttribute(new CAttribute("Alarm Code",
            std::to_string(m_nAlarmCode).c_str(), ""));
        attrubutes.addAttribute(new CAttribute("Alarm ID",
            std::to_string(m_nAlarmId).c_str(), ""));
        attrubutes.addAttribute(new CAttribute("Text",
            m_strText.c_str(), ""));
        attrubutes.addAttribute(new CAttribute("Description",
            m_strDescription.c_str(), ""));
    }
    int CEqAlarmStep::onReadData()
    {
        CStep::onReadData();
SourceCode/Bond/Servo/CEqAlarmStep.h
@@ -10,6 +10,7 @@
        ~CEqAlarmStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int onReadData();
        virtual int onComplete();
        virtual int onTimeout();
SourceCode/Bond/Servo/CEqModeStep.cpp
@@ -15,6 +15,17 @@
    }
    void CEqModeStep::getAttributeVector(CAttributeVector& attrubutes)
    {
        CStep::getAttributeVector(attrubutes);
        std::string strTemp;
        attrubutes.addAttribute(new CAttribute("Mode",
            std::to_string(m_nMode).c_str(), getModeDescription(strTemp).c_str()));
        attrubutes.addAttribute(new CAttribute("Mode Dev",
            std::to_string(m_nModeDev).c_str(), ""));
    }
    int CEqModeStep::onReadData()
    {
        CStep::onReadData();
SourceCode/Bond/Servo/CEqModeStep.h
@@ -10,6 +10,7 @@
        ~CEqModeStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int onReadData();
        virtual int onComplete();
        virtual int onTimeout();
SourceCode/Bond/Servo/CEqProcessStep.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,134 @@
#include "stdafx.h"
#include "Common.h"
#include "CEqProcessStep.h"
#include "Log.h"
#include "ToolUnits.h"
namespace SERVO {
    CEqProcessStep::CEqProcessStep()
    {
        m_nProcessDev = 0;
        m_nTotalParameter = 0;
    }
    CEqProcessStep::~CEqProcessStep()
    {
    }
#define PROGRESS_BUF_SIZE        (1024 + 64)
    int CEqProcessStep::onReadData()
    {
        CStep::onReadData();
        // W1864 ~ W1A74, 529个word, 1058 bytes
        char szBuffer[PROGRESS_BUF_SIZE];
        int nRet = m_pCclink->ReadData2(m_station, DeviceType::W,
            m_nProcessDev, PROGRESS_BUF_SIZE, szBuffer);
        if (0 != nRet) {
            return -1;
        }
        // è§£é‡Šæ•°æ®
        // Glass ID(1864~186D)
        int index = 0;
        convertString(&szBuffer[index], (0x186d - 0x1864 + 1) * 2, m_strStartTime);
        index += (0x186d - 0x1864 + 1) * 2;
        // Process Start Time(186e~1875)
        convertString(&szBuffer[index], (0x1875 - 0x186e + 1) * 2, m_strStartTime);
        index += (0x1875 - 0x186e + 1) * 2;
        // Process End Time(1876~187d)
        convertString(&szBuffer[index], (0x187d - 0x1876 + 1) * 2, m_strEndTime);
        index += (0x187d - 0x1876 + 1) * 2;
        // parameter count
        m_nTotalParameter = (unsigned int)CToolUnits::toInt16(&szBuffer[index]);
        index += 2;
        // total group
        m_nTotalGroup = (unsigned int)CToolUnits::toInt16(&szBuffer[index]);
        index += 2;
        // current group
        m_nCurrentGroup = (unsigned int)CToolUnits::toInt16(&szBuffer[index]);
        index += 2;
        // param list(0x1881~0x1a74), å…±1000 bytes, 20个字符为一个参数, 50组
        // æœ€åŽä¸€group可能不满足50, ä»¥m_nTotalParameter为依据
        int size = (m_nCurrentGroup == m_nTotalGroup) ? m_nTotalParameter % 50 : 50;
        for (int i = 0; i < size; i++) {
            std::string strParam;
            convertString(&szBuffer[index], 20, strParam);
            if (!strParam.empty()) {
                m_params.push_back(strParam);
            }
            index += 20;
        }
        if (m_nCurrentGroup == m_nTotalGroup && m_listener.onEvent != nullptr) {
            m_listener.onEvent(this, STEP_EVENT_PROCESS_DATA, nullptr);
        }
        LOGI("<CEqProcessStep> Process Data<GlassId:%s>\n",
            m_strGlassId.c_str());
        return 0;
    }
    int CEqProcessStep::onComplete()
    {
        CStep::onComplete();
        LOGI("<CEqProcessStep> onComplete.");
        return 0;
    }
    int CEqProcessStep::onTimeout()
    {
        CStep::onTimeout();
        LOGI("<CEqProcessStep> onTimeout.");
        return 0;
    }
    void CEqProcessStep::setProcessDev(int nDev)
    {
        m_nProcessDev = nDev;
    }
    std::string& CEqProcessStep::getGlassId()
    {
        return m_strGlassId;
    }
    std::string& CEqProcessStep::getStartTime()
    {
        return m_strStartTime;
    }
    std::string& CEqProcessStep::getEndTime()
    {
        return m_strEndTime;
    }
    unsigned int CEqProcessStep::getTotalParameter()
    {
        return m_nTotalParameter;
    }
    const std::list<std::string> CEqProcessStep::getParameters()
    {
        return m_params;
    }
    void CEqProcessStep::getParameters(std::list<std::string>& list)
    {
        Lock();
        std::copy(m_params.begin(), m_params.end(), std::back_inserter(list));
        Unlock();
    }
}
SourceCode/Bond/Servo/CEqProcessStep.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
#pragma once
#include "CStep.h"
#include <list>
namespace SERVO {
    class CEqProcessStep : public CStep
    {
    public:
        CEqProcessStep();
        ~CEqProcessStep();
    public:
        virtual int onReadData();
        virtual int onComplete();
        virtual int onTimeout();
        void setProcessDev(int nDev);
        std::string& getGlassId();
        std::string& getStartTime();
        std::string& getEndTime();
        unsigned int getTotalParameter();
        const std::list<std::string> getParameters();
        void getParameters(std::list<std::string>& list);
    private:
        int m_nProcessDev;
        std::string m_strGlassId;
        std::string m_strStartTime;
        std::string m_strEndTime;
        unsigned int m_nTotalParameter;
        unsigned int m_nTotalGroup;
        unsigned int m_nCurrentGroup;
        std::list<std::string> m_params;
    };
}
SourceCode/Bond/Servo/CEqStatusStep.cpp
@@ -21,6 +21,24 @@
    }
    void CEqStatusStep::getAttributeVector(CAttributeVector& attrubutes)
    {
        CStep::getAttributeVector(attrubutes);
        char szName[256];
        for (int i = 0; i < STATUS_MAX; i++) {
            sprintf_s(szName, 256, "Status %d", i + 1);
            attrubutes.addAttribute(new CAttribute(szName,
                std::to_string(m_nStatus[i]).c_str(), ""));
            sprintf_s(szName, 256, "Reason Code %d", i + 1);
            attrubutes.addAttribute(new CAttribute(szName,
                std::to_string(m_nReasonCode[i]).c_str(), ""));
        }
        attrubutes.addAttribute(new CAttribute("Status Dev",
            std::to_string(m_nStatusDev).c_str(), ""));
    }
    int CEqStatusStep::getStatus(unsigned int uint)
    {
        if (uint < STATUS_MAX) {
SourceCode/Bond/Servo/CEqStatusStep.h
@@ -13,6 +13,7 @@
        ~CEqStatusStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int onReadData();
        virtual int onComplete();
        virtual int onTimeout();
SourceCode/Bond/Servo/CEquipment.cpp
@@ -60,6 +60,11 @@
        container.push_back(std::make_pair("Version", "1.0"));
    }
    std::map<unsigned int, CStep*>& CEquipment::getSteps()
    {
        return m_mapStep;
    }
    CStep* CEquipment::getStep(unsigned int addr)
    {
        auto iter = m_mapStep.find(addr);
SourceCode/Bond/Servo/CEquipment.h
@@ -64,6 +64,7 @@
        void getProperties(std::vector<std::pair<std::string, std::string>>& container);
        int addStep(unsigned int addr, CStep* pStep);
        CStep* getStep(unsigned int addr);
        std::map<unsigned int, CStep*>& getSteps();
        virtual void init();
        virtual void term();
        virtual void onTimer(UINT nTimerid);
SourceCode/Bond/Servo/CMaster.cpp
@@ -74,7 +74,7 @@
        // åˆå§‹åŒ–添加各子设备
        addEFEM(listener);
        /*
        {
            CBonder* pBonder = new CBonder();
            pBonder->setName("Bonder 1");
@@ -84,7 +84,7 @@
            addEquipment(pBonder);
            LOGE("已添加“Bonder 1”.");
        }
        */
        // å®šæ—¶å™¨
        g_pMaster = this;
@@ -127,6 +127,11 @@
        return 0;
    }
    std::list<CEquipment*>& CMaster::getEquipmentList()
    {
        return m_listEquipment;
    }
    CEquipment* CMaster::getEquipment(int id)
    {
        for (auto item : m_listEquipment) {
SourceCode/Bond/Servo/CMaster.h
@@ -28,6 +28,7 @@
        int init();
        int term();
        void onTimer(UINT nTimerid);
        std::list<CEquipment*>& getEquipmentList();
        CEquipment* getEquipment(int id);
    private:
SourceCode/Bond/Servo/CPanelMaster.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,176 @@
// CPanelMaster.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "Servo.h"
#include "CPanelMaster.h"
#include "afxdialogex.h"
#include "Common.h"
#include "VerticalLine.h"
// CPanelMaster å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CPanelMaster, CDialogEx)
CPanelMaster::CPanelMaster(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_PANEL_MASTER, pParent)
{
    m_crBkgnd = PANEL_MASTER_BACKGROUND_COLOR;
    m_hbrBkgnd = nullptr;
    m_nPanelWidth = 388;
}
CPanelMaster::~CPanelMaster()
{
}
void CPanelMaster::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_TREE1, m_treeCtrl);
}
BEGIN_MESSAGE_MAP(CPanelMaster, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_NOTIFY(BYVERTICALLINE_MOVEX, IDC_LINE1, &CPanelMaster::OnVLineMoveX)
    ON_WM_TIMER()
END_MESSAGE_MAP()
// CPanelMaster æ¶ˆæ¯å¤„理程序
int CPanelMaster::getPanelWidth()
{
    return m_nPanelWidth;
}
BOOL CPanelMaster::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    CVerticalLine* pLine1 = CVerticalLine::Hook(GetDlgItem(IDC_LINE1)->GetSafeHwnd());
    pLine1->SetBkgndColor(RGB(225, 225, 225));
    pLine1->SetLineColor(RGB(198, 198, 198));
    pLine1->EnableResize();
    // è¯»å–面板宽
    CString strIniFile;
    strIniFile.Format(_T("%s\\%s.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir, (LPTSTR)(LPCTSTR)theApp.m_strAppFile);
    m_nPanelWidth = GetPrivateProfileInt(_T("App"), _T("MasterPanelWidth"),
        int((double)GetSystemMetrics(SM_CXSCREEN) * 0.25), (LPTSTR)(LPCTSTR)strIniFile);
    // treectrl
    m_treeCtrl.SetBkColor(PANEL_MASTER_BACKGROUND_COLOR);
    m_treeCtrl.SetItemHeight(28);
    SetTimer(1, 2000, nullptr);
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CPanelMaster::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    if (nCtlColor == CTLCOLOR_STATIC) {
        pDC->SetBkColor(m_crBkgnd);
        pDC->SetTextColor(RGB(0, 0, 0));
    }
    if (m_hbrBkgnd == nullptr) {
        m_hbrBkgnd = CreateSolidBrush(m_crBkgnd);
    }
    return m_hbrBkgnd;
}
void CPanelMaster::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
}
void CPanelMaster::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (GetDlgItem(IDC_LINE1) == nullptr) return;
    CWnd* pItem;
    CRect rcClient;
    GetClientRect(&rcClient);
    pItem = GetDlgItem(IDC_LINE1);
    pItem->MoveWindow(rcClient.right - 3, 0, 3, rcClient.Height());
    m_treeCtrl.MoveWindow(5, 5, rcClient.Width() - 13, rcClient.Height() - 10);
}
#define MASTER_PANEL_MIN_WIDTH        88
#define MASTER_PANEL_MAX_WIDTH        588
void CPanelMaster::OnVLineMoveX(NMHDR* nmhdr, LRESULT* result)
{
    BYVERTICALLINE_NMHDR* pNmhdrex = (BYVERTICALLINE_NMHDR*)nmhdr;
    int x = pNmhdrex->dwData;
    m_nPanelWidth += x;
    m_nPanelWidth = max(m_nPanelWidth, MASTER_PANEL_MIN_WIDTH);
    m_nPanelWidth = min(m_nPanelWidth, MASTER_PANEL_MAX_WIDTH);
    GetParent()->SendMessage(ID_MSG_PANEL_RESIZE, m_nPanelWidth, 0);
    CString strIniFile, strValue;
    strIniFile.Format(_T("%s\\%s.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir, (LPTSTR)(LPCTSTR)theApp.m_strAppFile);
    strValue.Format(_T("%d"), m_nPanelWidth);
    WritePrivateProfileString(_T("App"), _T("MasterPanelWidth"),
        (LPTSTR)(LPCTSTR)strValue, (LPTSTR)(LPCTSTR)strIniFile);
    OnSize(0, 0, 0);
    * result = 0;
}
void CPanelMaster::OnTimer(UINT_PTR nIDEvent)
{
    if (1 == nIDEvent) {
        KillTimer(1);
        loadEquipmentList();
    }
    CDialogEx::OnTimer(nIDEvent);
}
void CPanelMaster::loadEquipmentList()
{
    HTREEITEM hItemMaster = m_treeCtrl.InsertItem("Master");
    std::list<SERVO::CEquipment*>& eqs = theApp.m_model.m_master.getEquipmentList();
    for (auto item : eqs) {
        HTREEITEM hItemEq = m_treeCtrl.InsertItem(item->getName().c_str(), hItemMaster);
        m_treeCtrl.SetItemData(hItemEq, (DWORD_PTR)item);
        loadSteps(item, hItemEq);
        m_treeCtrl.Expand(hItemEq, TVE_EXPAND);
    }
    m_treeCtrl.Expand(hItemMaster, TVE_EXPAND);
}
void CPanelMaster::loadSteps(SERVO::CEquipment* pEquipment, HTREEITEM hItemEq)
{
    std::map<unsigned int, SERVO::CStep*>& steps = pEquipment->getSteps();
    for (auto item : steps) {
        HTREEITEM hStep = m_treeCtrl.InsertItem(item.second->getName().c_str(), hItemEq);
        m_treeCtrl.SetItemData(hStep, (DWORD_PTR)item.second);
    }
}
SourceCode/Bond/Servo/CPanelMaster.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
#pragma once
#include "ApredTreeCtrl2.h"
// CPanelMaster å¯¹è¯æ¡†
class CPanelMaster : public CDialogEx
{
    DECLARE_DYNAMIC(CPanelMaster)
public:
    CPanelMaster(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CPanelMaster();
    int getPanelWidth();
    void loadEquipmentList();
    void loadSteps(SERVO::CEquipment* pEquipment, HTREEITEM hItemEq);
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    CApredTreeCtrl2 m_treeCtrl;
    int m_nPanelWidth;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_PANEL_MASTER };
#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);
    afx_msg void OnVLineMoveX(NMHDR* nmhdr, LRESULT* result);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
};
SourceCode/Bond/Servo/CStep.cpp
@@ -1,5 +1,6 @@
#include "stdafx.h"
#include "CStep.h"
#include "Common.h"
namespace SERVO {
@@ -66,6 +67,19 @@
    std::string& CStep::getName()
    {
        return m_strName;
    }
    void CStep::getAttributeVector(CAttributeVector& attrubutes)
    {
        attrubutes.clear();
        attrubutes.addAttribute(new CAttribute("Network",
            std::to_string(m_station.nNetNo).c_str(), ""));
        attrubutes.addAttribute(new CAttribute("Station",
            std::to_string(m_station.nStNo).c_str(), ""));
        attrubutes.addAttribute(new CAttribute("Current Step",
            std::to_string(m_nCurStep).c_str(), ""));
        attrubutes.addAttribute(new CAttribute("Signal Dev",
            std::to_string(m_nWriteSignalDev).c_str(), ""));
    }
    void CStep::setWriteSignalDev(int dev)
@@ -205,5 +219,18 @@
        m_nCurStep++;
        Unlock();
    }
    void CStep::convertString(const char* pszBuffer, int size, std::string& strOut)
    {
        strOut.clear();
        int nLength = 0;
        for (int i = 0; i < size; i++) {
            if (pszBuffer[i] == '\0') break;
            nLength++;
        }
        if (nLength > 0) {
            strOut = std::string(pszBuffer, nLength);
        }
    }
}
SourceCode/Bond/Servo/CStep.h
@@ -1,10 +1,9 @@
#pragma once
#include "CCLinkIEControl.h"
#include "CAttributeVector.h"
namespace SERVO {
#define STEP_EVENT_READDATA            0x01
#define STEP_EVENT_COMPLETE            0x02
    typedef std::function<void(void* pStep, int code, void* pData)> ONSTEPEVENT;
    typedef struct _StepListener
@@ -27,6 +26,7 @@
        CEquipment* getEquipment();
        void setName(const char* pszName);
        std::string& getName();
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual void setWriteSignalDev(int dev);
        virtual void init();
        virtual void CStep::term();
@@ -40,6 +40,7 @@
        inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
        inline void nextStep();
        inline void resetStep();
        void convertString(const char* pszBuffer, int size, std::string& strOut);
    protected:
        StepListener m_listener;
@@ -48,7 +49,6 @@
        CEquipment* m_pEquipment;
        CCCLinkIEControl* m_pCclink;
        CRITICAL_SECTION m_criticalSection;
        std::string strName;
        HANDLE m_hWorkThreadHandle;
        unsigned m_nWordThreadAddr;
        HANDLE m_hWorkStop;
SourceCode/Bond/Servo/Common.h
@@ -17,6 +17,7 @@
/* é¢œè‰² */
#define APPDLG_BACKGROUND_COLOR            RGB(255, 255, 255)
#define LOGDLG_BACKGROUND_COLOR            RGB(255, 255, 255)
#define PANEL_MASTER_BACKGROUND_COLOR    RGB(255, 255, 255)
/* LOG BTN */
@@ -56,3 +57,13 @@
#define BASE_ALARM_EFEM        10000
#define BASE_ALARM_BONDER1    20000
#define BASE_ALARM_BONDER2    30000
/* step event */
#define STEP_EVENT_READDATA            0x01
#define STEP_EVENT_COMPLETE            0x02
#define STEP_EVENT_PROCESS_DATA        0x1001
/* è‡ªå®šä¹‰æ¶ˆæ¯ */
#define ID_MSG_PANEL_RESIZE            WM_USER + 1998
SourceCode/Bond/Servo/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/Servo/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/Servo/Servo.cpp
@@ -8,6 +8,8 @@
#include "ServoGraph.h"
#include "AlarmManager.h"
#include "SECSRuntimeManager.h"
#include "VerticalLine.h"
// å£°æ˜Žå…¨å±€å˜é‡ï¼Œç”¨äºŽç®¡ç† GDI+ åˆå§‹åŒ–
ULONG_PTR g_diplusToken;
@@ -92,6 +94,7 @@
    // æ³¨å†ŒæŽ§ä»¶
    CServoGraph::RegisterWndClass();
    CVerticalLine::RegisterWndClass();
    // åˆå§‹åŒ–Rx库
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/Servo.vcxproj
@@ -197,7 +197,10 @@
  <ItemGroup>
    <ClInclude Include="AlarmDlg.h" />
    <ClInclude Include="AlarmManager.h" />
    <ClInclude Include="ApredTreeCtrl2.h" />
    <ClInclude Include="BlButton.h" />
    <ClInclude Include="CAttribute.h" />
    <ClInclude Include="CAttributeVector.h" />
    <ClInclude Include="CBonder.h" />
    <ClInclude Include="CCLinkPerformance\CCLinkIEControl.h" />
    <ClInclude Include="CCLinkPerformance\PerformanceMelsec.h" />
@@ -205,6 +208,7 @@
    <ClInclude Include="CEqModeStep.h" />
    <ClInclude Include="CEqProcessStep.h" />
    <ClInclude Include="CEqStatusStep.h" />
    <ClInclude Include="CPanelMaster.h" />
    <ClInclude Include="CStep.h" />
    <ClInclude Include="DevicePropertyDlg.h" />
    <ClInclude Include="CEFEM.h" />
@@ -229,11 +233,15 @@
    <ClInclude Include="targetver.h" />
    <ClInclude Include="TerminalDisplayDlg.h" />
    <ClInclude Include="ToolUnits.h" />
    <ClInclude Include="VerticalLine.h" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="AlarmDlg.cpp" />
    <ClCompile Include="AlarmManager.cpp" />
    <ClCompile Include="ApredTreeCtrl2.cpp" />
    <ClCompile Include="BlButton.cpp" />
    <ClCompile Include="CAttribute.cpp" />
    <ClCompile Include="CAttributeVector.cpp" />
    <ClCompile Include="CBonder.cpp" />
    <ClCompile Include="CCLinkPerformance\CCLinkIEControl.cpp" />
    <ClCompile Include="CCLinkPerformance\PerformanceMelsec.cpp" />
@@ -241,6 +249,7 @@
    <ClCompile Include="CEqModeStep.cpp" />
    <ClCompile Include="CEqProcessStep.cpp" />
    <ClCompile Include="CEqStatusStep.cpp" />
    <ClCompile Include="CPanelMaster.cpp" />
    <ClCompile Include="CStep.cpp" />
    <ClCompile Include="DevicePropertyDlg.cpp" />
    <ClCompile Include="CEFEM.cpp" />
@@ -267,6 +276,7 @@
    </ClCompile>
    <ClCompile Include="TerminalDisplayDlg.cpp" />
    <ClCompile Include="ToolUnits.cpp" />
    <ClCompile Include="VerticalLine.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Servo.rc" />
SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -42,6 +42,11 @@
    <ClCompile Include="CEqAlarmStep.cpp" />
    <ClCompile Include="AlarmDlg.cpp" />
    <ClCompile Include="CEqProcessStep.cpp" />
    <ClCompile Include="CAttribute.cpp" />
    <ClCompile Include="CAttributeVector.cpp" />
    <ClCompile Include="CPanelMaster.cpp" />
    <ClCompile Include="VerticalLine.cpp" />
    <ClCompile Include="ApredTreeCtrl2.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AlarmManager.h" />
@@ -82,6 +87,11 @@
    <ClInclude Include="CEqAlarmStep.h" />
    <ClInclude Include="AlarmDlg.h" />
    <ClInclude Include="CEqProcessStep.h" />
    <ClInclude Include="CAttribute.h" />
    <ClInclude Include="CAttributeVector.h" />
    <ClInclude Include="CPanelMaster.h" />
    <ClInclude Include="VerticalLine.h" />
    <ClInclude Include="ApredTreeCtrl2.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Servo.rc" />
SourceCode/Bond/Servo/ServoDlg.cpp
@@ -90,6 +90,7 @@
    m_pLogDlg = nullptr;
    m_pTerminalDisplayDlg = nullptr;
    m_pObserver = nullptr;
    m_pPanelMaster = nullptr;
}
void CServoDlg::DoDataExchange(CDataExchange* pDX)
@@ -126,6 +127,9 @@
    ON_WM_TIMER()
    ON_WM_ERASEBKGND()
    ON_BN_CLICKED(IDC_BUTTON_ALARM, &CServoDlg::OnBnClickedButtonAlarm)
    ON_BN_CLICKED(IDC_BUTTON_ALARM, &CServoDlg::OnBnClickedButtonAlarm)
    ON_NOTIFY(BYSERVOGRAPH_ITEM_CLICKED, IDC_SERVO_GRAPH1, &CServoDlg::OnGraphItemClicked)
    ON_MESSAGE(ID_MSG_PANEL_RESIZE, OnPanelResize)
END_MESSAGE_MAP()
@@ -277,6 +281,8 @@
    m_pGraph->SetBoxText(INDICATE_ROBOT_ARM2, "6", "Robot");
    // Vacuum bake
    m_pGraph->AddIndicateBox(INDICATE_VACUUM_BAKE, 396, 516, 48, RGB(22, 22, 22),
        RGB(255, 127, 39), RGB(0, 176, 80));
@@ -293,6 +299,12 @@
    m_pGraph->AddIndicateBox(INDICATE_MEASUREMENT, 736, 516, 48, RGB(22, 22, 22),
        RGB(255, 127, 39), RGB(0, 176, 80));
    m_pGraph->SetBoxText(INDICATE_MEASUREMENT, "13", "Measurement");
    m_pPanelMaster = new CPanelMaster();
    m_pPanelMaster->Create(IDD_PANEL_MASTER, this);
    m_pPanelMaster->ShowWindow(SW_SHOW);
    // è°ƒæ•´åˆå§‹çª—口位置
@@ -317,6 +329,13 @@
    // ç›¸å½“于延时调用master的初始化
    theApp.m_model.m_master.init();
    // ç»‘定数据
    {
        SERVO::CEquipment* pEquipment = theApp.m_model.m_master.getEquipment(EQ_ID_EFEM);
        m_pGraph->SetIndicateBoxData(INDICATE_ROBOT_ARM1, pEquipment);
    }
    return TRUE;  // é™¤éžå°†ç„¦ç‚¹è®¾ç½®åˆ°æŽ§ä»¶ï¼Œå¦åˆ™è¿”回 TRUE
@@ -533,6 +552,12 @@
        m_pTerminalDisplayDlg = nullptr;
    }
    if (m_pPanelMaster != nullptr) {
        m_pPanelMaster->DestroyWindow();
        delete m_pPanelMaster;
        m_pPanelMaster = nullptr;
    }
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
@@ -731,6 +756,14 @@
    x = 0;
    y = 0;
    int nPanelWidth = 0;
    if (m_pPanelMaster != nullptr) {
        nPanelWidth = m_pPanelMaster->getPanelWidth();
        m_pPanelMaster->MoveWindow(x, y, nPanelWidth, rcClient.Height());
        x += nPanelWidth;
    }
    pItem = GetDlgItem(IDC_SERVO_GRAPH1);
    pItem->GetClientRect(&rcItem);
    pItem->MoveWindow(x, y, rcItem.Width(), rcItem.Height());
@@ -828,3 +861,26 @@
    CAlarmDlg dlg;
    dlg.DoModal();
}
void CServoDlg::OnGraphItemClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
    BYSERVOGRAPH_NMHDR* pGraphNmhdr = reinterpret_cast<BYSERVOGRAPH_NMHDR*>(pNMHDR);
    CString s; s.Format(_T("OnGraphItemClicked %d"), pGraphNmhdr->dwData);
    SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)m_pGraph->GetIndicateBoxData(pGraphNmhdr->dwData);
    if (pEquipment != nullptr) {
        AfxMessageBox(pEquipment->getName().c_str());
    }
    *pResult = 0;
}
LRESULT CServoDlg::OnPanelResize(WPARAM wParam, LPARAM lParam)
{
    int width = wParam;
    // m_pPanel->SetPanelWidth(width);
    Resize();
    return 0;
}
SourceCode/Bond/Servo/ServoDlg.h
@@ -7,6 +7,8 @@
#include "BlButton.h"
#include "LogDlg.h"
#include "TerminalDisplayDlg.h"
#include "CPanelMaster.h"
enum DeviceStatus {
    ONLINE,       // åœ¨çº¿
@@ -62,6 +64,7 @@
    HBRUSH m_hbrBkgnd;
    CBlButton m_btnLog;
    CBlButton m_btnAlarm;
    CPanelMaster* m_pPanelMaster;
    // ç”Ÿæˆçš„æ¶ˆæ¯æ˜ å°„函数
@@ -94,4 +97,6 @@
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnBnClickedButtonAlarm();
    afx_msg void OnGraphItemClicked(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg LRESULT OnPanelResize(WPARAM wParam, LPARAM lParam);
};
SourceCode/Bond/Servo/ServoGraph.cpp
@@ -693,4 +693,22 @@
        graphics.DrawImage(&bitmap, item.x, item.y);
        graphics.ResetTransform();
    }
}
void CServoGraph::SetIndicateBoxData(int id, void* pData)
{
    INDICATEBOX* pib = GetIndicateBox(id);
    if (pib != nullptr) {
        pib->m_pData = pData;
    }
}
void* CServoGraph::GetIndicateBoxData(int id)
{
    INDICATEBOX* pib = GetIndicateBox(id);
    if (pib != nullptr) {
        return pib->m_pData;
    }
    return nullptr;
}
SourceCode/Bond/Servo/ServoGraph.h
@@ -94,6 +94,7 @@
            this->box2BackgroundColor = RGB(0, 255, 255);;
            this->box2FrameColor = RGB(255, 255, 0);;
            this->bBox2Visible = FALSE;
            this->m_pData = nullptr;
        };
        ~INDICATEBOX() {};
@@ -110,6 +111,7 @@
        COLORREF box2FrameColor;
        BOOL bBox2Visible;
        std::vector<void*> m_contexts;
        void* m_pData;
    };
    class INDICATEBKGND
@@ -154,6 +156,8 @@
    BOOL RemoveIndicateBoxAllContext(int id);
    const std::vector<void*>& GetIndicateBoxContexts(int id);
    bool IsIndicateBoxContextsEmpty(int id);
    void SetIndicateBoxData(int id, void* pData);
    void* GetIndicateBoxData(int id);
    void ShowIndicateBoxInterior(int id, COLORREF color);
    void HideIndicateBoxInterior(int id);
    CServoGraph::INDICATEBOX* GetIndicateBox(int id);
SourceCode/Bond/Servo/VerticalLine.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,316 @@
// 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::SetLineColor(COLORREF cr)
{
    m_crLineColor = cr;
}
void CVerticalLine::EnableResize()
{
    m_bEnableResize = TRUE;
}
void CVerticalLine::DisableResize()
{
    m_bEnableResize = FALSE;
}
SourceCode/Bond/Servo/VerticalLine.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,95 @@
// 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);
    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 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_)
SourceCode/Bond/Servo/resource.h
Binary files differ