diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index f5bb998..4e7c370 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -62,6 +62,7 @@ #include "common/file_upload.h" #include "SplashDlg.h" #include "SearchBarDlg.h" +#include "LogSearchBar.h" #include #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(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() { diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index d6928fd..a9eafa6 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -75,6 +75,7 @@ class CSplashDlg; // 前向声明 class CClientListDlg; class CLicenseDlg; class CSearchBarDlg; +class CLogSearchBar; #include "pwd_gen.h" @@ -140,7 +141,9 @@ public: _ClientList *m_ClientMap = nullptr; CClientListDlg* m_pClientListDlg = nullptr; CLicenseDlg* m_pLicenseDlg = nullptr; - CSearchBarDlg* m_pSearchBar = nullptr; // 搜索工具栏 + CSearchBarDlg* m_pSearchBar = nullptr; + CLogSearchBar* m_pLogSearchBar = nullptr; + bool m_bLogSearchVisible = false; // 日志搜索条是否显示(右键菜单切换) BOOL m_bEnableFileV2 = FALSE; // V2 文件传输开关 // 构造 @@ -560,6 +563,7 @@ public: afx_msg void OnMsglogDelete(); afx_msg void OnMsglogCopy(); afx_msg void OnMsglogClear(); + afx_msg void OnMsglogSearch(); afx_msg void OnOnlineAddWatch(); afx_msg void OnNMCustomdrawOnline(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnOnlineRunAsAdmin(); diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj b/server/2015Remote/2015Remote_vs2015.vcxproj index 6a3b5de..1e972c7 100644 --- a/server/2015Remote/2015Remote_vs2015.vcxproj +++ b/server/2015Remote/2015Remote_vs2015.vcxproj @@ -291,6 +291,7 @@ + @@ -373,6 +374,7 @@ + NotUsing NotUsing diff --git a/server/2015Remote/LogSearchBar.cpp b/server/2015Remote/LogSearchBar.cpp new file mode 100644 index 0000000..b0e65a8 --- /dev/null +++ b/server/2015Remote/LogSearchBar.cpp @@ -0,0 +1,229 @@ +// LogSearchBar.cpp - 日志列表搜索条实现 +#include "stdafx.h" +#include "LogSearchBar.h" +#include "LangManager.h" + +BEGIN_MESSAGE_MAP(CLogSearchBar, CWnd) + ON_WM_CREATE() + ON_WM_SIZE() + ON_WM_ERASEBKGND() + ON_WM_TIMER() + ON_EN_CHANGE(IDC_LOG_SEARCH_EDIT, OnEnChangeSearch) + ON_BN_CLICKED(IDC_LOG_SEARCH_PREV, OnBnClickedPrev) + ON_BN_CLICKED(IDC_LOG_SEARCH_NEXT, OnBnClickedNext) + ON_BN_CLICKED(IDC_LOG_SEARCH_CLEAR, OnBnClickedClear) +END_MESSAGE_MAP() + +CLogSearchBar::CLogSearchBar() +{ +} + +CLogSearchBar::~CLogSearchBar() +{ +} + +BOOL CLogSearchBar::Create(CWnd* pParent, CListCtrl* pList) +{ + m_pList = pList; + LPCTSTR cls = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, + ::LoadCursor(NULL, IDC_ARROW)); + return CWnd::Create(cls, _T(""), WS_CHILD | WS_CLIPCHILDREN, + CRect(0, 0, 1, 1), pParent, 0); +} + +int CLogSearchBar::OnCreate(LPCREATESTRUCT lpcs) +{ + if (CWnd::OnCreate(lpcs) == -1) return -1; + + // 搜索输入框 + m_editSearch.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, + CRect(0, 0, 1, 1), this, IDC_LOG_SEARCH_EDIT); + m_editSearch.SetCueBanner(L"搜索日志...", TRUE); + + // 清除按钮 + m_btnClear.Create(_T("X"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_FLAT, + CRect(0, 0, 1, 1), this, IDC_LOG_SEARCH_CLEAR); + + // 上一个 / 下一个按钮(系统样式,与浅色背景融合) + m_btnPrev.Create(_T("▲"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_FLAT, + CRect(0, 0, 1, 1), this, IDC_LOG_SEARCH_PREV); + + m_btnNext.Create(_T("▼"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_FLAT, + CRect(0, 0, 1, 1), this, IDC_LOG_SEARCH_NEXT); + + // 结果计数 + m_staticCount.Create(_T(""), WS_CHILD | WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE, + CRect(0, 0, 1, 1), this, IDC_LOG_SEARCH_COUNT); + + // 统一字体:跟父窗口(主对话框)保持一致 + CFont* pFont = GetParent()->GetFont(); + if (pFont) { + m_staticCount.SetFont(pFont); + m_editSearch.SetFont(pFont); + m_btnClear.SetFont(pFont); + m_btnPrev.SetFont(pFont); + m_btnNext.SetFont(pFont); + } + + return 0; +} + +void CLogSearchBar::LayoutControls(int cx, int cy) +{ + if (!m_editSearch.GetSafeHwnd()) return; + const int m = 2; + const int h = cy - 2 * m; + if (h <= 0) return; + const int btnW = h; + const int cntW = 62; + // 搜索框填满剩余空间(barW 由外部控制总宽,这里保证控件铺满) + const int editW = max(20, cx - 2 * m - 3 * btnW - 2 * m - cntW); + + int x = m; + m_staticCount.MoveWindow(x, m, cntW, h); + x += cntW + m; + m_editSearch.MoveWindow(x, m, editW, h); + x += editW + m; + m_btnClear.MoveWindow(x, m, btnW, h); + x += btnW; + m_btnPrev.MoveWindow(x, m, btnW, h); + x += btnW; + m_btnNext.MoveWindow(x, m, btnW, h); +} + +void CLogSearchBar::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + LayoutControls(cx, cy); +} + +BOOL CLogSearchBar::OnEraseBkgnd(CDC* pDC) +{ + CRect rc; + GetClientRect(&rc); + pDC->FillSolidRect(rc, ::GetSysColor(COLOR_3DFACE)); + return TRUE; +} + +void CLogSearchBar::OnEnChangeSearch() +{ + KillTimer(TIMER_SEARCH); + SetTimer(TIMER_SEARCH, SEARCH_DELAY_MS, NULL); +} + +void CLogSearchBar::OnTimer(UINT_PTR nIDEvent) +{ + if (nIDEvent == TIMER_SEARCH) { + KillTimer(TIMER_SEARCH); + DoSearch(); + } + CWnd::OnTimer(nIDEvent); +} + +void CLogSearchBar::DoSearch() +{ + if (!m_pList || !m_pList->GetSafeHwnd()) return; + + CString kw; + m_editSearch.GetWindowText(kw); + + m_Results.clear(); + m_nCurrentIndex = -1; + + if (kw.IsEmpty()) { + UpdateCountText(); + return; + } + + CString kwLow = kw; + kwLow.MakeLower(); + + int nCols = m_pList->GetHeaderCtrl() ? m_pList->GetHeaderCtrl()->GetItemCount() : 1; + int nItems = m_pList->GetItemCount(); + + for (int i = 0; i < nItems; i++) { + for (int c = 0; c < nCols; c++) { + CString cell = m_pList->GetItemText(i, c); + cell.MakeLower(); + if (cell.Find(kwLow) >= 0) { + m_Results.push_back(i); + break; + } + } + } + + if (!m_Results.empty()) { + m_nCurrentIndex = 0; + GotoMatch(m_nCurrentIndex); + } + UpdateCountText(); +} + +void CLogSearchBar::GotoMatch(int idx) +{ + if (!m_pList || idx < 0 || idx >= (int)m_Results.size()) return; + int item = m_Results[idx]; + + // 取消所有选中 + int n = -1; + while ((n = m_pList->GetNextItem(-1, LVNI_SELECTED)) != -1) + m_pList->SetItemState(n, 0, LVIS_SELECTED | LVIS_FOCUSED); + + m_pList->SetItemState(item, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); + m_pList->EnsureVisible(item, FALSE); +} + +void CLogSearchBar::UpdateCountText() +{ + CString text; + if (m_Results.empty()) { + CString kw; + m_editSearch.GetWindowText(kw); + text = kw.IsEmpty() ? _TR("") : _TR("无结果"); + } else { + text.Format(_T("%d/%d"), m_nCurrentIndex + 1, (int)m_Results.size()); + } + m_staticCount.SetWindowText(text); +} + +void CLogSearchBar::InvalidateSearch() +{ + KillTimer(TIMER_SEARCH); + m_Results.clear(); + m_nCurrentIndex = -1; + UpdateCountText(); + + if (m_editSearch.GetSafeHwnd()) { + CString kw; + m_editSearch.GetWindowText(kw); + if (!kw.IsEmpty()) + SetTimer(TIMER_SEARCH, SEARCH_DELAY_MS, NULL); + } +} + +void CLogSearchBar::OnBnClickedPrev() +{ + if (m_Results.empty()) return; + m_nCurrentIndex--; + if (m_nCurrentIndex < 0) + m_nCurrentIndex = (int)m_Results.size() - 1; + GotoMatch(m_nCurrentIndex); + UpdateCountText(); +} + +void CLogSearchBar::OnBnClickedNext() +{ + if (m_Results.empty()) return; + m_nCurrentIndex++; + if (m_nCurrentIndex >= (int)m_Results.size()) + m_nCurrentIndex = 0; + GotoMatch(m_nCurrentIndex); + UpdateCountText(); +} + +void CLogSearchBar::OnBnClickedClear() +{ + m_editSearch.SetWindowText(_T("")); + m_editSearch.SetFocus(); + // 触发 EN_CHANGE → 定时器 → DoSearch 清空结果 +} diff --git a/server/2015Remote/LogSearchBar.h b/server/2015Remote/LogSearchBar.h new file mode 100644 index 0000000..33897af --- /dev/null +++ b/server/2015Remote/LogSearchBar.h @@ -0,0 +1,57 @@ +// LogSearchBar.h - 日志列表搜索条(嵌入式,固定在右侧) +#pragma once +#include +#include +#include + +#define IDC_LOG_SEARCH_EDIT 5001 +#define IDC_LOG_SEARCH_PREV 5002 +#define IDC_LOG_SEARCH_NEXT 5003 +#define IDC_LOG_SEARCH_COUNT 5004 +#define IDC_LOG_SEARCH_CLEAR 5005 + +class CLogSearchBar : public CWnd +{ +public: + CLogSearchBar(); + virtual ~CLogSearchBar(); + + // pParent: 主对话框; pList: 要搜索的 CListCtrl(m_CList_Message) + BOOL Create(CWnd* pParent, CListCtrl* pList); + void InvalidateSearch(); + + // 当前命中行的列表索引,无命中返回 -1(纯内存读) + int GetHighlightedRow() const { + if (m_nCurrentIndex < 0 || m_nCurrentIndex >= (int)m_Results.size()) return -1; + return m_Results[m_nCurrentIndex]; + } + +protected: + CListCtrl* m_pList = nullptr; + CEdit m_editSearch; + CButton m_btnPrev; + CButton m_btnNext; + CButton m_btnClear; + CStatic m_staticCount; + + std::vector m_Results; // 匹配行索引 + int m_nCurrentIndex = -1; + + void DoSearch(); + void GotoMatch(int idx); + void UpdateCountText(); + void LayoutControls(int cx, int cy); + + DECLARE_MESSAGE_MAP() + afx_msg int OnCreate(LPCREATESTRUCT lpcs); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnTimer(UINT_PTR nIDEvent); + afx_msg void OnEnChangeSearch(); + afx_msg void OnBnClickedPrev(); + afx_msg void OnBnClickedNext(); + afx_msg void OnBnClickedClear(); + + static const UINT TIMER_SEARCH = 1; + static const UINT SEARCH_DELAY_MS = 400; +}; diff --git a/server/2015Remote/lang/en_US.ini b/server/2015Remote/lang/en_US.ini index 9a03060..4bc36c1 100644 --- a/server/2015Remote/lang/en_US.ini +++ b/server/2015Remote/lang/en_US.ini @@ -1958,3 +1958,10 @@ FRPC Զ ͻ־=Client Log ʹ=Forbidden Client ȷѡıس?=Are you sure to forbidden the selected clients? +޽=Not found +Ͻ=Prohibited +ֹ=Forbidden +ʧ=Failed +־=Search Logs +=Hide Search +=Please diff --git a/server/2015Remote/lang/zh_TW.ini b/server/2015Remote/lang/zh_TW.ini index d5ece72..a385dbc 100644 --- a/server/2015Remote/lang/zh_TW.ini +++ b/server/2015Remote/lang/zh_TW.ini @@ -1949,3 +1949,10 @@ FRPC Զ ͻ־=ͻ־ ʹ=ʹ ȷѡıس?=ȷѡıس? +޽=޽ +Ͻ=Ͻ +ֹ=ֹ +ʧ=ʧ +־=־ += += diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h index f81e1d9..659ee50 100644 --- a/server/2015Remote/resource.h +++ b/server/2015Remote/resource.h @@ -990,6 +990,7 @@ #define ID_MSGLOG_CLEAR 33041 #define ID_CANCEL_SHARE 33042 #define ID_MSGLOG_COPY 33043 +#define ID_MSGLOG_SEARCH 33078 #define ID_WEB_REMOTE_CONTROL 33044 #define ID_TOOL_PLUGIN_SETTINGS 33045 #define ID_33046 33046 @@ -1031,7 +1032,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 398 -#define _APS_NEXT_COMMAND_VALUE 33077 +#define _APS_NEXT_COMMAND_VALUE 33079 #define _APS_NEXT_CONTROL_VALUE 2542 #define _APS_NEXT_SYMED_VALUE 105 #endif