Fix(cursor): correct trace cursor position on multi-monitor capture

This commit is contained in:
yuanyuanxiang
2026-05-22 23:24:26 +02:00
parent 62e962f216
commit 99fc15ae41
2 changed files with 26 additions and 6 deletions

View File

@@ -639,11 +639,10 @@ public:
// 写入算法类型 // 写入算法类型
data[0] = algo; data[0] = algo;
// 写入光标位置 // 写入光标位置(虚拟桌面绝对坐标 → 发送坐标系)
POINT CursorPos; POINT CursorPos;
GetCursorPos(&CursorPos); GetCursorPos(&CursorPos);
CursorPos.x /= m_wZoom; PointConversionInverse(CursorPos);
CursorPos.y /= m_hZoom;
memcpy(data + 1, &CursorPos, sizeof(POINT)); memcpy(data + 1, &CursorPos, sizeof(POINT));
// 写入当前光标类型(支持自定义光标) // 写入当前光标类型(支持自定义光标)
@@ -851,11 +850,10 @@ public:
// 写入使用了哪种算法 // 写入使用了哪种算法
memcpy(data, (LPBYTE)&algo, sizeof(BYTE)); memcpy(data, (LPBYTE)&algo, sizeof(BYTE));
// 写入光标位置 // 写入光标位置(虚拟桌面绝对坐标 → 发送坐标系)
POINT CursorPos; POINT CursorPos;
GetCursorPos(&CursorPos); GetCursorPos(&CursorPos);
CursorPos.x /= m_wZoom; PointConversionInverse(CursorPos);
CursorPos.y /= m_hZoom;
memcpy(data + sizeof(BYTE), (LPBYTE)&CursorPos, sizeof(POINT)); memcpy(data + sizeof(BYTE), (LPBYTE)&CursorPos, sizeof(POINT));
// 写入当前光标类型(支持自定义光标) // 写入当前光标类型(支持自定义光标)
@@ -1025,6 +1023,26 @@ public:
pt.y += m_iScreenY; 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 virtual const LPBITMAPINFO& GetBIData() const
{ {

View File

@@ -1866,11 +1866,13 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
switch (nID) { switch (nID) {
case IDM_CONTROL: { case IDM_CONTROL: {
m_bIsCtrl = !m_bIsCtrl; m_bIsCtrl = !m_bIsCtrl;
m_bIsTraceCursor = !m_bIsCtrl;
// 进入控制模式时重置放大状态 // 进入控制模式时重置放大状态
if (m_bIsCtrl && m_bZoomedIn) { if (m_bIsCtrl && m_bZoomedIn) {
ResetZoom(); ResetZoom();
} }
SysMenu->CheckMenuItem(IDM_CONTROL, m_bIsCtrl ? MF_CHECKED : MF_UNCHECKED); 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)); SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO));
// 控制模式:禁用本地 IME查看模式启用本地 IME // 控制模式:禁用本地 IME查看模式启用本地 IME
ImmAssociateContext(m_hWnd, m_bIsCtrl ? NULL : m_hOldIMC); ImmAssociateContext(m_hWnd, m_bIsCtrl ? NULL : m_hOldIMC);