mirror of
https://github.com/yuanyuanxiang/SimpleRemoter.git
synced 2026-01-28 02:03:13 +08:00
Feature: Support using remote cursor in screen control
This commit is contained in:
@@ -100,6 +100,7 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CMan
|
|||||||
m_ScreenSettings.ScreenWidth = cfg.GetInt("settings", "ScreenWidth", 0);
|
m_ScreenSettings.ScreenWidth = cfg.GetInt("settings", "ScreenWidth", 0);
|
||||||
m_ScreenSettings.ScreenHeight = cfg.GetInt("settings", "ScreenHeight", 0);
|
m_ScreenSettings.ScreenHeight = cfg.GetInt("settings", "ScreenHeight", 0);
|
||||||
m_ScreenSettings.FullScreen = cfg.GetInt("settings", "FullScreen", 0);
|
m_ScreenSettings.FullScreen = cfg.GetInt("settings", "FullScreen", 0);
|
||||||
|
m_ScreenSettings.RemoteCursor = cfg.GetInt("settings", "RemoteCursor", 0);
|
||||||
|
|
||||||
m_hWorkThread = __CreateThread(NULL,0, WorkThreadProc,this,0,NULL);
|
m_hWorkThread = __CreateThread(NULL,0, WorkThreadProc,this,0,NULL);
|
||||||
}
|
}
|
||||||
@@ -535,6 +536,13 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
|||||||
m_ScreenSettings.FullScreen = fullScreen;
|
m_ScreenSettings.FullScreen = fullScreen;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CMD_REMOTE_CURSOR: {
|
||||||
|
int remoteCursor = szBuffer[1];
|
||||||
|
iniFile cfg(CLIENT_PATH);
|
||||||
|
cfg.SetInt("settings", "RemoteCursor", remoteCursor);
|
||||||
|
m_ScreenSettings.RemoteCursor = remoteCursor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CMD_MULTITHREAD_COMPRESS: {
|
case CMD_MULTITHREAD_COMPRESS: {
|
||||||
int threadNum = szBuffer[1];
|
int threadNum = szBuffer[1];
|
||||||
m_ClientObject->SetMultiThreadCompress(threadNum);
|
m_ClientObject->SetMultiThreadCompress(threadNum);
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ enum {
|
|||||||
CMD_UNCOMPRESS_FILES = 73, // 解压文件
|
CMD_UNCOMPRESS_FILES = 73, // 解压文件
|
||||||
CMD_SCREEN_SIZE = 74,
|
CMD_SCREEN_SIZE = 74,
|
||||||
CMD_FULL_SCREEN = 75,
|
CMD_FULL_SCREEN = 75,
|
||||||
|
CMD_REMOTE_CURSOR = 76,
|
||||||
|
|
||||||
// 服务端发出的标识
|
// 服务端发出的标识
|
||||||
TOKEN_AUTH = 100, // 要求验证
|
TOKEN_AUTH = 100, // 要求验证
|
||||||
@@ -922,7 +923,8 @@ typedef struct ScreenSettings {
|
|||||||
int ScreenWidth; // 屏幕宽度
|
int ScreenWidth; // 屏幕宽度
|
||||||
int ScreenHeight; // 屏幕高度
|
int ScreenHeight; // 屏幕高度
|
||||||
int FullScreen; // 全屏模式
|
int FullScreen; // 全屏模式
|
||||||
char Reserved[76]; // 保留字段
|
int RemoteCursor; // 使用远程光标
|
||||||
|
char Reserved[72]; // 保留字段
|
||||||
} ScreenSettings;
|
} ScreenSettings;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ enum {
|
|||||||
IDM_FPS_UNLIMITED,
|
IDM_FPS_UNLIMITED,
|
||||||
IDM_ORIGINAL_SIZE,
|
IDM_ORIGINAL_SIZE,
|
||||||
IDM_SCREEN_1080P,
|
IDM_SCREEN_1080P,
|
||||||
|
IDM_REMOTE_CURSOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
IMPLEMENT_DYNAMIC(CScreenSpyDlg, CDialog)
|
IMPLEMENT_DYNAMIC(CScreenSpyDlg, CDialog)
|
||||||
@@ -162,6 +163,7 @@ void CScreenSpyDlg::DoDataExchange(CDataExchange* pDX)
|
|||||||
BEGIN_MESSAGE_MAP(CScreenSpyDlg, CDialog)
|
BEGIN_MESSAGE_MAP(CScreenSpyDlg, CDialog)
|
||||||
ON_WM_CLOSE()
|
ON_WM_CLOSE()
|
||||||
ON_WM_PAINT()
|
ON_WM_PAINT()
|
||||||
|
ON_WM_SETCURSOR()
|
||||||
ON_WM_SYSCOMMAND()
|
ON_WM_SYSCOMMAND()
|
||||||
ON_WM_HSCROLL()
|
ON_WM_HSCROLL()
|
||||||
ON_WM_VSCROLL()
|
ON_WM_VSCROLL()
|
||||||
@@ -242,6 +244,7 @@ BOOL CScreenSpyDlg::OnInitDialog()
|
|||||||
SysMenu->AppendMenu(MF_SEPARATOR);
|
SysMenu->AppendMenu(MF_SEPARATOR);
|
||||||
SysMenu->AppendMenu(MF_STRING, IDM_CONTROL, "控制屏幕(&Y)");
|
SysMenu->AppendMenu(MF_STRING, IDM_CONTROL, "控制屏幕(&Y)");
|
||||||
SysMenu->AppendMenu(MF_STRING, IDM_FULLSCREEN, "全屏(&F)");
|
SysMenu->AppendMenu(MF_STRING, IDM_FULLSCREEN, "全屏(&F)");
|
||||||
|
SysMenu->AppendMenu(MF_STRING, IDM_REMOTE_CURSOR, "使用远程光标(&C)");
|
||||||
SysMenu->AppendMenu(MF_STRING, IDM_ADAPTIVE_SIZE, "自适应窗口大小(&A)");
|
SysMenu->AppendMenu(MF_STRING, IDM_ADAPTIVE_SIZE, "自适应窗口大小(&A)");
|
||||||
SysMenu->AppendMenu(MF_STRING, IDM_TRACE_CURSOR, "跟踪被控端鼠标(&T)");
|
SysMenu->AppendMenu(MF_STRING, IDM_TRACE_CURSOR, "跟踪被控端鼠标(&T)");
|
||||||
SysMenu->AppendMenu(MF_STRING, IDM_BLOCK_INPUT, "锁定被控端鼠标和键盘(&L)");
|
SysMenu->AppendMenu(MF_STRING, IDM_BLOCK_INPUT, "锁定被控端鼠标和键盘(&L)");
|
||||||
@@ -258,6 +261,9 @@ BOOL CScreenSpyDlg::OnInitDialog()
|
|||||||
SysMenu->AppendMenu(MF_STRING, IDM_SCREEN_1080P, "限制为1080P(&4)");
|
SysMenu->AppendMenu(MF_STRING, IDM_SCREEN_1080P, "限制为1080P(&4)");
|
||||||
SysMenu->AppendMenu(MF_SEPARATOR);
|
SysMenu->AppendMenu(MF_SEPARATOR);
|
||||||
|
|
||||||
|
SysMenu->CheckMenuItem(IDM_FULLSCREEN, m_Settings.FullScreen ? MF_CHECKED : MF_UNCHECKED);
|
||||||
|
SysMenu->CheckMenuItem(IDM_REMOTE_CURSOR, m_Settings.RemoteCursor ? MF_CHECKED : MF_UNCHECKED);
|
||||||
|
|
||||||
CMenu fpsMenu;
|
CMenu fpsMenu;
|
||||||
if (fpsMenu.CreatePopupMenu()) {
|
if (fpsMenu.CreatePopupMenu()) {
|
||||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_10, "最大帧率FPS:10");
|
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_10, "最大帧率FPS:10");
|
||||||
@@ -477,12 +483,14 @@ VOID CScreenSpyDlg::DrawNextScreenDiff(bool keyFrame)
|
|||||||
m_bCursorIndex = m_ContextObject->InDeCompressedBuffer.GetBuffer(2+sizeof(POINT))[0];
|
m_bCursorIndex = m_ContextObject->InDeCompressedBuffer.GetBuffer(2+sizeof(POINT))[0];
|
||||||
if (bOldCursorIndex != m_bCursorIndex) {
|
if (bOldCursorIndex != m_bCursorIndex) {
|
||||||
bChange = TRUE;
|
bChange = TRUE;
|
||||||
if (m_bIsCtrl && !m_bIsTraceCursor)//替换指定窗口所属类的WNDCLASSEX结构
|
if (m_bIsCtrl && !m_bIsTraceCursor) {//替换指定窗口所属类的WNDCLASSEX结构
|
||||||
|
HCURSOR cursor = m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex);
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
SetClassLongPtrA(m_hWnd, GCLP_HCURSOR, (ULONG_PTR)m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex));
|
SetClassLongPtrA(m_hWnd, GCLP_HCURSOR, (ULONG_PTR)cursor);
|
||||||
#else
|
#else
|
||||||
SetClassLongA(m_hWnd, GCL_HCURSOR, (LONG)m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex));
|
SetClassLongA(m_hWnd, GCL_HCURSOR, (LONG)cursor);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 屏幕是否变化
|
// 屏幕是否变化
|
||||||
@@ -606,22 +614,45 @@ void CScreenSpyDlg::OnPaint()
|
|||||||
StretchBlt(m_hFullDC, 0, 0, m_CRect.Width(), m_CRect.Height(), m_hFullMemDC, 0, 0, m_BitmapInfor_Full->bmiHeader.biWidth, m_BitmapInfor_Full->bmiHeader.biHeight, SRCCOPY) :
|
StretchBlt(m_hFullDC, 0, 0, m_CRect.Width(), m_CRect.Height(), m_hFullMemDC, 0, 0, m_BitmapInfor_Full->bmiHeader.biWidth, m_BitmapInfor_Full->bmiHeader.biHeight, SRCCOPY) :
|
||||||
BitBlt(m_hFullDC, 0, 0, m_BitmapInfor_Full->bmiHeader.biWidth, m_BitmapInfor_Full->bmiHeader.biHeight, m_hFullMemDC, m_ulHScrollPos, m_ulVScrollPos, SRCCOPY);
|
BitBlt(m_hFullDC, 0, 0, m_BitmapInfor_Full->bmiHeader.biWidth, m_BitmapInfor_Full->bmiHeader.biHeight, m_hFullMemDC, m_ulHScrollPos, m_ulVScrollPos, SRCCOPY);
|
||||||
|
|
||||||
if (m_bIsTraceCursor)
|
if ((m_bIsCtrl && m_Settings.RemoteCursor) || m_bIsTraceCursor) {
|
||||||
DrawIconEx(
|
CPoint ptLocal;
|
||||||
m_hFullDC,
|
GetCursorPos(&ptLocal);
|
||||||
m_ClientCursorPos.x - m_ulHScrollPos,
|
ScreenToClient(&ptLocal);
|
||||||
m_ClientCursorPos.y - m_ulVScrollPos,
|
|
||||||
m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex),
|
CRect rcToolbar(0, 0, 0, 0);
|
||||||
0,0,
|
if (m_pToolbar) m_pToolbar->GetWindowRect(&rcToolbar), ScreenToClient(&rcToolbar);
|
||||||
0,
|
// 只有当本地鼠标不在工具栏区域时,才绘制远程位图光标
|
||||||
NULL,
|
if (!rcToolbar.PtInRect(ptLocal)) {
|
||||||
DI_NORMAL | DI_COMPAT
|
|
||||||
);
|
// 1. 计算缩放位置
|
||||||
|
int drawX = m_bAdaptiveSize ? (int)(m_ClientCursorPos.x / m_wZoom) : (m_ClientCursorPos.x - m_ulHScrollPos);
|
||||||
|
int drawY = m_bAdaptiveSize ? (int)(m_ClientCursorPos.y / m_hZoom) : (m_ClientCursorPos.y - m_ulVScrollPos);
|
||||||
|
|
||||||
|
// 2. 强制绘制
|
||||||
|
DrawIconEx(
|
||||||
|
m_hFullDC,
|
||||||
|
drawX,
|
||||||
|
drawY,
|
||||||
|
m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex),
|
||||||
|
0, 0, 0, NULL, DI_NORMAL | DI_COMPAT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!m_bConnected && GetTickCount64() - m_nDisconnectTime>2000) {
|
if (!m_bConnected && GetTickCount64() - m_nDisconnectTime>2000) {
|
||||||
DrawTipString("正在重连......", 2);
|
DrawTipString("正在重连......", 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL CScreenSpyDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
||||||
|
{
|
||||||
|
if ((m_bIsCtrl && m_Settings.RemoteCursor) && nHitTest == HTCLIENT)
|
||||||
|
{
|
||||||
|
::SetCursor(NULL); // 只要在客户区,始终隐藏系统光标
|
||||||
|
return TRUE; // 告诉 Windows 我们处理过了
|
||||||
|
}
|
||||||
|
return CDialog::OnSetCursor(pWnd, nHitTest, message);
|
||||||
|
}
|
||||||
|
|
||||||
VOID CScreenSpyDlg::DrawTipString(CString strString, int fillMode)
|
VOID CScreenSpyDlg::DrawTipString(CString strString, int fillMode)
|
||||||
{
|
{
|
||||||
// fillMode: 0=不填充, 1=全黑, 2=半透明
|
// fillMode: 0=不填充, 1=全黑, 2=半透明
|
||||||
@@ -716,6 +747,12 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
|
|||||||
m_ContextObject->Send2Client(cmd, sizeof(cmd));
|
m_ContextObject->Send2Client(cmd, sizeof(cmd));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case IDM_REMOTE_CURSOR: {
|
||||||
|
BYTE cmd[4] = { CMD_REMOTE_CURSOR, m_Settings.RemoteCursor = !m_Settings.RemoteCursor };
|
||||||
|
SysMenu->CheckMenuItem(IDM_REMOTE_CURSOR, m_Settings.RemoteCursor ? MF_CHECKED : MF_UNCHECKED);
|
||||||
|
m_ContextObject->Send2Client(cmd, sizeof(cmd));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case IDM_SAVEDIB: { // 快照保存
|
case IDM_SAVEDIB: { // 快照保存
|
||||||
SaveSnapshot();
|
SaveSnapshot();
|
||||||
break;
|
break;
|
||||||
@@ -1224,7 +1261,25 @@ BOOL CScreenSpyDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
|
|||||||
|
|
||||||
void CScreenSpyDlg::OnMouseMove(UINT nFlags, CPoint point)
|
void CScreenSpyDlg::OnMouseMove(UINT nFlags, CPoint point)
|
||||||
{
|
{
|
||||||
if (!m_bMouseTracking) {
|
if (m_Settings.RemoteCursor) {
|
||||||
|
if (m_pToolbar != NULL && ::IsWindow(m_pToolbar->m_hWnd) && m_pToolbar->IsWindowVisible())
|
||||||
|
{
|
||||||
|
CRect rcToolbar;
|
||||||
|
m_pToolbar->GetWindowRect(&rcToolbar);
|
||||||
|
ScreenToClient(&rcToolbar); // 转换到主窗口坐标系
|
||||||
|
|
||||||
|
if (rcToolbar.PtInRect(point))
|
||||||
|
{
|
||||||
|
// 如果鼠标在工具栏区域,直接显示本地光标并返回,不发送远程指令
|
||||||
|
::SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_bIsCtrl) {
|
||||||
|
// 关键:在控制模式下,强制设置光标为空,隐藏本地物理箭头
|
||||||
|
::SetCursor(NULL);
|
||||||
|
}
|
||||||
|
}else if (!m_bMouseTracking) {
|
||||||
m_bMouseTracking = true;
|
m_bMouseTracking = true;
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ public:
|
|||||||
virtual BOOL OnInitDialog();
|
virtual BOOL OnInitDialog();
|
||||||
afx_msg void OnClose();
|
afx_msg void OnClose();
|
||||||
afx_msg void OnPaint();
|
afx_msg void OnPaint();
|
||||||
|
BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
|
||||||
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
|
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
|
||||||
virtual BOOL PreTranslateMessage(MSG* pMsg);
|
virtual BOOL PreTranslateMessage(MSG* pMsg);
|
||||||
void OnLButtonDblClk(UINT nFlags, CPoint point);
|
void OnLButtonDblClk(UINT nFlags, CPoint point);
|
||||||
|
|||||||
@@ -6,9 +6,10 @@
|
|||||||
|
|
||||||
IMPLEMENT_DYNAMIC(CToolbarDlg, CDialogEx)
|
IMPLEMENT_DYNAMIC(CToolbarDlg, CDialogEx)
|
||||||
|
|
||||||
CToolbarDlg::CToolbarDlg(CWnd* pParent)
|
CToolbarDlg::CToolbarDlg(CScreenSpyDlg* pParent)
|
||||||
: CDialogEx(IDD_TOOLBAR_DLG, pParent)
|
: CDialogEx(IDD_TOOLBAR_DLG, pParent)
|
||||||
{
|
{
|
||||||
|
m_pParent = pParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
CToolbarDlg::~CToolbarDlg()
|
CToolbarDlg::~CToolbarDlg()
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
|
|
||||||
|
class CScreenSpyDlg;
|
||||||
|
|
||||||
class CToolbarDlg : public CDialogEx
|
class CToolbarDlg : public CDialogEx
|
||||||
{
|
{
|
||||||
DECLARE_DYNAMIC(CToolbarDlg)
|
DECLARE_DYNAMIC(CToolbarDlg)
|
||||||
@@ -8,7 +10,8 @@ private:
|
|||||||
int m_lastY = 0; // 记录上一次的 Y 坐标
|
int m_lastY = 0; // 记录上一次的 Y 坐标
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CToolbarDlg(CWnd* pParent = nullptr);
|
CScreenSpyDlg* m_pParent = nullptr;
|
||||||
|
CToolbarDlg(CScreenSpyDlg* pParent = nullptr);
|
||||||
virtual ~CToolbarDlg();
|
virtual ~CToolbarDlg();
|
||||||
|
|
||||||
enum { IDD = IDD_TOOLBAR_DLG };
|
enum { IDD = IDD_TOOLBAR_DLG };
|
||||||
|
|||||||
Reference in New Issue
Block a user