Compare commits
2
Commits
f24e7acc48
...
v1.3.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d99510e46d | ||
|
|
b97f086c0c |
No files matched your search
@@ -378,6 +378,28 @@ nohup ./server_linux_amd64 --port 6543 --http-port 9001 > yama.log 2>&1 &
|
|||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
|
### v1.3.8 (2026.8.3)
|
||||||
|
|
||||||
|
**SYSTEM 权限客户端 & 主控可用性增强 & Bug 修复**
|
||||||
|
|
||||||
|
**新功能:**
|
||||||
|
- **客户端 SYSTEM 权限运行**:双模式自动适配(SYSTEM / Admin / User),Winlogon + Run 双路径注册表启动;`ScreenManager` 无用户会话时自动切换 DXGI,`KernelManager` 绕过用户态 API 以 NT 路径操作;跨会话 DLL 注入(`session.cpp`)实现 SYSTEM 会话向用户会话注入控制模块
|
||||||
|
- **在线主机权限等级列**:主机列表新增「权限」列,实时显示 SYSTEM(蓝色高亮)/ Admin / User,一眼识别受控端权限上下文
|
||||||
|
- **远程窗口管理菜单(View Windows)**:远程桌面新增 View Windows 菜单,可枚举目标机器顶层窗口并进行最大化、最小化、隐藏、关闭操作
|
||||||
|
- **违禁用户拉黑**:主机列表右键新增「禁止连接」,服务端发送 `COMMAND_FORBIDDEN`;客户端收到后断开连接并拒绝重连;附带 Forbidden 图标
|
||||||
|
- **客户端运行日志对话框**:`ClientLogManager` 每 3 秒增量推送日志到主控(`TOKEN_REPORT_LOG`);推送线程 `join()` 防 use-after-free;IOCP → UI 线程 `PostMessage` 防丢包;自带图标与菜单位图
|
||||||
|
- **消息日志搜索栏**:`LogSearchBar` 组件(286 行),关键字高亮、Prev/Next 导航跳转、Clear 清除
|
||||||
|
- **调试菜单(YAMA_DBG)**:主菜单新增调试入口,动态输入 `YAMA_DBG` 环境变量值,无需重启主控
|
||||||
|
|
||||||
|
**改进:**
|
||||||
|
- 远程桌面光标自定义设置持久化到注册表,下次自动恢复偏好
|
||||||
|
|
||||||
|
**Bug 修复:**
|
||||||
|
- 32 位 / 64 位主控切换崩溃:`KeyboardManager` 参数类型兼容 + 服务端位数检查
|
||||||
|
- Safari 移动端切回卡死:前台切回时强制重建 WebSocket + 服务端 30s 宽限期
|
||||||
|
- `RunFileReceiver` 误注册 `ReconnectProcess` 导致文件传输结束后杀主屏幕会话
|
||||||
|
- 隐私壁纸已设置时切换菜单再次点击执行清除而非弹框
|
||||||
|
|
||||||
### v1.3.7 (2026.6.26)
|
### v1.3.7 (2026.6.26)
|
||||||
|
|
||||||
**Android 客户端 & 窗口捕获增强 & 安全加固**
|
**Android 客户端 & 窗口捕获增强 & 安全加固**
|
||||||
|
|||||||
@@ -378,6 +378,28 @@ Valid : 2026-02-01 to 2028-02-01
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### v1.3.8 (2026.8.3)
|
||||||
|
|
||||||
|
**SYSTEM-level Client & Master Usability Enhancements & Bug Fixes**
|
||||||
|
|
||||||
|
**New features:**
|
||||||
|
- **Client running as SYSTEM**: dual-mode auto-detection (SYSTEM / Admin / User), Winlogon + Run dual-path registry startup; `ScreenManager` auto-switches to DXGI when there is no user session; `KernelManager` bypasses user-mode APIs using NT paths; cross-session DLL injection (`session.cpp`) from SYSTEM to user session for desktop interaction
|
||||||
|
- **Privilege column in host list**: new "Privilege" column shows real-time permission level — **SYSTEM** (blue highlight), Admin, or User — instantly identifying each controlled endpoint's privilege context
|
||||||
|
- **View Windows menu for remote desktop**: new View Windows menu item enumerates all top-level windows on the target machine; supports maximize, minimize, hide, and close operations without leaving the remote desktop view
|
||||||
|
- **Forbid user (violation blacklist)**: right-click host list "Forbidden" sends `COMMAND_FORBIDDEN`; client disconnects and refuses reconnection to the same server; companion bitmap icon in menu
|
||||||
|
- **Client runtime log dialog**: `ClientLogManager` pushes incremental logs every 3s to the master (`TOKEN_REPORT_LOG`); push thread uses `join()` to prevent use-after-free; IOCP → UI thread via `PostMessage` to prevent dropped packets; dialog icon and menu bitmap included
|
||||||
|
- **Message log search bar**: `LogSearchBar` component (286 lines) with keyword highlighting, Prev/Next navigation, and Clear button
|
||||||
|
- **Debug menu (YAMA_DBG)**: new menu entry to input `YAMA_DBG` environment variable at runtime — no restart needed
|
||||||
|
|
||||||
|
**Improvements:**
|
||||||
|
- Remote desktop cursor customization settings now persisted to registry; preferences restored automatically on next session
|
||||||
|
|
||||||
|
**Bug fixes:**
|
||||||
|
- 32-bit / 64-bit master crash on switch: `KeyboardManager` parameter type compatibility + server-side bitness check
|
||||||
|
- Safari mobile Web remote desktop freeze on app-switch: force-clean WebSocket reconnect on foreground return + 30s server-side grace period
|
||||||
|
- `RunFileReceiver` incorrectly registering `ReconnectProcess`, killing the main screen session on file transfer completion
|
||||||
|
- Privacy wallpaper toggle menu now clears instead of re-picking when wallpaper is already set
|
||||||
|
|
||||||
### v1.3.7 (2026.6.26)
|
### v1.3.7 (2026.6.26)
|
||||||
|
|
||||||
**Android Client & Window Capture & Security Hardening**
|
**Android Client & Window Capture & Security Hardening**
|
||||||
|
|||||||
@@ -378,6 +378,28 @@ nohup ./server_linux_amd64 --port 6543 --http-port 9001 > yama.log 2>&1 &
|
|||||||
|
|
||||||
## 更新日誌
|
## 更新日誌
|
||||||
|
|
||||||
|
### v1.3.8 (2026.8.3)
|
||||||
|
|
||||||
|
**SYSTEM 權限用戶端 & 主控可用性增強 & Bug 修復**
|
||||||
|
|
||||||
|
**新功能:**
|
||||||
|
- **用戶端 SYSTEM 權限執行**:雙模式自動適配(SYSTEM / Admin / User),Winlogon + Run 雙路徑登錄檔啟動;`ScreenManager` 無使用者工作階段時自動切換 DXGI,`KernelManager` 繞過使用者態 API 以 NT 路徑操作;跨工作階段 DLL 注入(`session.cpp`)實現 SYSTEM 工作階段向使用者工作階段注入控制模組
|
||||||
|
- **線上主機權限等級欄**:主機列表新增「權限」欄,即時顯示 SYSTEM(藍色高亮)/ Admin / User,一眼識別受控端權限上下文
|
||||||
|
- **遠端視窗管理選單(View Windows)**:遠端桌面新增 View Windows 選單項目,可列舉目標機器頂層視窗並進行最大化、最小化、隱藏、關閉操作
|
||||||
|
- **違禁使用者封鎖**:主機列表右鍵新增「禁止連線」,伺服端發送 `COMMAND_FORBIDDEN`;用戶端收到後中斷連線並拒絕重連;附帶 Forbidden 圖示
|
||||||
|
- **用戶端執行記錄對話框**:`ClientLogManager` 每 3 秒增量推送記錄到主控(`TOKEN_REPORT_LOG`);推送執行緒使用 `join()` 防止 use-after-free;IOCP → UI 執行緒 `PostMessage` 防止遺失封包;自帶圖示與選單位圖
|
||||||
|
- **訊息記錄搜尋列**:`LogSearchBar` 元件(286 行),關鍵字高亮、Prev/Next 導航跳轉、Clear 清除
|
||||||
|
- **除錯選單(YAMA_DBG)**:主選單新增除錯入口,動態輸入 `YAMA_DBG` 環境變數值,無需重啟主控
|
||||||
|
|
||||||
|
**改進:**
|
||||||
|
- 遠端桌面游標自訂設定持久化到登錄檔,下次自動恢復偏好
|
||||||
|
|
||||||
|
**Bug 修復:**
|
||||||
|
- 32 位元 / 64 位元主控切換崩潰:`KeyboardManager` 參數型別相容 + 伺服端位元數檢查
|
||||||
|
- Safari 行動端切回凍結:前景切回時強制重建 WebSocket + 伺服端 30s 寬限期
|
||||||
|
- `RunFileReceiver` 誤註冊 `ReconnectProcess` 導致檔案傳輸結束後終止主螢幕工作階段
|
||||||
|
- 隱私桌布已設定時切換選單再次點擊執行清除而非彈框
|
||||||
|
|
||||||
### v1.3.7 (2026.6.26)
|
### v1.3.7 (2026.6.26)
|
||||||
|
|
||||||
**Android 用戶端 & 視窗擷取增強 & 安全加固**
|
**Android 用戶端 & 視窗擷取增強 & 安全加固**
|
||||||
|
|||||||
+2
-2
@@ -88,7 +88,7 @@ IDR_WAVE WAVE "Res\\msg.wav"
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,0,3,7
|
FILEVERSION 1,0,3,8
|
||||||
PRODUCTVERSION 1,0,0,1
|
PRODUCTVERSION 1,0,0,1
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
@@ -106,7 +106,7 @@ BEGIN
|
|||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "FUCK THE UNIVERSE"
|
VALUE "CompanyName", "FUCK THE UNIVERSE"
|
||||||
VALUE "FileDescription", "A GHOST"
|
VALUE "FileDescription", "A GHOST"
|
||||||
VALUE "FileVersion", "1.0.3.7"
|
VALUE "FileVersion", "1.0.3.8"
|
||||||
VALUE "InternalName", "ServerDll.dll"
|
VALUE "InternalName", "ServerDll.dll"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2019-2026"
|
VALUE "LegalCopyright", "Copyright (C) 2019-2026"
|
||||||
VALUE "OriginalFilename", "ServerDll.dll"
|
VALUE "OriginalFilename", "ServerDll.dll"
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -62,6 +62,7 @@
|
|||||||
#include "common/file_upload.h"
|
#include "common/file_upload.h"
|
||||||
#include "SplashDlg.h"
|
#include "SplashDlg.h"
|
||||||
#include "SearchBarDlg.h"
|
#include "SearchBarDlg.h"
|
||||||
|
#include "LogSearchBar.h"
|
||||||
#include <ServerServiceWrapper.h>
|
#include <ServerServiceWrapper.h>
|
||||||
#include "CDlgFileSend.h"
|
#include "CDlgFileSend.h"
|
||||||
#include "CClientListDlg.h"
|
#include "CClientListDlg.h"
|
||||||
@@ -689,6 +690,10 @@ CMy2015RemoteDlg::~CMy2015RemoteDlg()
|
|||||||
m_pSearchBar->DestroyWindow();
|
m_pSearchBar->DestroyWindow();
|
||||||
SAFE_DELETE(m_pSearchBar);
|
SAFE_DELETE(m_pSearchBar);
|
||||||
}
|
}
|
||||||
|
if (m_pLogSearchBar) {
|
||||||
|
m_pLogSearchBar->DestroyWindow();
|
||||||
|
SAFE_DELETE(m_pLogSearchBar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DLL 请求限流成员函数实现 (根据配置限制请求频率)
|
// DLL 请求限流成员函数实现 (根据配置限制请求频率)
|
||||||
@@ -932,6 +937,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
|
|||||||
ON_COMMAND(ID_MSGLOG_DELETE, &CMy2015RemoteDlg::OnMsglogDelete)
|
ON_COMMAND(ID_MSGLOG_DELETE, &CMy2015RemoteDlg::OnMsglogDelete)
|
||||||
ON_COMMAND(ID_MSGLOG_COPY, &CMy2015RemoteDlg::OnMsglogCopy)
|
ON_COMMAND(ID_MSGLOG_COPY, &CMy2015RemoteDlg::OnMsglogCopy)
|
||||||
ON_COMMAND(ID_MSGLOG_CLEAR, &CMy2015RemoteDlg::OnMsglogClear)
|
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_ADD_WATCH, &CMy2015RemoteDlg::OnOnlineAddWatch)
|
||||||
ON_COMMAND(ID_ONLINE_LOGIN_NOTIFY, &CMy2015RemoteDlg::OnOnlineLoginNotify)
|
ON_COMMAND(ID_ONLINE_LOGIN_NOTIFY, &CMy2015RemoteDlg::OnOnlineLoginNotify)
|
||||||
ON_NOTIFY(NM_CUSTOMDRAW, IDC_ONLINE, &CMy2015RemoteDlg::OnNMCustomdrawOnline)
|
ON_NOTIFY(NM_CUSTOMDRAW, IDC_ONLINE, &CMy2015RemoteDlg::OnNMCustomdrawOnline)
|
||||||
@@ -1429,6 +1435,9 @@ VOID CMy2015RemoteDlg::InitControl()
|
|||||||
m_nSplitPos = max(60, min(m_nSplitPos, 600));
|
m_nSplitPos = max(60, min(m_nSplitPos, 600));
|
||||||
m_SplitterBar.Create(this);
|
m_SplitterBar.Create(this);
|
||||||
|
|
||||||
|
m_pLogSearchBar = new CLogSearchBar();
|
||||||
|
m_pLogSearchBar->Create(this, &m_CList_Message);
|
||||||
|
|
||||||
// 不在这里调 ApplyThumbnailSettings —— 调用方在 LoadThumbnailSettingsFromCfg
|
// 不在这里调 ApplyThumbnailSettings —— 调用方在 LoadThumbnailSettingsFromCfg
|
||||||
// 之后统一 Apply(避免"先用默认值 Apply 一次,再读 INI 后再 Apply 一次"的双绘)。
|
// 之后统一 Apply(避免"先用默认值 Apply 一次,再读 INI 后再 Apply 一次"的双绘)。
|
||||||
}
|
}
|
||||||
@@ -1670,6 +1679,23 @@ LRESULT CMy2015RemoteDlg::OnShowMessage(WPARAM wParam, LPARAM lParam)
|
|||||||
// 消息日志最大条数,达到上限时删除最旧的记录
|
// 消息日志最大条数,达到上限时删除最旧的记录
|
||||||
#define MAX_MESSAGE_COUNT 1000
|
#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)
|
VOID CMy2015RemoteDlg::ShowMessage(CString strType, CString strMsg)
|
||||||
{
|
{
|
||||||
AUTO_TICK(200, "");
|
AUTO_TICK(200, "");
|
||||||
@@ -1682,9 +1708,10 @@ VOID CMy2015RemoteDlg::ShowMessage(CString strType, CString strMsg)
|
|||||||
m_CList_Message.DeleteItem(count - 1);
|
m_CList_Message.DeleteItem(count - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_CList_Message.InsertItem(0, strType); //向控件中设置数据
|
m_CList_Message.InsertItem(0, strType);
|
||||||
m_CList_Message.SetItemText(0,1,strTime);
|
m_CList_Message.SetItemText(0, 1, strTime);
|
||||||
m_CList_Message.SetItemText(0,2,strMsg);
|
m_CList_Message.SetItemText(0, 2, strMsg);
|
||||||
|
m_CList_Message.SetItemData(0, (DWORD_PTR)MsgColorLevel(strType, strMsg));
|
||||||
|
|
||||||
CString strStatusMsg;
|
CString strStatusMsg;
|
||||||
|
|
||||||
@@ -1759,9 +1786,12 @@ LRESULT CMy2015RemoteDlg::OnShowErrMessage(WPARAM wParam, LPARAM lParam)
|
|||||||
m_CList_Message.DeleteItem(count - 1);
|
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, 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(title)delete title;
|
||||||
if(text)delete text;
|
if(text)delete text;
|
||||||
|
|
||||||
@@ -3225,7 +3255,8 @@ void CMy2015RemoteDlg::OnSize(UINT nType, int cx, int cy)
|
|||||||
lastType = nType;
|
lastType = nType;
|
||||||
|
|
||||||
BOOL hideLog = THIS_CFG.GetInt("settings", "HideMsg", 0) == 1;
|
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(不含分割条),分割条紧贴日志区上方
|
// 日志区有效高度 = m_nSplitPos(不含分割条),分割条紧贴日志区上方
|
||||||
int splitPos = hideLog ? 0 : m_nSplitPos;
|
int splitPos = hideLog ? 0 : m_nSplitPos;
|
||||||
|
|
||||||
@@ -3252,6 +3283,22 @@ void CMy2015RemoteDlg::OnSize(UINT nType, int cx, int cy)
|
|||||||
}
|
}
|
||||||
LeaveCriticalSection(&m_cs);
|
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 (m_SplitterBar.m_hWnd != NULL) {
|
||||||
if (hideLog) {
|
if (hideLog) {
|
||||||
m_SplitterBar.ShowWindow(SW_HIDE);
|
m_SplitterBar.ShowWindow(SW_HIDE);
|
||||||
@@ -9196,10 +9243,40 @@ void CMy2015RemoteDlg::OnNMCustomdrawMessage(NMHDR* pNMHDR, LRESULT* pResult)
|
|||||||
|
|
||||||
case CDDS_ITEMPREPAINT: {
|
case CDDS_ITEMPREPAINT: {
|
||||||
int nRow = static_cast<int>(pLVCD->nmcd.dwItemSpec);
|
int nRow = static_cast<int>(pLVCD->nmcd.dwItemSpec);
|
||||||
int nLastRow = m_CList_Message.GetItemCount() - 1;
|
|
||||||
if (nRow == nLastRow && nLastRow >= 0) {
|
// 搜索命中行深蓝高亮(不依赖 CDIS_SELECTED,直接读搜索栏当前命中行号)
|
||||||
pLVCD->clrText = RGB(255, 0, 0);
|
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_DELETE, _TR("删除选中"));
|
||||||
menu.AppendMenu(MF_STRING, ID_MSGLOG_COPY, _TR("复制选中"));
|
menu.AppendMenu(MF_STRING, ID_MSGLOG_COPY, _TR("复制选中"));
|
||||||
menu.AppendMenu(MF_STRING, ID_MSGLOG_CLEAR, _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) {
|
if (m_CList_Message.GetSelectedCount() == 0) {
|
||||||
@@ -9237,7 +9317,7 @@ void CMy2015RemoteDlg::OnMsglogDelete()
|
|||||||
while (pos) {
|
while (pos) {
|
||||||
selected.push_back(m_CList_Message.GetNextSelectedItem(pos));
|
selected.push_back(m_CList_Message.GetNextSelectedItem(pos));
|
||||||
}
|
}
|
||||||
// 倒序删除
|
// 倒序删除,避免索引变化
|
||||||
for (auto it = selected.rbegin(); it != selected.rend(); ++it) {
|
for (auto it = selected.rbegin(); it != selected.rend(); ++it) {
|
||||||
m_CList_Message.DeleteItem(*it);
|
m_CList_Message.DeleteItem(*it);
|
||||||
}
|
}
|
||||||
@@ -9280,6 +9360,14 @@ void CMy2015RemoteDlg::OnMsglogClear()
|
|||||||
m_CList_Message.DeleteAllItems();
|
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()
|
void CMy2015RemoteDlg::OnOnlineAddWatch()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ class CSplashDlg; // 前向声明
|
|||||||
class CClientListDlg;
|
class CClientListDlg;
|
||||||
class CLicenseDlg;
|
class CLicenseDlg;
|
||||||
class CSearchBarDlg;
|
class CSearchBarDlg;
|
||||||
|
class CLogSearchBar;
|
||||||
|
|
||||||
#include "pwd_gen.h"
|
#include "pwd_gen.h"
|
||||||
|
|
||||||
@@ -140,7 +141,9 @@ public:
|
|||||||
_ClientList *m_ClientMap = nullptr;
|
_ClientList *m_ClientMap = nullptr;
|
||||||
CClientListDlg* m_pClientListDlg = nullptr;
|
CClientListDlg* m_pClientListDlg = nullptr;
|
||||||
CLicenseDlg* m_pLicenseDlg = 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 文件传输开关
|
BOOL m_bEnableFileV2 = FALSE; // V2 文件传输开关
|
||||||
|
|
||||||
// 构造
|
// 构造
|
||||||
@@ -560,6 +563,7 @@ public:
|
|||||||
afx_msg void OnMsglogDelete();
|
afx_msg void OnMsglogDelete();
|
||||||
afx_msg void OnMsglogCopy();
|
afx_msg void OnMsglogCopy();
|
||||||
afx_msg void OnMsglogClear();
|
afx_msg void OnMsglogClear();
|
||||||
|
afx_msg void OnMsglogSearch();
|
||||||
afx_msg void OnOnlineAddWatch();
|
afx_msg void OnOnlineAddWatch();
|
||||||
afx_msg void OnNMCustomdrawOnline(NMHDR* pNMHDR, LRESULT* pResult);
|
afx_msg void OnNMCustomdrawOnline(NMHDR* pNMHDR, LRESULT* pResult);
|
||||||
afx_msg void OnOnlineRunAsAdmin();
|
afx_msg void OnOnlineRunAsAdmin();
|
||||||
|
|||||||
@@ -291,6 +291,7 @@
|
|||||||
<ClInclude Include="BuildDlg.h" />
|
<ClInclude Include="BuildDlg.h" />
|
||||||
<ClInclude Include="CClientListDlg.h" />
|
<ClInclude Include="CClientListDlg.h" />
|
||||||
<ClInclude Include="CClientLog.h" />
|
<ClInclude Include="CClientLog.h" />
|
||||||
|
<ClInclude Include="LogSearchBar.h" />
|
||||||
<ClInclude Include="CDlgFileSend.h" />
|
<ClInclude Include="CDlgFileSend.h" />
|
||||||
<ClInclude Include="CDrawingBoard.h" />
|
<ClInclude Include="CDrawingBoard.h" />
|
||||||
<ClInclude Include="CGridDialog.h" />
|
<ClInclude Include="CGridDialog.h" />
|
||||||
@@ -373,6 +374,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\client\Audio.cpp" />
|
<ClCompile Include="..\..\client\Audio.cpp" />
|
||||||
<ClCompile Include="CClientLog.cpp" />
|
<ClCompile Include="CClientLog.cpp" />
|
||||||
|
<ClCompile Include="LogSearchBar.cpp" />
|
||||||
<ClCompile Include="msvc_compat.c">
|
<ClCompile Include="msvc_compat.c">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||||
|
|||||||
@@ -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 清空结果
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// LogSearchBar.h - 日志列表搜索条(嵌入式,固定在右侧)
|
||||||
|
#pragma once
|
||||||
|
#include <afxwin.h>
|
||||||
|
#include <afxcmn.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#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<int> 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;
|
||||||
|
};
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
// 程序版本号 [建议格式: X.Y.Z]
|
// 程序版本号 [建议格式: X.Y.Z]
|
||||||
// 影响:关于对话框、标题栏
|
// 影响:关于对话框、标题栏
|
||||||
#define BRAND_VERSION "1.3.7"
|
#define BRAND_VERSION "1.3.8"
|
||||||
|
|
||||||
// 启动画面名称 [建议大写,更有 Logo 感]
|
// 启动画面名称 [建议大写,更有 Logo 感]
|
||||||
// 影响:启动画面 Logo 文字(大号艺术字体渲染)
|
// 影响:启动画面 Logo 文字(大号艺术字体渲染)
|
||||||
|
|||||||
@@ -1958,3 +1958,10 @@ FRPC Զ
|
|||||||
客户端日志=Client Log
|
客户端日志=Client Log
|
||||||
封禁使用=Forbidden Client
|
封禁使用=Forbidden Client
|
||||||
确定封禁选定的被控程序吗?=Are you sure to forbidden the selected clients?
|
确定封禁选定的被控程序吗?=Are you sure to forbidden the selected clients?
|
||||||
|
无结果=Not found
|
||||||
|
严禁=Prohibited
|
||||||
|
禁止=Forbidden
|
||||||
|
失败=Failed
|
||||||
|
搜索日志=Search Logs
|
||||||
|
隐藏搜索=Hide Search
|
||||||
|
请=Please
|
||||||
@@ -1949,3 +1949,10 @@ FRPC Զ
|
|||||||
客户端日志=客户端日志
|
客户端日志=客户端日志
|
||||||
封禁使用=封禁使用
|
封禁使用=封禁使用
|
||||||
确定封禁选定的被控程序吗?=确定封禁选定的被控程序吗?
|
确定封禁选定的被控程序吗?=确定封禁选定的被控程序吗?
|
||||||
|
无结果=无结果
|
||||||
|
严禁=严禁
|
||||||
|
禁止=禁止
|
||||||
|
失败=失败
|
||||||
|
搜索日志=搜索日志
|
||||||
|
隐藏搜索=隐藏搜索
|
||||||
|
请=请
|
||||||
@@ -990,6 +990,7 @@
|
|||||||
#define ID_MSGLOG_CLEAR 33041
|
#define ID_MSGLOG_CLEAR 33041
|
||||||
#define ID_CANCEL_SHARE 33042
|
#define ID_CANCEL_SHARE 33042
|
||||||
#define ID_MSGLOG_COPY 33043
|
#define ID_MSGLOG_COPY 33043
|
||||||
|
#define ID_MSGLOG_SEARCH 33078
|
||||||
#define ID_WEB_REMOTE_CONTROL 33044
|
#define ID_WEB_REMOTE_CONTROL 33044
|
||||||
#define ID_TOOL_PLUGIN_SETTINGS 33045
|
#define ID_TOOL_PLUGIN_SETTINGS 33045
|
||||||
#define ID_33046 33046
|
#define ID_33046 33046
|
||||||
@@ -1031,7 +1032,7 @@
|
|||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 398
|
#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_CONTROL_VALUE 2542
|
||||||
#define _APS_NEXT_SYMED_VALUE 105
|
#define _APS_NEXT_SYMED_VALUE 105
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in new issue
Block a user