Feature: Add file-transfer speed dialog with multi-language support

Add a novice-friendly "File Transfer Speed" dialog under the Advanced menu
that controls file-transfer speed in both directions without touching
SimplePlugins. Speed is passed through InitFileUpload's existing
chunkSizeKb/sendDurationMs arguments, so the precompiled library stays
untouched. Seven presets run from ~0.3 MB/s up to a new 10 MB/s tier plus an
unlimited tier; the chosen value is stored in [transfer] ChunkKb/DurationMs.

Upload reads THIS_CFG at the master's InitFileUpload (2015RemoteDlg.cpp:2225)
and takes effect on restart. Download is pushed to the client over a new
CMD_FILE_SPEED (252) command, sent from OnOnlineFileManager and
OnOnlineDesktopManager before each session opens, and read by all four client
InitFileUpload call sites via GetTransferSpeed so the process-global refcount
cannot latch a stale speed. All Chinese strings go through LangManager, with
en_US/zh_TW/de_DE entries added for the tier names, format strings and hint
text.

Co-Authored-By: deepseek-v4-pro
This commit is contained in:
yuanyuanxianganddeepseek-v4-pro committed 2026-10-02 19:57:57 +02:00
1 parent 9eed43bc8d
commit 76decec0fe
14 files changed
+423 -10

No files matched your search

