From 3175d60b3b6e3f43ae62193743c4017db27005dc Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期四, 09 一月 2025 10:15:52 +0800
Subject: [PATCH] 1.增加底部日志窗口;

---
 SourceCode/Bond/BoounionPLC/BoounionPLC.rc              |    0 
 SourceCode/Bond/BoounionPLC/Common.h                    |    2 
 SourceCode/Bond/BoounionPLC/Resource.h                  |    0 
 SourceCode/Bond/BoounionPLC/CMainContainer.cpp          |   22 ++
 SourceCode/Bond/BoounionPLC/CMainContainer.h            |    4 
 SourceCode/Bond/BoounionPLC/CPageLogcat.cpp             |  304 +++++++++++++++++++++++++++++++++
 SourceCode/Bond/BoounionPLC/LogEdit.h                   |   21 ++
 SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp          |    9 +
 SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h            |    2 
 SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters |   12 +
 SourceCode/Bond/BoounionPLC/LogEdit.cpp                 |   87 +++++++++
 SourceCode/Bond/BoounionPLC/CPageLogcat.h               |   56 ++++++
 SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj         |    4 
 13 files changed, 520 insertions(+), 3 deletions(-)

diff --git a/SourceCode/Bond/BoounionPLC/BoounionPLC.rc b/SourceCode/Bond/BoounionPLC/BoounionPLC.rc
index c27ba0d..265c082 100644
--- a/SourceCode/Bond/BoounionPLC/BoounionPLC.rc
+++ b/SourceCode/Bond/BoounionPLC/BoounionPLC.rc
Binary files differ
diff --git a/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj b/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj
index d697913..4877768 100644
--- a/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj
+++ b/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj
@@ -205,12 +205,14 @@
     <ClInclude Include="Component.h" />
     <ClInclude Include="Configuration.h" />
     <ClInclude Include="Context.h" />
+    <ClInclude Include="CPageLogcat.h" />
     <ClInclude Include="DBManager\AlarmManager.h" />
     <ClInclude Include="DBManager\AxisManager.h" />
     <ClInclude Include="DBManager\SystemLogManager.h" />
     <ClInclude Include="DBManager\UserManager.h" />
     <ClInclude Include="Intent.h" />
     <ClInclude Include="Log.h" />
+    <ClInclude Include="LogEdit.h" />
     <ClInclude Include="McBool.h" />
     <ClInclude Include="McInt.h" />
     <ClInclude Include="McItem.h" />
@@ -240,6 +242,7 @@
     <ClCompile Include="Component.cpp" />
     <ClCompile Include="Configuration.cpp" />
     <ClCompile Include="Context.cpp" />
+    <ClCompile Include="CPageLogcat.cpp" />
     <ClCompile Include="DBManager\AlarmManager.cpp">
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Use</PrecompiledHeader>
     </ClCompile>
@@ -248,6 +251,7 @@
     <ClCompile Include="DBManager\UserManager.cpp" />
     <ClCompile Include="Intent.cpp" />
     <ClCompile Include="Log.cpp" />
+    <ClCompile Include="LogEdit.cpp" />
     <ClCompile Include="McBool.cpp" />
     <ClCompile Include="McInt.cpp" />
     <ClCompile Include="McItem.cpp" />
diff --git a/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters b/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters
index d7d8301..0a58c07 100644
--- a/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters
+++ b/SourceCode/Bond/BoounionPLC/BoounionPLC.vcxproj.filters
@@ -123,6 +123,12 @@
     <ClInclude Include="DBManager\UserManager.h">
       <Filter>DBManager</Filter>
     </ClInclude>
+    <ClInclude Include="CPageLogcat.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="LogEdit.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="BoounionPLC.cpp">
@@ -218,6 +224,12 @@
     <ClCompile Include="DBManager\UserManager.cpp">
       <Filter>DBManager</Filter>
     </ClCompile>
+    <ClCompile Include="CPageLogcat.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="LogEdit.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="BoounionPLC.rc">
diff --git a/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp b/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp
index c7bd004..4930c5f 100644
--- a/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp
+++ b/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp
@@ -62,6 +62,7 @@
 	m_crBkgnd = APP_MAIN_DLG_BACKGROUND;
 	m_hbrBkgnd = nullptr;
 	m_pActiveView = nullptr;
+	m_pPageLogcat = nullptr;
 }
 
 void CBoounionPLCDlg::DoDataExchange(CDataExchange* pDX)
