Feature: Add log search bar with prev/next/clear for m_CList_Message
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -62,6 +62,7 @@
|
||||
#include "common/file_upload.h"
|
||||
#include "SplashDlg.h"
|
||||
#include "SearchBarDlg.h"
|
||||
#include "LogSearchBar.h"
|
||||
#include <ServerServiceWrapper.h>
|
||||
#include "CDlgFileSend.h"
|
||||
#include "CClientListDlg.h"
|
||||
@@ -689,6 +690,10 @@ CMy2015RemoteDlg::~CMy2015RemoteDlg()
|
||||
m_pSearchBar->DestroyWindow();
|
||||
SAFE_DELETE(m_pSearchBar);
|
||||
}
|
||||
if (m_pLogSearchBar) {
|
||||
m_pLogSearchBar->DestroyWindow();
|
||||
SAFE_DELETE(m_pLogSearchBar);
|
||||
}
|
||||
}
|
||||
|
||||
// DLL 请求限流成员函数实现 (根据配置限制请求频率)
|
||||
@@ -932,6 +937,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
|
||||
ON_COMMAND(ID_MSGLOG_DELETE, &CMy2015RemoteDlg::OnMsglogDelete)
|
||||
ON_COMMAND(ID_MSGLOG_COPY, &CMy2015RemoteDlg::OnMsglogCopy)
|
||||
ON_COMMAND(ID_MSGLOG_CLEAR, &CMy2015RemoteDlg::OnMsglogClear)
|
||||
ON_COMMAND(ID_MSGLOG_SEARCH, &CMy2015RemoteDlg::OnMsglogSearch)
|
||||
ON_COMMAND(ID_ONLINE_ADD_WATCH, &CMy2015RemoteDlg::OnOnlineAddWatch)
|
||||
ON_COMMAND(ID_ONLINE_LOGIN_NOTIFY, &CMy2015RemoteDlg::OnOnlineLoginNotify)
|
||||
ON_NOTIFY(NM_CUSTOMDRAW, IDC_ONLINE, &CMy2015RemoteDlg::OnNMCustomdrawOnline)
|
||||
@@ -1429,6 +1435,9 @@ VOID CMy2015RemoteDlg::InitControl()
|
||||
m_nSplitPos = max(60, min(m_nSplitPos, 600));
|
||||
m_SplitterBar.Create(this);
|
||||
|
||||
m_pLogSearchBar = new CLogSearchBar();
|
||||
m_pLogSearchBar->Create(this, &m_CList_Message);
|
||||
|
||||
// 不在这里调 ApplyThumbnailSettings —— 调用方在 LoadThumbnailSettingsFromCfg
|
||||
// 之后统一 Apply(避免"先用默认值 Apply 一次,再读 INI 后再 Apply 一次"的双绘)。
|
||||
}
|
||||
@@ -1670,6 +1679,23 @@ LRESULT CMy2015RemoteDlg::OnShowMessage(WPARAM wParam, LPARAM lParam)
|
||||
// 消息日志最大条数,达到上限时删除最旧的记录
|
||||
#define MAX_MESSAGE_COUNT 1000
|
||||
|
||||
namespace {
|
||||
bool MsgHasKW(const CString& s, const CString* kw, int n) {
|
||||
for (int i = 0; i < n; i++)
|
||||
if (s.Find(kw[i]) >= 0) return true;
|
||||
return false;
|
||||
}
|
||||
int MsgColorLevel(const CString& type, const CString& msg) {
|
||||
const CString redKW[] = { _L("严禁"), _L("禁止") };
|
||||
const CString orangeKW[] = { _L("失败"), _L("警告") };
|
||||
const CString greenKW[] = { _L("成功"), _L("请") };
|
||||
if (MsgHasKW(type, redKW, _countof(redKW)) || MsgHasKW(msg, redKW, _countof(redKW))) return 1;
|
||||
if (MsgHasKW(type, orangeKW, _countof(orangeKW)) || MsgHasKW(msg, orangeKW, _countof(orangeKW))) return 2;
|
||||
if (MsgHasKW(msg, greenKW, _countof(greenKW))) return 3;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
VOID CMy2015RemoteDlg::ShowMessage(CString strType, CString strMsg)
|
||||
{
|
||||
AUTO_TICK(200, "");
|
||||
@@ -1682,9 +1708,10 @@ VOID CMy2015RemoteDlg::ShowMessage(CString strType, CString strMsg)
|
||||
m_CList_Message.DeleteItem(count - 1);
|
||||
}
|
||||
|
||||
m_CList_Message.InsertItem(0, strType); //向控件中设置数据
|
||||
m_CList_Message.SetItemText(0,1,strTime);
|
||||
m_CList_Message.SetItemText(0,2,strMsg);
|
||||
m_CList_Message.InsertItem(0, strType);
|
||||
m_CList_Message.SetItemText(0, 1, strTime);
|
||||
m_CList_Message.SetItemText(0, 2, strMsg);
|
||||
m_CList_Message.SetItemData(0, (DWORD_PTR)MsgColorLevel(strType, strMsg));
|
||||
|
||||
CString strStatusMsg;
|
||||
|
||||
@@ -1759,9 +1786,12 @@ LRESULT CMy2015RemoteDlg::OnShowErrMessage(WPARAM wParam, LPARAM lParam)
|
||||
m_CList_Message.DeleteItem(count - 1);
|
||||
}
|
||||
|
||||
m_CList_Message.InsertItem(0, title ? _L(*title) : _TR("操作错误"));
|
||||
CString strTitle = title ? _L(*title) : _TR("操作错误");
|
||||
CString strText = text ? _L(*text) : _TR("内部错误");
|
||||
m_CList_Message.InsertItem(0, strTitle);
|
||||
m_CList_Message.SetItemText(0, 1, strTime);
|
||||
m_CList_Message.SetItemText(0, 2, text ? _L(*text) : _TR("内部错误"));
|
||||
m_CList_Message.SetItemText(0, 2, strText);
|
||||
m_CList_Message.SetItemData(0, (DWORD_PTR)MsgColorLevel(strTitle, strText));
|
||||
if(title)delete title;
|
||||
if(text)delete text;
|
||||
|
||||
@@ -3225,7 +3255,8 @@ void CMy2015RemoteDlg::OnSize(UINT nType, int cx, int cy)
|
||||
lastType = nType;
|
||||
|
||||
BOOL hideLog = THIS_CFG.GetInt("settings", "HideMsg", 0) == 1;
|
||||
const int SPLITTER_H = 6;
|
||||
const int SPLITTER_H = 6;
|
||||
const int LOG_SEARCH_H = 26; // 日志搜索条高度
|
||||
// 日志区有效高度 = m_nSplitPos(不含分割条),分割条紧贴日志区上方
|
||||
int splitPos = hideLog ? 0 : m_nSplitPos;
|
||||
|
||||
@@ -3252,6 +3283,22 @@ void CMy2015RemoteDlg::OnSize(UINT nType, int cx, int cy)
|
||||
}
|
||||
LeaveCriticalSection(&m_cs);
|
||||
|
||||
if (m_pLogSearchBar && m_pLogSearchBar->GetSafeHwnd()) {
|
||||
if (hideLog || !m_bLogSearchVisible) {
|
||||
m_pLogSearchBar->ShowWindow(SW_HIDE);
|
||||
} else {
|
||||
m_pLogSearchBar->ShowWindow(SW_SHOW);
|
||||
// 右对齐,最多 380px;左侧留出 180px 给分组信息
|
||||
int barW = min(260, max(60, cx - 182));
|
||||
int barX = cx - 2 - barW;
|
||||
// 叠在在线列表底部右角:紧贴分割条上方,向上偏移一个条高
|
||||
int barY = cy - 20 - splitPos - SPLITTER_H - LOG_SEARCH_H + 5;
|
||||
m_pLogSearchBar->MoveWindow(barX, barY, barW, LOG_SEARCH_H);
|
||||
// 保证搜索条在列表控件上层(BringWindowToTop 仅影响 Z-order,不影响焦点)
|
||||
m_pLogSearchBar->BringWindowToTop();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_SplitterBar.m_hWnd != NULL) {
|
||||
if (hideLog) {
|
||||
m_SplitterBar.ShowWindow(SW_HIDE);
|
||||
@@ -9196,10 +9243,40 @@ void CMy2015RemoteDlg::OnNMCustomdrawMessage(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
|
||||
case CDDS_ITEMPREPAINT: {
|
||||
int nRow = static_cast<int>(pLVCD->nmcd.dwItemSpec);
|
||||
int nLastRow = m_CList_Message.GetItemCount() - 1;
|
||||
if (nRow == nLastRow && nLastRow >= 0) {
|
||||
pLVCD->clrText = RGB(255, 0, 0);
|
||||
|
||||
// 搜索命中行深蓝高亮(不依赖 CDIS_SELECTED,直接读搜索栏当前命中行号)
|
||||
if (m_pLogSearchBar) {
|
||||
int nHit = m_pLogSearchBar->GetHighlightedRow();
|
||||
if (nHit >= 0 && nRow == nHit) {
|
||||
pLVCD->clrTextBk = RGB(0, 80, 180);
|
||||
pLVCD->clrText = RGB(255, 255, 255);
|
||||
*pResult = CDRF_NEWFONT;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 关键字着色:必须同时设 clrText + clrTextBk,否则系统预填的蓝色会泄漏
|
||||
int colorLevel = (int)m_CList_Message.GetItemData(nRow);
|
||||
COLORREF bkDefault = ::GetSysColor(COLOR_WINDOW);
|
||||
if (colorLevel == 1) {
|
||||
pLVCD->clrText = RGB(220, 0, 0);
|
||||
pLVCD->clrTextBk = bkDefault;
|
||||
*pResult = CDRF_NEWFONT;
|
||||
return;
|
||||
}
|
||||
if (colorLevel == 2) {
|
||||
pLVCD->clrText = RGB(200, 100, 0);
|
||||
pLVCD->clrTextBk = bkDefault;
|
||||
*pResult = CDRF_NEWFONT;
|
||||
return;
|
||||
}
|
||||
if (colorLevel == 3) {
|
||||
pLVCD->clrText = RGB(0, 140, 0);
|
||||
pLVCD->clrTextBk = bkDefault;
|
||||
*pResult = CDRF_NEWFONT;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9213,6 +9290,9 @@ void CMy2015RemoteDlg::OnRClickMessage(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
menu.AppendMenu(MF_STRING, ID_MSGLOG_DELETE, _TR("删除选中"));
|
||||
menu.AppendMenu(MF_STRING, ID_MSGLOG_COPY, _TR("复制选中"));
|
||||
menu.AppendMenu(MF_STRING, ID_MSGLOG_CLEAR, _TR("清空日志"));
|
||||
menu.AppendMenu(MF_SEPARATOR);
|
||||
menu.AppendMenu(MF_STRING, ID_MSGLOG_SEARCH,
|
||||
m_bLogSearchVisible ? _TR("隐藏搜索") : _TR("搜索日志"));
|
||||
|
||||
// 没有选中项时禁用"删除选中"
|
||||
if (m_CList_Message.GetSelectedCount() == 0) {
|
||||
@@ -9237,7 +9317,7 @@ void CMy2015RemoteDlg::OnMsglogDelete()
|
||||
while (pos) {
|
||||
selected.push_back(m_CList_Message.GetNextSelectedItem(pos));
|
||||
}
|
||||
// 倒序删除
|
||||
// 倒序删除,避免索引变化
|
||||
for (auto it = selected.rbegin(); it != selected.rend(); ++it) {
|
||||
m_CList_Message.DeleteItem(*it);
|
||||
}
|
||||
@@ -9280,6 +9360,14 @@ void CMy2015RemoteDlg::OnMsglogClear()
|
||||
m_CList_Message.DeleteAllItems();
|
||||
}
|
||||
|
||||
void CMy2015RemoteDlg::OnMsglogSearch()
|
||||
{
|
||||
m_bLogSearchVisible = !m_bLogSearchVisible;
|
||||
// 复用 OnSize 里的布局逻辑
|
||||
CRect rc;
|
||||
GetClientRect(&rc);
|
||||
OnSize(SIZE_RESTORED, rc.Width(), rc.Height());
|
||||
}
|
||||
|
||||
void CMy2015RemoteDlg::OnOnlineAddWatch()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user