LAPTOP-SNT8I5JK\Boounion
2025-01-08 c2d22fc8efd988294ff4a34fd3e31a9743803964
1.PLC View的加入,关闭,关联等;
已添加10个文件
已修改9个文件
996 ■■■■■ 文件已修改
SourceCode/Bond/BoounionPLC/BoounionPLC.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/CBaseView.cpp 415 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/CBaseView.h 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/CMainContainer.cpp 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/CMainContainer.h 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/Common.h 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/PagePlcList.cpp 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/PagePlcList.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/PlcView.cpp 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/PlcView.h 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/Resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/BoounionPLC/Debug/Res/small_close0.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/BoounionPLC/Debug/Res/small_close1.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/BoounionPLC/Debug/Res/small_close2.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/BoounionPLC/Debug/Res/small_close3.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLC.rc
Binary files differ
SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj
@@ -195,12 +195,15 @@
    <ClInclude Include="BlButton.h" />
    <ClInclude Include="BoounionPLC.h" />
    <ClInclude Include="BoounionPLCDlg.h" />
    <ClInclude Include="CBaseView.h" />
    <ClInclude Include="CMainContainer.h" />
    <ClInclude Include="Common.h" />
    <ClInclude Include="Configuration.h" />
    <ClInclude Include="Log.h" />
    <ClInclude Include="Model.h" />
    <ClInclude Include="PagePlcList.h" />
    <ClInclude Include="PLC.h" />
    <ClInclude Include="PlcView.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="stdafx.h" />
    <ClInclude Include="targetver.h" />
@@ -213,11 +216,14 @@
    <ClCompile Include="BlButton.cpp" />
    <ClCompile Include="BoounionPLC.cpp" />
    <ClCompile Include="BoounionPLCDlg.cpp" />
    <ClCompile Include="CBaseView.cpp" />
    <ClCompile Include="CMainContainer.cpp" />
    <ClCompile Include="Configuration.cpp" />
    <ClCompile Include="Log.cpp" />
    <ClCompile Include="Model.cpp" />
    <ClCompile Include="PagePlcList.cpp" />
    <ClCompile Include="PLC.cpp" />
    <ClCompile Include="PlcView.cpp" />
    <ClCompile Include="stdafx.cpp">
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters
@@ -66,6 +66,15 @@
    <ClInclude Include="PLC.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CBaseView.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CMainContainer.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="PlcView.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="BoounionPLC.cpp">
@@ -107,6 +116,15 @@
    <ClCompile Include="PLC.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CBaseView.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CMainContainer.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="PlcView.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="BoounionPLC.rc">
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp
@@ -7,6 +7,7 @@
#include "BoounionPLCDlg.h"
#include "afxdialogex.h"
#include "Common.h"
#include "PlcView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -55,8 +56,10 @@
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_pTopToolbar = nullptr;
    m_pObserver = nullptr;
    m_crBkgnd = APP_MAIN_DLG_BACKGROUND;
    m_hbrBkgnd = nullptr;
    m_pActiveView = nullptr;
}
void CBoounionPLCDlg::DoDataExchange(CDataExchange* pDX)
@@ -78,10 +81,53 @@
    ON_COMMAND(ID_MENU_HELP_ABOUT, &CBoounionPLCDlg::OnMenuHelpAbout)
    ON_WM_INITMENUPOPUP()
    ON_MESSAGE(ID_MSG_TOOLBAR_BTN_CLICKED, &CBoounionPLCDlg::OnToolbarBtnClicked)
    ON_MESSAGE(ID_MSG_VIEW_ACTIVE, &CBoounionPLCDlg::OnViewActive)
    ON_MESSAGE(ID_MSG_BTN_CLICKED, &CBoounionPLCDlg::OnViewBtnClicked)
    ON_MESSAGE(ID_MSG_BTN_MENU_ITEM, &CBoounionPLCDlg::OnViewBtnMenuItem)