@@ -114,6 +115,7 @@
 					if (m_pActiveView->GetContext() != (void*)pPlc) {
 						m_pActiveView->SetWindowText(pPlc->getName().c_str());
 						m_pActiveView->SetContext(pPlc);
+						m_pActiveView->SendMessage(WM_NCPAINT, 0, 0);
 					}
 				}
 			}
@@ -193,6 +195,13 @@
 	m_pMainContainer->ShowWindow(SW_SHOW);
 
 
+	// 日志
+	m_pPageLogcat = new CPageLogcat();
+	m_pPageLogcat->Create(IDD_PAGE_LOGCAT, m_pMainContainer);
+	m_pPageLogcat->ShowWindow(SW_SHOW);
+	m_pMainContainer->SetBottomWnd(m_pPageLogcat, 220);
+
+
 	// 菜单
 	CMenu menu;
 	menu.LoadMenu(IDR_MENU_APP);
diff --git a/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h b/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h
index 286767b..60b7a7b 100644
--- a/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h
+++ b/SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h
@@ -8,6 +8,7 @@
 #include "CMainContainer.h"
 #include "CBaseView.h"
 #include "AlarmPopupDlg.h"
+#include "CPageLogcat.h"
 
 
 // CBoounionPLCDlg 对话框
@@ -33,6 +34,7 @@
 	CPagePlcList* m_pPagePlcList;
 	CMainContainer* m_pMainContainer;
 	CBaseView* m_pActiveView;
+	CPageLogcat* m_pPageLogcat;
 	CAlarmPopupDlg* m_pAlarmWnd;
 
 
diff --git a/SourceCode/Bond/BoounionPLC/CMainContainer.cpp b/SourceCode/Bond/BoounionPLC/CMainContainer.cpp
index 66365e6..861cc08 100644
--- a/SourceCode/Bond/BoounionPLC/CMainContainer.cpp
+++ b/SourceCode/Bond/BoounionPLC/CMainContainer.cpp
@@ -17,6 +17,8 @@
 {
 	m_crBkgnd = MAIN_CONTAINER_BACKGROUND;
 	m_hbrBkgnd = nullptr;
+	m_pBottomWnd = nullptr;
+	m_nBottomWndHeight = 0;
 }
 
 CMainContainer::~CMainContainer()
@@ -38,6 +40,12 @@
 
 // CMainContainer 娑堟伅澶勭悊绋嬪簭
 
