Init: Migrate SimpleRemoter (Since v1.3.1) to Gitea
This commit is contained in:
332
server/2015Remote/ScreenSpyDlg.h
Normal file
332
server/2015Remote/ScreenSpyDlg.h
Normal file
@@ -0,0 +1,332 @@
|
||||
#pragma once
|
||||
#include <imm.h>
|
||||
#include <map>
|
||||
#include "IOCPServer.h"
|
||||
#include "..\..\client\CursorInfo.h"
|
||||
#include "VideoDlg.h"
|
||||
#include "ToolbarDlg.h"
|
||||
#include "2015RemoteDlg.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "libavcodec\avcodec.h"
|
||||
#include "libavutil\avutil.h"
|
||||
#include "libyuv\libyuv.h"
|
||||
}
|
||||
|
||||
#ifndef _WIN64
|
||||
// https://github.com/Terodee/FFMpeg-windows-static-build/releases
|
||||
#pragma comment(lib,"ffmpeg/libavcodec.lib")
|
||||
#pragma comment(lib,"ffmpeg/libavutil.lib")
|
||||
#pragma comment(lib,"ffmpeg/libswresample.lib")
|
||||
|
||||
#pragma comment(lib,"libyuv/libyuv.lib")
|
||||
#else
|
||||
#pragma comment(lib,"x264/libx264_x64.lib")
|
||||
#pragma comment(lib,"libyuv/libyuv_x64.lib")
|
||||
// https://github.com/ShiftMediaProject/FFmpeg
|
||||
#pragma comment(lib,"ffmpeg/libavcodec_x64.lib")
|
||||
#pragma comment(lib,"ffmpeg/libavutil_x64.lib")
|
||||
#pragma comment(lib,"ffmpeg/libswresample_x64.lib")
|
||||
#endif
|
||||
|
||||
#pragma comment(lib, "Mfplat.lib")
|
||||
#pragma comment(lib, "Mfuuid.lib")
|
||||
#pragma comment(lib, "Bcrypt.lib")
|
||||
#pragma comment(lib, "Strmiids.lib")
|
||||
|
||||
// 文件接收消息(用于将工作线程的文件数据转发到主线程处理)
|
||||
#define WM_RECVFILEV2_CHUNK (WM_USER + 0x200)
|
||||
#define WM_RECVFILEV2_COMPLETE (WM_USER + 0x201)
|
||||
|
||||
// ScreenSpyDlg 系统菜单命令 ID
|
||||
enum {
|
||||
IDM_CONTROL = 0x1010,
|
||||
IDM_FULLSCREEN,
|
||||
IDM_SEND_CTRL_ALT_DEL,
|
||||
IDM_TRACE_CURSOR, // 跟踪显示远程鼠标
|
||||
IDM_BLOCK_INPUT, // 锁定远程计算机输入
|
||||
IDM_SAVEDIB, // 保存图片
|
||||
IDM_GET_CLIPBOARD, // 获取剪贴板
|
||||
IDM_SET_CLIPBOARD, // 设置剪贴板
|
||||
IDM_ADAPTIVE_SIZE,
|
||||
IDM_SAVEAVI,
|
||||
IDM_SAVEAVI_H264,
|
||||
IDM_SWITCHSCREEN,
|
||||
IDM_MULTITHREAD_COMPRESS,
|
||||
IDM_FPS_10,
|
||||
IDM_FPS_15,
|
||||
IDM_FPS_20,
|
||||
IDM_FPS_25,
|
||||
IDM_FPS_30,
|
||||
IDM_FPS_UNLIMITED,
|
||||
IDM_ORIGINAL_SIZE,
|
||||
IDM_SCREEN_1080P,
|
||||
IDM_REMOTE_CURSOR,
|
||||
IDM_SCROLL_DETECT_OFF, // 滚动检测:关闭(局域网)
|
||||
IDM_SCROLL_DETECT_2, // 滚动检测:跨网推荐
|
||||
IDM_SCROLL_DETECT_4, // 滚动检测:标准模式
|
||||
IDM_SCROLL_DETECT_8, // 滚动检测:省CPU模式
|
||||
IDM_QUALITY_OFF, // 关闭质量控制(使用原有算法)
|
||||
IDM_ADAPTIVE_QUALITY, // 自适应质量
|
||||
IDM_QUALITY_ULTRA, // 手动质量:Ultra
|
||||
IDM_QUALITY_HIGH, // 手动质量:High
|
||||
IDM_QUALITY_GOOD, // 手动质量:Good
|
||||
IDM_QUALITY_MEDIUM, // 手动质量:Medium
|
||||
IDM_QUALITY_LOW, // 手动质量:Low
|
||||
IDM_QUALITY_MINIMAL, // 手动质量:Minimal
|
||||
IDM_ENABLE_SSE2,
|
||||
IDM_FAST_STRETCH, // 快速缩放模式(降低CPU占用)
|
||||
IDM_CUSTOM_CURSOR, // 使用自定义光标
|
||||
IDM_RESTORE_CONSOLE, // RDP会话归位
|
||||
IDM_RESET_VIRTUAL_DESKTOP, // 重置虚拟桌面
|
||||
IDM_AUDIO_TOGGLE, // 音频开关
|
||||
};
|
||||
|
||||
// 状态信息窗口 - 全屏时显示帧率/速度/质量
|
||||
class CStatusInfoWnd : public CWnd
|
||||
{
|
||||
public:
|
||||
CStatusInfoWnd() : m_nOpacityLevel(0), m_bVisible(false), m_bDragging(false) {}
|
||||
|
||||
BOOL Create(CWnd* pParent);
|
||||
void UpdateInfo(double fps, double kbps, const CString& quality);
|
||||
void Show();
|
||||
void Hide();
|
||||
void SetOpacityLevel(int level);
|
||||
void UpdatePosition(const RECT& rcMonitor);
|
||||
void LoadSettings();
|
||||
void SaveSettings();
|
||||
|
||||
bool IsVisible() const { return m_bVisible; }
|
||||
bool IsParentInControlMode(); // 检查父窗口是否处于控制模式
|
||||
|
||||
protected:
|
||||
afx_msg void OnPaint();
|
||||
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
|
||||
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
|
||||
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
|
||||
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
private:
|
||||
CString m_strInfo;
|
||||
int m_nOpacityLevel;
|
||||
bool m_bVisible;
|
||||
|
||||
// 拖动支持
|
||||
bool m_bDragging;
|
||||
CPoint m_ptDragStart;
|
||||
|
||||
// 位置保存
|
||||
double m_dOffsetXRatio = 0.5;
|
||||
int m_nOffsetY = 50;
|
||||
bool m_bHasCustomPosition = false;
|
||||
};
|
||||
|
||||
// CScreenSpyDlg 对话框
|
||||
|
||||
class CScreenSpyDlg : public DialogBase
|
||||
{
|
||||
DECLARE_DYNAMIC(CScreenSpyDlg)
|
||||
CToolbarDlg* m_pToolbar = nullptr;
|
||||
CMy2015RemoteDlg* m_pParent = nullptr;
|
||||
|
||||
public:
|
||||
CStatusInfoWnd* m_pStatusInfoWnd = nullptr;
|
||||
// MaxFPS=20, ScrollDetectInterval=2, Reserved={}, Capabilities=0
|
||||
// MaxFPS=20, CompressThread=0, ScreenStrategy=0, ScreenWidth=0, ScreenHeight=0,
|
||||
// FullScreen=0, RemoteCursor=0, ScrollDetectInterval=2, QualityLevel=-1,
|
||||
// CpuSpeedup=0, ScreenType=0, AudioEnabled=0, Reserved={}, Capabilities=0
|
||||
ScreenSettings m_Settings = { 20, 0, 0, 0, 0, 0, 0, 2, -1, 0, 0, 0, {}, 0 };
|
||||
|
||||
public:
|
||||
// 快速缩放模式(全局配置,所有实例共享)
|
||||
static int s_nFastStretch; // -1=未初始化, 0=关闭, 1=开启
|
||||
static bool GetFastStretchMode();
|
||||
static void SetFastStretchMode(bool bFast);
|
||||
|
||||
CScreenSpyDlg(CMy2015RemoteDlg* Parent, Server* IOCPServer=NULL, CONTEXT_OBJECT *ContextObject=NULL);
|
||||
virtual ~CScreenSpyDlg();
|
||||
virtual BOOL ShouldReconnect()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID SendNext(void);
|
||||
VOID OnReceiveComplete();
|
||||
HDC m_hFullDC;
|
||||
HDC m_hFullMemDC;
|
||||
HBITMAP m_BitmapHandle;
|
||||
PVOID m_BitmapData_Full;
|
||||
LPBITMAPINFO m_BitmapInfor_Full;
|
||||
VOID DrawFirstScreen(void);
|
||||
VOID DrawNextScreenDiff(bool keyFrame);
|
||||
VOID DrawScrollFrame(void);
|
||||
BOOL m_bIsFirst;
|
||||
bool m_bQualitySwitch = false; // 质量切换中,不显示"请等待"
|
||||
ULONG m_ulHScrollPos;
|
||||
ULONG m_ulVScrollPos;
|
||||
// fillMode: 0=不填充, 1=全黑, 2=半透明
|
||||
VOID DrawTipString(CString strString, int fillMode=1);
|
||||
|
||||
POINT m_ClientCursorPos;
|
||||
BYTE m_bCursorIndex;
|
||||
BOOL m_bIsTraceCursor;
|
||||
CCursorInfo m_CursorInfo; //自定义的一个系统的光标类
|
||||
VOID SendCommand(const MYMSG* Msg);
|
||||
void SendScaledMouseMessage(MSG* pMsg, bool makeLP);
|
||||
VOID UpdateServerClipboard(char *szBuffer,ULONG ulLength);
|
||||
VOID SendServerClipboard(void);
|
||||
|
||||
BOOL m_bIsCtrl;
|
||||
LPBYTE m_szData;
|
||||
BOOL m_bSend;
|
||||
ULONG m_ulMsgCount;
|
||||
int m_FrameID;
|
||||
HIMC m_hOldIMC = NULL; // 保存原始 IME 上下文,控制模式切换时使用
|
||||
bool m_bHide = false;
|
||||
std::string m_strSaveNotice; // 截图保存路径提示
|
||||
ULONGLONG m_nSaveNoticeTime = 0; // 截图提示开始时间
|
||||
BOOL m_bUsingFRP = FALSE;
|
||||
|
||||
// 文件接收进度对话框(用于 Linux Ctrl+C -> 服务端 Ctrl+V)
|
||||
// 按 transferID 管理多个并发传输
|
||||
std::map<uint64_t, class CDlgFileSend*> m_FileRecvDlgs;
|
||||
|
||||
void SaveSnapshot(void);
|
||||
// 对话框数据
|
||||
enum { IDD = IDD_DIALOG_SCREEN_SPY };
|
||||
|
||||
WINDOWPLACEMENT m_struOldWndpl;
|
||||
|
||||
const AVCodec* m_pCodec;
|
||||
AVCodecContext* m_pCodecContext;
|
||||
AVPacket m_AVPacket;
|
||||
AVFrame m_AVFrame;
|
||||
|
||||
clock_t m_lastMouseMove; // 鼠标移动时间
|
||||
POINT m_lastMousePoint;// 上次鼠标位置
|
||||
BOOL m_bAdaptiveSize = TRUE;
|
||||
HCURSOR m_hRemoteCursor = NULL;
|
||||
HCURSOR m_hCustomCursor = NULL; // 缓存的自定义光标
|
||||
DWORD m_dwCustomCursorHash = 0; // 当前自定义光标哈希
|
||||
BOOL m_bUseCustomCursor = TRUE; // 是否使用自定义光标
|
||||
CRect m_CRect;
|
||||
double m_wZoom=1, m_hZoom=1;
|
||||
bool m_bMouseTracking = false;
|
||||
|
||||
CString m_aviFile;
|
||||
CBmpToAvi m_aviStream;
|
||||
|
||||
// 传输速率统计
|
||||
ULONG m_ulBytesThisSecond = 0; // 本秒累计字节
|
||||
double m_dTransferRate = 0; // 当前速率 (KB/s)
|
||||
// 帧率统计 (使用EMA平滑)
|
||||
ULONG m_ulFramesThisSecond = 0; // 本秒累计帧数
|
||||
double m_dFrameRate = 0; // 平滑后的帧率 (FPS)
|
||||
|
||||
// 自适应质量
|
||||
struct {
|
||||
bool enabled = false; // 是否启用自适应 (默认关闭)
|
||||
int currentLevel = QUALITY_HIGH; // 当前质量等级
|
||||
int currentMaxWidth = 0; // 当前分辨率限制 (0=原始)
|
||||
int lastRTT = 0; // 上次RTT值
|
||||
ULONGLONG lastChangeTime = 0; // 上次切换时间
|
||||
ULONGLONG lastResChangeTime = 0; // 上次分辨率变化时间
|
||||
ULONGLONG startTime = 0; // 启动时间 (用于延迟启动自适应)
|
||||
int stableCount = 0; // 稳定计数 (用于防抖)
|
||||
} m_AdaptiveQuality;
|
||||
|
||||
volatile bool m_bResolutionChanging = false; // 分辨率切换中,阻止解码
|
||||
|
||||
// ========== 音频播放 ==========
|
||||
// m_Settings.AudioEnabled 表示是否启用音频(与客户端同步)
|
||||
BOOL m_bAudioPlaying = FALSE; // 音频是否正在播放
|
||||
HWAVEOUT m_hWaveOut = NULL; // 波形输出设备句柄
|
||||
WAVEFORMATEX m_AudioFormat = {}; // 音频格式
|
||||
static const int AUDIO_BUFFER_COUNT = 8; // 缓冲区数量(增加到8个)
|
||||
WAVEHDR m_WaveHdr[AUDIO_BUFFER_COUNT] = {}; // 波形头
|
||||
LPBYTE m_pAudioBuf[AUDIO_BUFFER_COUNT] = {};// 音频缓冲区
|
||||
int m_nAudioBufIndex = 0; // 当前缓冲区索引
|
||||
static const DWORD AUDIO_BUF_SIZE = 8192; // 8KB 每个缓冲区(更小更频繁)
|
||||
|
||||
// 环形缓冲区(吸收网络抖动)
|
||||
static const DWORD RING_BUF_SIZE = 65536; // 64KB 环形缓冲区
|
||||
BYTE* m_pRingBuf = nullptr; // 环形缓冲区
|
||||
DWORD m_nRingHead = 0; // 写入位置
|
||||
DWORD m_nRingTail = 0; // 读取位置
|
||||
DWORD m_nRingDataLen = 0; // 缓冲数据量
|
||||
int m_nPrebufferCount = 0; // 预缓冲计数
|
||||
static const int PREBUFFER_TARGET = 5; // 预缓冲目标(积累5个包再开始播放,约50ms)
|
||||
|
||||
BYTE m_nAudioCompression = 0; // 音频压缩类型 (AudioCompression)
|
||||
#if USING_OPUS
|
||||
void* m_pOpusDecoder = nullptr; // Opus 解码器
|
||||
short* m_pOpusDecodeBuffer = nullptr; // Opus 解码输出缓冲区
|
||||
#endif
|
||||
|
||||
void OnAudioData(BYTE* pData, UINT32 len); // 处理音频数据
|
||||
BOOL InitAudioPlayback(const AudioFormat* fmt); // 初始化音频播放
|
||||
void StopAudioPlayback(); // 停止音频播放
|
||||
void SendAudioCtrl(BYTE enable, BYTE persist); // 发送音频控制命令
|
||||
void FeedAudioBuffers(); // 填充音频缓冲区
|
||||
|
||||
int GetClientRTT(); // 获取客户端RTT(ms)
|
||||
void EvaluateQuality(); // 评估并调整质量
|
||||
void ApplyQualityLevel(int level, bool persist = false); // 应用质量等级
|
||||
const char* GetQualityName(int level); // 获取质量等级名称
|
||||
void UpdateQualityMenuCheck(CMenu* SysMenu = nullptr); // 更新质量菜单勾选状态
|
||||
|
||||
void OnTimer(UINT_PTR nIDEvent);
|
||||
void UpdateWindowTitle();
|
||||
|
||||
bool Decode(LPBYTE Buffer, int size);
|
||||
void EnterFullScreen();
|
||||
bool LeaveFullScreen();
|
||||
void UpdateCtrlStatus(BOOL ctrl);
|
||||
void OnDropFiles(HDROP hDropInfo);
|
||||
|
||||
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
|
||||
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
|
||||
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
|
||||
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
|
||||
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
|
||||
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
|
||||
afx_msg void OnMouseLeave();
|
||||
afx_msg void OnKillFocus(CWnd* pNewWnd);
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
|
||||
afx_msg LRESULT OnDisconnect(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg LRESULT OnWaveOutDone(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg LRESULT OnRecvFileV2Chunk(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg LRESULT OnRecvFileV2Complete(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg void OnExitFullscreen()
|
||||
{
|
||||
BYTE cmd[4] = { CMD_FULL_SCREEN, m_Settings.FullScreen = FALSE };
|
||||
m_ContextObject->Send2Client(cmd, sizeof(cmd));
|
||||
LeaveFullScreen();
|
||||
}
|
||||
afx_msg void OnShowStatusInfo()
|
||||
{
|
||||
if (m_pStatusInfoWnd) m_pStatusInfoWnd->Show();
|
||||
}
|
||||
afx_msg void OnHideStatusInfo()
|
||||
{
|
||||
if (m_pStatusInfoWnd) m_pStatusInfoWnd->Hide();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
|
||||
|
||||
DECLARE_MESSAGE_MAP()
|
||||
public:
|
||||
void PrepareDrawing(const LPBITMAPINFO bmp);
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnClose();
|
||||
afx_msg void OnPaint();
|
||||
BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
|
||||
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
|
||||
virtual BOOL PreTranslateMessage(MSG* pMsg);
|
||||
void OnLButtonDblClk(UINT nFlags, CPoint point);
|
||||
};
|
||||
Reference in New Issue
Block a user