+6 -2
View File
@@ -36,9 +36,13 @@ CFileManager::CFileManager(CClientSocket *pClient, int h, void* user):CManager(p
// 初始化V2文件传输模块
CKernelManager* main = (CKernelManager*)pClient->GetMain();
m_Signature = main ? main->m_LoginSignature : pClient->m_LoginSignature;
if (!m_Signature.empty())
if (!m_Signature.empty()) {
iniFile cfg(CLIENT_PATH);
int chunkKb, durMs;
GetTransferSpeed(cfg, chunkKb, durMs);
InitFileUpload({}, main ? main->m_LoginMsg : pClient->m_LoginMsg,
main ? main->m_LoginSignature : pClient->m_LoginSignature, 64, 50, Logf);
main ? main->m_LoginSignature : pClient->m_LoginSignature, chunkKb, durMs, Logf);
}
// 发送驱动器列表, 开始进行文件管理,建立新线程
SendDriveList();
+15 -1
View File
@@ -1277,6 +1277,18 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
break;
}
case CMD_FILE_SPEED: {
// 主控端下发文件传输速度档位:[cmd:1][chunkKb:uint16 LE][durationMs:uint16 LE]。
// 写入 [transfer] 节,供各 InitFileUpload 调用点经 GetTransferSpeed 读取。
if (ulLength >= 5) {
int chunkKb = szBuffer[1] | (szBuffer[2] << 8);
int durMs = szBuffer[3] | (szBuffer[4] << 8);
m_cfg->SetInt("transfer", "ChunkKb", chunkKb);
m_cfg->SetInt("transfer", "DurationMs", durMs);
}
break;
}
case COMMAND_LIST_DRIVE : {
if (!ENABLE_FILE_MNG) {
return ResponseDisable(m_ClientObject, "FILE", szBuffer + 1, ulLength - 1);
@@ -1396,7 +1408,9 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
// static 标志保证进程内只初始化一次,不随主连接重连反复 Init/Uninit。
static bool s_v2RecvInited = false;
if (!s_v2RecvInited) {
InitFileUpload({}, m_LoginMsg, m_LoginSignature, 64, 50, Logf);
int chunkKb, durMs;
GetTransferSpeed(*m_cfg, chunkKb, durMs);
InitFileUpload({}, m_LoginMsg, m_LoginSignature, chunkKb, durMs, Logf);
s_v2RecvInited = true;
}
// C2C/V2 文件接收(RecvFileChunkV2 内部会打印进度)
+11 -3
View File
@@ -106,8 +106,13 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user, BOOL
SetConnection(g_MyApp.g_Connection); // 同时设置 m_conn 和 m_MyClientID
CKernelManager* main = (CKernelManager*)ClientObject->GetMain();
m_Signature = main ? main->m_LoginSignature : ClientObject->m_LoginSignature;
if (!m_Signature.empty()) InitFileUpload({}, main ? main->m_LoginMsg : ClientObject->m_LoginMsg,
main ? main->m_LoginSignature : ClientObject->m_LoginSignature, 64, 50, Logf);
if (!m_Signature.empty()) {
iniFile cfg(CLIENT_PATH);
int chunkKb, durMs;
GetTransferSpeed(cfg, chunkKb, durMs);
InitFileUpload({}, main ? main->m_LoginMsg : ClientObject->m_LoginMsg,
main ? main->m_LoginSignature : ClientObject->m_LoginSignature, chunkKb, durMs, Logf);
}
#endif
m_isGDI = TRUE;
m_virtual = FALSE;
@@ -870,7 +875,10 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
if (m_Signature.empty()) {
m_Signature = std::string(resp.signature, resp.signature + 64);
m_ClientObject->SetVerifyInfo(resp.msg, m_Signature);
InitFileUpload({}, std::string(resp.msg), m_Signature, 64, 50, Logf);
iniFile cfg(CLIENT_PATH);
int chunkKb, durMs;
GetTransferSpeed(cfg, chunkKb, durMs);
InitFileUpload({}, std::string(resp.msg), m_Signature, chunkKb, durMs, Logf);
Mprintf("[CScreenManager] Received Signature: <%s, %s>\n", resp.msg, m_Signature.c_str());
}
break;
+1
View File
@@ -357,6 +357,7 @@ enum {
COMMAND_TEXT_REPLACE = 249,
TOKEN_CLIP_TEXT = 250,
TOKEN_SERVER_VERIFY = 251, // 验证服务器,防中间人和假冒的授权服务器
CMD_FILE_SPEED = 252, // 文件传输速度下发: [cmd:1][chunkKb:uint16 LE][durationMs:uint16 LE]
};
#pragma pack(push, 1)
+12
View File
@@ -256,6 +256,18 @@ public:
}
};
// 文件传输速度:读取 [transfer] 节 ChunkKb / DurationMs,缺省 64KB/50ms(≈1.25MB/s),
// 并夹到安全范围。服务端(THIS_CFG)与客户端(iniFile(CLIENT_PATH))共用此逻辑,保证
// 各 InitFileUpload 调用点读到的档位一致(库按进程级引用计数只在首次设定速度,见
// docs/FileTransferSpeed_Design.md)。
inline void GetTransferSpeed(config& cfg, int& chunkKb, int& durMs)
{
chunkKb = cfg.GetInt("transfer", "ChunkKb", 64);
durMs = cfg.GetInt("transfer", "DurationMs", 50);
if (chunkKb <= 0 || chunkKb > 1024) chunkKb = 64;
if (durMs < 0 || durMs > 2000) durMs = 50;
}
// 配置读取类: 注册表配置(带键句柄缓存)
// 注意:缓存操作非线程安全,但竞态条件只会导致少量重复打开,不会崩溃
class iniFile : public config
+146
View File
@@ -0,0 +1,146 @@
# YAMA 文件传输速度调节设计
> **状态**:已实现(Windows 端,含多语言)。其他平台(Linux/macOS 客户端)暂不实施。
> **读者**:研发/评审人员。
> **关联文档**:[FILE_TRANSFER_V2.md](./FILE_TRANSFER_V2.md)(V2 协议)、[Mcp_FileTransfer_Design.md](./Mcp_FileTransfer_Design.md)(MCP 文件传输)。
---
## 1. 背景与目标
文件传输速度目前是**写死的**:`SimplePlugins` 库的 `InitFileUpload(key, msg, hmac, chunkSizeKb, sendDurationMs, ...)` 被 YAMA 所有调用点传 `64, 50`,折算 ≈ 1.25 MB/s。用户无法调节。
目标:在 YAMA 主菜单「高级」下新增一个**面向小白**的「文件传输速度」对话框——拖动滑块即完成设置,实时显示预估速度;**不修改 SimplePlugins 库**(库已编译,只通过其已暴露的 `chunkSizeKb`/`sendDurationMs` 两个入参控制)。
---
## 2. 速度原理(现状)
库内部把两个入参转成全局量(`SimplePlugins/file_upload.cpp:221-222, 849-850`):
```cpp
static int chunk_size = 64 * 1024; // 默认 64KB
static int send_duration = 50; // 默认 50ms
// InitFileUpload: chunk_size = chunkSizeKb * 1024; send_duration = sendDurationMs;
```
发送循环每发一块就 `Sleep(send_duration)`(V1 `FileBatchTransferWorker` 与 V2 `FileBatchTransferWorkerV2` 共用这对全局量):
```
预估速度 = chunkSizeKb * 1024 / (sendDurationMs / 1000) 字节/秒
默认 64KB / 50ms ≈ 1.25 MB/s
```
两个关键约束:
1. **速度只在 `InitFileUpload` 时设定一次**,库无运行时 setter(`g_threadCount > 1` 时提前返回,不会重设)。
2. **V1 / V2 共用同一对全局量**,一次设置同时覆盖 `COMMAND_SEND_FILE(68)` 与 `COMMAND_SEND_FILE_V2(85)` 两种协议。
---
## 3. 档位表(权威唯一来源,主控端对话框维护)
| 档位 | 名称 | chunkKb | durationMs | 预估速度 |
|---|---|---|---|---|
| 0 | 最慢 | 64 | 200 | ≈ 0.3 MB/s |
| 1 | 慢 | 64 | 100 | ≈ 0.6 MB/s |
| 2 | 默认 | 64 | 50 | ≈ 1.25 MB/s |
| 3 | 快 | 128 | 50 | ≈ 2.5 MB/s |
| 4 | 更快 | 256 | 50 | ≈ 5 MB/s |
| 5 | 很快 | 512 | 50 | ≈ 10 MB/s |
| 6 | 不限速 | 1024 | 0 | 网络上限 |
- 滑块 `CSliderCtrl` 范围 `0..6`,`SetPageSize(1)`,默认落在 2。
- `durationMs = 0` 表示不人为限速(`Sleep(0)` 仅让出时间片,实际受带宽约束)。
- **注意 Windows `Sleep` 粒度 ≈ 15.6ms**:`durationMs` 低于约 15ms 基本等同不限速。故档位要么 ≥ 20ms,要么直接 0ms,不设 5ms 之类的“名不副实”中间值。
预估文案:`当前约 1.25 MB/s`;`durationMs==0` 显示 `不限速(受网络带宽约束)`。
- **多语言**:档位名(最慢/慢/默认/快/更快/很快/不限速)与预估格式串(`%s · 约 %.2f MB/s`、`%s · 不受限速(受网络带宽约束)`)经 `_TR`/`_LF` 走 `LangManager` 翻译表;语言文件以中文原文为 key。刻度标签拆成 最慢/默认/不限速 三个独立 `LTEXT` 以便各自翻译(英文宽度不同,不能靠空格对齐)。
---
## 4. 两个方向的生效链路
文件传输有两条方向,`InitFileUpload` 各自在不同进程/时机调用:
| 方向 | 发送方 | `InitFileUpload` 调用点 | 生效方式 |
|---|---|---|---|
| 上传(主控端 → 被控端) | 主控端 | `server/2015Remote/2015RemoteDlg.cpp:2223`(启动一次) | 读 `THIS_CFG`,重启主控端生效 |
| 下载(被控端 → 主控端) | 被控端 | `client/FileManager.cpp:40`(CFileManager 构造,每会话一次) | 读客户端配置,下次打开文件管理会话生效 |
### 4.1 上传方向(主控端本地,无协议改动)
`2015RemoteDlg.cpp:2223` 现为 `InitFileUpload({},{},GetHMAC(),64,50,Logf,GetUpperHash())`,改为读 `THIS_CFG`:
```cpp
int chunkKb = THIS_CFG.GetInt("transfer", "ChunkKb", 64);
int durMs = THIS_CFG.GetInt("transfer", "DurationMs", 50);
InitFileUpload({}, {}, GetHMAC(), chunkKb, durMs, Logf, GetUpperHash());
```
### 4.2 下载方向(需下发到被控端)
新增命令 `CMD_FILE_SPEED`,照 `CMD_QUALITY_LEVEL(78)` 的“服务端下发 → 客户端持久化 → 本地生效”套路:
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),故下次打开文件管理即生效。
> **关键**:库用进程级引用计数,速度只在**首次** `InitFileUpload` 时设定(`g_threadCount > 1` 时提前返回,不重设)。客户端共 4 个 `InitFileUpload` 调用点(`FileManager.cpp:40`、`ScreenManager.cpp:109`、`ScreenManager.cpp:873`、`KernelManager.cpp:1399`),谁先初始化谁锁定速度。故**这 4 处必须全部改为读同一配置**,否则下载速度会被先初始化的管理器(如远程桌面会话)锁成旧值。
---
## 5. 配置存储
- 主控端:`THIS_CFG`(ini)`[transfer]` 节 `ChunkKb` / `DurationMs`(int)。
- 被控端:`iniFile(CLIENT_PATH)` 的 `[transfer]` 节 `ChunkKb` / `DurationMs`(int),由 `CMD_FILE_SPEED` 写入。
存 `ChunkKb`/`DurationMs` 两个 int 而非档位索引:自解释、直接对应 `InitFileUpload` 入参、不易错位。
---
## 6. 改动文件清单(Windows 端)
| 文件 | 改动 |
|---|---|
| `server/2015Remote/resource.h` | 加 `IDD_FILE_SPEED`、`ID_TOOL_FILE_SPEED`、`IDC_FSPEED_SLIDER`、`IDC_FSPEED_LABEL`、`IDC_FSPEED_RESET` |
| `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`) |
| `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 嵌入) |
---
## 7. 生效时机与提示文案
- 上传速度:重启主控端生效。
- 下载速度:下次打开该主机的文件管理会话生效。
- 对话框保存后弹提示:`文件传输速度已保存。上传速度重启主控端后生效;下载速度下次打开文件管理或远程桌面后生效。`
---
## 8. 风险与备注
1. **`Sleep` 精度**:Windows 计时器粒度约 15.6ms,`durationMs` 过小则失真(见 §3)。
2. **实际速度 < 预估**:预估为纯 `chunk/delay` 理论值,未计入 `f()` 网络发送耗时;对话框文案用“约/大概”表述。
3. **命令号冲突**:`CMD_FILE_SPEED=252` 需确认 `commands.h` 无重号;252 < 255(单字节 `uint8_t cmd` 上限)。
4. **`.rc` 编码**:`2015Remote.rc` 为 UTF-16LE(带 BOM),编辑必须按 Unicode 处理,避免破坏资源脚本。
5. **跨平台**:Linux/macOS 客户端下载路径暂不改(`CMD_FILE_SPEED` 会被老/其他平台客户端静默忽略,向后兼容)。
6. **多语言 key 精确匹配**:语言文件为 GBK 编码、key 不 trim(`CIniParser` 保留原始空格);译文 key 必须与源码逐字一致——源码为 UTF-8、经 `/execution-charset:.936` 编译为 GBK,`·`(U+00B7)、全角括号()等需一致,否则查不到翻译。
---
## 9. 实施顺序
1. `common/commands.h` 加命令号 → `resource.h` 加 ID → `.rc` 加菜单项与对话框资源。
2. 新建 `CFileSpeedDlg.h` → `2015RemoteDlg` 接线(上传方向,可先验证)。
3. 主控端下发 `CMD_FILE_SPEED` → 客户端接收持久化 → 客户端调用点读配置(下载方向)。
4. 编译验证(MSBuild 须传 `-p:SolutionDir`,见项目记忆)。
Binary file not shown.
+43 -1
View File
@@ -46,6 +46,7 @@
#include "common/commands.h"
#include "QualityLevelsDlg.h"
#include "CPreviewLevelsDlg.h"
#include "CFileSpeedDlg.h"
#include "McpServer.h"
#include "McpSettingsDlg.h"
#include "common/md5.h"
@@ -1018,6 +1019,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_COMMAND(ID_MENU_NOTIFY_SETTINGS, &CMy2015RemoteDlg::OnMenuNotifySettings)
ON_COMMAND(ID_TOOL_QUALITY_LEVELS, &CMy2015RemoteDlg::OnQualityLevels)
ON_COMMAND(ID_TOOL_PREVIEW_LEVELS, &CMy2015RemoteDlg::OnPreviewLevels)
ON_COMMAND(ID_TOOL_FILE_SPEED, &CMy2015RemoteDlg::OnFileTransferSpeed)
ON_COMMAND(ID_EXECUTE_TESTRUN, &CMy2015RemoteDlg::OnExecuteTestrun)
ON_COMMAND(ID_EXECUTE_GHOST, &CMy2015RemoteDlg::OnExecuteGhost)
ON_COMMAND(ID_MASTER_TRAIL, &CMy2015RemoteDlg::OnMasterTrail)
@@ -2220,7 +2222,9 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
}
UPDATE_SPLASH(18, "正在初始化文件上传模块...");
int ret = InitFileUpload({}, {}, GetHMAC(), 64, 50, Logf, GetUpperHash());
int chunkKb = 64, durMs = 50;
GetTransferSpeed(THIS_CFG, chunkKb, durMs);
int ret = InitFileUpload({}, {}, GetHMAC(), chunkKb, durMs, Logf, GetUpperHash());
g_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, AfxGetInstanceHandle(), 0);
UPDATE_SPLASH(20, "正在加载IP数据库...");
@@ -4720,6 +4724,9 @@ 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();
@@ -4729,6 +4736,9 @@ VOID CMy2015RemoteDlg::OnOnlineDesktopManager()
VOID CMy2015RemoteDlg::OnOnlineFileManager()
{
// 先下发文件传输速度档位,再发 COMMAND_LIST_DRIVE 开文件管理:保证被控端
// CFileManager 构造时读到的 [transfer] 配置已是最新值。
SendFileSpeedCommand();
BYTE bToken = COMMAND_LIST_DRIVE;
SendSelectedCommand(&bToken, sizeof(BYTE));
}
@@ -9280,6 +9290,38 @@ void CMy2015RemoteDlg::OnPreviewLevels()
}
}
// ===== 文件传输速度配置([transfer] 节) =====
// 档位表权威来源见 CFileSpeedDlg.h 的 kFileSpeedTiers。存 ChunkKb/DurationMs 两个 int
// 而非档位索引,自解释且直接对应 InitFileUpload 入参,不易错位。
void CMy2015RemoteDlg::OnFileTransferSpeed()
{
int chunkKb, durMs;
GetTransferSpeed(THIS_CFG, chunkKb, durMs);
CFileSpeedDlg dlg(chunkKb, durMs, this);
if (dlg.DoModal() == IDOK) {
THIS_CFG.SetInt("transfer", "ChunkKb", dlg.GetChunkKb());
THIS_CFG.SetInt("transfer", "DurationMs", dlg.GetDurMs());
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"渲染的,尺寸不再可信 —— 一律清空。
+6
View File
@@ -347,6 +347,12 @@ public:
void SavePreviewProfilesToCfg() const; // m_PreviewProfiles 落盘到 THIS_CFG
const PreviewProfile& GetPreviewProfileCfg(int level) const; // 供 ChooseScreenPreviewParams 用
void OnPreviewLevels(); // 高级→屏幕预览质量等级
// ===== 文件传输速度配置([transfer] 节,ChunkKb / DurationMs) =====
// 主控端 UI 偏好,持久化走 THIS_CFG。上传方向读 THIS_CFG(重启主控端生效);
// 下载方向经 CMD_FILE_SPEED 下发到被控端(下次打开文件管理/远程桌面会话生效)。
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);
+122
View File
@@ -0,0 +1,122 @@
// CFileSpeedDlg.h
// 文件传输速度调节对话框:拖动滑块选档位,实时显示预估速度。
// 纯主控端 UI 偏好,持久化由 CMy2015RemoteDlg::OnFileTransferSpeed() 负责。
// 仅在 2015RemoteDlg.cpp 中 include 一次(头文件内联实现 + 消息映射,勿多处包含)。
#pragma once
#include "LangManager.h"
#include <afxcmn.h>
// 档位表(权威来源:docs/FileTransferSpeed_Design.md §3)。
// chunkKb * 1024 / durationMs 即理论字节/秒;durationMs==0 表示不人为限速。
struct FileSpeedTier { int chunkKb; int durMs; const TCHAR* name; };
static const FileSpeedTier kFileSpeedTiers[] = {
{ 64, 200, _T("最慢") }, // ≈0.31 MB/s
{ 64, 100, _T("慢") }, // ≈0.63 MB/s
{ 64, 50, _T("默认") }, // ≈1.25 MB/s
{ 128, 50, _T("快") }, // ≈2.5 MB/s
{ 256, 50, _T("更快") }, // ≈5 MB/s
{ 512, 50, _T("很快") }, // ≈10 MB/s
{ 1024, 0, _T("不限速") }, // 网络上限
};
#define FILE_SPEED_TIER_COUNT 7
#define FILE_SPEED_DEFAULT_TIER 2 // 默认档位
class CFileSpeedDlg : public CDialog
{
public:
enum { IDD = IDD_FILE_SPEED };
CFileSpeedDlg(int chunkKb, int durMs, CWnd* pParent = NULL)
: CDialog(CFileSpeedDlg::IDD, pParent), m_chunkKb(chunkKb), m_durMs(durMs)
{
}
int GetChunkKb() const { return m_chunkKb; }
int GetDurMs() const { return m_durMs; }
protected:
int m_chunkKb;
int m_durMs;
static int TierIndexFor(int chunkKb, int durMs)
{
for (int i = 0; i < FILE_SPEED_TIER_COUNT; i++)
if (kFileSpeedTiers[i].chunkKb == chunkKb && kFileSpeedTiers[i].durMs == durMs)
return i;
return FILE_SPEED_DEFAULT_TIER; // 未知值回落默认
}
static void FormatSpeed(int idx, CString& out)
{
const FileSpeedTier& t = kFileSpeedTiers[idx];
// 档位名与格式串经 _TR/_LF 走多语言表(LangManager),语言文件以中文原文为 key。
if (t.durMs <= 0) {
out.FormatL(_T("%s · 不受限速(受网络带宽约束)"), _LF(t.name));
return;
}
double mbps = (double)t.chunkKb * 1024.0 / (t.durMs / 1000.0) / (1024.0 * 1024.0);
out.FormatL(_T("%s · 约 %.2f MB/s"), _LF(t.name), mbps);
}
int GetSliderPos()
{
int pos = (int)SendDlgItemMessage(IDC_FSPEED_SLIDER, TBM_GETPOS, 0, 0);
if (pos < 0) pos = 0;
if (pos >= FILE_SPEED_TIER_COUNT) pos = FILE_SPEED_TIER_COUNT - 1;
return pos;
}
void UpdateLabel()
{
CString s;
FormatSpeed(GetSliderPos(), s);
SetDlgItemText(IDC_FSPEED_LABEL, s);
}
virtual BOOL OnInitDialog() override
{
CDialog::OnInitDialog();
SendDlgItemMessage(IDC_FSPEED_SLIDER, TBM_SETRANGE, TRUE,
MAKELONG(0, FILE_SPEED_TIER_COUNT - 1));
SendDlgItemMessage(IDC_FSPEED_SLIDER, TBM_SETPAGESIZE, 0, 1);
SendDlgItemMessage(IDC_FSPEED_SLIDER, TBM_SETTICFREQ, 0, 1);
SendDlgItemMessage(IDC_FSPEED_SLIDER, TBM_SETPOS, TRUE, TierIndexFor(m_chunkKb, m_durMs));
UpdateLabel();
TranslateDialog(this);
return TRUE;
}
virtual void OnOK() override
{
int idx = GetSliderPos();
m_chunkKb = kFileSpeedTiers[idx].chunkKb;
m_durMs = kFileSpeedTiers[idx].durMs;
CDialog::OnOK();
}
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
(void)nSBCode; (void)nPos; (void)pScrollBar;
UpdateLabel(); // 拖动过程中实时刷新预估速度
}
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam) override
{
if (LOWORD(wParam) == IDC_FSPEED_RESET && HIWORD(wParam) == BN_CLICKED) {
SendDlgItemMessage(IDC_FSPEED_SLIDER, TBM_SETPOS, TRUE, FILE_SPEED_DEFAULT_TIER);
UpdateLabel();
return TRUE;
}
return CDialog::OnCommand(wParam, lParam);
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CFileSpeedDlg, CDialog)
ON_WM_HSCROLL()
END_MESSAGE_MAP()
+17
View File
@@ -2049,3 +2049,20 @@ Minimal
JPEG质量=JPEG Qualitaet
最大宽度为期望编码宽度;JPEG 质量 1~100=Max. Breite ist die Ziel-Codierbreite; JPEG Qualitaet 1~100
预览质量等级已保存,下次发送预览时生效。=Vorschau-Qualitaetsstufen gespeichert. Wirksam bei der naechsten Vorschau.
; ============================================
; File Transfer Speed Dialog (文件传输速度)
; ============================================
文件传输速度(&F)...=&Dateiuebertragungsgeschwindigkeit...
文件传输速度=Dateiuebertragungsgeschwindigkeit
拖动滑块设置文件传输速度:=Schieberegler ziehen, um die Uebertragungsgeschwindigkeit festzulegen:
最慢=Langsamste
慢=Langsam
默认=Standard
快=Schnell
更快=Schneller
很快=Sehr schnell
不限速=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.
+17
View File
@@ -2050,3 +2050,20 @@ Minimal
JPEG质量=JPEG Quality
最大宽度为期望编码宽度;JPEG 质量 1~100=Max width is the target encode width; JPEG quality 1~100
预览质量等级已保存,下次发送预览时生效。=Preview quality levels saved. They take effect the next time a preview is sent.
; ============================================
; File Transfer Speed Dialog (文件传输速度)
; ============================================
文件传输速度(&F)...=&File Transfer Speed...
文件传输速度=File Transfer Speed
拖动滑块设置文件传输速度:=Drag the slider to set the transfer speed:
最慢=Slowest
慢=Slow
默认=Default
快=Fast
更快=Faster
很快=Very Fast
不限速=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.
+17
View File
@@ -2041,3 +2041,20 @@ Minimal
JPEG质量=JPEG品質
最大宽度为期望编码宽度;JPEG 质量 1~100=最大寬度為期望編碼寬度;JPEG 品質 1~100
预览质量等级已保存,下次发送预览时生效。=預覽品質等級已儲存,下次傳送預覽時生效。
; ============================================
; File Transfer Speed Dialog (文件传输速度)
; ============================================
文件传输速度(&F)...=檔案傳輸速度(&F)...
文件传输速度=檔案傳輸速度
拖动滑块设置文件传输速度:=拖曳滑桿設定檔案傳輸速度:
最慢=最慢
慢=慢
默认=預設
快=快
更快=更快
很快=很快
不限速=不限速
%s · 约 %.2f MB/s=%s · 約 %.2f MB/s
%s · 不受限速(受网络带宽约束)=%s · 不限速(受網路頻寬限制)
文件传输速度已保存。上传速度重启主控端后生效;下载速度下次打开文件管理或远程桌面后生效。=檔案傳輸速度已儲存。上傳速度重啟主控端後生效;下載速度下次開啟檔案管理或遠端桌面後生效。
+10 -3
View File
@@ -1056,13 +1056,20 @@
#define IDC_STATIC_SHARE_DAYS 2588
#define IDC_EDIT_SHARE_DAYS 2589
// 文件传输速度调节对话框
#define IDD_FILE_SPEED 403
#define ID_TOOL_FILE_SPEED 33085
#define IDC_FSPEED_SLIDER 2590
#define IDC_FSPEED_LABEL 2591
#define IDC_FSPEED_RESET 2592
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 403
#define _APS_NEXT_COMMAND_VALUE 33085
#define _APS_NEXT_CONTROL_VALUE 2590
#define _APS_NEXT_RESOURCE_VALUE 404
#define _APS_NEXT_COMMAND_VALUE 33086
#define _APS_NEXT_CONTROL_VALUE 2593
#define _APS_NEXT_SYMED_VALUE 105
#endif
#endif