+
+void CMainContainer::SetBottomWnd(CWnd* pWnd, int nHeight)
+{
+	m_pBottomWnd = pWnd;
+	m_nBottomWndHeight = nHeight;
+}
 
 BOOL CMainContainer::OnInitDialog()
 {
@@ -84,8 +92,12 @@
 
 void CMainContainer::Resize()
 {
-	CRect rcClient;
+	CRect rcClient, rcChild;
 	GetClientRect(&rcClient);
+	rcChild = rcClient;
+	if (m_pBottomWnd != nullptr && m_nBottomWndHeight > 0) {
+		rcChild.bottom -= m_nBottomWndHeight;
+	}
 
 	// 鍏堝彇寰楀瓙绐楀彛鏁伴噺
 	int count = 0;
@@ -97,7 +109,13 @@
 
 	pClild = FindWindowEx(m_hWnd, NULL, NULL, NULL);
 	while (pClild != nullptr) {
-		pClild->MoveWindow(&rcClient);
+		if (pClild != m_pBottomWnd) {
+			pClild->MoveWindow(&rcChild);
+		}
+		else if (m_pBottomWnd != nullptr) {
+			m_pBottomWnd->MoveWindow(0, rcChild.bottom, rcClient.Width(), rcClient.bottom - rcChild.bottom);
+		}
+
 		if (::GetProp(pClild->GetSafeHwnd(), "Home") == (HANDLE)1) {
 			pClild->ShowWindow(count == 1 ? SW_SHOW : SW_HIDE);
 		}
diff --git a/SourceCode/Bond/BoounionPLC/CMainContainer.h b/SourceCode/Bond/BoounionPLC/CMainContainer.h
index ff3d271..aa51cc2 100644
--- a/SourceCode/Bond/BoounionPLC/CMainContainer.h
+++ b/SourceCode/Bond/BoounionPLC/CMainContainer.h
@@ -14,11 +14,13 @@
 
 public:
 	void Resize();
-
+	void SetBottomWnd(CWnd* pWnd, int nHeight);
 
 private:
 	COLORREF m_crBkgnd;
 	HBRUSH m_hbrBkgnd;
+	CWnd* m_pBottomWnd;
+	int m_nBottomWndHeight;
 
 
 // 瀵硅瘽妗嗘暟鎹�
diff --git a/SourceCode/Bond/BoounionPLC/CPageLogcat.cpp b/SourceCode/Bond/BoounionPLC/CPageLogcat.cpp
new file mode 100644
index 0000000..9781053
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/CPageLogcat.cpp
@@ -0,0 +1,304 @@
+锘�// CPageLogcat.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "stdafx.h"
+#include "BoounionPLC.h"
+#include "Common.h"
+#include "CPageLogcat.h"
+#include "afxdialogex.h"
+#include <regex>
+
+
+// CPageLogcat 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CPageLogcat, CDialogEx)
+
+CPageLogcat::CPageLogcat(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_PAGE_LOGCAT, pParent)
+{
+	m_crBkgnd = LOGCAT_BACKGROUND_COLOR;
+	m_hbrBkgnd = nullptr;
+	m_pObserver = nullptr;
+	m_nLevel = 0;
+	m_strIncludeText = _T("");
+	m_bIncludeRegex = FALSE;
+}
+
+CPageLogcat::~CPageLogcat()
+{
+}
+
+void CPageLogcat::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+	DDX_Control(pDX, IDC_BUTTON_LEVEL, m_btnLevel);
+	DDX_Control(pDX, IDC_BUTTON_INCLUDE, m_btnInclude);
+	DDX_Control(pDX, IDC_EDIT_LOG, m_logEdit);
+	
+}
+
+
+BEGIN_MESSAGE_MAP(CPageLogcat, CDialogEx)
+	ON_WM_CTLCOLOR()
+	ON_WM_DESTROY()
+	ON_WM_SIZE()
+	ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_LEVEL, &CPageLogcat::OnButtonLevelMenuClicked)
+	ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_INCLUDE, &CPageLogcat::OnButtonIncludeMenuClicked)
+	ON_EN_CHANGE(IDC_EDIT_INCLUDE, &CPageLogcat::OnEnChangeEditInclude)
+	ON_BN_CLICKED(IDC_CHECK_REGEX, &CPageLogcat::OnBnClickedCheckRegex)
+END_MESSAGE_MAP()
+
+
+// CPageLogcat 娑堟伅澶勭悊绋嬪簭
+
+void CPageLogcat::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_LOG == code && ::IsWindow(m_hWnd)) {
+				const char* pszLogMsg;
+				int level;
+				if (pAny->getStringValue("text", pszLogMsg)
+					&& pAny->getIntValue("exCode", level)) {
+					if (level >= m_nLevel) {
+						CString strText = pszLogMsg;
+						BOOL bInclude = TRUE;
+						if (!m_strIncludeText.IsEmpty()) {
+							if (!m_bIncludeRegex) {
+								bInclude = (strText.Find(m_strIncludeText) >= 0);
+							}
+							else {
+								bInclude = std::regex_search((LPTSTR)(LPCTSTR)strText,
+									std::regex((LPTSTR)(LPCTSTR)m_strIncludeText));
+							}
+						}
+							
+							
+						if (bInclude) {
+							strText.Replace("\n", "\r\n");
+							AppendLog(level, (LPTSTR)(LPCTSTR)strText);
+						}
+					}
+				}
+			}
+
+			pAny->release();
+			}, [&]() -> void {
+				// onComplete
+			}, [&](IThrowable* pThrowable) -> void {
+				// onErrorm
+				pThrowable->printf();
+			});
+
+		theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
+			->subscribe(m_pObserver);
+	}
+}
+
+BOOL CPageLogcat::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+
+	// 缂撳瓨
+	m_nLevel = theApp.m_model.m_configuration.getLogcatLevel();
+	theApp.m_model.m_configuration.getLogcatIncludeText(m_strIncludeText);
+	m_bIncludeRegex = theApp.m_model.m_configuration.isLogcatIncludeRegex();
+	theApp.m_model.m_configuration.getCustomLogcatIncludeTexts(m_customIncludeTexts);
+
+
+	// Level
+	HMENU hMenu = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCEA(IDR_MENU_LOGCAT_LEVEL));
+	m_btnLevel.SetMenu(hMenu);
+	m_btnLevel.SetCurrentMenuItem(m_nLevel);
+	m_btnLevel.SetBkgndColor(BS_NORMAL, RGB(241, 242, 244));
+	m_btnLevel.SetBkgndColor(BS_HOVER, RGB(220, 223, 228));
+	m_btnLevel.SetBkgndColor(BS_PRESS, RGB(179, 185, 196));
+	m_btnLevel.SetFrameColor(BS_NORMAL, RGB(133, 144, 162));
+	m_btnLevel.SetFrameColor(BS_HOVER, RGB(56, 139, 255));
+	m_btnLevel.SetFrameColor(BS_PRESS, RGB(56, 139, 255));
+	m_btnLevel.SetFrameColor(BS_FOCUS, RGB(56, 139, 255));
+
+
+	// 鍖呭惈瀛楃涓�
+	CString strIcon1;
+	strIcon1.Format(_T("%s\\Res\\logcat_include.ico"), theApp.m_strAppDir);
+	HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(),
+		strIcon1, IMAGE_ICON, 24, 24,
+		LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
+	m_btnInclude.SetIcon(hIcon, hIcon, 24);
+
+	{
+		HMENU hMenu = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCEA(IDR_MENU_INCLUDE));
+		HMENU hSubMenu = GetSubMenu(hMenu, 0);
+		DeleteMenu(hSubMenu, 0, MF_BYPOSITION);
+		int i = 0;
+		for (auto& item : m_customIncludeTexts) {
+			i++;
+			InsertMenu(hSubMenu, 0, MF_BYPOSITION, 0x1998+i, item.c_str());
+			m_btnInclude.SetMenu(hMenu);
+		}
+	}
+
+
+	SetDlgItemText(IDC_EDIT_INCLUDE, m_strIncludeText);
+	CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK_REGEX);
+	pCheckBox->SetCheck(m_bIncludeRegex ? BST_CHECKED : BST_UNCHECKED);
+
+
+	// 鍐呭
+	m_logEdit.SetMaxLineCount(20);
+	m_logEdit.SetLimitText(-1);
+
+
+	InitRxWindow();
+
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+
+HBRUSH CPageLogcat::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 CPageLogcat::OnDestroy()
+{
+	CDialogEx::OnDestroy();
+
+	{
+		HMENU hMenu = m_btnLevel.GetMenu();
+		if (hMenu != NULL) {
+			::DestroyMenu(hMenu);
+		}
+	}
+
+	{
+		HMENU hMenu = m_btnInclude.GetMenu();
+		if (hMenu != NULL) {
+			::DestroyMenu(hMenu);
+		}
+	}
+
+	if (m_hbrBkgnd != nullptr) {
+		::DeleteObject(m_hbrBkgnd);
+	}
+
+	ASSERT(m_pObserver != NULL);
+	m_pObserver->unsubscribe();
+	m_pObserver = NULL;
+}
+
+
+void CPageLogcat::OnSize(UINT nType, int cx, int cy)
+{
+	CDialogEx::OnSize(nType, cx, cy);
+	if (GetDlgItem(IDC_EDIT_LOG) == nullptr) return;
+
+	int x, y, temp;
+	CRect rcClient, rcItem;
+	CWnd* pItem;
+	GetClientRect(&rcClient);
+
+	x = 12;
+	y = 0;
+	pItem = GetDlgItem(IDC_LINE1);
+	pItem->MoveWindow(x, y, rcClient.Width(), 2);
+
+	pItem = GetDlgItem(IDC_BUTTON_LEVEL);
+	pItem->GetWindowRect(&rcItem);
+	ScreenToClient(&rcItem);
+	pItem->MoveWindow(x, 12, rcItem.Width(), rcItem.Height());
+	x += rcItem.Width();
+	x += 18;
+	y = rcItem.bottom;
+	y += 12;
+
+	pItem = GetDlgItem(IDC_BUTTON_INCLUDE);
+	pItem->GetWindowRect(&rcItem);
+	pItem->MoveWindow(x, 12, rcItem.Width(), rcItem.Height());
+	x += rcItem.Width();
+	x += 2;
+
+	pItem = GetDlgItem(IDC_EDIT_INCLUDE);
+	pItem->GetWindowRect(&rcItem);
+	pItem->MoveWindow(x, 12, rcItem.Width(), rcItem.Height());
+	x += rcItem.Width();
+	x += 12;
+	temp = rcItem.Height();
+
+	pItem = GetDlgItem(IDC_CHECK_REGEX);
+	pItem->GetWindowRect(&rcItem);
+	pItem->MoveWindow(x, 12 + (temp - rcItem.Height()) / 2, rcItem.Width(), rcItem.Height());
+
+	pItem = GetDlgItem(IDC_EDIT_LOG);
+	pItem->MoveWindow(12, y, rcClient.Width() - 24, rcClient.Height() - 12 - y);
+
+}
+
+void CPageLogcat::AppendLog(int level, const char* pszText)
+{
+	if (!::IsWindow(m_logEdit.m_hWnd)) {
+		return;
+	}
+	m_logEdit.AppendText(pszText);
+}
+
+void CPageLogcat::OnButtonLevelMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
+{
+	BLBUTTON_NMHDR* pblbNmhdr = reinterpret_cast<BLBUTTON_NMHDR*>(pNMHDR);
+	m_nLevel = (int)pblbNmhdr->dwData;
+	theApp.m_model.m_configuration.setLogcatLevel(m_nLevel);
+	m_btnLevel.SetCurrentMenuItem(m_nLevel);
+
+	*pResult = 0;
+}
+
+void CPageLogcat::OnButtonIncludeMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
+{
+	BLBUTTON_NMHDR* pblbNmhdr = reinterpret_cast<BLBUTTON_NMHDR*>(pNMHDR);
+	int position = (int)pblbNmhdr->dwData;
+	std::string& strInclude = m_customIncludeTexts.at(position);
+	SetDlgItemText(IDC_EDIT_INCLUDE, strInclude.c_str());
+	CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK_REGEX);
+	m_bIncludeRegex = FALSE;
+	pCheckBox->SetCheck(BST_UNCHECKED);
+
+	theApp.m_model.m_configuration.setLogcatIncludeRegex(m_bIncludeRegex);
+	theApp.m_model.m_configuration.setLogcatIncludeText(m_strIncludeText);
+
+	*pResult = 0;
+}
+
+void CPageLogcat::OnEnChangeEditInclude()
+{
+	GetDlgItemText(IDC_EDIT_INCLUDE, m_strIncludeText);
+	theApp.m_model.m_configuration.setLogcatIncludeText(m_strIncludeText);
+}
+
+void CPageLogcat::OnBnClickedCheckRegex()
+{
+	CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK_REGEX);
+	m_bIncludeRegex = pCheckBox->GetCheck();
+	theApp.m_model.m_configuration.setLogcatIncludeRegex(m_bIncludeRegex);
+}
diff --git a/SourceCode/Bond/BoounionPLC/CPageLogcat.h b/SourceCode/Bond/BoounionPLC/CPageLogcat.h
new file mode 100644
index 0000000..78eae19
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/CPageLogcat.h
@@ -0,0 +1,56 @@
+锘�#pragma once
+#include "BlButton.h"
+#include "LogEdit.h"
+#include <vector>
+#include <string>
+
+
+// CPageLogcat 瀵硅瘽妗�
+
+class CPageLogcat : public CDialogEx
+{
+	DECLARE_DYNAMIC(CPageLogcat)
+
+public:
+	CPageLogcat(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CPageLogcat();
+
+
+private:
+	void InitRxWindow();
+	void AppendLog(int level, const char* pszText);
+
+
+private:
+	COLORREF m_crBkgnd;
+	HBRUSH m_hbrBkgnd;
+	IObserver* m_pObserver;
+	int m_nLevel;
+	CString m_strIncludeText;
+	BOOL m_bIncludeRegex;
+	std::vector<std::string> m_customIncludeTexts;
+
+private:
+	CBlButton m_btnLevel;
+	CBlButton m_btnInclude;
+	CLogEdit m_logEdit;
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_PAGE_LOGCAT };
+#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 OnButtonLevelMenuClicked(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnButtonIncludeMenuClicked(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnEnChangeEditInclude();
+	afx_msg void OnBnClickedCheckRegex();
+};
diff --git a/SourceCode/Bond/BoounionPLC/Common.h b/SourceCode/Bond/BoounionPLC/Common.h
index 6f11ade..deaea4c 100644
--- a/SourceCode/Bond/BoounionPLC/Common.h
+++ b/SourceCode/Bond/BoounionPLC/Common.h
@@ -19,6 +19,8 @@
 #define MAIN_CONTAINER_BACKGROUND		RGB(252, 252, 255)
 #define BASE_VIEW_BACKGROUND			RGB(252, 252, 255)
 #define PLC_VIEW_BACKGROUND				RGB(252, 252, 255)
