// SystemLogManagerDlg.cpp: 实现文件 // #include "stdafx.h" #include "BondEq.h" #include "afxdialogex.h" #include "SystemLogManagerDlg.h" // CSystemLogManagerDlg 对话框 IMPLEMENT_DYNAMIC(CSystemLogManagerDlg, CDialogEx) CSystemLogManagerDlg::CSystemLogManagerDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_DIALOG_SYSTEM_LOG_MANAGER, pParent) { } CSystemLogManagerDlg::~CSystemLogManagerDlg() { for (auto& pair : m_mapFonts) { if (pair.second) { pair.second->DeleteObject(); delete pair.second; } } m_mapFonts.clear(); } void CSystemLogManagerDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_COMBO_TYPE, m_comboType); DDX_Control(pDX, IDC_COMBO_USER, m_comboUser); DDX_Control(pDX, IDC_DATETIMEPICKER_START, m_dateTimeStart); DDX_Control(pDX, IDC_DATETIMEPICKER_END, m_dateTimeEnd); DDX_Control(pDX, IDC_EDIT_DESCRIPTION, m_editDescription); DDX_Control(pDX, IDC_CUSTOM_LIST_LOGS, m_listLogs); DDX_Control(pDX, IDC_STATIC_PAGE_NUMBER, m_staticPageNum); } void CSystemLogManagerDlg::InitSystemLogManager() { if (m_listLogs.GetSafeHwnd() == NULL) return; int nRows = 21; // 包括表头(1 行)和数据(20 行) int nCols = 5; int nFixRows = 1; int nFixCols = 0; int nRowIdx = 0; int nColIdx = 0; m_listLogs.DeleteAllItems(); m_listLogs.SetVirtualMode(FALSE); m_listLogs.GetDefaultCell(TRUE, FALSE)->SetBackClr(g_nGridFixCellColor); // 设置固定行背景色 m_listLogs.GetDefaultCell(FALSE, TRUE)->SetBackClr(g_nGridFixCellColor); // 设置固定列背景色 m_listLogs.GetDefaultCell(FALSE, FALSE)->SetBackClr(g_nGridCellColor); // 设置单元格背景色 m_listLogs.SetFixedTextColor(g_nGridFixFontColor); // 设置固定行列字体颜色 m_listLogs.SetRowCount(nRows); m_listLogs.SetColumnCount(nCols); m_listLogs.SetFixedRowCount(nFixRows); m_listLogs.SetFixedColumnCount(nFixCols); // Col m_listLogs.SetColumnWidth(nColIdx, 10); m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("No.")); m_listLogs.SetColumnWidth(nColIdx, 10); m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("类型")); m_listLogs.SetColumnWidth(nColIdx, 200); m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("事件")); m_listLogs.SetColumnWidth(nColIdx, 30); m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("用户")); m_listLogs.SetColumnWidth(nColIdx, 70); m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("时间")); // 创建 20 行空白数据行 for (int i = 1; i < nRows; ++i) { for (int j = 0; j < nCols; ++j) { m_listLogs.SetItemText(i, j, _T("")); // 初始化为空字符串 } } m_listLogs.SetFixedRowSelection(FALSE); m_listLogs.SetFixedColumnSelection(FALSE); m_listLogs.SetEditable(FALSE); m_listLogs.SetRowResize(FALSE); m_listLogs.SetColumnResize(TRUE); m_listLogs.ExpandColumnsToFit(TRUE); m_listLogs.SetListMode(TRUE); // 启用列表模式 m_listLogs.EnableSelection(TRUE); // 启用选择 m_listLogs.SetSingleRowSelection(TRUE); // 自动整行高亮(限制为单行选择) m_listLogs.ExpandLastColumn(); // 最后一列填充网格 try { FillSystemLogManager(); } catch (const std::exception& ex) { CString errorMsg; errorMsg.Format(_T("初始化运行日志失败:%s"), CString(ex.what())); AfxMessageBox(errorMsg, MB_ICONERROR); } } void CSystemLogManagerDlg::FillSystemLogManager() { // 获取筛选条件 CString selectedType, selectedUser, description; m_comboType.GetLBText(m_comboType.GetCurSel(), selectedType); m_comboUser.GetLBText(m_comboUser.GetCurSel(), selectedUser); m_editDescription.GetWindowText(description); COleDateTime startTime, endTime; m_dateTimeStart.GetTime(startTime); m_dateTimeEnd.GetTime(endTime); CString strStartTime = startTime.Format(_T("%Y-%m-%d %H:%M:%S")); CString strEndTime = endTime.Format(_T("%Y-%m-%d %H:%M:%S")); std::string type = CT2A(selectedType); std::string user = CT2A(selectedUser); std::string desc = CT2A(description); std::string start = CT2A(strStartTime); std::string end = CT2A(strEndTime); // 获取日志管理实例 SystemLogManager& logManager = SystemLogManager::getInstance(); int pageSize = 20; // 每页显示 20 条记录 int totalRecords = logManager.getTotalLogCount(type, user, desc, start, end); m_nTotalPages = (totalRecords + pageSize - 1) / pageSize; auto logs = logManager.getFilteredLogs(type, user, desc, start, end, m_nCurrentPage, pageSize); // 更新表格数据 int rowIdx = 1; for (const auto& log : logs) { m_listLogs.SetItemText(rowIdx, 0, CString(std::to_string(rowIdx).c_str())); // 序号 m_listLogs.SetItemText(rowIdx, 1, CString(log[1].c_str())); // 类型 m_listLogs.SetItemText(rowIdx, 2, CString(log[2].c_str())); // 事件 m_listLogs.SetItemText(rowIdx, 3, CString(log[3].c_str())); // 用户 m_listLogs.SetItemText(rowIdx, 4, CString(log[4].c_str())); // 时间 ++rowIdx; } // 清空多余行 for (; rowIdx <= 20; ++rowIdx) { m_listLogs.SetItemText(rowIdx, 0, CString(std::to_string(rowIdx).c_str())); // 序号列 for (int colIdx = 1; colIdx < m_listLogs.GetColumnCount(); ++colIdx) { m_listLogs.SetItemText(rowIdx, colIdx, _T("")); } } m_listLogs.Invalidate(); m_listLogs.UpdateWindow(); m_listLogs.ExpandColumnsToFit(FALSE); m_listLogs.ExpandLastColumn(); UpdatePageInfo(); } void CSystemLogManagerDlg::UpdatePageInfo() { // 格式化页码信息为 "当前页/总页数" CString pageInfo; pageInfo.Format(_T("%d/%d 页"), m_nCurrentPage, m_nTotalPages); m_staticPageNum.SetWindowText(pageInfo); } void CSystemLogManagerDlg::SetDefaultFont() { CFont* defaultFont = nullptr; // 如果字体管理容器中有默认大小(如 12)的字体,直接使用 auto it = m_mapFonts.find(12); if (it != m_mapFonts.end()) { defaultFont = it->second; } else { // 创建默认字体 defaultFont = new CFont(); LOGFONT logFont = { 0 }; _tcscpy_s(logFont.lfFaceName, _T("Segoe UI")); logFont.lfHeight = -12; logFont.lfQuality = CLEARTYPE_QUALITY; defaultFont->CreateFontIndirect(&logFont); m_mapFonts[12] = defaultFont; // 存储到字体管理容器 } // 遍历所有控件,应用默认字体 CWnd* pWnd = GetWindow(GW_CHILD); while (pWnd) { // 跳过特殊控件(如 MFCGridCtrl) TCHAR szClassName[256]; GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName)); if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) { pWnd = pWnd->GetNextWindow(); continue; } pWnd->SetFont(defaultFont, TRUE); pWnd = pWnd->GetNextWindow(); } } void CSystemLogManagerDlg::AdjustControls(int nWidth, int nHeight) { CWnd* pWnd = GetWindow(GW_CHILD); while (pWnd) { UINT nCtrlID = pWnd->GetDlgCtrlID(); CRect ctrlRect; pWnd->GetWindowRect(&ctrlRect); ScreenToClient(&ctrlRect); // 计算控件的新位置和大小,按比例调整 int newX = (int)(ctrlRect.left * (nWidth / (float)m_nInitialWidth)); int newY = (int)(ctrlRect.top * (nHeight / (float)m_nInitialHeight)); int newWidth = (int)(ctrlRect.Width() * (nWidth / (float)m_nInitialWidth)); int newHeight = (int)(ctrlRect.Height() * (nHeight / (float)m_nInitialHeight)); TCHAR szClassName[256]; GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName)); if (_tcsicmp(szClassName, _T("ComboBox")) == 0) { CComboBox* pComboBox = (CComboBox*)pWnd; pComboBox->SetItemHeight(-1, nHeight); // -1 表示所有项的高度 } if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) { CGridCtrl* pGridCtrl = (CGridCtrl*)pWnd; pGridCtrl->SetDefCellHeight(newHeight / 21); pGridCtrl->ExpandColumnsToFit(TRUE); pGridCtrl->Invalidate(); } pWnd->MoveWindow(newX, newY, newWidth, newHeight); AdjustControlFont(pWnd, newWidth, newHeight); // 获取下一个控件 pWnd = pWnd->GetNextWindow(); } } void CSystemLogManagerDlg::AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight) { TCHAR szClassName[256]; GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName)); // 跳过特殊控件(如 MFCGridCtrl) if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) { return; } // 根据控件高度动态调整字体大小 int fontSize = nHeight / 2; if (fontSize < 8) fontSize = 8; // 检查字体是否已经存在 auto it = m_mapFonts.find(fontSize); if (it == m_mapFonts.end()) { // 动态创建新字体 CFont* newFont = new CFont(); LOGFONT logFont = { 0 }; _tcscpy_s(logFont.lfFaceName, _T("Segoe UI")); logFont.lfHeight = -fontSize; logFont.lfQuality = CLEARTYPE_QUALITY; // 启用 ClearType 抗锯齿 newFont->CreateFontIndirect(&logFont); // 存储到字体管理容器中 m_mapFonts[fontSize] = newFont; it = m_mapFonts.find(fontSize); } pWnd->SetFont(it->second); pWnd->Invalidate(); // 刷新控件显示 } void CSystemLogManagerDlg::AdjustComboBoxStyle(CComboBox& comboBox) { DWORD dwStyle = comboBox.GetStyle(); comboBox.ModifyStyle(0, CBS_DROPDOWNLIST | CBS_HASSTRINGS | CBS_OWNERDRAWFIXED); comboBox.Invalidate(); comboBox.UpdateWindow(); } void CSystemLogManagerDlg::AdjustDateTimeCtrlStyle(CDateTimeCtrl& dateTimeCtrl) { dateTimeCtrl.ModifyStyle(0, DTS_RIGHTALIGN); dateTimeCtrl.Invalidate(); dateTimeCtrl.UpdateWindow(); } BEGIN_MESSAGE_MAP(CSystemLogManagerDlg, CDialogEx) ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CSystemLogManagerDlg::OnBnClickedButtonSearch) ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CSystemLogManagerDlg::OnBnClickedButtonPrevPage) ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CSystemLogManagerDlg::OnBnClickedButtonNextPage) ON_CBN_SELCHANGE(IDC_COMBO_TYPE, &CSystemLogManagerDlg::OnSelchangeComboType) ON_CBN_SELCHANGE(IDC_COMBO_USER, &CSystemLogManagerDlg::OnSelchangeComboUser) ON_WM_SIZE() END_MESSAGE_MAP() // CSystemLogManagerDlg 消息处理程序 BOOL CSystemLogManagerDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // TODO: 在此添加额外的初始化 SetWindowText(_T("系统运行日志")); // 设置默认字体 SetDefaultFont(); m_nCurrentPage = 1; // 从第一页开始 m_nTotalPages = 1; // 默认总页数为 1 m_comboType.AddString(_T("ALL")); m_comboType.AddString(_T("信息")); m_comboType.AddString(_T("操作")); m_comboType.AddString(_T("错误")); m_comboType.AddString(_T("未知")); m_comboType.SetCurSel(0); m_comboUser.AddString(_T("ALL")); m_comboUser.AddString(_T("SYSTEM")); auto usernames = UserManager::getInstance().getUsernames(); for (const auto& username : usernames) { CString cstrUsername(username.c_str()); m_comboUser.AddString(cstrUsername); } m_comboUser.SetCurSel(0); // 设置为 30 天前 COleDateTime currentTime = COleDateTime::GetCurrentTime(); COleDateTime defaultStartTime = currentTime - COleDateTimeSpan(30, 0, 0, 0); m_dateTimeStart.SetTime(defaultStartTime); CRect screenRect, dlgRect, clientRect; GetClientRect(&clientRect); m_nInitialWidth = clientRect.Width(); m_nInitialHeight = clientRect.Height(); GetWindowRect(&dlgRect); int dlgWidth = dlgRect.Width() * 2; int dlgHeight = dlgRect.Height() * 2; SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0); if (dlgWidth > screenRect.Width()) { dlgWidth = screenRect.Width(); } if (dlgHeight > screenRect.Height()) { dlgHeight = screenRect.Height(); } int centerX = screenRect.left + (screenRect.Width() - dlgWidth) / 2; int centerY = screenRect.top + (screenRect.Height() - dlgHeight) / 2; MoveWindow(centerX, centerY, dlgWidth, dlgHeight); InitSystemLogManager(); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } void CSystemLogManagerDlg::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); // TODO: 在此处添加消息处理程序代码 CRect rect; GetClientRect(&rect); // 遍历对话框中的所有控件 AdjustControls(rect.Width(), rect.Height()); } void CSystemLogManagerDlg::OnBnClickedButtonSearch() { // TODO: 在此添加控件通知处理程序代码 try { m_nCurrentPage = 1; FillSystemLogManager(); } catch (const std::exception& ex) { CString errorMsg; errorMsg.Format(_T("搜索失败:%s"), CString(ex.what())); AfxMessageBox(errorMsg, MB_ICONERROR); } } void CSystemLogManagerDlg::OnBnClickedButtonPrevPage() { // TODO: 在此添加控件通知处理程序代码 try { if (m_nCurrentPage > 1) { m_nCurrentPage--; FillSystemLogManager(); } else { AfxMessageBox(_T("已经是第一页!")); } } catch (const std::exception& ex) { CString errorMsg; errorMsg.Format(_T("切换到上一页失败:%s"), CString(ex.what())); AfxMessageBox(errorMsg, MB_ICONERROR); } } void CSystemLogManagerDlg::OnBnClickedButtonNextPage() { // TODO: 在此添加控件通知处理程序代码 try { if (m_nCurrentPage < m_nTotalPages) { m_nCurrentPage++; FillSystemLogManager(); } else { AfxMessageBox(_T("已经是最后一页!")); } } catch (const std::exception& ex) { CString errorMsg; errorMsg.Format(_T("切换到下一页失败:%s"), CString(ex.what())); AfxMessageBox(errorMsg, MB_ICONERROR); } } void CSystemLogManagerDlg::OnSelchangeComboType() { // TODO: 在此添加控件通知处理程序代码 try { m_nCurrentPage = 1; FillSystemLogManager(); } catch (const std::exception& ex) { CString errorMsg; errorMsg.Format(_T("切换类型失败:%s"), CString(ex.what())); AfxMessageBox(errorMsg, MB_ICONERROR); } } void CSystemLogManagerDlg::OnSelchangeComboUser() { // TODO: 在此添加控件通知处理程序代码 try { m_nCurrentPage = 1; FillSystemLogManager(); } catch (const std::exception& ex) { CString errorMsg; errorMsg.Format(_T("切换角色失败:%s"), CString(ex.what())); AfxMessageBox(errorMsg, MB_ICONERROR); } }