#include "stdafx.h" #include "Servo.h" #include "CUserXLogDlg.h" #include "afxdialogex.h" #include #include #include namespace { std::wstring ReadBufferVia(const std::function& fn) { int need = fn(nullptr, 0); if (need <= 0) { return L""; } std::wstring buffer; buffer.resize(static_cast(need)); if (fn(buffer.data(), need) == UX_OK) { if (!buffer.empty() && buffer.back() == L'\0') { buffer.pop_back(); } return buffer; } return L""; } std::vector SplitLines(const std::wstring& text) { std::vector lines; std::wstringstream ss(text); std::wstring line; while (std::getline(ss, line)) { lines.push_back(line); } return lines; } } IMPLEMENT_DYNAMIC(CUserXLogDlg, CDialogEx) CUserXLogDlg::CUserXLogDlg(CWnd* pParent) : CDialogEx(IDD_DIALOG_USERX_LOG, pParent) { } CUserXLogDlg::~CUserXLogDlg() { } void CUserXLogDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST1, m_listLogs); } BEGIN_MESSAGE_MAP(CUserXLogDlg, CDialogEx) ON_WM_SIZE() ON_WM_DESTROY() END_MESSAGE_MAP() BOOL CUserXLogDlg::OnInitDialog() { CDialogEx::OnInitDialog(); InitListCtrl(); RefreshLogs(); AdjustLayout(); return TRUE; } void CUserXLogDlg::InitListCtrl() { DWORD dwStyle = m_listLogs.GetExtendedStyle(); m_listLogs.SetExtendedStyle(dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); m_listLogs.InsertColumn(0, _T("时间"), LVCFMT_LEFT, 180); m_listLogs.InsertColumn(1, _T("用户"), LVCFMT_LEFT, 120); m_listLogs.InsertColumn(2, _T("动作"), LVCFMT_LEFT, 120); m_listLogs.InsertColumn(3, _T("描述"), LVCFMT_LEFT, 200); } void CUserXLogDlg::RefreshLogs() { m_logs.clear(); m_listLogs.DeleteAllItems(); auto allLogs = ReadBufferVia([](wchar_t* buffer, int size) { return UX_QueryLogs(200, buffer, size); }); for (auto& rawLine : SplitLines(allLogs)) { if (rawLine.empty()) continue; auto trim = [](std::wstring value) { size_t first = value.find_first_not_of(L" \t\r\n"); size_t last = value.find_last_not_of(L" \t\r\n"); if (first == std::wstring::npos || last == std::wstring::npos) { return std::wstring(); } return value.substr(first, last - first + 1); }; auto takeField = [&](size_t& cursor) { if (cursor == std::wstring::npos || cursor >= rawLine.length()) { return std::wstring(); } size_t pos = rawLine.find(L',', cursor); std::wstring part = (pos == std::wstring::npos) ? rawLine.substr(cursor) : rawLine.substr(cursor, pos - cursor); cursor = (pos == std::wstring::npos) ? std::wstring::npos : pos + 1; return trim(part); }; size_t cursor = 0; LogItem item; item.time = takeField(cursor).c_str(); item.user = takeField(cursor).c_str(); item.action = takeField(cursor).c_str(); if (cursor != std::wstring::npos && cursor < rawLine.length()) { item.detail = trim(rawLine.substr(cursor)).c_str(); } m_logs.push_back(item); } for (size_t i = 0; i < m_logs.size(); ++i) { const auto& log = m_logs[i]; int row = m_listLogs.InsertItem(static_cast(i), log.time); m_listLogs.SetItemText(row, 1, log.user); m_listLogs.SetItemText(row, 2, log.action); m_listLogs.SetItemText(row, 3, log.detail); } } void CUserXLogDlg::AdjustLayout() { if (!::IsWindow(m_listLogs.GetSafeHwnd())) { return; } CRect rcClient; GetClientRect(&rcClient); const int margin = 7; CRect rcList(margin, margin, rcClient.right - margin, rcClient.bottom - 40); m_listLogs.MoveWindow(rcList); auto moveButton = [&](int id, int order) { if (CWnd* pBtn = GetDlgItem(id)) { CRect rc; pBtn->GetWindowRect(&rc); ScreenToClient(&rc); int width = rc.Width(); int height = rc.Height(); rc.left = rcClient.right - margin - width - order * (width + margin); rc.right = rc.left + width; rc.top = rcClient.bottom - margin - height; rc.bottom = rc.top + height; pBtn->MoveWindow(rc); } }; moveButton(IDOK, 1); moveButton(IDCANCEL, 0); } void CUserXLogDlg::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); AdjustLayout(); } void CUserXLogDlg::OnDestroy() { CDialogEx::OnDestroy(); }