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>
58 lines
2.0 KiB
C++
58 lines
2.0 KiB
C++
// PreviewTipWnd.h
|
||
// 双击在线主机时弹出的浮窗:上方 JPEG 缩略图,下方主机信息文本。
|
||
// 无图片时显示"加载预览…"占位,供 OnListClick 即时弹窗、收到响应后再 SetImage 重画。
|
||
#pragma once
|
||
|
||
#include <afxwin.h>
|
||
#include <memory>
|
||
#include <vector>
|
||
|
||
namespace Gdiplus { class Bitmap; }
|
||
|
||
class CPreviewTipWnd : public CWnd
|
||
{
|
||
public:
|
||
CPreviewTipWnd();
|
||
virtual ~CPreviewTipWnd();
|
||
|
||
// 创建浮窗。
|
||
// anchor 屏幕坐标,浮窗左上角
|
||
// text 下方显示的主机详情文本(宽字符,确保跨语言系统正确渲染)
|
||
// imageReserveW 上方图像区域预留宽度(即将到来的预览最大宽度,仅作初始布局)
|
||
// 为 0 表示不预留 — 与老 STATIC 路径行为一致(仅文本)
|
||
BOOL Create(CWnd* pParent, CPoint anchor, const CStringW& text, int imageReserveW);
|
||
|
||
// 收到 JPEG 后调用:解码并重画。线程安全前提是只在主 UI 线程调用。
|
||
void SetImageFromJpeg(const BYTE* data, size_t bytes);
|
||
// 标记预览不可用(请求超时 / 客户端报错)。
|
||
void MarkPreviewUnavailable();
|
||
|
||
WORD GetReqId() const { return m_reqId; }
|
||
void SetReqId(WORD id) { m_reqId = id; }
|
||
|
||
protected:
|
||
afx_msg void OnPaint();
|
||
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
|
||
DECLARE_MESSAGE_MAP()
|
||
|
||
private:
|
||
void RecalcLayoutAndResize();
|
||
void DrawImageArea(CDC& dc, const CRect& rc);
|
||
void DrawTextArea(CDC& dc, const CRect& rc);
|
||
|
||
CStringW m_text;
|
||
int m_imageReserveW = 0; // 预留图像宽度(图像未到达时占位)
|
||
int m_imageReserveH = 0; // 预留图像高度(按 16:9)
|
||
int m_imageDrawW = 0; // 实际图像绘制宽度
|
||
int m_imageDrawH = 0; // 实际图像绘制高度
|
||
int m_textW = 0;
|
||
int m_textH = 0;
|
||
|
||
bool m_hasImage = false;
|
||
bool m_unavailable = false;
|
||
std::unique_ptr<Gdiplus::Bitmap> m_image;
|
||
|
||
CFont m_font;
|
||
WORD m_reqId = 0;
|
||
};
|