Server sends COMMAND_SCREEN_PREVIEW_REQ when user double-clicks an active (non-Locked/Inactive) host that advertises CLIENT_CAP_SCREEN_PREVIEW. Client BitBlts primary screen, encodes to JPEG via GDI+ and replies. The existing STATIC tooltip is replaced with a self-drawn CPreviewTipWnd showing the thumbnail above the host info text, with wide-character rendering so the popup also works on non-Chinese servers. - Quality tiers reuse QualityProfile pattern: PreviewProfile + 6 levels driven by GetTargetQualityLevel (FRP-aware), with 4K/ultrawide auto upscale on Ultra/High tiers up to min(screenWidth/4, 1280). - Client limits to 1 in-flight capture via atomic counter to defend against flood/DoS; Send2Server is already mutex-serialized. - Server validates responses by reqId only (single in-flight tip); 4s arrival timeout marks "preview unavailable" without blocking the text fallback path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
79 lines
2.9 KiB
C++
79 lines
2.9 KiB
C++
#pragma once
|
||
|
||
#include "common/header.h"
|
||
#include "common/commands.h"
|
||
#include <atlstr.h>
|
||
|
||
enum {
|
||
ONLINELIST_IP = 0, // IP的列顺序
|
||
ONLINELIST_ADDR, // 地址
|
||
ONLINELIST_LOCATION, // 地理位置
|
||
ONLINELIST_COMPUTER_NAME, // 计算机名/备注
|
||
ONLINELIST_OS, // 操作系统
|
||
ONLINELIST_CPU, // CPU
|
||
ONLINELIST_VIDEO, // 摄像头(有无)
|
||
ONLINELIST_PING, // PING(对方的网速)
|
||
ONLINELIST_VERSION, // 版本信息
|
||
ONLINELIST_INSTALLTIME, // 安装时间
|
||
ONLINELIST_LOGINTIME, // 活动窗口
|
||
ONLINELIST_CLIENTTYPE, // 客户端类型
|
||
ONLINELIST_PATH, // 文件路径
|
||
ONLINELIST_PUBIP,
|
||
ONLINELIST_STARTTIME,
|
||
ONLINELIST_CAPABILITIES, // 客户端能力位
|
||
ONLINELIST_MAX,
|
||
};
|
||
|
||
class context
|
||
{
|
||
public:
|
||
// 纯虚函数
|
||
virtual VOID InitMember(SOCKET s, VOID* svr) = 0;
|
||
virtual BOOL Send2Client(PBYTE szBuffer, ULONG ulOriginalLength) = 0;
|
||
virtual CString GetClientData(int index)const = 0;
|
||
virtual void GetAdditionalData(CString(&s)[RES_MAX]) const = 0;
|
||
virtual CString GetAdditionalData(int index) const = 0;
|
||
virtual uint64_t GetClientID() const = 0;
|
||
virtual std::string GetPeerName() const = 0;
|
||
virtual int GetPort() const = 0;
|
||
virtual std::string GetProtocol() const = 0;
|
||
virtual int GetServerPort() const = 0;
|
||
virtual FlagType GetFlagType() const = 0;
|
||
virtual std::string GetGroupName() const = 0;
|
||
virtual uint64_t GetAliveTime()const = 0;
|
||
virtual void SetLastHeartbeat(uint64_t time) = 0;
|
||
virtual uint64_t GetLastHeartbeat() = 0;
|
||
virtual void CancelIO() = 0;
|
||
virtual std::string GetMasterID() const = 0;
|
||
public:
|
||
virtual ~context() {}
|
||
virtual void Destroy() {}
|
||
virtual BOOL IsLogin() const
|
||
{
|
||
return TRUE;
|
||
}
|
||
virtual void SetGroupName(const std::string& group) {}
|
||
|
||
// 检查客户端是否支持 V2 文件传输
|
||
bool SupportsFileV2() const {
|
||
CString caps = GetClientData(ONLINELIST_CAPABILITIES);
|
||
if (caps.IsEmpty()) return false;
|
||
return (strtoul(caps.GetString(), nullptr, 16) & CLIENT_CAP_V2) != 0;
|
||
}
|
||
|
||
// 检查客户端是否使用 UTF-8 协议字符串编码。
|
||
// 无此能力位的老客户端:服务端按 CP_ACP(CP936,覆盖 95% 的简中/英语 ASCII 老客户端)解读。
|
||
bool SupportsUtf8() const {
|
||
CString caps = GetClientData(ONLINELIST_CAPABILITIES);
|
||
if (caps.IsEmpty()) return false;
|
||
return (strtoul(caps.GetString(), nullptr, 16) & CLIENT_CAP_UTF8) != 0;
|
||
}
|
||
|
||
// 检查客户端是否支持屏幕预览(双击主机时拉缩略图)。
|
||
bool SupportsScreenPreview() const {
|
||
CString caps = GetClientData(ONLINELIST_CAPABILITIES);
|
||
if (caps.IsEmpty()) return false;
|
||
return (strtoul(caps.GetString(), nullptr, 16) & CLIENT_CAP_SCREEN_PREVIEW) != 0;
|
||
}
|
||
};
|