END_MESSAGE_MAP()
// CBoounionPLCDlg æ¶ˆæ¯å¤„理程序
void CBoounionPLCDlg::InitRxWindows()
{
    /* 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_SELECT_PLC == code) {
                CPLC* pPlc;
                if (pAny->getPtrValue("ptr", (void*&)pPlc)) {
                    ASSERT(m_pMainContainer != nullptr);
                    if (m_pActiveView == nullptr) {
                        m_pActiveView = (CPlcView*)CreatePlcView(pPlc);
                    }
                    ASSERT(m_pActiveView);
                    if (m_pActiveView->GetContext() != (void*)pPlc) {
                        m_pActiveView->SetWindowText(pPlc->getName().c_str());
                        m_pActiveView->SetContext(pPlc);
                    }
                }
            }
            pAny->release();
        }, [&]() -> void {
            // onComplete
        }, [&](IThrowable* pThrowable) -> void {
            // onErrorm
            pThrowable->printf();
        });
        theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
            ->subscribe(m_pObserver);
    }
}
BOOL CBoounionPLCDlg::OnInitDialog()
{
@@ -129,12 +175,19 @@
    m_pPagePlcList->ShowWindow(SW_SHOW);
    // ä¸»çª—口页
    m_pMainContainer = new CMainContainer();
    m_pMainContainer->Create(IDD_MAIN_CONTAINER, this);
    m_pMainContainer->ShowWindow(SW_SHOW);
    // èœå•
    CMenu menu;
    menu.LoadMenu(IDR_MENU_APP);
    SetMenu(&menu);
    InitRxWindows();
    ShowWindow(SW_MAXIMIZE);
    Resize();
@@ -278,12 +331,28 @@
        m_pPagePlcList = nullptr;
    }
    
    if (m_pMainContainer != nullptr) {
        m_pMainContainer->DestroyWindow();
        delete m_pMainContainer;
        m_pMainContainer = nullptr;
    }
    if (m_pActiveView != nullptr) {
        m_pActiveView->DestroyWindow();
        delete m_pActiveView;
        m_pActiveView = nullptr;
    }
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
        m_hbrBkgnd = nullptr;
    }
}
    if (m_pObserver != nullptr) {
        m_pObserver->unsubscribe();
        m_pObserver = NULL;
    }
}
void CBoounionPLCDlg::OnSize(UINT nType, int cx, int cy)
{
@@ -300,13 +369,15 @@
    CRect rcClient, rcItem;
    GetClientRect(&rcClient);
    int x = 0;
    int y = 0;
    m_pTopToolbar->MoveWindow(0, 0, rcClient.Width(), TOOLBAR_HEIGHT);
    y += TOOLBAR_HEIGHT;
    m_pPagePlcList->MoveWindow(0, y, PAGE_PLC_LIST_WIDTH, rcClient.Height() - y - 2);
    x = PAGE_PLC_LIST_WIDTH;
    m_pMainContainer->MoveWindow(x + 1, y, rcClient.Width() - x - 0, rcClient.bottom - y - 2);
}
HBRUSH CBoounionPLCDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
@@ -424,3 +495,62 @@
    return 0;
}
LRESULT CBoounionPLCDlg::OnViewActive(WPARAM wParam, LPARAM lParam)
{
    CBaseView* pView = (CBaseView*)wParam;
    int code = (int)lParam;
    if (code == MA_ACTIVATE || code == MA_ACTIVATEANDEAT) {
    }
    return 0;
}
LRESULT CBoounionPLCDlg::OnViewBtnClicked(WPARAM wParam, LPARAM lParam)
{
    int id = (int)lParam;
    if (id == VIEW_TOOL_BTN_CLOSE) {
        CloseView((CBaseView*)wParam);
    }
    return 0;
}
LRESULT CBoounionPLCDlg::OnViewBtnMenuItem(WPARAM wParam, LPARAM lParam)
{
    UINT id = (UINT)lParam;
    return 0;
}
CBaseView* CBoounionPLCDlg::CreatePlcView(CPLC* pPlc)
{
    CPlcView* pDlg = new CPlcView(m_pMainContainer);
    pDlg->SetContext(pPlc);
    pDlg->Create(IDD_VIEW_PLC, m_pMainContainer);
    CString strIcon0, strIcon1, strIcon2, strIcon3;
    strIcon0.Format(_T("%s\\Res\\small_close0.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    strIcon1.Format(_T("%s\\Res\\small_close1.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    strIcon2.Format(_T("%s\\Res\\small_close2.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    strIcon3.Format(_T("%s\\Res\\small_close3.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
    pDlg->AddToolBtn(VIEW_TOOL_BTN_CLOSE,
        (LPTSTR)(LPCTSTR)strIcon0,
        (LPTSTR)(LPCTSTR)strIcon1,
        (LPTSTR)(LPCTSTR)strIcon2,
        (LPTSTR)(LPCTSTR)strIcon3, "关闭");
    pDlg->SetWindowText(pPlc->getName().c_str());
    m_pMainContainer->Resize();
    return pDlg;
}
void CBoounionPLCDlg::CloseView(CBaseView* pView)
{
    pView->DestroyWindow();
    delete (CBaseView*)pView;
    m_pActiveView = nullptr;
    m_pMainContainer->Resize();
}
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h
@@ -5,6 +5,9 @@
#pragma once
#include "TopToolbar.h"
#include "PagePlcList.h"
#include "CMainContainer.h"
#include "CBaseView.h"
// CBoounionPLCDlg å¯¹è¯æ¡†
class CBoounionPLCDlg : public CDialogEx
@@ -14,8 +17,10 @@
    CBoounionPLCDlg(CWnd* pParent = NULL);    // æ ‡å‡†æž„造函数
private:
    void InitRxWindows();
    void Resize();
    CBaseView* CreatePlcView(CPLC* pPlc);
    void CloseView(CBaseView* pView);
private:
    COLORREF m_crBkgnd;
@@ -23,6 +28,8 @@
    IObserver* m_pObserver;
    CTopToolbar* m_pTopToolbar;
    CPagePlcList* m_pPagePlcList;
    CMainContainer* m_pMainContainer;
    CBaseView* m_pActiveView;
// å¯¹è¯æ¡†æ•°æ®
@@ -55,4 +62,7 @@
    afx_msg void OnUpdateMenuFileExit(CCmdUI* pCmdUI);
    afx_msg void OnMenuHelpAbout();
    afx_msg LRESULT OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam);
    LRESULT OnViewActive(WPARAM wParam, LPARAM lParam);
    LRESULT OnViewBtnClicked(WPARAM wParam, LPARAM lParam);
    LRESULT OnViewBtnMenuItem(WPARAM wParam, LPARAM lParam);
};
SourceCode/Bond/BoounionPLC/CBaseView.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,415 @@
#include "stdafx.h"
#include "CBaseView.h"
#include "Common.h"
#define CAPTION_HEIGHT        36
#define CAPBTN                99
IMPLEMENT_DYNAMIC(CBaseView, CDialogEx)
CBaseView::CBaseView(UINT id, CWnd* pPage) : CDialogEx(id, pPage)
{
    m_crBkgnd = BASE_VIEW_BACKGROUND;
    m_hbrBkgnd = nullptr;
    m_pContext = nullptr;
    m_nState = 0;
    m_pHotBtn = nullptr;
    m_pPressBtn = nullptr;
}
CBaseView::~CBaseView()
{
}
BEGIN_MESSAGE_MAP(CBaseView, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_ACTIVATE()
    ON_WM_NCPAINT()
    ON_WM_MOUSEACTIVATE()
    ON_WM_SIZE()
    ON_WM_NCCALCSIZE()
    ON_WM_LBUTTONDOWN()
    ON_WM_NCHITTEST()
    ON_WM_NCMOUSEMOVE()
    ON_WM_NCLBUTTONDOWN()
    ON_WM_NCLBUTTONUP()
END_MESSAGE_MAP()
HBRUSH CBaseView::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 CBaseView::OnDestroy()
{
    CDialogEx::OnDestroy();
}
void CBaseView::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
    CDialogEx::OnActivate(nState, pWndOther, bMinimized);
    if (WA_INACTIVE == nState) {
        OnApply();
    }
}
void CBaseView::OnNcPaint()
{
    // TODO: åœ¨æ­¤å¤„添加消息处理程序代码
    // ä¸ä¸ºç»˜å›¾æ¶ˆæ¯è°ƒç”¨ CDialogEx::OnNcPaint()
    RECT rect, rcClient;
    ::GetClientRect(m_hWnd, &rcClient);
    ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.left);
    ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.right);
    ::GetWindowRect(m_hWnd, &rect);
    ::OffsetRect(&rcClient, -rect.left, -rect.top);
    rect.right -= rect.left;
    rect.bottom -= rect.top;
    rect.left = 0;
    rect.top = 0;
    HRGN hRgnWnd = CreateRectRgnIndirect(&rect);
    HRGN hRgnClient = CreateRectRgnIndirect(&rcClient);
    HBRUSH hBrushBK, hBrushFrame;
    HDC hDC = ::GetWindowDC(m_hWnd);
    ::SelectClipRgn(hDC, hRgnWnd);
    ::ExtSelectClipRgn(hDC, hRgnClient, RGN_DIFF);
    // èƒŒæ™¯
    hBrushBK = CreateSolidBrush(m_crBkgnd);
    ::FillRect(hDC, &rect, hBrushBK);
    DeleteObject(hBrushBK);
    // æ ‡é¢˜æ ï¼Œæ–‡å­—,横线
    HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    ::SelectObject(hDC, hFont);
    RECT rcCaption, rcText;
    rcCaption = rect;
    rcCaption.bottom = rcCaption.top + CAPTION_HEIGHT;
    rcText = rcCaption;
    rcText.left += 12;
    char szCaption[64];
    int nCaptionLen = GetWindowText(szCaption, 64);
    ::DrawText(hDC, szCaption, nCaptionLen, &rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    HPEN hPen = CreatePen(PS_SOLID, 1, RGB(222, 222, 222));
    HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
    ::MoveToEx(hDC, 0, rcCaption.bottom, NULL);
    ::LineTo(hDC, rect.right, rcCaption.bottom);
    ::SelectObject(hDC, hOldPen);
    ::DeleteObject(hPen);
    // ç»˜åˆ¶æŒ‰é’®
    int y = (rcCaption.bottom - rcCaption.top - 24) / 2;
    int x = rcCaption.right - 12;
    for (auto& item : m_toolbtns) {
        if (item.hIcon != nullptr) {
            if (!item.bEnable) {
                DrawIconEx(hDC, x - 24, y,
                    item.hIcon[3], 24, 24, 0, 0, DI_NORMAL);
            }
            else if (m_pPressBtn == &item) {
                DrawIconEx(hDC, x - 24, y,
                    item.hIcon[2], 24, 24, 0, 0, DI_NORMAL);
            }
            else if (m_pHotBtn == &item) {
                DrawIconEx(hDC, x - 24, y,
                    item.hIcon[1], 24, 24, 0, 0, DI_NORMAL);
            }
            else {
                DrawIconEx(hDC, x - 24, y,
                    item.hIcon[0], 24, 24, 0, 0, DI_NORMAL);
            }
            x -= 24;
            x -= 3;
        }
    }
    hBrushFrame = CreateSolidBrush(RGB(255, 0, 0));
    // ::FrameRect(hDC, &rect, hBrushFrame);
    ::DeleteObject(hRgnWnd);
    ::DeleteObject(hRgnClient);
    DeleteObject(hBrushFrame);
    ::ReleaseDC(m_hWnd, hDC);
}
int CBaseView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    int nRet = CDialogEx::OnMouseActivate(pDesktopWnd, nHitTest, message);
    GetParent()->GetParent()->SendMessage(ID_MSG_VIEW_ACTIVE, (WPARAM)this, nRet);
    return nRet;
}
void CBaseView::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
    lpncsp->rgrc[0].top += (CAPTION_HEIGHT);
    CDialogEx::OnNcCalcSize(bCalcValidRects, lpncsp);
}
void CBaseView::SetContext(void* pContext)
{
    m_pContext = pContext;
}
void* CBaseView::GetContext()
{
    return m_pContext;
}
void CBaseView::OnApply()
{
}
void CBaseView::Show(CWnd* pParent, LPRECT lprcBtn)
{
    RECT rcClient, rcBox;
    pParent->GetClientRect(&rcClient);
    pParent->ClientToScreen(&rcClient);
    GetWindowRect(&rcBox);
    int x = lprcBtn->left;
    if (x + (rcBox.right - rcBox.left) > rcClient.right) {
        x = rcClient.right - (rcBox.right - rcBox.left);
    }
    SetWindowPos(NULL, x, lprcBtn->bottom + 2, 0, 0, SWP_NOSIZE);
    ShowWindow(SW_SHOW);
}
void CBaseView::OnViewActive()
{
    m_nState = 1;
    SendMessage(WM_NCPAINT, 0, 0);
}
void CBaseView::OnViewInactive()
{
    m_nState = 0;
    SendMessage(WM_NCPAINT, 0, 0);
}
void CBaseView::AddToolBtn(int id, const char* pszIcon0Path, const char* pszIcon1Path, const char* pszIcon2Path, const char* pszIcon3Path, const char* pszTooltip)
{
    TOOLBTN tb;
    memset(&tb, 0, sizeof(TOOLBTN));
    tb.id = id;
    tb.hIcon[0] = (HICON)::LoadImage(GetModuleHandle(NULL), pszIcon0Path, IMAGE_ICON, 24, 24,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    tb.hIcon[1] = (HICON)::LoadImage(GetModuleHandle(NULL), pszIcon1Path, IMAGE_ICON, 24, 24,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    tb.hIcon[2] = (HICON)::LoadImage(GetModuleHandle(NULL), pszIcon2Path, IMAGE_ICON, 24, 24,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    tb.hIcon[3] = (HICON)::LoadImage(GetModuleHandle(NULL), pszIcon3Path, IMAGE_ICON, 24, 24,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    strcpy_s(tb.szTooltip, 256, pszTooltip);
    tb.bEnable = TRUE;
    m_toolbtns.push_back(tb);
    EnableToolTips(TRUE);
}
void CBaseView::SetToolBtnEnable(int id, BOOL bEnable)
{
    CBaseView::TOOLBTN* pBtn = GetToolBtn(id);
    if (pBtn != nullptr) {
        pBtn->bEnable = bEnable;
        SendMessage(WM_NCPAINT);
    }
}
void CBaseView::SetToolBtnMenu(int id, HMENU hMenu)
{
    CBaseView::TOOLBTN* pBtn = GetToolBtn(id);
    if (pBtn != nullptr) {
        pBtn->hMenu = hMenu;
    }
}
void CBaseView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    CDialogEx::OnLButtonDown(nFlags, point);
}
LRESULT CBaseView::OnNcHitTest(CPoint point)
{
    TOOLBTN* pBtn;
    LRESULT hit = MyHitTest(point, pBtn);
    if (hit == HTCAPTION || hit == CAPBTN) {
        return hit;
    }
    return CDialogEx::OnNcHitTest(point);
}
void CBaseView::OnNcMouseMove(UINT nHitTest, CPoint point)
{
    TOOLBTN* pLastHot = m_pHotBtn;
    int code = MyHitTest(point, m_pHotBtn);
    if (pLastHot != m_pHotBtn) {
        SendMessage(WM_NCPAINT, 0, 0);
    }
    CDialogEx::OnNcMouseMove(nHitTest, point);
}
void CBaseView::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
    int code = MyHitTest(point, m_pPressBtn);
    SendMessage(WM_NCPAINT, 0, 0);
    GetParent()->GetParent()->SendMessage(ID_MSG_VIEW_ACTIVE, (WPARAM)this, MA_ACTIVATE);
    CDialogEx::OnNcLButtonDown(nHitTest, point);
}
void CBaseView::OnNcLButtonUp(UINT nHitTest, CPoint point)
{
    MyHitTest(point, m_pHotBtn);
    if (m_pPressBtn == m_pHotBtn && m_pPressBtn != nullptr && m_pPressBtn->bEnable) {
        if (m_pPressBtn->hMenu != nullptr) {
            int cmd = ::TrackPopupMenu(::GetSubMenu(m_pPressBtn->hMenu, 0),
                TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
                point.x, point.y + 2, 0, m_hWnd, NULL);
            GetParent()->GetParent()->PostMessage(ID_MSG_BTN_MENU_ITEM, (WPARAM)this, cmd);
        }
        else {
            GetParent()->GetParent()->PostMessage(ID_MSG_BTN_CLICKED, (WPARAM)this, m_pPressBtn->id);
        }
    }
    m_pPressBtn = nullptr;
    SendMessage(WM_NCPAINT, 0, 0);
    CDialogEx::OnNcLButtonUp(nHitTest, point);
}
int CBaseView::MyHitTest(POINT& point, TOOLBTN*& pBtn)
{
    RECT rcWnd, rcCaption;
    GetWindowRect(&rcWnd);
    LRESULT hit = HTNOWHERE;
    pBtn = nullptr;
    rcCaption.left = rcWnd.left + 2;
    rcCaption.right = rcWnd.right - 2;
    rcCaption.top = rcWnd.top += 2;
    rcCaption.bottom = rcCaption.top + 2 + CAPTION_HEIGHT;
    if (::PtInRect(&rcCaption, point)) {
        hit = HTCAPTION;
        RECT rcIcon;
        rcIcon.top = rcCaption.top + (rcCaption.bottom - rcCaption.top - 24) / 2;
        rcIcon.bottom = rcIcon.top + 24;
        rcIcon.right = rcCaption.right - 12;
        for (auto& item : m_toolbtns) {
            rcIcon.left = rcIcon.right - 24;
            if (::PtInRect(&rcIcon, point)) {
                pBtn = &item;
                hit = CAPBTN;
                break;
            }
            rcIcon.right = rcIcon.left - 3;
        }
    }
    return (int)hit;
}
CBaseView::TOOLBTN* CBaseView::GetToolBtn(int id)
{
    for (auto& item : m_toolbtns) {
        if (item.id == id) return &item;
    }
    return nullptr;
}
BOOL CBaseView::GetBtnRect(int id, LPRECT lprcBtn)
{
    RECT rcWnd, rcCaption;
    GetWindowRect(&rcWnd);
    ::OffsetRect(&rcWnd, -rcWnd.left, -rcWnd.top);
    rcCaption.left = rcWnd.left + 2;
    rcCaption.right = rcWnd.right - 2;
    rcCaption.top = rcWnd.top += 2;
    rcCaption.bottom = rcCaption.top + 2 + CAPTION_HEIGHT;
    lprcBtn->top = rcCaption.top + (rcCaption.bottom - rcCaption.top - 24) / 2;
    lprcBtn->bottom = lprcBtn->top + 24;
    lprcBtn->right = rcCaption.right - 12;
    for (auto& item : m_toolbtns) {
        lprcBtn->left = lprcBtn->right - 24;
        if (item.id == id) {
            return TRUE;
        }
        lprcBtn->right = lprcBtn->left - 3;
    }
    return FALSE;
}
INT_PTR CBaseView::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
    RECT rcClient, rcCaption, rcBtn;
    ::GetClientRect(m_hWnd, &rcClient);
    rcCaption.bottom = 0;
    rcCaption.top = rcCaption.bottom - CAPTION_HEIGHT;
    rcCaption.left = rcClient.left;
    rcCaption.right = rcClient.right;
    rcBtn.top = rcCaption.top + (rcCaption.bottom - rcCaption.top - 24) / 2;
    rcBtn.bottom = rcBtn.top + 24;
    rcBtn.right = rcCaption.right - 12;
    ::OffsetRect(&rcBtn, +5, -5);        // 5为边框粗的修正
    if ((point.y <= 0)) {
        for (auto& item : m_toolbtns) {
            rcBtn.left = rcBtn.right - 24;
            if (::PtInRect(&rcBtn, point)) {
                pTI->rect = rcBtn;
                pTI->hwnd = m_hWnd;
                pTI->uId = (UINT)1020; // Tooltip should show `1020
                pTI->lpszText = _tcsdup(item.szTooltip);
                return pTI->uId;
            }
            rcBtn.right = rcBtn.left - 3;
        }
    }
    return CDialogEx::OnToolHitTest(point, pTI);
}
SourceCode/Bond/BoounionPLC/CBaseView.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
#pragma once
#define ID_MSG_VIEW_ACTIVE        WM_USER+2356
#define ID_MSG_BTN_CLICKED        WM_USER+2357
#define ID_MSG_BTN_MENU_ITEM    WM_USER+2358
class CBaseView : public CDialogEx
{
private:
    typedef struct _TOOLBTN
    {
        int id;
        HICON hIcon[4];
        char szTooltip[256];
        BOOL bEnable;
        HMENU hMenu;
    } TOOLBTN;
    DECLARE_DYNAMIC(CBaseView)
public:
    CBaseView(UINT id, CWnd* pPage);   // æ ‡å‡†æž„造函数
    virtual ~CBaseView();
public:
    void OnViewActive();
    void OnViewInactive();
    void AddToolBtn(int id, const char* pszIcon0Path, const char* pszIcon1Path, const char* pszIcon2Path, const char* pszIcon3Path, const char* pszTooltip);
    void SetToolBtnEnable(int id, BOOL bEnable);
    void SetToolBtnMenu(int id, HMENU hMenu);
    void Show(CWnd* pParent, LPRECT lprcBtn);
    virtual void SetContext(void* pContext);
    void* GetContext();
    virtual void OnApply();
private:
    int MyHitTest(POINT& point, TOOLBTN*& pBtn);
    CBaseView::TOOLBTN* GetToolBtn(int id);
    BOOL GetBtnRect(int id, LPRECT lprcBtn);
private:
    std::vector<TOOLBTN> m_toolbtns;
    TOOLBTN* m_pHotBtn;
    TOOLBTN* m_pPressBtn;
    int m_nState;
protected:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    void* m_pContext;
    DECLARE_MESSAGE_MAP()
public:
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnDestroy();
    afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
    afx_msg void OnNcPaint();
    afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
    afx_msg void OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg LRESULT OnNcHitTest(CPoint point);
    afx_msg void OnNcMouseMove(UINT nHitTest, CPoint point);
    afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point);
    afx_msg void OnNcLButtonUp(UINT nHitTest, CPoint point);
    virtual INT_PTR OnToolHitTest(CPoint point, TOOLINFO* pTI) const;
};
SourceCode/Bond/BoounionPLC/CMainContainer.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,110 @@
// CMainContainer.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BoounionPLC.h"
#include "Common.h"
#include "CMainContainer.h"
#include "afxdialogex.h"
// CMainContainer å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CMainContainer, CDialogEx)
CMainContainer::CMainContainer(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_MAIN_CONTAINER, pParent)
{
    m_crBkgnd = MAIN_CONTAINER_BACKGROUND;
    m_hbrBkgnd = nullptr;
}
CMainContainer::~CMainContainer()
{
}
void CMainContainer::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMainContainer, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
END_MESSAGE_MAP()
// CMainContainer æ¶ˆæ¯å¤„理程序
BOOL CMainContainer::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CMainContainer::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 CMainContainer::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
}
void CMainContainer::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    Resize();
}
void CMainContainer::Resize()
{
    CRect rcClient;
    GetClientRect(&rcClient);
    // å…ˆå–得子窗口数量
    int count = 0;
    CWnd* pClild = FindWindowEx(m_hWnd, NULL, NULL, NULL);
    while (pClild != nullptr) {
        count++;
        pClild = FindWindowEx(m_hWnd, pClild->m_hWnd, NULL, NULL);
    }
    pClild = FindWindowEx(m_hWnd, NULL, NULL, NULL);
    while (pClild != nullptr) {
        pClild->MoveWindow(&rcClient);
        if (::GetProp(pClild->GetSafeHwnd(), "Home") == (HANDLE)1) {
            pClild->ShowWindow(count == 1 ? SW_SHOW : SW_HIDE);
        }
        else {
            pClild->ShowWindow(SW_SHOW);
        }
        pClild = FindWindowEx(m_hWnd, pClild->m_hWnd, NULL, NULL);
    }
}
SourceCode/Bond/BoounionPLC/CMainContainer.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
#pragma once
// CMainContainer å¯¹è¯æ¡†
class CMainContainer : public CDialogEx
{
    DECLARE_DYNAMIC(CMainContainer)
public:
    CMainContainer(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CMainContainer();
public:
    void Resize();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_MAIN_CONTAINER };
#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);
};
SourceCode/Bond/BoounionPLC/Common.h
@@ -6,9 +6,17 @@
#define RX_CODE_LOG                        1000
#define RX_CODE_ADD_PLC                    1001
#define RX_CODE_REMOVE_PLC                1002
#define RX_CODE_SELECT_PLC                1003
/* å®šåˆ¶é¢œè‰² */
#define APP_MAIN_DLG_BACKGROUND            RGB(255, 255, 255)    
#define TOP_TOOLBAR_BACKGROUND            RGB(240, 240, 240)    
#define PAGE_PLC_LIST_BACKGROUND        RGB(245, 245, 250)    
#define MAIN_CONTAINER_BACKGROUND        RGB(252, 252, 255)
#define BASE_VIEW_BACKGROUND            RGB(252, 252, 255)
#define PLC_VIEW_BACKGROUND                RGB(252, 252, 255)
/* æŒ‰é’®id */
#define VIEW_TOOL_BTN_CLOSE                0x1016
SourceCode/Bond/BoounionPLC/PagePlcList.cpp
@@ -35,6 +35,7 @@
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_MESSAGE(ID_MSG_TREE_CLICK_ITEM, OnTreeClickItem)
END_MESSAGE_MAP()
@@ -160,6 +161,17 @@
        rcItem.Width(), rcItem.Height());
}
LRESULT CPagePlcList::OnTreeClickItem(WPARAM wParam, LPARAM lParam)
{
    HTREEITEM hItem = (HTREEITEM)wParam;
    ASSERT(hItem);
    CPLC* pPlc = (CPLC*)m_treeCtrl.GetItemData(hItem);
    ASSERT(pPlc);
    theApp.m_model.notifyPtr(RX_CODE_SELECT_PLC, pPlc);
    return 0;
}
void CPagePlcList::ReadPLCList()
{
    //m_treeCtrl.InsertItem("PLC1", nullptr, nullptr);
SourceCode/Bond/BoounionPLC/PagePlcList.h
@@ -42,4 +42,5 @@
    afx_msg void OnDestroy();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    afx_msg LRESULT OnTreeClickItem(WPARAM wParam, LPARAM lParam);
};
SourceCode/Bond/BoounionPLC/PlcView.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,126 @@
#include "stdafx.h"
#include "PlcView.h"
#include "BoounionPLC.h"
#include "Common.h"
// CPlcView å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CPlcView, CBaseView)
CPlcView::CPlcView(CWnd* pParent /*=nullptr*/)
    : CBaseView(IDD_VIEW_PLC, pParent)
{
    m_pObserver = nullptr;
    m_crBkgnd = PLC_VIEW_BACKGROUND;
    m_hbrBkgnd = nullptr;
    m_pPlc = nullptr;
}
CPlcView::~CPlcView()
{
}
void CPlcView::DoDataExchange(CDataExchange* pDX)
{
    CBaseView::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CPlcView, CBaseView)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
