From 99fc15ae418cb903c9fa94b8276dacfb2cfa6b46 Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Fri, 22 May 2026 23:24:26 +0200 Subject: [PATCH] Fix(cursor): correct trace cursor position on multi-monitor capture --- client/ScreenCapture.h | 30 ++++++++++++++++++++++++------ server/2015Remote/ScreenSpyDlg.cpp | 2 ++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/client/ScreenCapture.h b/client/ScreenCapture.h index 47e2e0e..7a4b778 100644 --- a/client/ScreenCapture.h +++ b/client/ScreenCapture.h @@ -639,11 +639,10 @@ public: // 写入算法类型 data[0] = algo; - // 写入光标位置 + // 写入光标位置(虚拟桌面绝对坐标 → 发送坐标系) POINT CursorPos; GetCursorPos(&CursorPos); - CursorPos.x /= m_wZoom; - CursorPos.y /= m_hZoom; + PointConversionInverse(CursorPos); memcpy(data + 1, &CursorPos, sizeof(POINT)); // 写入当前光标类型(支持自定义光标) @@ -851,11 +850,10 @@ public: // 写入使用了哪种算法 memcpy(data, (LPBYTE)&algo, sizeof(BYTE)); - // 写入光标位置 + // 写入光标位置(虚拟桌面绝对坐标 → 发送坐标系) POINT CursorPos; GetCursorPos(&CursorPos); - CursorPos.x /= m_wZoom; - CursorPos.y /= m_hZoom; + PointConversionInverse(CursorPos); memcpy(data + sizeof(BYTE), (LPBYTE)&CursorPos, sizeof(POINT)); // 写入当前光标类型(支持自定义光标) @@ -1025,6 +1023,26 @@ public: pt.y += m_iScreenY; } + // 鼠标位置反向转换:将客户端绝对坐标(GetCursorPos)转换为发送坐标系,逐项是 PointConversion 的逆 + virtual void PointConversionInverse(POINT& pt) const + { + // 3'. 减去屏幕偏移(多显示器) + pt.x -= m_iScreenX; + pt.y -= m_iScreenY; + // 2'. 反向 DPI 缩放 + if (m_bZoomed) { + pt.x = (LONG)(pt.x / m_wZoom); + pt.y = (LONG)(pt.y / m_hZoom); + } + // 1'. full → send 缩放(位图下采样传输时) + int sendWidth = m_BitmapInfor_Send->bmiHeader.biWidth; + int sendHeight = m_BitmapInfor_Send->bmiHeader.biHeight; + if (sendWidth != (int)m_ulFullWidth || sendHeight != (int)m_ulFullHeight) { + pt.x = (LONG)((double)pt.x * sendWidth / m_ulFullWidth + 0.5); + pt.y = (LONG)((double)pt.y * sendHeight / m_ulFullHeight + 0.5); + } + } + // 获取位图结构信息 virtual const LPBITMAPINFO& GetBIData() const { diff --git a/server/2015Remote/ScreenSpyDlg.cpp b/server/2015Remote/ScreenSpyDlg.cpp index f640fdb..f412072 100644 --- a/server/2015Remote/ScreenSpyDlg.cpp +++ b/server/2015Remote/ScreenSpyDlg.cpp @@ -1866,11 +1866,13 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam) switch (nID) { case IDM_CONTROL: { m_bIsCtrl = !m_bIsCtrl; + m_bIsTraceCursor = !m_bIsCtrl; // 进入控制模式时重置放大状态 if (m_bIsCtrl && m_bZoomedIn) { ResetZoom(); } SysMenu->CheckMenuItem(IDM_CONTROL, m_bIsCtrl ? MF_CHECKED : MF_UNCHECKED); + SysMenu->CheckMenuItem(IDM_TRACE_CURSOR, m_bIsTraceCursor ? MF_CHECKED : MF_UNCHECKED); SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO)); // 控制模式:禁用本地 IME;查看模式:启用本地 IME ImmAssociateContext(m_hWnd, m_bIsCtrl ? NULL : m_hOldIMC);