diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index dd14c04..6dd95fe 100644 Binary files a/server/2015Remote/2015Remote.rc and b/server/2015Remote/2015Remote.rc differ diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index aa97c4e..edc16cb 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -44,6 +44,7 @@ #include "common/skCrypter.h" #include "common/commands.h" #include "QualityLevelsDlg.h" +#include "CPreviewLevelsDlg.h" #include "McpServer.h" #include "McpSettingsDlg.h" #include "common/md5.h" @@ -1015,6 +1016,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx) ON_COMMAND(ID_TOOL_V2_PRIVATEKEY, &CMy2015RemoteDlg::OnToolV2PrivateKey) 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_EXECUTE_TESTRUN, &CMy2015RemoteDlg::OnExecuteTestrun) ON_COMMAND(ID_EXECUTE_GHOST, &CMy2015RemoteDlg::OnExecuteGhost) ON_COMMAND(ID_MASTER_TRAIL, &CMy2015RemoteDlg::OnMasterTrail) @@ -2409,6 +2411,7 @@ BOOL CMy2015RemoteDlg::OnInitDialog() LoadThumbnailSettingsFromCfg(); ApplyThumbnailSettings(); LoadQualityProfilesFromCfg(); + LoadPreviewProfilesFromCfg(); m_runNormal = THIS_CFG.GetInt("settings", "RunNormal", 0); CMenu* SubMenu = m_MainMenu.GetSubMenu(2); @@ -8797,7 +8800,7 @@ void CMy2015RemoteDlg::OnListSingleClick(NMHDR* pNMHDR, LRESULT* pResult) OpenLoopTip(ctx, anchor); } -// å±�幕预览å�‚数挑选:å¤�用既有 GetTargetQualityLevel + GetScreenPreviewProfile +// å±�幕预览å�‚数挑选:å¤�用 GetTargetQualityLevel + GetPreviewProfileCfg(å�¯é…�置的 6 档预览å�‚数表) // RTT 阈值表与å±�幕共享共用(FRP 模å¼�阈值更宽æ�¾ï¼‰ï¼›è¶…清档(Ultra/High)+ 4K/超宽å±� // 时按 min(screenWidth/4, 1280) 自适应放大,é�¿å…�高分å±�被压æˆ�æ— ä¿¡æ�¯ç¼©ç•¥å›¾ void CMy2015RemoteDlg::ChooseScreenPreviewParams(context* ctx, WORD& maxWidth, BYTE& jpegQuality) const @@ -8811,7 +8814,7 @@ void CMy2015RemoteDlg::ChooseScreenPreviewParams(context* ctx, WORD& maxWidth, B int rttForLevel = ping > 0 ? ping : 250; int level = GetTargetQualityLevel(rttForLevel, m_settings.UsingFRPProxy ? 1 : 0); - const PreviewProfile& prof = GetScreenPreviewProfile(level); + const PreviewProfile& prof = GetPreviewProfileCfg(level); int base = prof.maxWidth; BYTE q = (BYTE)prof.jpegQuality; @@ -9205,6 +9208,58 @@ void CMy2015RemoteDlg::OnQualityLevels() } } +// ===== å±�幕预览质é‡�等级é…�置([preview] 节) ===== +// 6 æ¡£ PreviewProfile 的读写入å�£ã€‚缺çœ�值回è�½åˆ° common/commands.h çš„ +// GetScreenPreviewProfile(),与内置预览å�‚数表一致;用户改过的档ä½�å�•独è�½ç›˜åˆ° INI。 + +void CMy2015RemoteDlg::LoadPreviewProfilesFromCfg() +{ + // 先整体回è�½åˆ°å†…置默认,å†�é€�字段覆盖,é�¿å…� INI 缺项时读到 0 + for (int i = 0; i < QUALITY_COUNT; i++) { + m_PreviewProfiles[i] = GetScreenPreviewProfile(i); + } + + for (int i = 0; i < QUALITY_COUNT; i++) { + std::string sec = "preview" + std::to_string(i); + PreviewProfile& p = m_PreviewProfiles[i]; + + p.maxWidth = THIS_CFG.GetInt("preview", sec + "_maxWidth", p.maxWidth); + p.jpegQuality = THIS_CFG.GetInt("preview", sec + "_jpegQuality", p.jpegQuality); + + // Clamp 到安全范围(防 INI 被手工编错) + if (p.maxWidth < 64) p.maxWidth = 64; + if (p.maxWidth > 2560) p.maxWidth = 2560; + if (p.jpegQuality < 1) p.jpegQuality = 1; + if (p.jpegQuality > 100) p.jpegQuality = 100; + } +} + +void CMy2015RemoteDlg::SavePreviewProfilesToCfg() const +{ + for (int i = 0; i < QUALITY_COUNT; i++) { + std::string sec = "preview" + std::to_string(i); + const PreviewProfile& p = m_PreviewProfiles[i]; + THIS_CFG.SetInt("preview", sec + "_maxWidth", p.maxWidth); + THIS_CFG.SetInt("preview", sec + "_jpegQuality", p.jpegQuality); + } +} + +const PreviewProfile& CMy2015RemoteDlg::GetPreviewProfileCfg(int level) const +{ + if (level < 0 || level >= QUALITY_COUNT) + return GetScreenPreviewProfile(level); // 越界:与 common 默认表å�Œæº�兜底 + return m_PreviewProfiles[level]; +} + +void CMy2015RemoteDlg::OnPreviewLevels() +{ + CPreviewLevelsDlg dlg(m_PreviewProfiles, this); + if (dlg.DoModal() == IDOK) { + SavePreviewProfilesToCfg(); + MessageBoxL("预览质é‡�等级已ä¿�存,下次å�‘é€�预览时生效。", "æ��示", MB_ICONINFORMATION); + } +} + void CMy2015RemoteDlg::ApplyThumbnailSettings() { // 任何已缓存的 HBITMAP 都是按"æ—§ ThumbWidth"渲染的,尺寸ä¸�å†�å�¯ä¿¡ —— 一律清空。 diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index 08fe15d..9a2c756 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -338,6 +338,15 @@ public: void SaveQualityProfilesToCfg() const; // m_QualityProfiles è�½ç›˜åˆ° THIS_CFG const QualityProfile& GetQualityProfileCfg(int level) const; // ä¾› ScreenSpyDlg 下å�‘用 void OnQualityLevels(); // 高级→远程桌é�¢è´¨é‡�等级 + + // ===== å±�幕预览质é‡�等级é…�置(6 æ¡£ PreviewProfile) ===== + // å�Œå‡»ä¸»æœºå�•å�‘预览 / 循环快照浮窗所用。æŒ�久化走 THIS_CFG [preview] 节。 + // ä»… UI 线程访问;修改å�Žä¸‹æ¬¡å�‘预览请求å�³ç”Ÿæ•ˆã€‚ + PreviewProfile m_PreviewProfiles[QUALITY_COUNT]; + void LoadPreviewProfilesFromCfg(); // 从 THIS_CFG 读到 m_PreviewProfiles(缺çœ�回è�½ GetScreenPreviewProfile) + void SavePreviewProfilesToCfg() const; // m_PreviewProfiles è�½ç›˜åˆ° THIS_CFG + const PreviewProfile& GetPreviewProfileCfg(int level) const; // ä¾› ChooseScreenPreviewParams 用 + void OnPreviewLevels(); // 高级→å±�幕预览质é‡�等级 void SendThumbnailRequest(class context* ctx);// å�‘一次缩略图请求 void CacheThumbnail(uint64_t clientID, const BYTE* jpeg, size_t bytes); void ClearThumbnailCacheEntry(uint64_t clientID); diff --git a/server/2015Remote/CPreviewLevelsDlg.h b/server/2015Remote/CPreviewLevelsDlg.h new file mode 100644 index 0000000..b211d3f --- /dev/null +++ b/server/2015Remote/CPreviewLevelsDlg.h @@ -0,0 +1,121 @@ +// CPreviewLevelsDlg.h +// å±�幕预览质é‡�等级é…�置对è¯�框:编辑 6 æ¡£ PreviewProfile(编ç �宽度 / JPEG è´¨é‡�)。 +// 纯主控端 UI å��好,æŒ�久化由 CMy2015RemoteDlg::SavePreviewProfilesToCfg() 负责。 +// 仅在 2015RemoteDlg.cpp 中 include 一次(头文件内è�”实现,勿多处包å�«ï¼‰ã€‚ +#pragma once + +#include "LangManager.h" + +class CPreviewLevelsDlg : public CDialog +{ +public: + enum { IDD = IDD_PREVIEW_LEVELS }; + + // profiles: 指å�‘ 6 元素 PreviewProfile 数组,确认å�Žå†™å›ž + CPreviewLevelsDlg(PreviewProfile* profiles, CWnd* pParent = NULL) + : CDialog(CPreviewLevelsDlg::IDD, pParent), m_profiles(profiles) + { + } + +protected: + PreviewProfile* m_profiles; + PreviewProfile m_working[QUALITY_COUNT]; + + static const char* LevelName(int i) + { + static const char* names[QUALITY_COUNT] = { + "Ultra", "High", "Good", "Medium", "Low", "Minimal" + }; + return (i >= 0 && i < QUALITY_COUNT) ? names[i] : "?"; + } + + void LoadToControls() + { + CString s; + for (int i = 0; i < QUALITY_COUNT; i++) { + s.Format(_T("%d"), m_working[i].maxWidth); + SetDlgItemText(IDC_PLEVEL_WIDTH + i, s); + s.Format(_T("%d"), m_working[i].jpegQuality); + SetDlgItemText(IDC_PLEVEL_QUALITY + i, s); + } + } + + bool ReadInt(int id, int& out) + { + CString s; + GetDlgItemText(id, s); + s.Trim(); + if (s.IsEmpty()) return false; + + int v = 0; + for (int k = 0; k < s.GetLength(); k++) { + TCHAR ch = s[k]; + if (ch < _T('0') || ch > _T('9')) return false; + v = v * 10 + (ch - _T('0')); + } + out = v; + return true; + } + + bool ReadFromControls(CString& err) + { + for (int i = 0; i < QUALITY_COUNT; i++) { + int w, q; + if (!ReadInt(IDC_PLEVEL_WIDTH + i, w)) + { err.Format(_T("等级 %s 的最大宽度ä¸�是有效数字"), LevelName(i)); return false; } + if (!ReadInt(IDC_PLEVEL_QUALITY + i, q)) + { err.Format(_T("等级 %s çš„ JPEG è´¨é‡�ä¸�是有效数字"), LevelName(i)); return false; } + + if (w < 64 || w > 2560) + { err.Format(_T("等级 %s 的最大宽度需在 64~2560 之间"), LevelName(i)); return false; } + if (q < 1 || q > 100) + { err.Format(_T("等级 %s çš„ JPEG è´¨é‡�需在 1~100 之间"), LevelName(i)); return false; } + + m_working[i].maxWidth = w; + m_working[i].jpegQuality = q; + } + return true; + } + + void ResetToDefaults() + { + for (int i = 0; i < QUALITY_COUNT; i++) { + m_working[i] = GetScreenPreviewProfile(i); + } + LoadToControls(); + } + + virtual BOOL OnInitDialog() override + { + CDialog::OnInitDialog(); + + for (int i = 0; i < QUALITY_COUNT; i++) { + m_working[i] = m_profiles[i]; + } + LoadToControls(); + TranslateDialog(this); + return TRUE; + } + + virtual void OnOK() override + { + CString err; + if (!ReadFromControls(err)) { + MessageBox(err, _TR("æ��示"), MB_ICONWARNING); + return; + } + for (int i = 0; i < QUALITY_COUNT; i++) { + m_profiles[i] = m_working[i]; + } + CDialog::OnOK(); + } + + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam) override + { + if (LOWORD(wParam) == IDC_PLEVEL_RESET && HIWORD(wParam) == BN_CLICKED) { + ResetToDefaults(); + return TRUE; + } + return CDialog::OnCommand(wParam, lParam); + } +}; diff --git a/server/2015Remote/lang/de_DE.ini b/server/2015Remote/lang/de_DE.ini index 071c8f1..b8a72d3 100644 --- a/server/2015Remote/lang/de_DE.ini +++ b/server/2015Remote/lang/de_DE.ini @@ -2042,3 +2042,8 @@ Minimal ×î´ó¿í¶È 0 ±íʾԭʼ·Ö±æÂÊ£»DIFF/RGB565 ÊʺϾÖÓòÍø£¬H264 ÊʺϿçÍø=Max. Breite 0 = Originalaufloesung; DIFF/RGB565 fuer LAN, H264 fuer WAN »Ö¸´Ä¬ÈÏ=Standard ÖÊÁ¿µÈ¼¶Òѱ£´æ£¬Ï´δò¿ªÔ¶³Ì×ÀÃæÊ±ÉúЧ¡£=Qualitaetsstufen gespeichert. Wirksam beim naechsten Oeffnen des Remote Desktops. +ÆÁĻԤÀÀÖÊÁ¿µÈ¼¶(&P)=Vorschau &Qualitaetsstufen +ÆÁĻԤÀÀÖÊÁ¿µÈ¼¶=Vorschau Qualitaetsstufen +JPEGÖÊÁ¿=JPEG Qualitaet +×î´ó¿í¶ÈΪÆÚÍû±àÂë¿í¶È£»JPEG ÖÊÁ¿ 1~100=Max. Breite ist die Ziel-Codierbreite; JPEG Qualitaet 1~100 +Ô¤ÀÀÖÊÁ¿µÈ¼¶Òѱ£´æ£¬Ï´η¢ËÍÔ¤ÀÀʱÉúЧ¡£=Vorschau-Qualitaetsstufen gespeichert. Wirksam bei der naechsten Vorschau. diff --git a/server/2015Remote/lang/en_US.ini b/server/2015Remote/lang/en_US.ini index 2b16b1e..9be94b0 100644 --- a/server/2015Remote/lang/en_US.ini +++ b/server/2015Remote/lang/en_US.ini @@ -2042,3 +2042,8 @@ Minimal ×î´ó¿í¶È 0 ±íʾԭʼ·Ö±æÂÊ£»DIFF/RGB565 ÊʺϾÖÓòÍø£¬H264 ÊʺϿçÍø=Max Width 0 = native resolution; DIFF/RGB565 for LAN, H264 for WAN »Ö¸´Ä¬ÈÏ=Restore Defaults ÖÊÁ¿µÈ¼¶Òѱ£´æ£¬Ï´δò¿ªÔ¶³Ì×ÀÃæÊ±ÉúЧ¡£=Quality levels saved. They take effect the next time you open Remote Desktop. +ÆÁĻԤÀÀÖÊÁ¿µÈ¼¶(&P)=Screen Preview &Quality Levels +ÆÁĻԤÀÀÖÊÁ¿µÈ¼¶=Screen Preview Quality Levels +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. diff --git a/server/2015Remote/lang/zh_TW.ini b/server/2015Remote/lang/zh_TW.ini index 4d07aea..4c95044 100644 --- a/server/2015Remote/lang/zh_TW.ini +++ b/server/2015Remote/lang/zh_TW.ini @@ -2033,3 +2033,8 @@ Minimal ×î´ó¿í¶È 0 ±íʾԭʼ·Ö±æÂÊ£»DIFF/RGB565 ÊʺϾÖÓòÍø£¬H264 ÊʺϿçÍø=×î´óŒ’¶È 0 = ԭʼ½âÎö¶È£»DIFF/RGB565 ßmºÏ…^Óò¾W·£¬H264 ßmºÏ¿ç¾W »Ö¸´Ä¬ÈÏ=»Ö�ÍîAÔO ÖÊÁ¿µÈ¼¶Òѱ£´æ£¬Ï´δò¿ªÔ¶³Ì×ÀÃæÊ±ÉúЧ¡£=Æ·Ù|µÈ¼‰Òу¦´æ£¬Ï´Îé_†¢ßh¶Ë×ÀÃæ•rÉúЧ¡£ +ÆÁĻԤÀÀÖÊÁ¿µÈ¼¶(&P)=ΞĻîAÓ[Æ·Ù|µÈ¼‰(&P) +ÆÁĻԤÀÀÖÊÁ¿µÈ¼¶=ΞĻîAÓ[Æ·Ù|µÈ¼‰ +JPEGÖÊÁ¿=JPEGÆ·Ù| +×î´ó¿í¶ÈΪÆÚÍû±àÂë¿í¶È£»JPEG ÖÊÁ¿ 1~100=×î´óŒ’¶ÈžéÆÚÍû¾Ž´aŒ’¶È£»JPEG Æ·Ù| 1~100 +Ô¤ÀÀÖÊÁ¿µÈ¼¶Òѱ£´æ£¬Ï´η¢ËÍÔ¤ÀÀʱÉúЧ¡£=îAÓ[Æ·Ù|µÈ¼‰Òу¦´æ£¬Ï´΂÷ËÍîAÓ[•rÉúЧ¡£ diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h index 0e7e21f..ef7fdcc 100644 --- a/server/2015Remote/resource.h +++ b/server/2015Remote/resource.h @@ -354,6 +354,7 @@ #define IDC_DOT 2036 #define IDD_AUDIO 2038 #define IDD_QUALITY_LEVELS 3000 +#define IDD_PREVIEW_LEVELS 3001 #define IDI_AUDIO 2039 #define IDC_LIST_REMOTE 2040 #define IDC_LIST_LOCAL 2041 @@ -1038,19 +1039,23 @@ #define ID_ONLINE_HISTORY_ACTIVITY 33082 #define ID_EXIT_FULLSCREEN 40001 #define ID_TOOL_QUALITY_LEVELS 33083 +#define ID_TOOL_PREVIEW_LEVELS 33084 #define IDC_QLEVEL_FPS 2547 #define IDC_QLEVEL_WIDTH 2553 #define IDC_QLEVEL_ALGO 2559 #define IDC_QLEVEL_BITRATE 2565 #define IDC_QLEVEL_RESET 2571 +#define IDC_PLEVEL_WIDTH 2572 +#define IDC_PLEVEL_QUALITY 2578 +#define IDC_PLEVEL_RESET 2584 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 401 -#define _APS_NEXT_COMMAND_VALUE 33083 -#define _APS_NEXT_CONTROL_VALUE 2542 +#define _APS_NEXT_COMMAND_VALUE 33085 +#define _APS_NEXT_CONTROL_VALUE 2585 #define _APS_NEXT_SYMED_VALUE 105 #endif #endif