END_MESSAGE_MAP()
// CComponentData1Dlg æ¶ˆæ¯å¤„理程序
void CPlcView::SetContext(void* pContext)
{
    CBaseView::SetContext(pContext);
    if (::IsWindow(m_hWnd) && m_pContext != nullptr) {
        SetDlgItemText(IDC_LABEL_PLC_NAME, ((CPLC*)m_pContext)->getName().c_str());
    }
}
void CPlcView::InitRxWindows()
{
    /* code */
    // è®¢é˜…数据
    IRxWindows* pRxWindows = RX_GetRxWindows();
    if (m_pObserver == NULL) {
        m_pObserver = pRxWindows->allocObserver([&](IAny* pAny) -> void {
            // onNext
            pAny->addRef();
            int code = pAny->getCode();
            pAny->release();
        }, [&]() -> void {
            // onComplete
        }, [&](IThrowable* pThrowable) -> void {
            // onErrorm
            pThrowable->printf();
        });
        theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
            ->subscribe(m_pObserver);
    }
}
BOOL CPlcView::OnInitDialog()
{
    CBaseView::OnInitDialog();
    if (m_pContext != nullptr) {
        SetDlgItemText(IDC_LABEL_PLC_NAME, ((CPLC*)m_pContext)->getName().c_str());
    }
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CPlcView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CBaseView::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 CPlcView::OnDestroy()
{
    CBaseView::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
    }
    if (m_pObserver != NULL) {
        m_pObserver->unsubscribe();
        m_pObserver = NULL;
    }
}
void CPlcView::OnSize(UINT nType, int cx, int cy)
{
    CBaseView::OnSize(nType, cx, cy);
}
void CPlcView::Resize()
{
    int y = 12;
    int x = 0;
    CRect rcClient, rcItem;
    CWnd* pItem;
    GetClientRect(&rcClient);
}
SourceCode/Bond/BoounionPLC/PlcView.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
#pragma once
#include "CBaseView.h"
#include "PLC.h"
class CPlcView :public CBaseView
{
    DECLARE_DYNAMIC(CPlcView)
public:
    CPlcView(CWnd* pParent = nullptr);
    ~CPlcView();
public:
    virtual void SetContext(void* pContext);
private:
    void InitRxWindows();
    void Resize();
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    IObserver* m_pObserver;
    CPLC* m_pPlc;
    // å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_VIEW_PLC};
#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);
};
SourceCode/Bond/BoounionPLC/Resource.h
Binary files differ
SourceCode/Bond/x64/BoounionPLC/Debug/Res/small_close0.ico
SourceCode/Bond/x64/BoounionPLC/Debug/Res/small_close1.ico
SourceCode/Bond/x64/BoounionPLC/Debug/Res/small_close2.ico
SourceCode/Bond/x64/BoounionPLC/Debug/Res/small_close3.ico