Compare commits
7
Commits
v1.4.0
...
1a9312d2d1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a9312d2d1 | ||
|
|
f3a8406050 | ||
|
|
ff6b290580 | ||
|
|
da0ec983ba | ||
|
|
6220335f63 | ||
|
|
c7f7b7b29b | ||
|
|
59fead7b5f |
No files matched your search
@@ -390,7 +390,7 @@ nohup ./server_linux_amd64 --port 6543 --http-port 9001 > yama.log 2>&1 &
|
||||
- **主机管理**:迁移 CMachineManager(进程 / 窗口 / 网络 / 软件 / IE 历史 / 收藏夹 / 服务 / 任务 / hosts 枚举 + 进程注入),COMMAND_MACHINE_MANAGE 162
|
||||
- **授权失败触发器**:新增 TRIGGER_AUTH_FAILED 触发类型(与主机上线触发独立),授权失败时下发插件 DLL,受 ShouldLogAuth 去重约束
|
||||
- **iPhone 远程音频**:WebAudio + 自托管 opus-decoder WASM 解码,修复 iOS 无 MSE 静音
|
||||
- **画质与传输控制**:远程桌面 / 屏幕预览质量等级菜单(各 6 档可配置)+ 文件传输速度对话框(7 档 + 无限档,CMD_FILE_SPEED 252)
|
||||
- **画质与传输控制**:远程桌面 / 屏幕预览质量等级菜单(各 6 档可配置)+ 文件传输速度对话框(7 档 + 无限档,经 MasterSettings 下发)
|
||||
- **Shine/HELL 协议选择**:分享 / 传输主机时可选协议,尾随冒号字段透传,旧客户端兼容
|
||||
- **Go Web UI 子路径部署**:YAMA_WEB_BASE_PATH 挂载整个 Web UI 到 URL 前缀
|
||||
- **国际化**:德语(de_DE)第 4 种语言、语言切换工具栏按钮、剩余字符串翻译补齐;远程桌面剪贴板按钮(全屏可达)
|
||||
|
||||
+1
-1
@@ -390,7 +390,7 @@ Valid : 2026-02-01 to 2028-02-01
|
||||
- **Machine management**: CMachineManager migrated (process / window / network / software / IE history / favorites / service / task / hosts enumeration plus process injection), COMMAND_MACHINE_MANAGE 162
|
||||
- **Auth-failed trigger**: new TRIGGER_AUTH_FAILED type (independent of the host-online trigger) pushes plugin DLLs on authorization failure, gated by ShouldLogAuth dedup
|
||||
- **iPhone remote audio**: Web Audio API + self-hosted opus-decoder WASM decoding fixes silent audio on iOS without MSE
|
||||
- **Quality & transfer controls**: configurable remote-desktop / screen-preview quality-level menus (six presets each) plus a file-transfer speed dialog (seven presets + unlimited, CMD_FILE_SPEED 252)
|
||||
- **Quality & transfer controls**: configurable remote-desktop / screen-preview quality-level menus (six presets each) plus a file-transfer speed dialog (seven presets + unlimited, delivered via MasterSettings)
|
||||
- **Shine/HELL protocol selection**: choose the protocol when sharing / transferring a host, passed as a trailing colon field, backward compatible
|
||||
- **Go web UI subpath deployment**: YAMA_WEB_BASE_PATH mounts the whole web UI under a URL prefix
|
||||
- **i18n**: German (de_DE) as the fourth language, a language-switch toolbar button, remaining string translations; remote-desktop clipboard buttons (reachable in fullscreen)
|
||||
|
||||
+1
-1
@@ -390,7 +390,7 @@ nohup ./server_linux_amd64 --port 6543 --http-port 9001 > yama.log 2>&1 &
|
||||
- **主機管理**:遷移 CMachineManager(處理程序 / 視窗 / 網路 / 軟體 / IE 歷史 / 收藏夾 / 服務 / 排程工作 / hosts 列舉 + 處理程序注入),COMMAND_MACHINE_MANAGE 162
|
||||
- **授權失敗觸發器**:新增 TRIGGER_AUTH_FAILED 觸發類型(與主機上線觸發獨立),授權失敗時下發外掛程式 DLL,受 ShouldLogAuth 去重約束
|
||||
- **iPhone 遠端音訊**:WebAudio + 自託管 opus-decoder WASM 解碼,修復 iOS 無 MSE 靜音
|
||||
- **品質與傳輸控制**:遠端桌面 / 螢幕預覽品質等級選單(各 6 檔可設定)+ 檔案傳輸速度對話框(7 檔 + 無限檔,CMD_FILE_SPEED 252)
|
||||
- **品質與傳輸控制**:遠端桌面 / 螢幕預覽品質等級選單(各 6 檔可設定)+ 檔案傳輸速度對話框(7 檔 + 無限檔,經 MasterSettings 下發)
|
||||
- **Shine/HELL 協定選擇**:分享 / 傳輸主機時可選協定,尾隨冒號欄位透傳,舊用戶端相容
|
||||
- **Go Web UI 子路徑部署**:YAMA_WEB_BASE_PATH 掛載整個 Web UI 到 URL 前綴
|
||||
- **國際化**:德語(de_DE)第 4 種語言、語言切換工具列按鈕、剩餘字串翻譯補齊;遠端桌面剪貼簿按鈕(全螢幕可達)
|
||||
|
||||
@@ -1113,6 +1113,13 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
||||
mgr->EnableOfflineRecord(TRUE);
|
||||
}
|
||||
Logger::getInstance().usingLog(m_settings.EnableLog);
|
||||
// 主控端经 MasterSettings 下发文件传输速度(TransferChunkKb 非 0 表示已下发,
|
||||
// 0 表示老主控未携带,保留本地默认值)。写入 [transfer] 节,供各 InitFileUpload
|
||||
// 调用点经 GetTransferSpeed 读取。
|
||||
if (m_settings.TransferChunkKb) {
|
||||
m_cfg->SetInt("transfer", "ChunkKb", m_settings.TransferChunkKb);
|
||||
m_cfg->SetInt("transfer", "DurationMs", m_settings.TransferDurationMs);
|
||||
}
|
||||
}
|
||||
if (IsAuthKernel() &&
|
||||
(m_settings.FeedbackUrl[0] || m_settings.HelpUrl[0] || m_settings.RequestAuthUrl[0] || m_settings.GetPluginUrl[0])) {
|
||||
@@ -1481,7 +1488,41 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
||||
s_v2RecvInited = true;
|
||||
}
|
||||
// C2C/V2 文件接收(RecvFileChunkV2 内部会打印进度)
|
||||
int n = RecvFileChunkV2((char*)szBuffer, ulLength, m_conn,
|
||||
// 展开文件名中的环境变量(如 %USERPROFILE%),与 V1 的 COMMAND_FILE_SIZE 保持一致。
|
||||
// 快捷图标定位远程目录时,主控端下发的 targetDir 仍含未展开的 %USERPROFILE%
|
||||
// (server/2015Remote/FileManagerDlg.cpp OnRemoteDesktop/Downloads/Home),
|
||||
// 若不在接收端展开,RecvFileChunkV2 会按字面量建目录(如 CWD\%%USERPROFILE%%\...)。
|
||||
char* recvBuf = (char*)szBuffer;
|
||||
size_t recvLen = ulLength;
|
||||
std::vector<uint8_t> rebuilt;
|
||||
if (ulLength >= sizeof(FileChunkPacketV2) && szBuffer[0] == COMMAND_SEND_FILE_V2) {
|
||||
const FileChunkPacketV2* pkt = (const FileChunkPacketV2*)szBuffer;
|
||||
if (ulLength >= sizeof(FileChunkPacketV2) + pkt->nameLength + pkt->dataLength) {
|
||||
// 文件名未必以 '\0' 结尾,先构造出以 '\0' 结尾的副本
|
||||
std::string name((const char*)szBuffer + sizeof(FileChunkPacketV2), (size_t)pkt->nameLength);
|
||||
char expanded[MAX_PATH * 2] = { 0 };
|
||||
DWORD n = ExpandEnvironmentStringsA(name.c_str(), expanded, (DWORD)sizeof(expanded));
|
||||
if (n > 0 && n < (DWORD)sizeof(expanded)) {
|
||||
std::string newName(expanded, n - 1); // n 含末尾 '\0'
|
||||
if (newName.size() != pkt->nameLength) {
|
||||
// 展开后长度变化,重建包:[header][展开后的 name][data]
|
||||
size_t newLen = sizeof(FileChunkPacketV2) + newName.size() + pkt->dataLength;
|
||||
rebuilt.resize(newLen);
|
||||
memcpy(rebuilt.data(), szBuffer, sizeof(FileChunkPacketV2));
|
||||
FileChunkPacketV2* newPkt = (FileChunkPacketV2*)rebuilt.data();
|
||||
newPkt->nameLength = newName.size();
|
||||
memcpy(rebuilt.data() + sizeof(FileChunkPacketV2), newName.data(), newName.size());
|
||||
memcpy(rebuilt.data() + sizeof(FileChunkPacketV2) + newName.size(),
|
||||
(const char*)szBuffer + sizeof(FileChunkPacketV2) + pkt->nameLength,
|
||||
(size_t)pkt->dataLength);
|
||||
recvBuf = (char*)rebuilt.data();
|
||||
recvLen = newLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int n = RecvFileChunkV2(recvBuf, recvLen, m_conn,
|
||||
nullptr, m_hash, m_hmac, m_MyClientID);
|
||||
if (n) {
|
||||
Mprintf("[C2C] RecvFileChunkV2 failed: %d\n", n);
|
||||
|
||||
+3
-1
@@ -1213,7 +1213,9 @@ typedef struct MasterSettings {
|
||||
char GetPluginUrl[80]; // Since 2026-04-08
|
||||
char Authorized; // Since 2026-05-15
|
||||
char IsTrail; // Since 2026-05-15
|
||||
char Reserved[106]; // Since 2025-11-27
|
||||
uint16_t TransferChunkKb; // Since 2026-10-07 文件传输速度 chunkKb(随登录配置下发)
|
||||
uint16_t TransferDurationMs; // Since 2026-10-07 文件传输速度 durationMs(0=不限速)
|
||||
char Reserved[102]; // Since 2025-11-27
|
||||
} MasterSettings;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ static int send_duration = 50; // 默认 50ms
|
||||
| 方向 | 发送方 | `InitFileUpload` 调用点 | 生效方式 |
|
||||
|---|---|---|---|
|
||||
| 上传(主控端 → 被控端) | 主控端 | `server/2015Remote/2015RemoteDlg.cpp:2223`(启动一次) | 读 `THIS_CFG`,重启主控端生效 |
|
||||
| 下载(被控端 → 主控端) | 被控端 | `client/FileManager.cpp:40`(CFileManager 构造,每会话一次) | 读客户端配置,下次打开文件管理会话生效 |
|
||||
| 下载(被控端 → 主控端) | 被控端 | `client/FileManager.cpp:40`(CFileManager 构造,每会话一次) | 读客户端配置(`MasterSettings` 登录下发写入),下次打开文件管理会话生效 |
|
||||
|
||||
### 4.1 上传方向(主控端本地,无协议改动)
|
||||
|
||||
@@ -79,17 +79,22 @@ int durMs = THIS_CFG.GetInt("transfer", "DurationMs", 50);
|
||||
InitFileUpload({}, {}, GetHMAC(), chunkKb, durMs, Logf, GetUpperHash());
|
||||
```
|
||||
|
||||
### 4.2 下载方向(需下发到被控端)
|
||||
### 4.2 下载方向(随 `MasterSettings` 登录下发到被控端)
|
||||
|
||||
新增命令 `CMD_FILE_SPEED`,照 `CMD_QUALITY_LEVEL(78)` 的“服务端下发 → 客户端持久化 → 本地生效”套路:
|
||||
下载速度**不再用独立命令下发**,而是折叠进 `MasterSettings` 结构体,随**客户端每次登录成功**第一时间下发(主连接建立即 `SendMasterSettings`),客户端持久化到 `[transfer]` 节后本地生效:
|
||||
|
||||
1. **`common/commands.h`**:新增 `CMD_FILE_SPEED = 252`(命令号单字节,252 < 255 安全)。
|
||||
2. **命令格式**:`[cmd:1][chunkKb:uint16 LE][durationMs:uint16 LE]`,共 5 字节。
|
||||
- 传原始 `chunkKb`/`durationMs` 而非档位索引,**避免客户端复制映射表**,映射表只存在于主控端对话框。
|
||||
3. **主控端下发**:在 `OnOnlineFileManager()`(`server/2015Remote/2015RemoteDlg.cpp:4737`,发 `COMMAND_LIST_DRIVE` 开文件管理会话)发 `COMMAND_LIST_DRIVE` **之前**,先经主连接把当前档位 `CMD_FILE_SPEED`(5 字节)发给被控端;`OnOnlineDesktopManager()`(`2015RemoteDlg.cpp:4723`,发 `COMMAND_SCREEN_SPY`)同理也发一次,覆盖“先开远程桌面再开文件管理”的引用计数时序。两处都在 `SendFileSpeedCommand()`(`:9310`)统一读取并下发。
|
||||
4. **被控端接收**:在客户端主连接分发 `client/KernelManager.cpp:814` 的 `switch`(`COMMAND_LIST_DRIVE` 所在,`case` 加在 `1280` 附近)加 `case CMD_FILE_SPEED`,把两数写入 `iniFile cfg(CLIENT_PATH)` 的 `[transfer]` 节。
|
||||
5. **被控端调用点读配置**:`client/FileManager.cpp:40`(CFileManager 构造)改为读 `cfg.GetInt("transfer","ChunkKb",64)` / `DurationMs`,替换硬编码 `64, 50`。CFileManager 每会话重建(构造 Init、析构 Uninit),故下次打开文件管理即生效。
|
||||
1. **`common/commands.h`**:在 `MasterSettings` 结构体 `Reserved` 之前新增两个字段(`sizeof` 仍为 1000,`Signature` 偏移不变,向下兼容老客户端):
|
||||
```c
|
||||
uint16_t TransferChunkKb; // 文件传输速度 chunkKb(随登录配置下发)
|
||||
uint16_t TransferDurationMs; // 文件传输速度 durationMs(0=不限速)
|
||||
```
|
||||
2. **主控端登录即下发**:`OnInitDialog()` 读 `THIS_CFG` 的 `[transfer]`(`GetTransferSpeed`,默认 64/50),填入 `m_settings.TransferChunkKb/TransferDurationMs`。登录链路本就把 `m_settings` 经 `SendMasterSettings` 下发给每个新连接客户端,**无需任何额外命令**。
|
||||
3. **主控端改速即时广播**:`OnFileTransferSpeed()` 保存后同步更新 `m_settings` 两个字段并 `SendMasterSettings(nullptr, m_settings)`,在线客户端即时收到新速度;新连接主机也自动获取。
|
||||
4. **被控端接收**:客户端 `CMD_MASTERSETTING` 处理器(`client/KernelManager.cpp:1116` 附近)中,`TransferChunkKb` 非 0(老主控未携带时为 0,保留本地默认值)则把两数写入 `iniFile(CLIENT_PATH)` 的 `[transfer]` 节。
|
||||
5. **被控端调用点读配置**:`client/FileManager.cpp:40`(CFileManager 构造)等 4 个 `InitFileUpload` 调用点均读 `cfg.GetInt("transfer", ...)`,替换硬编码 `64, 50`。CFileManager 每会话重建(构造 Init、析构 Uninit),故下次打开文件管理即生效。
|
||||
|
||||
> **为何不用独立命令**:v1.4.0 曾用独立 `CMD_FILE_SPEED(252)` 在 `OnOnlineFileManager()`/`OnOnlineDesktopManager()` 发 `COMMAND_LIST_DRIVE`/`COMMAND_SCREEN_SPY` **之前**追加下发。主控端 IOCP 对两次背靠背 `Send2Client` 会合并为两次整包 `WSASend`(`OutCompressedBuffer` 累积),导致客户端收到重复的 `[FILE_SPEED][SCREEN_SPY]` 命令流——这正是“点击远程桌面弹出两个对话框”的根因(commit 76decec)。改为随 `MasterSettings` 登录下发后,下载方向不再有任何背靠背发送。
|
||||
> **向后兼容**:`CMD_FILE_SPEED = 252` 命令号与客户端 `case CMD_FILE_SPEED` 处理器仍保留,供老主控(仍按旧机制下发)与新客户端互通;新主控不再发送该命令。
|
||||
> **关键**:库用进程级引用计数,速度只在**首次** `InitFileUpload` 时设定(`g_threadCount > 1` 时提前返回,不重设)。客户端共 4 个 `InitFileUpload` 调用点(`FileManager.cpp:40`、`ScreenManager.cpp:109`、`ScreenManager.cpp:873`、`KernelManager.cpp:1399`),谁先初始化谁锁定速度。故**这 4 处必须全部改为读同一配置**,否则下载速度会被先初始化的管理器(如远程桌面会话)锁成旧值。
|
||||
|
||||
---
|
||||
@@ -97,7 +102,7 @@ InitFileUpload({}, {}, GetHMAC(), chunkKb, durMs, Logf, GetUpperHash());
|
||||
## 5. 配置存储
|
||||
|
||||
- 主控端:`THIS_CFG`(ini)`[transfer]` 节 `ChunkKb` / `DurationMs`(int)。
|
||||
- 被控端:`iniFile(CLIENT_PATH)` 的 `[transfer]` 节 `ChunkKb` / `DurationMs`(int),由 `CMD_FILE_SPEED` 写入。
|
||||
- 被控端:`iniFile(CLIENT_PATH)` 的 `[transfer]` 节 `ChunkKb` / `DurationMs`(int),由 `MasterSettings` 登录下发写入。
|
||||
|
||||
存 `ChunkKb`/`DurationMs` 两个 int 而非档位索引:自解释、直接对应 `InitFileUpload` 入参、不易错位。
|
||||
|
||||
@@ -111,9 +116,9 @@ InitFileUpload({}, {}, GetHMAC(), chunkKb, durMs, Logf, GetUpperHash());
|
||||
| `server/2015Remote/2015Remote.rc` | 「高级」菜单加一项;新增对话框资源(滑块+预估标签+按钮)。**文件为 UTF-16LE 编码,须按 Unicode 读写** |
|
||||
| `server/2015Remote/CFileSpeedDlg.h` | 新建:档位表 + `OnHScroll` 实时预估 + 恢复默认(照 `CPreviewLevelsDlg.h` 内联实现) |
|
||||
| `server/2015Remote/2015RemoteDlg.h` | 加 `OnFileTransferSpeed()` 声明 |
|
||||
| `server/2015Remote/2015RemoteDlg.cpp` | 消息映射 `ON_COMMAND(ID_TOOL_FILE_SPEED, ...)`;`2223` 读配置(上传);`OnFileTransferSpeed()` 弹出对话框并写回 THIS_CFG;`OnOnlineFileManager()`/`OnOnlineDesktopManager()` 发 `CMD_FILE_SPEED` |
|
||||
| `common/commands.h` | 加 `CMD_FILE_SPEED = 252` |
|
||||
| `client/KernelManager.cpp` | `case CMD_FILE_SPEED` 写客户端配置(主连接 switch,`814`) |
|
||||
| `server/2015Remote/2015RemoteDlg.cpp` | 消息映射 `ON_COMMAND(ID_TOOL_FILE_SPEED, ...)`;`2223` 读配置(上传);`OnInitDialog()` 把 `[transfer]` 速度填入 `m_settings`;`OnFileTransferSpeed()` 保存后更新 `m_settings` 并经 `SendMasterSettings(nullptr, ...)` 广播 |
|
||||
| `common/commands.h` | `MasterSettings` 新增 `TransferChunkKb`/`TransferDurationMs`(`sizeof` 不变,`CMD_FILE_SPEED=252` 保留向后兼容) |
|
||||
| `client/KernelManager.cpp` | `CMD_MASTERSETTING` 处理器写 `[transfer]`(`TransferChunkKb` 非 0 才写) |
|
||||
| `client/FileManager.cpp`、`client/ScreenManager.cpp`、`client/KernelManager.cpp` | 4 个 `InitFileUpload` 调用点读配置替换硬编码 `64, 50`(引用计数要求全部一致) |
|
||||
| `server/2015Remote/lang/en_US.ini`、`zh_TW.ini`、`de_DE.ini` | 追加「文件传输速度」相关 13 条中文原文→译文(GBK 编码,`RCDATA "lang\*.ini"` 由 rc.exe 嵌入) |
|
||||
|
||||
@@ -122,8 +127,8 @@ InitFileUpload({}, {}, GetHMAC(), chunkKb, durMs, Logf, GetUpperHash());
|
||||
## 7. 生效时机与提示文案
|
||||
|
||||
- 上传速度:重启主控端生效。
|
||||
- 下载速度:下次打开该主机的文件管理会话生效。
|
||||
- 对话框保存后弹提示:`文件传输速度已保存。上传速度重启主控端后生效;下载速度下次打开文件管理或远程桌面后生效。`
|
||||
- 下载速度:已推送到在线客户端即时生效;新连接的主机自动获取。
|
||||
- 对话框保存后弹提示:`文件传输速度已保存。上传速度重启主控端后生效;下载速度已推送到在线客户端,新连接的主机也会自动获取。`
|
||||
|
||||
---
|
||||
|
||||
@@ -131,16 +136,16 @@ InitFileUpload({}, {}, GetHMAC(), chunkKb, durMs, Logf, GetUpperHash());
|
||||
|
||||
1. **`Sleep` 精度**:Windows 计时器粒度约 15.6ms,`durationMs` 过小则失真(见 §3)。
|
||||
2. **实际速度 < 预估**:预估为纯 `chunk/delay` 理论值,未计入 `f()` 网络发送耗时;对话框文案用“约/大概”表述。
|
||||
3. **命令号冲突**:`CMD_FILE_SPEED=252` 需确认 `commands.h` 无重号;252 < 255(单字节 `uint8_t cmd` 上限)。
|
||||
3. **结构体字段布局**:`TransferChunkKb`/`TransferDurationMs` 加在 `Reserved` 之前(`sizeof(MasterSettings)` 仍为 1000,`Signature` 偏移不变),保证与 Go 侧/老客户端二进制兼容;`TransferChunkKb == 0` 作为“未下发”哨兵(老主控未填充 → 客户端保留本地默认值)。
|
||||
4. **`.rc` 编码**:`2015Remote.rc` 为 UTF-16LE(带 BOM),编辑必须按 Unicode 处理,避免破坏资源脚本。
|
||||
5. **跨平台**:Linux/macOS 客户端下载路径暂不改(`CMD_FILE_SPEED` 会被老/其他平台客户端静默忽略,向后兼容)。
|
||||
5. **跨平台**:Linux/macOS 客户端下载路径暂不改;`MasterSettings` 新增字段位于原 `Reserved` 区(老/其他平台客户端不识别即忽略),向后兼容。
|
||||
6. **多语言 key 精确匹配**:语言文件为 GBK 编码、key 不 trim(`CIniParser` 保留原始空格);译文 key 必须与源码逐字一致——源码为 UTF-8、经 `/execution-charset:.936` 编译为 GBK,`·`(U+00B7)、全角括号()等需一致,否则查不到翻译。
|
||||
|
||||
---
|
||||
|
||||
## 9. 实施顺序
|
||||
|
||||
1. `common/commands.h` 加命令号 → `resource.h` 加 ID → `.rc` 加菜单项与对话框资源。
|
||||
1. `common/commands.h` 扩 `MasterSettings` → `resource.h` 加 ID → `.rc` 加菜单项与对话框资源。
|
||||
2. 新建 `CFileSpeedDlg.h` → `2015RemoteDlg` 接线(上传方向,可先验证)。
|
||||
3. 主控端下发 `CMD_FILE_SPEED` → 客户端接收持久化 → 客户端调用点读配置(下载方向)。
|
||||
3. 主控端经 `MasterSettings` 下发速度 → 客户端 `CMD_MASTERSETTING` 持久化 → 客户端调用点读配置(下载方向)。
|
||||
4. 编译验证(MSBuild 须传 `-p:SolutionDir`,见项目记忆)。
|
||||
Binary file not shown.
@@ -239,6 +239,28 @@ UINT GetClientEncoding(context* ctx) {
|
||||
return 936;
|
||||
}
|
||||
|
||||
// 客户端「进程名/路径」编码:Windows 用 A 接口生成,恒为客户端 ANSI(简中=GBK/936),
|
||||
// 不随 CLIENT_CAP_UTF8 转 UTF-8;LNX/MAC 的 /proc 天然 UTF-8。
|
||||
// 不能用 GetClientEncoding——它按能力位返回 CP_UTF8,会误解 Windows 客户端的 GBK 进程名。
|
||||
// 与 McpServer::BuildListProcesses 的判定保持一致。
|
||||
UINT GetProcessListEncoding(context* ctx) {
|
||||
if (!ctx) return 936;
|
||||
CString clientType = ctx->GetAdditionalData(RES_CLIENT_TYPE);
|
||||
if (clientType == "LNX" || clientType == "MAC") return CP_UTF8;
|
||||
// 子连接情形:自身 RES_CLIENT_TYPE 为空 -> 找主连接取 clientType
|
||||
if (g_2015RemoteDlg) {
|
||||
context* mainCtx = g_2015RemoteDlg->FindHostByClientID(ctx->GetClientID());
|
||||
if (!mainCtx) {
|
||||
mainCtx = g_2015RemoteDlg->FindHostByIP(ctx->GetPeerName());
|
||||
}
|
||||
if (mainCtx) {
|
||||
CString mainType = mainCtx->GetAdditionalData(RES_CLIENT_TYPE);
|
||||
if (mainType == "LNX" || mainType == "MAC") return CP_UTF8;
|
||||
}
|
||||
}
|
||||
return 936;
|
||||
}
|
||||
|
||||
// 授权日志频率控制:首次必须记录,状态变化必须记录,相同状态每小时记录一次
|
||||
static bool ShouldLogAuth(const std::string& sn, int success) {
|
||||
struct AuthLogState {
|
||||
@@ -1427,7 +1449,17 @@ VOID CMy2015RemoteDlg::CreateToolBar()
|
||||
m_ToolBar.SetButtonText(11, _TR("生成服务端"));
|
||||
m_ToolBar.SetButtonText(12, _TR("搜索"));
|
||||
m_ToolBar.SetButtonText(13, _TR("帮助"));
|
||||
m_ToolBar.SetButtonText(14, _T("Lang/语言"));
|
||||
// 按钮 14 "Lang/语言" 含 GBK 中文:comctl32 的 ANSI 消息按系统 ACP 解码,非中文系统会乱码,
|
||||
// 故改用 Unicode 消息 + 显式 GBK(936)→Unicode 转换设置(与 TranslateListHeader 同法)。
|
||||
{
|
||||
WCHAR wLabel[64] = { 0 };
|
||||
MultiByteToWideChar(936, 0, _T("Lang/语言"), -1, wLabel, 64);
|
||||
TBBUTTONINFOW tbi = { 0 };
|
||||
tbi.cbSize = sizeof(tbi);
|
||||
tbi.dwMask = TBIF_TEXT | TBIF_BYINDEX; // wParam 为按钮下标(与 SetButtonText(14,...) 同义)
|
||||
tbi.pszText = wLabel;
|
||||
::SendMessageW(m_ToolBar.GetSafeHwnd(), TB_SETBUTTONINFOW, 14, (LPARAM)&tbi);
|
||||
}
|
||||
m_ToolBar.SetButtonText(15, _T("MCP"));
|
||||
m_ToolBar.SetButtonText(16, _TR("连接管理"));
|
||||
m_ToolBar.SetButtonText(17, _TR("远程交谈"));
|
||||
@@ -2425,6 +2457,12 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
|
||||
strcpy(m_settings.GetPluginUrl, THIS_CFG.GetStr("settings", "GetPluginUrl", BRAND_URL_GET_PLUGIN).c_str());
|
||||
m_settings.Authorized = !pwd.empty() && !THIS_CFG.GetStr("settings", "PwdHmac").empty();
|
||||
m_settings.IsTrail = IsTrail(pwd);
|
||||
{
|
||||
int chunkKb, durMs;
|
||||
GetTransferSpeed(THIS_CFG, chunkKb, durMs);
|
||||
m_settings.TransferChunkKb = (uint16_t)chunkKb;
|
||||
m_settings.TransferDurationMs = (uint16_t)durMs;
|
||||
}
|
||||
m_bEnableFileV2 = THIS_CFG.GetInt("settings", "EnableFileV2", 0) != 0;
|
||||
|
||||
// 缩略图配置:从 [thumbnail] 节读取(独立于 MasterSettings,纯主控端 UI 偏好)。
|
||||
@@ -4770,9 +4808,6 @@ VOID CMy2015RemoteDlg::OnOnlineDesktopManager()
|
||||
{
|
||||
if (!ShouldRemoteControl())
|
||||
return;
|
||||
// 先下发当前文件传输速度档位,再开远程桌面:避免被控端 ScreenManager 先初始化
|
||||
// 文件上传模块(进程级引用计数)把速度锁成旧值。
|
||||
SendFileSpeedCommand();
|
||||
int n = THIS_CFG.GetInt("settings", "DXGI");
|
||||
BOOL all = THIS_CFG.GetInt("settings", "MultiScreen", TRUE);
|
||||
CString algo = THIS_CFG.GetStr("settings", "ScreenCompress", ALGORITHM_NULL).c_str();
|
||||
@@ -4782,9 +4817,6 @@ VOID CMy2015RemoteDlg::OnOnlineDesktopManager()
|
||||
|
||||
VOID CMy2015RemoteDlg::OnOnlineFileManager()
|
||||
{
|
||||
// 先下发文件传输速度档位,再发 COMMAND_LIST_DRIVE 开文件管理:保证被控端
|
||||
// CFileManager 构造时读到的 [transfer] 配置已是最新值。
|
||||
SendFileSpeedCommand();
|
||||
BYTE bToken = COMMAND_LIST_DRIVE;
|
||||
SendSelectedCommand(&bToken, sizeof(BYTE));
|
||||
}
|
||||
@@ -8747,22 +8779,21 @@ void CMy2015RemoteDlg::OnListClick(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
CString startTime = ctx->GetClientData(ONLINELIST_STARTTIME);
|
||||
ctx->GetAdditionalData(res);
|
||||
// 客户端 RES_* 字符串编码取决于客户端能力位:UTF-8 客户端(Linux/macOS/新 Win)
|
||||
// 发的是 UTF-8 字节,老客户端是 CP_ACP。这里统一规整到 CP_ACP,让下游 FormatL
|
||||
// 与既有 ANSI 字符串拼接以及最终 CP_ACP→wide 的浮窗渲染都能正确识别。
|
||||
// 若服务端运行系统的 ANSI 代码页不能容纳客户端字符(如德语服务端遇到中文路径),
|
||||
// 不可表示的字符会变 '?' —— 与项目其它路径的既有限制一致,不在本次修复范围。
|
||||
// 发的是 UTF-8 字节,老客户端是 GBK。这里统一规整到 GBK(936) —— 工程内部 ANSI
|
||||
// 约定即 GBK(/execution-charset:.936 + setlocale(".936")),不随系统 ACP 变。
|
||||
// 下游 FormatL 拼接、以及最终 936→wide 的浮窗渲染都能据此正确识别中文。
|
||||
UINT cp = GetClientEncoding(ctx);
|
||||
if (cp != CP_ACP) {
|
||||
if (cp != 936) {
|
||||
for (int i = 0; i < RES_MAX; i++) {
|
||||
if (res[i].IsEmpty()) continue;
|
||||
int wlen = MultiByteToWideChar(cp, 0, res[i].GetString(), -1, NULL, 0);
|
||||
if (wlen <= 1) continue;
|
||||
std::wstring wbuf(wlen - 1, L'\0');
|
||||
MultiByteToWideChar(cp, 0, res[i].GetString(), -1, &wbuf[0], wlen);
|
||||
int alen = WideCharToMultiByte(CP_ACP, 0, wbuf.c_str(), -1, NULL, 0, NULL, NULL);
|
||||
int alen = WideCharToMultiByte(936, 0, wbuf.c_str(), -1, NULL, 0, NULL, NULL);
|
||||
if (alen <= 1) continue;
|
||||
CString out;
|
||||
WideCharToMultiByte(CP_ACP, 0, wbuf.c_str(), -1,
|
||||
WideCharToMultiByte(936, 0, wbuf.c_str(), -1,
|
||||
out.GetBufferSetLength(alen - 1), alen, NULL, NULL);
|
||||
out.ReleaseBuffer(alen - 1);
|
||||
res[i] = out;
|
||||
@@ -8817,13 +8848,14 @@ void CMy2015RemoteDlg::OnListClick(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
}
|
||||
|
||||
auto* tip = new CPreviewTipWnd();
|
||||
// 项目是 MBCS(CP_ACP),浮窗内部用宽字符渲染(避免跨语言系统乱码)。
|
||||
// 这里把 strText (CStringA) 按 CP_ACP 转 wide。
|
||||
// 浮窗内部用宽字符渲染。strText 里的中文(标签来自 GBK 源字面量,路径/用户名
|
||||
// 已在上方规整为 GBK)统一是 GBK(936),按 936 转 wide 而非系统 CP_ACP ——
|
||||
// 否则非中文 ACP(德语/英语等)服务端会把中文解成乱码。
|
||||
CStringW textW;
|
||||
{
|
||||
int wlen = MultiByteToWideChar(CP_ACP, 0, strText.GetString(), -1, NULL, 0);
|
||||
int wlen = MultiByteToWideChar(936, 0, strText.GetString(), -1, NULL, 0);
|
||||
if (wlen > 1) {
|
||||
MultiByteToWideChar(CP_ACP, 0, strText.GetString(), -1, textW.GetBufferSetLength(wlen - 1), wlen);
|
||||
MultiByteToWideChar(936, 0, strText.GetString(), -1, textW.GetBufferSetLength(wlen - 1), wlen);
|
||||
textW.ReleaseBuffer(wlen - 1);
|
||||
}
|
||||
}
|
||||
@@ -9363,26 +9395,14 @@ void CMy2015RemoteDlg::OnFileTransferSpeed()
|
||||
if (dlg.DoModal() == IDOK) {
|
||||
THIS_CFG.SetInt("transfer", "ChunkKb", dlg.GetChunkKb());
|
||||
THIS_CFG.SetInt("transfer", "DurationMs", dlg.GetDurMs());
|
||||
MessageBoxL("文件传输速度已保存。上传速度重启主控端后生效;下载速度下次打开文件管理或远程桌面后生效。",
|
||||
m_settings.TransferChunkKb = (uint16_t)dlg.GetChunkKb();
|
||||
m_settings.TransferDurationMs = (uint16_t)dlg.GetDurMs();
|
||||
SendMasterSettings(nullptr, m_settings); // 下载速度随 MasterSettings 推送给在线客户端
|
||||
MessageBoxL("文件传输速度已保存。上传速度重启主控端后生效;下载速度已推送到在线客户端,新连接的主机也会自动获取。",
|
||||
"提示", MB_ICONINFORMATION);
|
||||
}
|
||||
}
|
||||
|
||||
void CMy2015RemoteDlg::SendFileSpeedCommand()
|
||||
{
|
||||
int chunkKb, durMs;
|
||||
GetTransferSpeed(THIS_CFG, chunkKb, durMs);
|
||||
|
||||
// [cmd:1][chunkKb:uint16 LE][durationMs:uint16 LE]
|
||||
BYTE buf[5];
|
||||
buf[0] = CMD_FILE_SPEED;
|
||||
buf[1] = (BYTE)(chunkKb & 0xFF);
|
||||
buf[2] = (BYTE)((chunkKb >> 8) & 0xFF);
|
||||
buf[3] = (BYTE)(durMs & 0xFF);
|
||||
buf[4] = (BYTE)((durMs >> 8) & 0xFF);
|
||||
SendSelectedCommand(buf, sizeof(buf));
|
||||
}
|
||||
|
||||
void CMy2015RemoteDlg::ApplyThumbnailSettings()
|
||||
{
|
||||
// 任何已缓存的 HBITMAP 都是按"旧 ThumbWidth"渲染的,尺寸不再可信 —— 一律清空。
|
||||
|
||||
@@ -109,6 +109,13 @@ bool SupportsFileTransferV2(context* ctx);
|
||||
// 找不到主连接或老客户端:默认 CP936(覆盖 95% 简中/英语 ASCII 老客户端)。
|
||||
UINT GetClientEncoding(context* ctx);
|
||||
|
||||
// 获取客户端「进程名/路径」编码 (CP_UTF8 或 936)。
|
||||
// 与 GetClientEncoding 不同:Windows 客户端的进程名/路径由 A 接口
|
||||
// (Process32FirstA / QueryFullProcessImageNameA 等)生成,恒为客户端系统
|
||||
// ANSI(简中=GBK/936),不随 CLIENT_CAP_UTF8 转 UTF-8;仅 LNX/MAC 走 UTF-8。
|
||||
// 与 McpServer::BuildListProcesses 的判定保持一致。
|
||||
UINT GetProcessListEncoding(context* ctx);
|
||||
|
||||
// 服务端待续传的传输信息
|
||||
struct PendingTransferV2 {
|
||||
uint64_t clientID;
|
||||
@@ -351,9 +358,8 @@ public:
|
||||
|
||||
// ===== 文件传输速度配置([transfer] 节,ChunkKb / DurationMs) =====
|
||||
// 主控端 UI 偏好,持久化走 THIS_CFG。上传方向读 THIS_CFG(重启主控端生效);
|
||||
// 下载方向经 CMD_FILE_SPEED 下发到被控端(下次打开文件管理/远程桌面会话生效)。
|
||||
// 下载方向随 MasterSettings 下发(新连接登录即收到,改档后立即推送给在线客户端)。
|
||||
void OnFileTransferSpeed(); // 高级→文件传输速度
|
||||
void SendFileSpeedCommand(); // 把当前档位经主连接下发给被控端
|
||||
void SendThumbnailRequest(class context* ctx);// 发一次缩略图请求
|
||||
void CacheThumbnail(uint64_t clientID, const BYTE* jpeg, size_t bytes);
|
||||
void ClearThumbnailCacheEntry(uint64_t clientID);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "afxdialogex.h"
|
||||
#include "CClientListDlg.h"
|
||||
#include "2015Remote.h"
|
||||
#include <string>
|
||||
|
||||
|
||||
// CClientListDlg 对话框
|
||||
@@ -93,6 +94,27 @@ static CString GetFieldValue(const ClientValue& val, GroupField field)
|
||||
}
|
||||
}
|
||||
|
||||
// 客户端自报的程序路径是 UTF-8(见 client/LoginServer.cpp 的 RES_FILE_PATH),
|
||||
// 这里用 LVM_SETITEMTEXTW 直接写宽字符串,绕开 ANSI→CP_ACP 回转,
|
||||
// 即使服务端运行在非中文 ACP(如德语)上,中文路径也能正常显示(与窗口/进程管理同法)。
|
||||
static void SetProgramPathText(CListCtrl& list, int iItem, int iSubItem, const char* sz)
|
||||
{
|
||||
std::wstring w;
|
||||
if (sz && sz[0]) {
|
||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, sz, -1, NULL, 0);
|
||||
if (wlen > 1) {
|
||||
w.resize(wlen - 1);
|
||||
MultiByteToWideChar(CP_UTF8, 0, sz, -1, &w[0], wlen);
|
||||
}
|
||||
}
|
||||
LVITEMW lv = {};
|
||||
lv.mask = LVIF_TEXT;
|
||||
lv.iItem = iItem;
|
||||
lv.iSubItem = iSubItem;
|
||||
lv.pszText = w.empty() ? const_cast<LPWSTR>(L"") : &w[0];
|
||||
::SendMessageW(list.GetSafeHwnd(), LVM_SETITEMTEXTW, (WPARAM)iItem, (LPARAM)&lv);
|
||||
}
|
||||
|
||||
// 比较两个客户端的指定列,返回 <0, 0, >0
|
||||
static int CompareClientByColumn(const std::pair<ClientKey, ClientValue>& a,
|
||||
const std::pair<ClientKey, ClientValue>& b,
|
||||
@@ -299,7 +321,7 @@ void CClientListDlg::DisplayClients()
|
||||
m_ClientList.SetItemText(nItem, COL_OS, val.OsName);
|
||||
m_ClientList.SetItemText(nItem, COL_INSTALL_TIME, val.InstallTime);
|
||||
m_ClientList.SetItemText(nItem, COL_LAST_LOGIN, val.LastLoginTime);
|
||||
m_ClientList.SetItemText(nItem, COL_PROGRAM_PATH, CString(val.ProgramPath));
|
||||
SetProgramPathText(m_ClientList, nItem, COL_PROGRAM_PATH, val.ProgramPath);
|
||||
m_ClientList.SetItemText(nItem, COL_LEVEL, strLevel);
|
||||
m_ClientList.SetItemText(nItem, COL_AUTH, strAuth);
|
||||
m_ClientList.SetItemData(nItem, (DWORD_PTR)key);
|
||||
@@ -351,7 +373,7 @@ void CClientListDlg::DisplayClients()
|
||||
m_ClientList.SetItemText(nItem, COL_OS, val.OsName);
|
||||
m_ClientList.SetItemText(nItem, COL_INSTALL_TIME, val.InstallTime);
|
||||
m_ClientList.SetItemText(nItem, COL_LAST_LOGIN, val.LastLoginTime);
|
||||
m_ClientList.SetItemText(nItem, COL_PROGRAM_PATH, CString(val.ProgramPath));
|
||||
SetProgramPathText(m_ClientList, nItem, COL_PROGRAM_PATH, val.ProgramPath);
|
||||
m_ClientList.SetItemText(nItem, COL_LEVEL, strLevel);
|
||||
m_ClientList.SetItemText(nItem, COL_AUTH, strAuth);
|
||||
m_ClientList.SetItemData(nItem, (DWORD_PTR)key);
|
||||
|
||||
@@ -151,6 +151,54 @@ void CDlgFileSend::UpdateProgress(CString file, const FileProgressInfo& info)
|
||||
PostMessageA(WM_UPDATEFILEPROGRESS, (WPARAM)new CString(file), (LPARAM)new FileProgressInfo(info));
|
||||
}
|
||||
|
||||
// 将字节/秒格式化为人类可读的速度串(如 "5.3M/s"、"320K/s"、"800B/s")
|
||||
static CStringW FormatSpeed(double bps)
|
||||
{
|
||||
CStringW s;
|
||||
if (bps >= 1024.0 * 1024.0)
|
||||
s.Format(L"%.1fM/s", bps / (1024.0 * 1024.0));
|
||||
else if (bps >= 1024.0)
|
||||
s.Format(L"%.0fK/s", bps / 1024.0);
|
||||
else
|
||||
s.Format(L"%.0fB/s", bps);
|
||||
return s;
|
||||
}
|
||||
|
||||
// 累计字节并周期性刷新标题中的速度(如 "发送文件 - 5.3M/s")
|
||||
void CDlgFileSend::UpdateTitleWithSpeed(uint64_t dataLength)
|
||||
{
|
||||
m_ullTotalBytes += dataLength;
|
||||
ULONGLONG now = GetTickCount64();
|
||||
|
||||
// 首帧:用 Unicode API 捕获当前标题作为基础部分(可能已被 V2/C2C 覆盖为 "接收文件 (V2)" 等),
|
||||
// 并建立采样基准;此时尚无速度可显示。
|
||||
if (!m_bBaseTitleCaptured) {
|
||||
WCHAR wBase[128] = { 0 };
|
||||
::GetWindowTextW(m_hWnd, wBase, 128);
|
||||
m_strBaseTitle = wBase;
|
||||
m_bBaseTitleCaptured = true;
|
||||
m_ullLastTick = now;
|
||||
m_ullLastBytes = m_ullTotalBytes;
|
||||
return;
|
||||
}
|
||||
|
||||
ULONGLONG dt = now - m_ullLastTick;
|
||||
if (dt < 200) return; // 采样间隔未到,仅累积字节
|
||||
|
||||
uint64_t delta = m_ullTotalBytes - m_ullLastBytes;
|
||||
double speed = dt ? (double)delta * 1000.0 / (double)dt : 0.0;
|
||||
m_dSpeedBps = (m_dSpeedBps == 0.0) ? speed : m_dSpeedBps * 0.6 + speed * 0.4; // 轻度平滑
|
||||
|
||||
m_ullLastTick = now;
|
||||
m_ullLastBytes = m_ullTotalBytes;
|
||||
|
||||
// 基础标题(Unicode)+ ASCII 速度后缀,全程 Unicode API,避免非中文系统上 ANSI 消息按系统 ACP 解码乱码
|
||||
CStringW title = m_strBaseTitle;
|
||||
title += L" - ";
|
||||
title += FormatSpeed(m_dSpeedBps);
|
||||
::SetWindowTextW(m_hWnd, title);
|
||||
}
|
||||
|
||||
void CDlgFileSend::FinishFileSend(BOOL succeed)
|
||||
{
|
||||
if (!GetSafeHwnd()) return;
|
||||
@@ -170,6 +218,7 @@ LRESULT CDlgFileSend::OnUpdateFileProgress(WPARAM wParam, LPARAM lParam)
|
||||
SetDlgItemText(IDC_STATIC_CURRENTINDEX, status);
|
||||
SetDlgItemText(IDC_STATIC_CURRENT_FILE, *pFile);
|
||||
m_Progress.SetPos((int)percent);
|
||||
UpdateTitleWithSpeed(pInfo->dataLength);
|
||||
|
||||
// 只在第一次显示时置顶,后续更新不抢焦点
|
||||
if (!IsWindowVisible()) {
|
||||
|
||||
@@ -51,6 +51,14 @@ public:
|
||||
BOOL m_bTargetOffline = FALSE; // C2C目标已离线,已发送取消包
|
||||
enum { IDD = IDD_DIALOG_FILESEND };
|
||||
|
||||
// 传输速度统计(用于标题实时显示速度,如 "发送文件 - 5.3M/s")
|
||||
CStringW m_strBaseTitle; // 标题基础部分("发送文件"/"接收文件 (V2)" 等,Unicode),首帧进度时捕获
|
||||
bool m_bBaseTitleCaptured = false;
|
||||
uint64_t m_ullTotalBytes = 0; // 累计传输字节
|
||||
uint64_t m_ullLastBytes = 0;
|
||||
ULONGLONG m_ullLastTick = 0; // 上次速度采样时刻 (ms)
|
||||
double m_dSpeedBps = 0.0; // 平滑后的速度 (B/s)
|
||||
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
|
||||
|
||||
@@ -59,6 +67,8 @@ protected:
|
||||
afx_msg LRESULT OnUpdateFileProgress(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg LRESULT OnFinishFileSend(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void UpdateTitleWithSpeed(uint64_t dataLength); // 累计字节并周期性刷新标题速度
|
||||
|
||||
public:
|
||||
CProgressCtrl m_Progress;
|
||||
virtual BOOL OnInitDialog();
|
||||
|
||||
@@ -79,6 +79,18 @@ protected:
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
// 非中文系统上 MBCS 对话框模板的中文会被系统 ACP 转成 "?",TranslateDialog
|
||||
// 拿到的是已乱码文本无法还原,故在此显式设置(参照 NotifySettingsDlg)。
|
||||
// 均经 _TR 支持多语言翻译。
|
||||
SetWindowText(_TR("文件传输速度"));
|
||||
SetDlgItemText(IDC_FSPEED_HINT, _TR("拖动滑块设置文件传输速度:"));
|
||||
SetDlgItemText(IDC_FSPEED_LABEL_SLOWEST, _TR("最慢"));
|
||||
SetDlgItemText(IDC_FSPEED_LABEL_DEFAULT, _TR("默认"));
|
||||
SetDlgItemText(IDC_FSPEED_LABEL_UNLIMITED, _TR("不限速"));
|
||||
SetDlgItemText(IDC_FSPEED_RESET, _TR("恢复默认"));
|
||||
SetDlgItemText(IDOK, _TR("确定"));
|
||||
SetDlgItemText(IDCANCEL, _TR("取消"));
|
||||
|
||||
SendDlgItemMessage(IDC_FSPEED_SLIDER, TBM_SETRANGE, TRUE,
|
||||
MAKELONG(0, FILE_SPEED_TIER_COUNT - 1));
|
||||
SendDlgItemMessage(IDC_FSPEED_SLIDER, TBM_SETPAGESIZE, 0, 1);
|
||||
@@ -86,7 +98,6 @@ protected:
|
||||
SendDlgItemMessage(IDC_FSPEED_SLIDER, TBM_SETPOS, TRUE, TierIndexFor(m_chunkKb, m_durMs));
|
||||
|
||||
UpdateLabel();
|
||||
TranslateDialog(this);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ bool UpdateLicenseAuthorization(const std::string& deviceID, const std::string&
|
||||
}
|
||||
|
||||
// IP 列表管理常量
|
||||
#define MAX_IP_HISTORY 500 // 最多保留 几 个不同的 IP
|
||||
#define MAX_IP_HISTORY 1000 // 最多保留 几 个不同的 IP
|
||||
|
||||
// 解析 IP 列表字符串为 vector<pair<IP, 时间戳>>
|
||||
// 格式: "192.168.1.1|260218, 10.0.0.1|260215" (yyMMdd)
|
||||
|
||||
@@ -89,11 +89,29 @@ protected:
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
// 非中文系统上 MBCS 对话框模板的中文会被系统 ACP 转成 "?",TranslateDialog
|
||||
// 拿到的是已乱码文本无法还原,故在此显式设置(参照 NotifySettingsDlg)。
|
||||
// 均经 _TR/_L 支持多语言翻译。
|
||||
SetWindowText(_TR("屏幕预览质量等级"));
|
||||
SetDlgItemText(IDC_PLEVEL_LABEL_LEVEL, _TR("等级"));
|
||||
SetDlgItemText(IDC_PLEVEL_LABEL_WIDTH, _TR("最大宽度"));
|
||||
SetDlgItemText(IDC_PLEVEL_LABEL_QUALITY, _TR("JPEG质量"));
|
||||
static const TCHAR* kLevelNames[QUALITY_COUNT] = {
|
||||
_T("Ultra 极佳"), _T("High 优秀"), _T("Good 良好"),
|
||||
_T("Medium 一般"), _T("Low 较差"), _T("Minimal 最低")
|
||||
};
|
||||
for (int i = 0; i < QUALITY_COUNT; i++)
|
||||
SetDlgItemText(IDC_PLEVEL_LABEL_LEVEL0 + i, _L(kLevelNames[i]));
|
||||
SetDlgItemText(IDC_PLEVEL_LABEL_HINT,
|
||||
_TR("最大宽度为期望编码宽度;JPEG 质量 1~100"));
|
||||
SetDlgItemText(IDC_PLEVEL_RESET, _TR("恢复默认"));
|
||||
SetDlgItemText(IDOK, _TR("确定"));
|
||||
SetDlgItemText(IDCANCEL, _TR("取消"));
|
||||
|
||||
for (int i = 0; i < QUALITY_COUNT; i++) {
|
||||
m_working[i] = m_profiles[i];
|
||||
}
|
||||
LoadToControls();
|
||||
TranslateDialog(this);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -223,6 +223,27 @@ int GetIconIndex(LPCTSTR lpFileName, DWORD dwFileAttributes)
|
||||
return index;
|
||||
}
|
||||
|
||||
// 远程文件名/路径编码按 clientType 判定:Windows 走 A 接口(FindFirstFileA)=GBK/936,
|
||||
// LNX/MAC 文件系统天然 UTF-8(同 McpServer.cpp::BuildListFiles)。这里用 LVM_SETITEMTEXTW
|
||||
// 直接写宽字符串,绕开 ANSI→CP_ACP 回转,即使服务端运行在非中文 ACP 上中文名也能正常显示。
|
||||
static void SetFileTextItem(CListCtrl& list, int iItem, int iSubItem, const char* sz, UINT cp)
|
||||
{
|
||||
std::wstring w;
|
||||
if (sz && sz[0]) {
|
||||
int wlen = MultiByteToWideChar(cp, 0, sz, -1, NULL, 0);
|
||||
if (wlen > 1) {
|
||||
w.resize(wlen - 1);
|
||||
MultiByteToWideChar(cp, 0, sz, -1, &w[0], wlen);
|
||||
}
|
||||
}
|
||||
LVITEMW lv = {};
|
||||
lv.mask = LVIF_TEXT;
|
||||
lv.iItem = iItem;
|
||||
lv.iSubItem = iSubItem;
|
||||
lv.pszText = w.empty() ? const_cast<LPWSTR>(L"") : &w[0];
|
||||
::SendMessageW(list.GetSafeHwnd(), LVM_SETITEMTEXTW, (WPARAM)iItem, (LPARAM)&lv);
|
||||
}
|
||||
|
||||
BOOL CFileManagerDlg::OnInitDialog()
|
||||
{
|
||||
__super::OnInitDialog();
|
||||
@@ -1104,6 +1125,9 @@ void CFileManagerDlg::OnDblclkListRemote(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
|
||||
void CFileManagerDlg::FixedRemoteFileList(BYTE *pbBuffer, DWORD dwBufferLen)
|
||||
{
|
||||
CString clientType = m_ContextObject->GetAdditionalData(RES_CLIENT_TYPE);
|
||||
UINT cp = (clientType == _T("LNX") || clientType == _T("MAC")) ? CP_UTF8 : 936;
|
||||
|
||||
// 重新设置ImageList
|
||||
SHFILEINFO sfi = {};
|
||||
HIMAGELIST hImageListLarge = (HIMAGELIST)SHGetFileInfo(NULL, 0, &sfi,sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
|
||||
@@ -1151,7 +1175,8 @@ void CFileManagerDlg::FixedRemoteFileList(BYTE *pbBuffer, DWORD dwBufferLen)
|
||||
pszFileName = ++pList;
|
||||
|
||||
if (bIsInsert) {
|
||||
nItem = m_list_remote.InsertItem(nItemIndex++, pszFileName, GetIconIndex(pszFileName, nType));
|
||||
nItem = m_list_remote.InsertItem(nItemIndex++, "", GetIconIndex(pszFileName, nType));
|
||||
SetFileTextItem(m_list_remote, nItem, 0, pszFileName, cp);
|
||||
m_list_remote.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY);
|
||||
SHFILEINFO sfi = {};
|
||||
SHGetFileInfo(pszFileName, FILE_ATTRIBUTE_NORMAL | nType, &sfi,sizeof(SHFILEINFO), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES);
|
||||
@@ -1184,6 +1209,9 @@ void CFileManagerDlg::FixedRemoteFileList(BYTE *pbBuffer, DWORD dwBufferLen)
|
||||
|
||||
void CFileManagerDlg::FixedRemoteSearchFileList(BYTE *pbBuffer, DWORD dwBufferLen)
|
||||
{
|
||||
CString clientType = m_ContextObject->GetAdditionalData(RES_CLIENT_TYPE);
|
||||
UINT cp = (clientType == _T("LNX") || clientType == _T("MAC")) ? CP_UTF8 : 936;
|
||||
|
||||
// 第一批结果到达时,初始化搜索列表
|
||||
if (!m_bSearching) {
|
||||
m_bSearching = true;
|
||||
@@ -1241,7 +1269,8 @@ void CFileManagerDlg::FixedRemoteSearchFileList(BYTE *pbBuffer, DWORD dwBufferLe
|
||||
}
|
||||
}
|
||||
|
||||
int nItem = m_list_remote.InsertItem(m_nSearchResultCount, csFileName, nIcon);
|
||||
int nItem = m_list_remote.InsertItem(m_nSearchResultCount, "", nIcon);
|
||||
SetFileTextItem(m_list_remote, nItem, 0, csFileName, cp);
|
||||
m_list_remote.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY);
|
||||
|
||||
pList += lstrlen(pszFullPath) + 1;
|
||||
@@ -1261,7 +1290,7 @@ void CFileManagerDlg::FixedRemoteSearchFileList(BYTE *pbBuffer, DWORD dwBufferLe
|
||||
m_list_remote.SetItemText(nItem, 2, time.FormatL("%Y-%m-%d %H:%M"));
|
||||
|
||||
// 路径
|
||||
m_list_remote.SetItemText(nItem, 3, csDir);
|
||||
SetFileTextItem(m_list_remote, nItem, 3, csDir, cp);
|
||||
|
||||
pList += 16;
|
||||
m_nSearchResultCount++;
|
||||
|
||||
@@ -723,11 +723,11 @@ protected:
|
||||
AppendData(&dlgTemplate, sizeof(DLGTEMPLATE));
|
||||
AppendWord(0); // 菜单
|
||||
AppendWord(0); // 窗口类
|
||||
AppendString(_T("切换语言 / Switch Language"));
|
||||
AppendString(_T("切换语言"));
|
||||
AlignToDword();
|
||||
|
||||
// 静态文本
|
||||
AddControl(0x0082, 15, 15, 50, 12, (WORD)-1,
|
||||
AddControl(0x0082, 15, 15, 50, 12, 1002,
|
||||
SS_LEFT | WS_CHILD | WS_VISIBLE, _T("语言:"));
|
||||
|
||||
// ComboBox
|
||||
@@ -796,8 +796,17 @@ protected:
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
// 翻译对话框控件(标题、标签、按钮)
|
||||
TranslateDialog(this);
|
||||
// 模板为动态构造的 Unicode 模板,MBCS 下被 ANSI 创建路径误读,标题/标签/按钮文字会乱码,
|
||||
// 故在此显式设置(走线程 locale GBK,与其它对话框同法),不再对已乱码文本调用 TranslateDialog。
|
||||
// 标题含中文:非中文系统上 ANSI 消息按系统 ACP 解码会乱码,用 _TR 取翻译(中文→切换语言,
|
||||
// 英语→Switch Language)后,显式 GBK(936)→Unicode 转换再用 Unicode 消息设置(与工具栏同法)。
|
||||
CString strTitle = _TR("切换语言");
|
||||
WCHAR wTitle[64] = { 0 };
|
||||
MultiByteToWideChar(936, 0, strTitle, -1, wTitle, 64);
|
||||
::SetWindowTextW(m_hWnd, wTitle);
|
||||
SetDlgItemText(1002, _TR("语言:"));
|
||||
SetDlgItemText(IDOK, _TR("确定"));
|
||||
SetDlgItemText(IDCANCEL, _TR("取消"));
|
||||
|
||||
m_comboLang.SubclassDlgItem(1001, this);
|
||||
|
||||
|
||||
@@ -102,6 +102,10 @@ void CPluginSettingsDlg::InitListCtrl()
|
||||
GetDlgItem(IDC_STATIC_PLUGIN_INTERVAL)->SetWindowText(_TR("间隔(秒):"));
|
||||
GetDlgItem(IDC_STATIC_PLUGIN_COUNTER)->SetWindowText(_TR("最大次数:"));
|
||||
SetWindowText(_TR("插件设置"));
|
||||
|
||||
// 按钮文字来自对话框模板,非中文系统上会被系统 ACP 转成 "??",须显式设置(参照 NotifySettingsDlg)
|
||||
SetDlgItemText(IDC_BTN_SAVE, _TR("保存"));
|
||||
SetDlgItemText(IDOK, _TR("关闭"));
|
||||
}
|
||||
|
||||
void CPluginSettingsDlg::LoadPluginsToList()
|
||||
|
||||
@@ -124,11 +124,31 @@ protected:
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
// 非中文系统上 MBCS 对话框模板的中文会被系统 ACP 转成 "?",TranslateDialog
|
||||
// 拿到的是已乱码文本无法还原,故在此显式设置(参照 NotifySettingsDlg)。
|
||||
// 均经 _TR/_L 支持多语言翻译。
|
||||
SetWindowText(_TR("远程桌面质量等级"));
|
||||
SetDlgItemText(IDC_QLEVEL_LABEL_LEVEL, _TR("等级"));
|
||||
SetDlgItemText(IDC_QLEVEL_LABEL_FPS, _TR("帧率(FPS)"));
|
||||
SetDlgItemText(IDC_QLEVEL_LABEL_WIDTH, _TR("最大宽度"));
|
||||
SetDlgItemText(IDC_QLEVEL_LABEL_ALGO, _TR("编码算法"));
|
||||
SetDlgItemText(IDC_QLEVEL_LABEL_BITRATE, _TR("码率(kbps)"));
|
||||
static const TCHAR* kLevelNames[QUALITY_COUNT] = {
|
||||
_T("Ultra 极佳"), _T("High 优秀"), _T("Good 良好"),
|
||||
_T("Medium 一般"), _T("Low 较差"), _T("Minimal 最低")
|
||||
};
|
||||
for (int i = 0; i < QUALITY_COUNT; i++)
|
||||
SetDlgItemText(IDC_QLEVEL_LABEL_LEVEL0 + i, _L(kLevelNames[i]));
|
||||
SetDlgItemText(IDC_QLEVEL_LABEL_HINT,
|
||||
_TR("最大宽度 0 表示原始分辨率;DIFF/RGB565 适合局域网,H264 适合跨网"));
|
||||
SetDlgItemText(IDC_QLEVEL_RESET, _TR("恢复默认"));
|
||||
SetDlgItemText(IDOK, _TR("确定"));
|
||||
SetDlgItemText(IDCANCEL, _TR("取消"));
|
||||
|
||||
for (int i = 0; i < QUALITY_COUNT; i++) {
|
||||
m_working[i] = m_profiles[i];
|
||||
}
|
||||
LoadToControls();
|
||||
TranslateDialog(this);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -232,6 +232,26 @@ void CSystemDlg::ShowWindowsList(void)
|
||||
ApplySort(); // 应用记忆的排序偏好
|
||||
}
|
||||
|
||||
// 按客户端编码 (936 或 UTF-8) 解码字节串,并用 LVM_SETITEMTEXTW 写入列表单元格,
|
||||
// 绕开 ANSI→CP_ACP 回转(非中文 ACP 服务端上中文也能正常显示,与窗口管理同法)。
|
||||
static void SetClientTextItem(CListCtrl& list, int iItem, int iSubItem, const char* sz, UINT cp)
|
||||
{
|
||||
std::wstring w;
|
||||
if (sz && sz[0]) {
|
||||
int wlen = MultiByteToWideChar(cp, 0, sz, -1, NULL, 0);
|
||||
if (wlen > 1) {
|
||||
w.resize(wlen - 1);
|
||||
MultiByteToWideChar(cp, 0, sz, -1, &w[0], wlen);
|
||||
}
|
||||
}
|
||||
LVITEMW lv = {};
|
||||
lv.mask = LVIF_TEXT;
|
||||
lv.iItem = iItem;
|
||||
lv.iSubItem = iSubItem;
|
||||
lv.pszText = w.empty() ? const_cast<LPWSTR>(L"") : &w[0];
|
||||
::SendMessageW(list.GetSafeHwnd(), LVM_SETITEMTEXTW, (WPARAM)iItem, (LPARAM)&lv);
|
||||
}
|
||||
|
||||
void CSystemDlg::ShowProcessList(void)
|
||||
{
|
||||
// GetMyBuffer(1) 深拷贝数据,跳过 TOKEN 字节
|
||||
@@ -248,6 +268,10 @@ void CSystemDlg::ShowProcessList(void)
|
||||
const char *szProcessFullPath;
|
||||
DWORD dwOffset = 0;
|
||||
CString str;
|
||||
// 进程名/路径编码:Windows 客户端 A 接口生成,恒为 GBK/936;仅 LNX/MAC 为 UTF-8。
|
||||
// 不能用 GetClientEncoding(它对新客户端返回 CP_UTF8,会把 GBK 进程名解成乱码)。
|
||||
UINT cp = GetProcessListEncoding(m_ContextObject);
|
||||
|
||||
DeleteAllItems();
|
||||
//遍历发送来的每一个字符别忘了他的数据结构啊 Id+进程名+0+完整名+0
|
||||
int i;
|
||||
@@ -258,10 +282,11 @@ void CSystemDlg::ShowProcessList(void)
|
||||
szProcessFullPath = szExeFile + lstrlen(szExeFile) + 1; //完整名就是进程名之后的啦
|
||||
//他的数据结构的构建很巧妙
|
||||
|
||||
m_ControlList.InsertItem(i, arr[0].c_str()); //将得到的数据加入到列表当中
|
||||
m_ControlList.InsertItem(i, ""); // 占位,首列随后用 Unicode 写入
|
||||
str.FormatL("%5u", *PID);
|
||||
m_ControlList.SetItemText(i, 1, str);
|
||||
m_ControlList.SetItemText(i, 2, szProcessFullPath);
|
||||
m_ControlList.SetItemText(i, 1, str); // PID (ASCII)
|
||||
SetClientTextItem(m_ControlList, i, 0, arr[0].c_str(), cp); // 进程名(按客户端编码)
|
||||
SetClientTextItem(m_ControlList, i, 2, szProcessFullPath, cp); // 程序路径(按客户端编码)
|
||||
m_ControlList.SetItemText(i, 3, arr[1].empty() ? "N/A" : arr[1].c_str());
|
||||
// ItemData 为进程ID;Data[3] 需与第 4 列"架构"一致,否则按架构排序拿到空串而无意义
|
||||
auto data = new ItemData{ *PID, {arr[0].c_str(), str, szProcessFullPath, arr[1].empty() ? "N/A" : arr[1].c_str()}, arr[1].c_str() };
|
||||
|
||||
@@ -134,6 +134,13 @@ void CTriggerSettingsDlg::InitControls()
|
||||
SetWindowText(_TR("触发器设置"));
|
||||
GetDlgItem(IDC_STATIC_TRIGGER_TYPE)->SetWindowText(_TR("触发类型:"));
|
||||
GetDlgItem(IDC_STATIC_TRIGGER_ACTION)->SetWindowText(_TR("执行动作:"));
|
||||
|
||||
// 按钮/分组框文字来自对话框模板,非中文系统上会被系统 ACP 转成 "?",须显式设置
|
||||
SetDlgItemText(IDC_STATIC_TRIGGER_LIST, _TR("已配置的触发器"));
|
||||
SetDlgItemText(IDC_BTN_TRIGGER_ADD, _TR("添加 >>"));
|
||||
SetDlgItemText(IDC_BTN_TRIGGER_REMOVE, _TR("<< 移除"));
|
||||
SetDlgItemText(IDC_BTN_SAVE, _TR("保存(&S)"));
|
||||
SetDlgItemText(IDOK, _TR("关闭"));
|
||||
}
|
||||
|
||||
void CTriggerSettingsDlg::LoadPluginsToList()
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "InputDlg.h"
|
||||
#include <windows.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <string>
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
@@ -157,6 +158,15 @@ BOOL CFileManagerDlg::OnInitDialog()
|
||||
SetDlgItemText(IDC_STATIC_FILE_WINOS_SEARCH, _TR("搜索文件名:"));
|
||||
SetDlgItemText(IDC_STATIC_FILE_WINOS_PATH, _TR("路径:"));
|
||||
|
||||
// 多语言翻译 - 按钮/复选框(模板文字在非中文系统会被系统 ACP 转成 "?",须显式设置)
|
||||
SetDlgItemText(IDC_CK_SUBFORDLE, _TR("包含子文件夹"));
|
||||
SetDlgItemText(IDC_BTN_SEARCH, _TR("开始搜索"));
|
||||
SetDlgItemText(ID_SEARCH_STOP, _TR("停止搜索"));
|
||||
SetDlgItemText(ID_SEARCH_RESULT, _TR("搜索栏"));
|
||||
SetDlgItemText(IDT_REMOTE_PREV, _TR("上一层"));
|
||||
SetDlgItemText(IDT_REMOTE_VIEW, _TR("切换显示"));
|
||||
SetDlgItemText(IDT_REMOTE_STOP, _TR("取消"));
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(&rect);
|
||||
|
||||
@@ -809,8 +819,32 @@ void CFileManagerDlg::OnclickListSearch(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
|
||||
int GetIconIndex(LPCTSTR lpFileName, DWORD dwFileAttributes);
|
||||
|
||||
// 远程文件名/路径编码按 clientType 判定:Windows 走 A 接口(FindFirstFileA)=GBK/936,
|
||||
// LNX/MAC 文件系统天然 UTF-8(同 McpServer.cpp::BuildListFiles)。这里用 LVM_SETITEMTEXTW
|
||||
// 直接写宽字符串,绕开 ANSI→CP_ACP 回转,即使服务端运行在非中文 ACP 上中文名也能正常显示。
|
||||
static void SetFileTextItem(CListCtrl& list, int iItem, int iSubItem, const char* sz, UINT cp)
|
||||
{
|
||||
std::wstring w;
|
||||
if (sz && sz[0]) {
|
||||
int wlen = MultiByteToWideChar(cp, 0, sz, -1, NULL, 0);
|
||||
if (wlen > 1) {
|
||||
w.resize(wlen - 1);
|
||||
MultiByteToWideChar(cp, 0, sz, -1, &w[0], wlen);
|
||||
}
|
||||
}
|
||||
LVITEMW lv = {};
|
||||
lv.mask = LVIF_TEXT;
|
||||
lv.iItem = iItem;
|
||||
lv.iSubItem = iSubItem;
|
||||
lv.pszText = w.empty() ? const_cast<LPWSTR>(L"") : &w[0];
|
||||
::SendMessageW(list.GetSafeHwnd(), LVM_SETITEMTEXTW, (WPARAM)iItem, (LPARAM)&lv);
|
||||
}
|
||||
|
||||
void CFileManagerDlg::FixedRemoteFileList(BYTE* pbBuffer, DWORD dwBufferLen)
|
||||
{
|
||||
CString clientType = m_ContextObject->GetAdditionalData(RES_CLIENT_TYPE);
|
||||
UINT cp = (clientType == _T("LNX") || clientType == _T("MAC")) ? CP_UTF8 : 936;
|
||||
|
||||
// 重建标题
|
||||
m_list_remote.DeleteAllItems();
|
||||
int nItemIndex = 0;
|
||||
@@ -846,7 +880,8 @@ void CFileManagerDlg::FixedRemoteFileList(BYTE* pbBuffer, DWORD dwBufferLen)
|
||||
|
||||
if (bIsInsert) {
|
||||
int iicon = GetIconIndex(pszFileName, nType);
|
||||
nItem = m_list_remote.InsertItem(nItemIndex++, pszFileName, iicon);
|
||||
nItem = m_list_remote.InsertItem(nItemIndex++, _T(""), iicon);
|
||||
SetFileTextItem(m_list_remote, nItem, 0, pszFileName, cp);
|
||||
m_list_remote.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY);
|
||||
SHFILEINFO sfi = {};
|
||||
SHGetFileInfo(pszFileName, FILE_ATTRIBUTE_NORMAL | nType, &sfi, sizeof(SHFILEINFO), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES);
|
||||
@@ -2412,6 +2447,9 @@ void CFileManagerDlg::SearchEnd()
|
||||
|
||||
void CFileManagerDlg::FixedRemoteSearchFileList(BYTE* pbBuffer, DWORD dwBufferLen)
|
||||
{
|
||||
CString clientType = m_ContextObject->GetAdditionalData(RES_CLIENT_TYPE);
|
||||
UINT cp = (clientType == _T("LNX") || clientType == _T("MAC")) ? CP_UTF8 : 936;
|
||||
|
||||
byte* pList = pbBuffer + 1;
|
||||
int nItemIndex = 0;
|
||||
for (byte* pBase = pList; (int)(pList - pBase) < (int)(dwBufferLen - 1);) {
|
||||
@@ -2430,7 +2468,8 @@ void CFileManagerDlg::FixedRemoteSearchFileList(BYTE* pbBuffer, DWORD dwBufferLe
|
||||
int nPos = csFilePath.ReverseFind(_T('\\'));
|
||||
csFileFullName = csFilePath.Right(csFilePath.GetLength() - nPos - 1);// 获取文件全名,包括文件名和扩展名
|
||||
|
||||
nItem = m_list_remote_search.InsertItem(nItemIndex++, csFileFullName, GetIconIndex(pszFileName, nType));
|
||||
nItem = m_list_remote_search.InsertItem(nItemIndex++, _T(""), GetIconIndex(pszFileName, nType));
|
||||
SetFileTextItem(m_list_remote_search, nItem, 0, csFileFullName, cp);
|
||||
m_list_remote_search.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY);
|
||||
|
||||
pList += (lstrlen(pszFileName) + 1) * sizeof(TCHAR);
|
||||
@@ -2446,7 +2485,7 @@ void CFileManagerDlg::FixedRemoteSearchFileList(BYTE* pbBuffer, DWORD dwBufferLe
|
||||
m_list_remote_search.SetItemText(nItem, 2, time.FormatL(_T("%Y-%m-%d %H:%M")));
|
||||
|
||||
PathRemoveFileSpec(pszFileName); //去除文件名获取文件路径
|
||||
m_list_remote_search.SetItemText(nItem, 3, pszFileName);
|
||||
SetFileTextItem(m_list_remote_search, nItem, 3, pszFileName, cp);
|
||||
|
||||
pList += 16;
|
||||
}
|
||||
@@ -2482,6 +2521,9 @@ void CFileManagerDlg::ShowSearchPlugList()
|
||||
char* Filename;
|
||||
char* Pathname;
|
||||
|
||||
CString clientType = m_ContextObject->GetAdditionalData(RES_CLIENT_TYPE);
|
||||
UINT cp = (clientType == _T("LNX") || clientType == _T("MAC")) ? CP_UTF8 : 936;
|
||||
|
||||
DWORD dwOffset = 0;
|
||||
m_list_remote_search.DeleteAllItems();
|
||||
int i = 0;
|
||||
@@ -2489,13 +2531,13 @@ void CFileManagerDlg::ShowSearchPlugList()
|
||||
Filename = lpBuffer + dwOffset;
|
||||
Pathname = Filename + strlen(Filename) + 1;
|
||||
CString CS_tem;
|
||||
CS_tem = Filename;
|
||||
m_list_remote_search.InsertItem(i, CS_tem, 0);
|
||||
m_list_remote_search.InsertItem(i, _T(""), 0);
|
||||
SetFileTextItem(m_list_remote_search, i, 0, Filename, cp);
|
||||
CS_tem = Pathname;
|
||||
int index = CS_tem.ReverseFind('\\');
|
||||
if (index >= 0)
|
||||
CS_tem = CS_tem.Left(index);
|
||||
m_list_remote_search.SetItemText(i,3, CS_tem);
|
||||
SetFileTextItem(m_list_remote_search, i, 3, CS_tem, cp);
|
||||
dwOffset += strlen(Filename) + strlen(Pathname) + 2;
|
||||
}
|
||||
m_list_remote_search.EnableWindow(TRUE);
|
||||
|
||||
@@ -2067,4 +2067,4 @@ JPEG
|
||||
不限速=Unbegrenzt
|
||||
%s · 约 %.2f MB/s=%s · ca. %.2f MB/s
|
||||
%s · 不受限速(受网络带宽约束)=%s · Unbegrenzt (durch Netzwerkbandbreite begrenzt)
|
||||
文件传输速度已保存。上传速度重启主控端后生效;下载速度下次打开文件管理或远程桌面后生效。=Uebertragungsgeschwindigkeit gespeichert. Upload-Geschwindigkeit wird nach Neustart des Masters wirksam; Download-Geschwindigkeit beim naechsten Oeffnen des Dateimanagers oder des Remotedesktops.
|
||||
文件传输速度已保存。上传速度重启主控端后生效;下载速度已推送到在线客户端,新连接的主机也会自动获取。=Uebertragungsgeschwindigkeit gespeichert. Upload-Geschwindigkeit wird nach Neustart des Masters wirksam; Download-Geschwindigkeit wurde an Online-Clients gesendet, neu verbundene Hosts erhalten sie automatisch.
|
||||
@@ -99,6 +99,8 @@ RTT=RTT
|
||||
即时消息=Message
|
||||
虚拟屏幕=Virtual Screen
|
||||
隐私屏幕=Privacy Screen
|
||||
实验功能=Experimental Features
|
||||
远程画板=Remote Drawing Board
|
||||
代理服务=Proxy Service
|
||||
注入设置=Inject Config
|
||||
创建计划任务=Scheduled Task
|
||||
@@ -121,6 +123,7 @@ RTT=RTT
|
||||
|
||||
; ============================================
|
||||
; Language Selection Dialog
|
||||
切换语言=Switch Language
|
||||
; ============================================
|
||||
选择语言 / Select Language=Select Language
|
||||
语言:=Language:
|
||||
@@ -1397,6 +1400,7 @@ RDP
|
||||
C2C 文件传输=C2C File Transfer
|
||||
续传文件 (V2)=Resume File Upload (V2)
|
||||
发送文件 (V2)=Send File (V2)
|
||||
接收文件 (V2)=Receive File (V2)
|
||||
发送文件(%d/%d): %.2f%%=Send Files(%d/%d): %.2f%%
|
||||
接收文件(%d/%d): %.2f%%=Recv Files(%d/%d): %.2f%%
|
||||
[远程右键复制, 本地 Ctrl+V 粘贴]= [Remote Right-click Copy, Local Ctrl+V Paste]
|
||||
@@ -2068,7 +2072,7 @@ JPEG
|
||||
不限速=Unlimited
|
||||
%s · 约 %.2f MB/s=%s · about %.2f MB/s
|
||||
%s · 不受限速(受网络带宽约束)=%s · Unlimited (limited by network bandwidth)
|
||||
文件传输速度已保存。上传速度重启主控端后生效;下载速度下次打开文件管理或远程桌面后生效。=Transfer speed saved. Upload speed takes effect after restarting the master; download speed takes effect the next time you open File Manager or Remote Desktop.
|
||||
文件传输速度已保存。上传速度重启主控端后生效;下载速度已推送到在线客户端,新连接的主机也会自动获取。=Transfer speed saved. Upload speed takes effect after restarting the master; download speed has been pushed to online clients, and newly connected hosts will get it automatically.
|
||||
|
||||
连接管理=Connections
|
||||
%s - 连接管理=%s - Connections
|
||||
|
||||
@@ -99,6 +99,8 @@ RTT=RTT
|
||||
即时消息=即時訊息
|
||||
虚拟屏幕=虛擬桌面
|
||||
隐私屏幕=隱私螢幕
|
||||
实验功能=實驗功能
|
||||
远程画板=遠端繪圖板
|
||||
代理服务=代理服務
|
||||
注入设置=注入設定
|
||||
创建计划任务=建立排程工作
|
||||
@@ -121,6 +123,7 @@ RTT=RTT
|
||||
|
||||
; ============================================
|
||||
; Language Selection Dialog
|
||||
切換語言=切換語言
|
||||
; ============================================
|
||||
选择语言 / Select Language=選擇語言
|
||||
语言:=語言:
|
||||
@@ -1393,6 +1396,7 @@ RDP
|
||||
C2C 文件传输=C2C 檔案傳輸
|
||||
续传文件 (V2)=續傳檔案 (V2)
|
||||
发送文件 (V2)=傳送檔案 (V2)
|
||||
接收文件 (V2)=接收檔案 (V2)
|
||||
发送文件(%d/%d): %.2f%%=发送文件(%d/%d): %.2f%%
|
||||
接收文件(%d/%d): %.2f%%=接收文件(%d/%d): %.2f%%
|
||||
[远程右键复制, 本地 Ctrl+V 粘贴]= [遠端右鍵複製, 本地 Ctrl+V 貼上]
|
||||
@@ -2059,7 +2063,7 @@ JPEG
|
||||
不限速=不限速
|
||||
%s · 约 %.2f MB/s=%s · 約 %.2f MB/s
|
||||
%s · 不受限速(受网络带宽约束)=%s · 不限速(受網路頻寬限制)
|
||||
文件传输速度已保存。上传速度重启主控端后生效;下载速度下次打开文件管理或远程桌面后生效。=檔案傳輸速度已儲存。上傳速度重啟主控端後生效;下載速度下次開啟檔案管理或遠端桌面後生效。
|
||||
文件传输速度已保存。上传速度重启主控端后生效;下载速度已推送到在线客户端,新连接的主机也会自动获取。=檔案傳輸速度已儲存。上傳速度重啟主控端後生效;下載速度已推送到線上用戶端,新連線的主機也會自動取得。
|
||||
|
||||
连接管理=連線管理
|
||||
%s - 连接管理=%s - 連線管理
|
||||
|
||||
@@ -1077,13 +1077,46 @@
|
||||
#define IDC_FSPEED_LABEL 2591
|
||||
#define IDC_FSPEED_RESET 2592
|
||||
|
||||
// 高级菜单三个对话框的静态文本(显式在 OnInitDialog 设置中文,修复非中文系统乱码)
|
||||
#define IDC_QLEVEL_LABEL_LEVEL 2593
|
||||
#define IDC_QLEVEL_LABEL_FPS 2594
|
||||
#define IDC_QLEVEL_LABEL_WIDTH 2595
|
||||
#define IDC_QLEVEL_LABEL_ALGO 2596
|
||||
#define IDC_QLEVEL_LABEL_BITRATE 2597
|
||||
#define IDC_QLEVEL_LABEL_LEVEL0 2598 // 2598~2603:Ultra..Minimal 六档
|
||||
#define IDC_QLEVEL_LABEL_LEVEL1 2599
|
||||
#define IDC_QLEVEL_LABEL_LEVEL2 2600
|
||||
#define IDC_QLEVEL_LABEL_LEVEL3 2601
|
||||
#define IDC_QLEVEL_LABEL_LEVEL4 2602
|
||||
#define IDC_QLEVEL_LABEL_LEVEL5 2603
|
||||
#define IDC_QLEVEL_LABEL_HINT 2604
|
||||
|
||||
#define IDC_PLEVEL_LABEL_LEVEL 2605
|
||||
#define IDC_PLEVEL_LABEL_WIDTH 2606
|
||||
#define IDC_PLEVEL_LABEL_QUALITY 2607
|
||||
#define IDC_PLEVEL_LABEL_LEVEL0 2608 // 2608~2613:Ultra..Minimal 六档
|
||||
#define IDC_PLEVEL_LABEL_LEVEL1 2609
|
||||
#define IDC_PLEVEL_LABEL_LEVEL2 2610
|
||||
#define IDC_PLEVEL_LABEL_LEVEL3 2611
|
||||
#define IDC_PLEVEL_LABEL_LEVEL4 2612
|
||||
#define IDC_PLEVEL_LABEL_LEVEL5 2613
|
||||
#define IDC_PLEVEL_LABEL_HINT 2614
|
||||
|
||||
#define IDC_FSPEED_HINT 2615
|
||||
#define IDC_FSPEED_LABEL_SLOWEST 2616
|
||||
#define IDC_FSPEED_LABEL_DEFAULT 2617
|
||||
#define IDC_FSPEED_LABEL_UNLIMITED 2618
|
||||
|
||||
// 触发器设置对话框的分组框(显式在 OnInitDialog 设置中文,修复非中文系统乱码)
|
||||
#define IDC_STATIC_TRIGGER_LIST 2619
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 410
|
||||
#define _APS_NEXT_COMMAND_VALUE 33093
|
||||
#define _APS_NEXT_CONTROL_VALUE 2593
|
||||
#define _APS_NEXT_CONTROL_VALUE 2620
|
||||
#define _APS_NEXT_SYMED_VALUE 105
|
||||
#endif
|
||||
#endif
|
||||
Reference in new issue
Block a user