// PreviewTipWnd.h // 双击在线主机时弹出的浮窗:上方 JPEG 缩略图,下方主机信息文本。 // 无图片时显示"加载预览…"占位,供 OnListClick 即时弹窗、收到响应后再 SetImage 重画。 #pragma once #include #include #include 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 m_image; CFont m_font; WORD m_reqId = 0; };