+#define LOGCAT_BACKGROUND_COLOR			RGB(252, 252, 255)
+
 
 /* 解除警告 按钮 */
 #define BTN_ALARM_OFF_FRAME_NORMAL		RGB(88, 88, 88)
diff --git a/SourceCode/Bond/BoounionPLC/LogEdit.cpp b/SourceCode/Bond/BoounionPLC/LogEdit.cpp
new file mode 100644
index 0000000..0e9fd35
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/LogEdit.cpp
@@ -0,0 +1,87 @@
+#include "stdafx.h"
+#include "LogEdit.h"
+
+
+#define MENU_ITEM_SEL_ALL		0x666
+#define MENU_ITEM_COPY			0x667
+#define MENU_ITEM_CLEAR			0x668
+
+CLogEdit::CLogEdit()
+{
+	m_nMaxLineCount = 0xffff;
+}
+
+
+CLogEdit::~CLogEdit()
+{
+}
+
+BEGIN_MESSAGE_MAP(CLogEdit, CEdit)
+	ON_WM_CONTEXTMENU()
+END_MESSAGE_MAP()
+
+void CLogEdit::SetMaxLineCount(int line)
+{
+	m_nMaxLineCount = line;
+}
+
+void CLogEdit::OnContextMenu(CWnd* pWnd, CPoint point)
+{
+	HMENU hMenu = CreatePopupMenu();
+	InsertMenu(hMenu, 0, MF_BYPOSITION, MENU_ITEM_SEL_ALL, "全选");
+	InsertMenu(hMenu, 1, MF_BYPOSITION, MENU_ITEM_COPY, "复制");
+	InsertMenu(hMenu, 2, MF_BYPOSITION | MF_SEPARATOR, NULL, NULL);	
+	InsertMenu(hMenu, 3, MF_BYPOSITION, MENU_ITEM_CLEAR, "全部清除");
+	int cmd = ::TrackPopupMenu(hMenu,
+		TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
+		point.x, point.y + 2, 0, m_hWnd, NULL);
+	DestroyMenu(hMenu);
+
+	if (cmd == MENU_ITEM_SEL_ALL) {
+		SetFocus();
+		this->SetSel(0, -1);
+	}
+	else if (cmd == MENU_ITEM_COPY) {
+		this->Copy();
+	}
+	else if (cmd == MENU_ITEM_CLEAR) {
+		SetWindowText(_T(""));
+	}
+}
+
+void CLogEdit::AppendText(const char* pszText)
+{
+	// 获取选择范围以便恢复
+	int nStart, nEnd;
+	GetSel(nStart, nEnd);
+
+
+	// 超过指定行数则删除最前面的行
+	int nLineCount = GetLineCount();
+	while (nLineCount > m_nMaxLineCount) {
+		int nLin1End = LineIndex(1);
+		nStart -= nLin1End;
+		if (nStart < 0) nStart = 0;
+		nEnd -= nLin1End;
+		if (nEnd < 0) nEnd = 0;
+
+		SetSel(0, nLin1End);
+		ReplaceSel(_T(""));
+		nLineCount = GetLineCount();
+	}
+
+
+	// 追加到最后
+	int length = GetWindowTextLength();
+	SetSel(length, length);
+	ReplaceSel(pszText);
+	PostMessage(WM_VSCROLL, SB_BOTTOM, 0);
+
+
+	// 恢复
+	if (nStart == 0 && nEnd == 0) {
+		nStart = GetWindowTextLength();
+		nEnd = nStart;
+	}
+	SetSel(nStart, nEnd);
+}
diff --git a/SourceCode/Bond/BoounionPLC/LogEdit.h b/SourceCode/Bond/BoounionPLC/LogEdit.h
new file mode 100644
index 0000000..cdccb5c
--- /dev/null
+++ b/SourceCode/Bond/BoounionPLC/LogEdit.h
@@ -0,0 +1,21 @@
+#pragma once
+#include "afxwin.h"
+class CLogEdit :
+	public CEdit
+{
+public:
+	CLogEdit();
+	~CLogEdit();
+
+public:
+	void SetMaxLineCount(int line);
+	void AppendText(const char* pszText);
+
+
+private:
+	int m_nMaxLineCount;
+
+	DECLARE_MESSAGE_MAP()
+	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
+};
+
diff --git a/SourceCode/Bond/BoounionPLC/Resource.h b/SourceCode/Bond/BoounionPLC/Resource.h
index 1e2104c..7f80a40 100644
--- a/SourceCode/Bond/BoounionPLC/Resource.h
+++ b/SourceCode/Bond/BoounionPLC/Resource.h
Binary files differ

--
Gitblit v1.9.3