2024-12-26 17:07:43 +08:00
|
|
|
|
// ScreenSpyDlg.cpp : 实现文件
|
2019-01-05 20:21:43 +08:00
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
#include "2015Remote.h"
|
|
|
|
|
|
#include "ScreenSpyDlg.h"
|
|
|
|
|
|
#include "afxdialogex.h"
|
2019-01-21 21:04:17 +08:00
|
|
|
|
#include <imm.h>
|
2025-02-06 03:34:57 +08:00
|
|
|
|
#include <WinUser.h>
|
2025-09-07 20:31:34 +08:00
|
|
|
|
#include "CGridDialog.h"
|
2025-10-20 03:56:54 +08:00
|
|
|
|
#include "2015RemoteDlg.h"
|
2025-10-25 16:13:18 +08:00
|
|
|
|
#include <file_upload.h>
|
2025-12-28 14:39:52 +01:00
|
|
|
|
#include <md5.h>
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-12-26 17:07:43 +08:00
|
|
|
|
// CScreenSpyDlg 对话框
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
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,
|
2025-11-23 10:57:52 +01:00
|
|
|
|
IDM_SAVEAVI,
|
|
|
|
|
|
IDM_SAVEAVI_H264,
|
2025-11-28 20:53:28 +01:00
|
|
|
|
IDM_SWITCHSCREEN,
|
2025-11-30 08:02:44 +01:00
|
|
|
|
IDM_MULTITHREAD_COMPRESS,
|
2025-12-28 21:25:45 +01:00
|
|
|
|
IDM_FPS_10,
|
|
|
|
|
|
IDM_FPS_15,
|
|
|
|
|
|
IDM_FPS_20,
|
|
|
|
|
|
IDM_FPS_25,
|
|
|
|
|
|
IDM_FPS_30,
|
|
|
|
|
|
IDM_FPS_UNLIMITED,
|
2019-01-05 20:21:43 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_DYNAMIC(CScreenSpyDlg, CDialog)
|
|
|
|
|
|
|
|
|
|
|
|
#define ALGORITHM_DIFF 1
|
2025-11-23 10:57:52 +01:00
|
|
|
|
#define TIMER_ID 132
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-25 16:13:18 +08:00
|
|
|
|
#ifdef _WIN64
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
|
#pragma comment(lib, "FileUpload_Libx64d.lib")
|
|
|
|
|
|
#pragma comment(lib, "PrivateDesktop_Libx64d.lib")
|
|
|
|
|
|
#else
|
|
|
|
|
|
#pragma comment(lib, "FileUpload_Libx64.lib")
|
|
|
|
|
|
#pragma comment(lib, "PrivateDesktop_Libx64.lib")
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#else
|
2025-12-21 00:27:40 +01:00
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
|
#pragma comment(lib, "FileUpload_Libd.lib")
|
|
|
|
|
|
#pragma comment(lib, "PrivateDesktop_Libd.lib")
|
|
|
|
|
|
#else
|
|
|
|
|
|
#pragma comment(lib, "FileUpload_Lib.lib")
|
|
|
|
|
|
#pragma comment(lib, "PrivateDesktop_Lib.lib")
|
|
|
|
|
|
#endif
|
2025-10-25 16:13:18 +08:00
|
|
|
|
#endif
|
|
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
extern "C" void* x265_api_get_192()
|
|
|
|
|
|
{
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
2025-04-19 21:04:11 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
extern "C" char* __imp_strtok(char* str, const char* delim)
|
|
|
|
|
|
{
|
|
|
|
|
|
return strtok(str, delim);
|
|
|
|
|
|
}
|
2025-04-19 21:04:11 +08:00
|
|
|
|
|
2025-12-28 14:39:52 +01:00
|
|
|
|
CScreenSpyDlg::CScreenSpyDlg(CMy2015RemoteDlg* Parent, Server* IOCPServer, CONTEXT_OBJECT* ContextObject)
|
2025-10-15 04:32:59 +08:00
|
|
|
|
: DialogBase(CScreenSpyDlg::IDD, Parent, IOCPServer, ContextObject, 0)
|
|
|
|
|
|
{
|
2025-12-28 14:39:52 +01:00
|
|
|
|
m_pParent = Parent;
|
2025-11-28 20:53:28 +01:00
|
|
|
|
m_hFullDC = NULL;
|
|
|
|
|
|
m_hFullMemDC = NULL;
|
|
|
|
|
|
m_BitmapHandle = NULL;
|
|
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_lastMouseMove = 0;
|
|
|
|
|
|
m_lastMousePoint = {};
|
|
|
|
|
|
m_pCodec = nullptr;
|
|
|
|
|
|
m_pCodecContext = nullptr;
|
|
|
|
|
|
memset(&m_AVPacket, 0, sizeof(AVPacket));
|
|
|
|
|
|
memset(&m_AVFrame, 0, sizeof(AVFrame));
|
|
|
|
|
|
|
|
|
|
|
|
//创建解码器.
|
|
|
|
|
|
bool succeed = false;
|
|
|
|
|
|
m_pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
|
|
|
|
|
|
if (m_pCodec) {
|
|
|
|
|
|
m_pCodecContext = avcodec_alloc_context3(m_pCodec);
|
|
|
|
|
|
if (m_pCodecContext) {
|
|
|
|
|
|
succeed = (0 == avcodec_open2(m_pCodecContext, m_pCodec, 0));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
m_FrameID = 0;
|
|
|
|
|
|
ImmDisableIME(0);// 禁用输入法
|
|
|
|
|
|
m_bFullScreen = FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
CHAR szFullPath[MAX_PATH];
|
|
|
|
|
|
GetSystemDirectory(szFullPath, MAX_PATH);
|
|
|
|
|
|
lstrcat(szFullPath, "\\shell32.dll"); //图标
|
|
|
|
|
|
m_hIcon = ExtractIcon(THIS_APP->m_hInstance, szFullPath, 17);
|
|
|
|
|
|
|
|
|
|
|
|
m_bIsFirst = TRUE;
|
|
|
|
|
|
m_ulHScrollPos = 0;
|
|
|
|
|
|
m_ulVScrollPos = 0;
|
|
|
|
|
|
|
2025-12-14 00:46:36 +01:00
|
|
|
|
const ULONG ulBitmapInforLength = sizeof(BITMAPINFOHEADER);
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_BitmapInfor_Full = (BITMAPINFO *) new BYTE[ulBitmapInforLength];
|
|
|
|
|
|
m_ContextObject->InDeCompressedBuffer.CopyBuffer(m_BitmapInfor_Full, ulBitmapInforLength, 1);
|
|
|
|
|
|
|
|
|
|
|
|
m_bIsCtrl = FALSE;
|
|
|
|
|
|
m_bIsTraceCursor = FALSE;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID CScreenSpyDlg::SendNext(void)
|
|
|
|
|
|
{
|
2025-12-15 23:09:56 +01:00
|
|
|
|
BYTE bToken[32] = { COMMAND_NEXT };
|
|
|
|
|
|
uint64_t dlg = (uint64_t)this;
|
|
|
|
|
|
memcpy(bToken+1, &dlg, sizeof(uint64_t));
|
|
|
|
|
|
m_ContextObject->Send2Client(bToken, sizeof(bToken));
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CScreenSpyDlg::~CScreenSpyDlg()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (m_BitmapInfor_Full!=NULL) {
|
|
|
|
|
|
delete m_BitmapInfor_Full;
|
|
|
|
|
|
m_BitmapInfor_Full = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::ReleaseDC(m_hWnd, m_hFullDC); //GetDC
|
|
|
|
|
|
::DeleteDC(m_hFullMemDC); //Create匹配内存DC
|
|
|
|
|
|
|
|
|
|
|
|
::DeleteObject(m_BitmapHandle);
|
|
|
|
|
|
if (m_BitmapData_Full!=NULL) {
|
|
|
|
|
|
m_BitmapData_Full = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (m_pCodecContext) {
|
|
|
|
|
|
avcodec_free_context(&m_pCodecContext);
|
|
|
|
|
|
m_pCodecContext = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_pCodec = 0;
|
|
|
|
|
|
// AVFrame需要清除
|
|
|
|
|
|
av_frame_unref(&m_AVFrame);
|
2025-12-22 23:01:19 +01:00
|
|
|
|
|
|
|
|
|
|
SAFE_DELETE(m_pToolbar);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::DoDataExchange(CDataExchange* pDX)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CDialog::DoDataExchange(pDX);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CScreenSpyDlg, CDialog)
|
2025-10-15 04:32:59 +08:00
|
|
|
|
ON_WM_CLOSE()
|
|
|
|
|
|
ON_WM_PAINT()
|
|
|
|
|
|
ON_WM_SYSCOMMAND()
|
|
|
|
|
|
ON_WM_HSCROLL()
|
|
|
|
|
|
ON_WM_VSCROLL()
|
|
|
|
|
|
ON_WM_LBUTTONDOWN()
|
|
|
|
|
|
ON_WM_LBUTTONUP()
|
|
|
|
|
|
ON_WM_MOUSEWHEEL()
|
|
|
|
|
|
ON_WM_MOUSEMOVE()
|
|
|
|
|
|
ON_WM_MOUSELEAVE()
|
|
|
|
|
|
ON_WM_KILLFOCUS()
|
|
|
|
|
|
ON_WM_SIZE()
|
|
|
|
|
|
ON_WM_LBUTTONDBLCLK()
|
2025-10-20 03:56:54 +08:00
|
|
|
|
ON_WM_ACTIVATE()
|
2025-11-23 10:57:52 +01:00
|
|
|
|
ON_WM_TIMER()
|
2025-12-22 23:01:19 +01:00
|
|
|
|
ON_COMMAND(ID_EXIT_FULLSCREEN, &CScreenSpyDlg::OnExitFullscreen)
|
2025-12-24 09:24:15 +01:00
|
|
|
|
ON_MESSAGE(WM_DISCONNECT, &CScreenSpyDlg::OnDisconnect)
|
2025-12-26 19:35:10 +01:00
|
|
|
|
ON_WM_DROPFILES()
|
2019-01-05 20:21:43 +08:00
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-12-26 17:07:43 +08:00
|
|
|
|
// CScreenSpyDlg 消息处理程序
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-09-07 20:31:34 +08:00
|
|
|
|
void CScreenSpyDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (!m_bIsCtrl) {
|
|
|
|
|
|
CWnd* parent = GetParent();
|
|
|
|
|
|
if (parent) {
|
|
|
|
|
|
// 通知父对话框,传递点击点
|
|
|
|
|
|
CPoint ptScreen = point;
|
|
|
|
|
|
ClientToScreen(&ptScreen);
|
|
|
|
|
|
GetParent()->ScreenToClient(&ptScreen);
|
|
|
|
|
|
GetParent()->SendMessage(WM_LBUTTONDBLCLK, nFlags, MAKELPARAM(ptScreen.x, ptScreen.y));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
CDialog::OnLButtonDblClk(nFlags, point);
|
2025-09-07 20:31:34 +08:00
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-11-29 23:22:55 +01:00
|
|
|
|
void CScreenSpyDlg::PrepareDrawing(const LPBITMAPINFO bmp)
|
|
|
|
|
|
{
|
2025-11-28 20:53:28 +01:00
|
|
|
|
if (m_hFullDC) ::ReleaseDC(m_hWnd, m_hFullDC);
|
|
|
|
|
|
if (m_hFullMemDC) ::DeleteDC(m_hFullMemDC);
|
|
|
|
|
|
if (m_BitmapHandle) ::DeleteObject(m_BitmapHandle);
|
|
|
|
|
|
m_BitmapData_Full = NULL;
|
|
|
|
|
|
|
2025-11-29 23:22:55 +01:00
|
|
|
|
CString strString;
|
|
|
|
|
|
strString.Format("%s - 远程桌面控制 %d×%d", m_IPAddress, bmp->bmiHeader.biWidth, bmp->bmiHeader.biHeight);
|
|
|
|
|
|
SetWindowText(strString);
|
2025-12-18 11:55:28 +01:00
|
|
|
|
uint64_t dlg = (uint64_t)this;
|
|
|
|
|
|
Mprintf("%s [对话框ID: %lld]\n", strString.GetString(), dlg);
|
2025-11-28 20:53:28 +01:00
|
|
|
|
|
2025-11-29 23:22:55 +01:00
|
|
|
|
m_hFullDC = ::GetDC(m_hWnd);
|
|
|
|
|
|
SetStretchBltMode(m_hFullDC, HALFTONE);
|
|
|
|
|
|
SetBrushOrgEx(m_hFullDC, 0, 0, NULL);
|
|
|
|
|
|
m_hFullMemDC = CreateCompatibleDC(m_hFullDC);
|
|
|
|
|
|
m_BitmapHandle = CreateDIBSection(m_hFullDC, bmp, DIB_RGB_COLORS, &m_BitmapData_Full, NULL, NULL);
|
2025-11-28 20:53:28 +01:00
|
|
|
|
|
2025-11-29 23:22:55 +01:00
|
|
|
|
SelectObject(m_hFullMemDC, m_BitmapHandle);
|
2025-11-28 20:53:28 +01:00
|
|
|
|
|
2025-11-29 23:22:55 +01:00
|
|
|
|
SetScrollRange(SB_HORZ, 0, bmp->bmiHeader.biWidth);
|
|
|
|
|
|
SetScrollRange(SB_VERT, 0, bmp->bmiHeader.biHeight);
|
2025-11-28 20:53:28 +01:00
|
|
|
|
|
2025-11-29 23:22:55 +01:00
|
|
|
|
GetClientRect(&m_CRect);
|
|
|
|
|
|
m_wZoom = ((double)bmp->bmiHeader.biWidth) / ((double)(m_CRect.Width()));
|
|
|
|
|
|
m_hZoom = ((double)bmp->bmiHeader.biHeight) / ((double)(m_CRect.Height()));
|
2025-11-28 20:53:28 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-01-05 20:21:43 +08:00
|
|
|
|
BOOL CScreenSpyDlg::OnInitDialog()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CDialog::OnInitDialog();
|
|
|
|
|
|
SetIcon(m_hIcon,FALSE);
|
2025-12-26 19:35:10 +01:00
|
|
|
|
DragAcceptFiles(TRUE);
|
|
|
|
|
|
ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD);
|
|
|
|
|
|
ChangeWindowMessageFilter(0x0049, MSGFLT_ADD);
|
2025-10-15 04:32:59 +08:00
|
|
|
|
|
2025-11-28 20:53:28 +01:00
|
|
|
|
PrepareDrawing(m_BitmapInfor_Full);
|
2025-10-15 04:32:59 +08:00
|
|
|
|
|
|
|
|
|
|
CMenu* SysMenu = GetSystemMenu(FALSE);
|
|
|
|
|
|
if (SysMenu != NULL) {
|
|
|
|
|
|
SysMenu->AppendMenu(MF_SEPARATOR);
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_CONTROL, "控制屏幕(&Y)");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_FULLSCREEN, "全屏(&F)");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_ADAPTIVE_SIZE, "自适应窗口大小(&A)");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_TRACE_CURSOR, "跟踪被控端鼠标(&T)");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_BLOCK_INPUT, "锁定被控端鼠标和键盘(&L)");
|
2025-11-23 10:57:52 +01:00
|
|
|
|
SysMenu->AppendMenu(MF_SEPARATOR);
|
2025-10-15 04:32:59 +08:00
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_SAVEDIB, "保存快照(&S)");
|
2025-11-23 10:57:52 +01:00
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_SAVEAVI, _T("录像(MJPEG)"));
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_SAVEAVI_H264, _T("录像(H264)"));
|
2025-10-15 04:32:59 +08:00
|
|
|
|
SysMenu->AppendMenu(MF_SEPARATOR);
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_GET_CLIPBOARD, "获取剪贴板(&R)");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_SET_CLIPBOARD, "设置剪贴板(&L)");
|
2025-11-30 08:02:44 +01:00
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_SWITCHSCREEN, "切换显示器(&1)");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_MULTITHREAD_COMPRESS, "多线程压缩(&2)");
|
2025-12-28 21:25:45 +01:00
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_FPS_10, "最大帧率FPS:10");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_FPS_15, "最大帧率FPS:15");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_FPS_20, "最大帧率FPS:20");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_FPS_25, "最大帧率FPS:25");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_FPS_30, "最大帧率FPS:30");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_FPS_UNLIMITED, "最大帧率无限制");
|
2025-10-15 04:32:59 +08:00
|
|
|
|
SysMenu->AppendMenu(MF_SEPARATOR);
|
2025-11-28 20:53:28 +01:00
|
|
|
|
|
|
|
|
|
|
BOOL all = THIS_CFG.GetInt("settings", "MultiScreen");
|
|
|
|
|
|
SysMenu->EnableMenuItem(IDM_SWITCHSCREEN, all ? MF_ENABLED : MF_GRAYED);
|
2025-10-15 04:32:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_bIsCtrl = THIS_CFG.GetInt("settings", "DXGI") == USING_VIRTUAL;
|
|
|
|
|
|
m_bIsTraceCursor = FALSE; //不是跟踪
|
|
|
|
|
|
m_ClientCursorPos.x = 0;
|
|
|
|
|
|
m_ClientCursorPos.y = 0;
|
|
|
|
|
|
m_bCursorIndex = 0;
|
|
|
|
|
|
|
|
|
|
|
|
m_hRemoteCursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
|
|
ICONINFO CursorInfo;
|
|
|
|
|
|
::GetIconInfo(m_hRemoteCursor, &CursorInfo);
|
|
|
|
|
|
SysMenu->CheckMenuItem(IDM_CONTROL, m_bIsCtrl ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
|
|
SysMenu->CheckMenuItem(IDM_ADAPTIVE_SIZE, m_bAdaptiveSize ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
|
|
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO));
|
|
|
|
|
|
ShowScrollBar(SB_BOTH, !m_bAdaptiveSize);
|
|
|
|
|
|
|
|
|
|
|
|
SendNext();
|
|
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID CScreenSpyDlg::OnClose()
|
|
|
|
|
|
{
|
2025-11-29 23:22:55 +01:00
|
|
|
|
if (!m_aviFile.IsEmpty()) {
|
|
|
|
|
|
KillTimer(TIMER_ID);
|
|
|
|
|
|
m_aviFile = "";
|
|
|
|
|
|
m_aviStream.Close();
|
|
|
|
|
|
}
|
2025-12-24 09:24:15 +01:00
|
|
|
|
if (ShouldReconnect() && SayByeBye()) Sleep(500);
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CancelIO();
|
|
|
|
|
|
// 恢复鼠标状态
|
|
|
|
|
|
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor(NULL, IDC_ARROW));
|
|
|
|
|
|
// 通知父窗口
|
|
|
|
|
|
CWnd* parent = GetParent();
|
|
|
|
|
|
if (parent)
|
|
|
|
|
|
parent->SendMessage(WM_CHILD_CLOSED, (WPARAM)this, 0);
|
2025-10-20 03:56:54 +08:00
|
|
|
|
extern CMy2015RemoteDlg *g_2015RemoteDlg;
|
|
|
|
|
|
if(g_2015RemoteDlg)
|
|
|
|
|
|
g_2015RemoteDlg->RemoveRemoteWindow(GetSafeHwnd());
|
2025-10-15 04:32:59 +08:00
|
|
|
|
|
|
|
|
|
|
// 等待数据处理完毕
|
|
|
|
|
|
if (IsProcessing()) {
|
2025-11-23 10:57:52 +01:00
|
|
|
|
m_bHide = true;
|
2025-10-15 04:32:59 +08:00
|
|
|
|
ShowWindow(SW_HIDE);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DialogBase::OnClose();
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-24 09:24:15 +01:00
|
|
|
|
afx_msg LRESULT CScreenSpyDlg::OnDisconnect(WPARAM wParam, LPARAM lParam) {
|
|
|
|
|
|
m_bConnected = FALSE;
|
|
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-01-05 20:21:43 +08:00
|
|
|
|
VOID CScreenSpyDlg::OnReceiveComplete()
|
|
|
|
|
|
{
|
2025-11-23 18:13:39 +01:00
|
|
|
|
if (m_bIsClosed) return;
|
2025-10-15 04:32:59 +08:00
|
|
|
|
assert (m_ContextObject);
|
|
|
|
|
|
auto cmd = m_ContextObject->InDeCompressedBuffer.GetBYTE(0);
|
2025-11-09 00:49:34 +08:00
|
|
|
|
LPBYTE szBuffer = m_ContextObject->InDeCompressedBuffer.GetBuffer();
|
|
|
|
|
|
unsigned len = m_ContextObject->InDeCompressedBuffer.GetBufferLen();
|
2025-10-15 04:32:59 +08:00
|
|
|
|
switch(cmd) {
|
2025-11-09 00:49:34 +08:00
|
|
|
|
case COMMAND_GET_FOLDER: {
|
|
|
|
|
|
std::string folder;
|
|
|
|
|
|
if (GetCurrentFolderPath(folder)) {
|
2025-10-25 16:13:18 +08:00
|
|
|
|
// 发送目录并准备接收文件
|
2025-11-09 00:49:34 +08:00
|
|
|
|
BYTE cmd[300] = { COMMAND_GET_FILE };
|
|
|
|
|
|
memcpy(cmd + 1, folder.c_str(), folder.length());
|
|
|
|
|
|
m_ContextObject->Send2Client(cmd, sizeof(cmd));
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-10-15 04:32:59 +08:00
|
|
|
|
case TOKEN_FIRSTSCREEN: {
|
|
|
|
|
|
DrawFirstScreen();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case TOKEN_NEXTSCREEN: {
|
|
|
|
|
|
DrawNextScreenDiff(false);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case TOKEN_KEYFRAME: {
|
|
|
|
|
|
if (!m_bIsFirst) {
|
|
|
|
|
|
DrawNextScreenDiff(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case TOKEN_CLIPBOARD_TEXT: {
|
|
|
|
|
|
Buffer str = m_ContextObject->InDeCompressedBuffer.GetMyBuffer(1);
|
|
|
|
|
|
UpdateServerClipboard(str.c_str(), str.length());
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-11-28 20:53:28 +01:00
|
|
|
|
case TOKEN_BITMAPINFO: {
|
|
|
|
|
|
SAFE_DELETE(m_BitmapInfor_Full);
|
2025-12-15 23:09:56 +01:00
|
|
|
|
m_bIsFirst = TRUE;
|
2025-12-14 00:46:36 +01:00
|
|
|
|
const ULONG ulBitmapInforLength = sizeof(BITMAPINFOHEADER);
|
2025-11-29 23:22:55 +01:00
|
|
|
|
m_BitmapInfor_Full = (BITMAPINFO*) new BYTE[ulBitmapInforLength];
|
|
|
|
|
|
m_ContextObject->InDeCompressedBuffer.CopyBuffer(m_BitmapInfor_Full, ulBitmapInforLength, 1);
|
2025-11-28 20:53:28 +01:00
|
|
|
|
PrepareDrawing(m_BitmapInfor_Full);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-10-15 04:32:59 +08:00
|
|
|
|
default: {
|
2025-12-14 00:46:36 +01:00
|
|
|
|
Mprintf("CScreenSpyDlg unknown command: %d!!!\n", int(cmd));
|
2025-10-15 04:32:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID CScreenSpyDlg::DrawFirstScreen(void)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_bIsFirst = FALSE;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
//得到被控端发来的数据 ,将他拷贝到HBITMAP的缓冲区中,这样一个图像就出现了
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_ContextObject->InDeCompressedBuffer.CopyBuffer(m_BitmapData_Full, m_BitmapInfor_Full->bmiHeader.biSizeImage, 1);
|
|
|
|
|
|
PostMessage(WM_PAINT);//触发WM_PAINT消息
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-13 23:34:33 +08:00
|
|
|
|
VOID CScreenSpyDlg::DrawNextScreenDiff(bool keyFrame)
|
2019-01-05 20:21:43 +08:00
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
//该函数不是直接画到屏幕上,而是更新一下变化部分的屏幕数据然后调用
|
|
|
|
|
|
//OnPaint画上去
|
|
|
|
|
|
//根据鼠标是否移动和屏幕是否变化判断是否重绘鼠标,防止鼠标闪烁
|
|
|
|
|
|
BOOL bChange = FALSE;
|
|
|
|
|
|
ULONG ulHeadLength = 1 + 1 + sizeof(POINT) + sizeof(BYTE); // 标识 + 算法 + 光标 位置 + 光标类型索引
|
2025-03-13 23:34:33 +08:00
|
|
|
|
#if SCREENYSPY_IMPROVE
|
2025-10-15 04:32:59 +08:00
|
|
|
|
int frameID = -1;
|
|
|
|
|
|
memcpy(&frameID, m_ContextObject->InDeCompressedBuffer.GetBuffer(ulHeadLength), sizeof(int));
|
|
|
|
|
|
ulHeadLength += sizeof(int);
|
|
|
|
|
|
if (++m_FrameID != frameID) {
|
|
|
|
|
|
TRACE("DrawNextScreenDiff [%d] bmp is lost from %d\n", frameID-m_FrameID, m_FrameID);
|
|
|
|
|
|
m_FrameID = frameID;
|
|
|
|
|
|
}
|
2025-03-13 23:34:33 +08:00
|
|
|
|
#else
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_FrameID++;
|
2025-03-13 23:34:33 +08:00
|
|
|
|
#endif
|
2025-10-15 04:32:59 +08:00
|
|
|
|
LPVOID FirstScreenData = m_BitmapData_Full;
|
2025-11-23 18:13:39 +01:00
|
|
|
|
if (FirstScreenData == NULL) return;
|
2025-10-15 04:32:59 +08:00
|
|
|
|
LPVOID NextScreenData = m_ContextObject->InDeCompressedBuffer.GetBuffer(ulHeadLength);
|
|
|
|
|
|
ULONG NextScreenLength = m_ContextObject->InDeCompressedBuffer.GetBufferLength() - ulHeadLength;
|
|
|
|
|
|
|
|
|
|
|
|
POINT OldClientCursorPos;
|
|
|
|
|
|
memcpy(&OldClientCursorPos, &m_ClientCursorPos, sizeof(POINT));
|
|
|
|
|
|
memcpy(&m_ClientCursorPos, m_ContextObject->InDeCompressedBuffer.GetBuffer(2), sizeof(POINT));
|
|
|
|
|
|
|
|
|
|
|
|
// 鼠标移动了
|
|
|
|
|
|
if (memcmp(&OldClientCursorPos, &m_ClientCursorPos, sizeof(POINT)) != 0) {
|
|
|
|
|
|
bChange = TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 光标类型发生变化
|
|
|
|
|
|
BYTE bOldCursorIndex = m_bCursorIndex;
|
|
|
|
|
|
m_bCursorIndex = m_ContextObject->InDeCompressedBuffer.GetBuffer(2+sizeof(POINT))[0];
|
|
|
|
|
|
if (bOldCursorIndex != m_bCursorIndex) {
|
|
|
|
|
|
bChange = TRUE;
|
|
|
|
|
|
if (m_bIsCtrl && !m_bIsTraceCursor)//替换指定窗口所属类的WNDCLASSEX结构
|
2025-02-06 03:34:57 +08:00
|
|
|
|
#ifdef _WIN64
|
2025-10-15 04:32:59 +08:00
|
|
|
|
SetClassLongPtrA(m_hWnd, GCLP_HCURSOR, (ULONG_PTR)m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex));
|
2025-02-06 03:34:57 +08:00
|
|
|
|
#else
|
2025-10-15 04:32:59 +08:00
|
|
|
|
SetClassLongA(m_hWnd, GCL_HCURSOR, (LONG)m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex));
|
2025-02-06 03:34:57 +08:00
|
|
|
|
#endif
|
2025-10-15 04:32:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 屏幕是否变化
|
|
|
|
|
|
if (NextScreenLength > 0) {
|
|
|
|
|
|
bChange = TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BYTE algorithm = m_ContextObject->InDeCompressedBuffer.GetBYTE(1);
|
|
|
|
|
|
LPBYTE dst = (LPBYTE)FirstScreenData, p = (LPBYTE)NextScreenData;
|
|
|
|
|
|
if (keyFrame) {
|
|
|
|
|
|
switch (algorithm) {
|
|
|
|
|
|
case ALGORITHM_DIFF:
|
|
|
|
|
|
case ALGORITHM_GRAY: {
|
|
|
|
|
|
if (m_BitmapInfor_Full->bmiHeader.biSizeImage == NextScreenLength)
|
|
|
|
|
|
memcpy(dst, p, m_BitmapInfor_Full->bmiHeader.biSizeImage);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case ALGORITHM_H264: {
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (0 != NextScreenLength) {
|
|
|
|
|
|
switch (algorithm) {
|
|
|
|
|
|
case ALGORITHM_DIFF: {
|
|
|
|
|
|
for (LPBYTE end = p + NextScreenLength; p < end; ) {
|
|
|
|
|
|
ULONG ulCount = *(LPDWORD(p + sizeof(ULONG)));
|
|
|
|
|
|
memcpy(dst + *(LPDWORD)p, p + 2 * sizeof(ULONG), ulCount);
|
|
|
|
|
|
|
|
|
|
|
|
p += 2 * sizeof(ULONG) + ulCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case ALGORITHM_GRAY: {
|
|
|
|
|
|
for (LPBYTE end = p + NextScreenLength; p < end; ) {
|
|
|
|
|
|
ULONG ulCount = *(LPDWORD(p + sizeof(ULONG)));
|
|
|
|
|
|
LPBYTE p1 = dst + *(LPDWORD)p, p2 = p + 2 * sizeof(ULONG);
|
|
|
|
|
|
for (int i = 0; i < ulCount; ++i, p1 += 4)
|
|
|
|
|
|
memset(p1, *p2++, sizeof(DWORD));
|
|
|
|
|
|
|
|
|
|
|
|
p += 2 * sizeof(ULONG) + ulCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case ALGORITHM_H264: {
|
|
|
|
|
|
if (Decode((LPBYTE)NextScreenData, NextScreenLength)) {
|
|
|
|
|
|
bChange = TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-03-13 23:34:33 +08:00
|
|
|
|
|
|
|
|
|
|
#if SCREENSPY_WRITE
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (!WriteBitmap(m_BitmapInfor_Full, m_BitmapData_Full, "YAMA", frameID)) {
|
|
|
|
|
|
TRACE("WriteBitmap [%d] failed!!!\n", frameID);
|
|
|
|
|
|
}
|
2025-03-13 23:34:33 +08:00
|
|
|
|
#endif
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-11-23 10:57:52 +01:00
|
|
|
|
if (bChange && !m_bHide) {
|
2025-10-15 04:32:59 +08:00
|
|
|
|
PostMessage(WM_PAINT);
|
|
|
|
|
|
}
|
2025-03-30 18:03:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
bool CScreenSpyDlg::Decode(LPBYTE Buffer, int size)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 解码数据.
|
|
|
|
|
|
av_init_packet(&m_AVPacket);
|
|
|
|
|
|
|
|
|
|
|
|
m_AVPacket.data = (uint8_t*)Buffer;
|
|
|
|
|
|
m_AVPacket.size = size;
|
|
|
|
|
|
|
|
|
|
|
|
int err = avcodec_send_packet(m_pCodecContext, &m_AVPacket);
|
|
|
|
|
|
if (!err) {
|
|
|
|
|
|
err = avcodec_receive_frame(m_pCodecContext, &m_AVFrame);
|
|
|
|
|
|
if (err == AVERROR(EAGAIN)) {
|
|
|
|
|
|
Mprintf("avcodec_receive_frame error: EAGAIN\n");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解码数据前会清除m_AVFrame的内容.
|
|
|
|
|
|
if (!err) {
|
|
|
|
|
|
LPVOID Image[2] = { 0 };
|
|
|
|
|
|
LPVOID CursorInfo[2] = { 0 };
|
|
|
|
|
|
//成功.
|
|
|
|
|
|
//I420 ---> ARGB.
|
|
|
|
|
|
//WaitForSingleObject(m_hMutex,INFINITE);
|
|
|
|
|
|
|
|
|
|
|
|
libyuv::I420ToARGB(
|
|
|
|
|
|
m_AVFrame.data[0], m_AVFrame.linesize[0],
|
|
|
|
|
|
m_AVFrame.data[1], m_AVFrame.linesize[1],
|
|
|
|
|
|
m_AVFrame.data[2], m_AVFrame.linesize[2],
|
|
|
|
|
|
(uint8_t*)m_BitmapData_Full,
|
|
|
|
|
|
m_BitmapInfor_Full->bmiHeader.biWidth*4,
|
|
|
|
|
|
m_BitmapInfor_Full->bmiHeader.biWidth,
|
|
|
|
|
|
m_BitmapInfor_Full->bmiHeader.biHeight);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
Mprintf("avcodec_receive_frame failed with error: %d\n", err);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Mprintf("avcodec_send_packet failed with error: %d\n", err);
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
void CScreenSpyDlg::OnPaint()
|
|
|
|
|
|
{
|
|
|
|
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
|
|
|
|
|
|
|
|
if (m_bIsFirst) {
|
|
|
|
|
|
DrawTipString("请等待......");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_bAdaptiveSize ?
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
if (m_bIsTraceCursor)
|
|
|
|
|
|
DrawIconEx(
|
|
|
|
|
|
m_hFullDC,
|
|
|
|
|
|
m_ClientCursorPos.x - m_ulHScrollPos,
|
|
|
|
|
|
m_ClientCursorPos.y - m_ulVScrollPos,
|
|
|
|
|
|
m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex),
|
|
|
|
|
|
0,0,
|
|
|
|
|
|
0,
|
|
|
|
|
|
NULL,
|
|
|
|
|
|
DI_NORMAL | DI_COMPAT
|
|
|
|
|
|
);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID CScreenSpyDlg::DrawTipString(CString strString)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
RECT Rect;
|
|
|
|
|
|
GetClientRect(&Rect);
|
|
|
|
|
|
//COLORREF用来描绘一个RGB颜色
|
|
|
|
|
|
COLORREF BackgroundColor = RGB(0x00, 0x00, 0x00);
|
|
|
|
|
|
COLORREF OldBackgroundColor = SetBkColor(m_hFullDC, BackgroundColor);
|
|
|
|
|
|
COLORREF OldTextColor = SetTextColor(m_hFullDC, RGB(0xff,0x00,0x00));
|
|
|
|
|
|
//ExtTextOut函数可以提供一个可供选择的矩形,用当前选择的字体、背景颜色和正文颜色来绘制一个字符串
|
|
|
|
|
|
ExtTextOut(m_hFullDC, 0, 0, ETO_OPAQUE, &Rect, NULL, 0, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
DrawText (m_hFullDC, strString, -1, &Rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER);
|
|
|
|
|
|
|
|
|
|
|
|
SetBkColor(m_hFullDC, BackgroundColor);
|
|
|
|
|
|
SetTextColor(m_hFullDC, OldBackgroundColor);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-29 23:22:55 +01:00
|
|
|
|
bool DirectoryExists(const char* path)
|
|
|
|
|
|
{
|
|
|
|
|
|
DWORD attr = GetFileAttributesA(path);
|
|
|
|
|
|
return (attr != INVALID_FILE_ATTRIBUTES &&
|
|
|
|
|
|
(attr & FILE_ATTRIBUTE_DIRECTORY));
|
2025-11-23 10:57:52 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-29 23:22:55 +01:00
|
|
|
|
std::string GetScreenShotPath(CWnd *parent, const CString& ip, const CString &filter, const CString& suffix)
|
|
|
|
|
|
{
|
2025-11-23 10:57:52 +01:00
|
|
|
|
std::string path;
|
2025-11-29 23:22:55 +01:00
|
|
|
|
std::string folder = THIS_CFG.GetStr("settings", "ScreenShot", "");
|
|
|
|
|
|
if (folder.empty() || !DirectoryExists(folder.c_str())) {
|
|
|
|
|
|
CString strFileName = ip + CTime::GetCurrentTime().Format(_T("_%Y%m%d%H%M%S.")) + suffix;
|
|
|
|
|
|
CFileDialog dlg(FALSE, suffix, strFileName, OFN_OVERWRITEPROMPT, filter, parent);
|
|
|
|
|
|
if (dlg.DoModal() != IDOK)
|
|
|
|
|
|
return "";
|
|
|
|
|
|
folder = dlg.GetFolderPath();
|
|
|
|
|
|
if (!folder.empty() && folder.back() != '\\') {
|
|
|
|
|
|
folder += '\\';
|
|
|
|
|
|
}
|
|
|
|
|
|
path = dlg.GetPathName();
|
|
|
|
|
|
THIS_CFG.SetStr("settings", "ScreenShot", folder);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (!folder.empty() && folder.back() != '\\') {
|
|
|
|
|
|
folder += '\\';
|
|
|
|
|
|
}
|
|
|
|
|
|
path = folder + std::string(ip) + "_" + ToPekingDateTime(0) + "." + std::string(suffix);
|
|
|
|
|
|
}
|
2025-11-23 10:57:52 +01:00
|
|
|
|
return path;
|
|
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// TODO: 在此添加消息处理程序代码和/或调用默认值
|
|
|
|
|
|
CMenu* SysMenu = GetSystemMenu(FALSE);
|
|
|
|
|
|
|
|
|
|
|
|
switch (nID) {
|
|
|
|
|
|
case IDM_CONTROL: {
|
|
|
|
|
|
m_bIsCtrl = !m_bIsCtrl;
|
|
|
|
|
|
SysMenu->CheckMenuItem(IDM_CONTROL, m_bIsCtrl ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
|
|
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO));
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case IDM_FULLSCREEN: { // 全屏
|
|
|
|
|
|
EnterFullScreen();
|
|
|
|
|
|
SysMenu->CheckMenuItem(IDM_FULLSCREEN, MF_CHECKED); //菜单样式
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case IDM_SAVEDIB: { // 快照保存
|
|
|
|
|
|
SaveSnapshot();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-11-29 23:22:55 +01:00
|
|
|
|
case IDM_SAVEAVI:
|
|
|
|
|
|
case IDM_SAVEAVI_H264: {
|
|
|
|
|
|
if (SysMenu->GetMenuState(nID, MF_BYCOMMAND) & MF_CHECKED) {
|
|
|
|
|
|
KillTimer(TIMER_ID);
|
|
|
|
|
|
SysMenu->CheckMenuItem(nID, MF_UNCHECKED);
|
|
|
|
|
|
SysMenu->EnableMenuItem(IDM_SAVEAVI, MF_ENABLED);
|
|
|
|
|
|
SysMenu->EnableMenuItem(IDM_SAVEAVI_H264, MF_ENABLED);
|
|
|
|
|
|
m_aviFile = "";
|
|
|
|
|
|
m_aviStream.Close();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-11-23 10:57:52 +01:00
|
|
|
|
m_aviFile = GetScreenShotPath(this, m_IPAddress, "Video(*.avi)|*.avi|", "avi").c_str();
|
|
|
|
|
|
const int duration = 250, rate = 1000 / duration;
|
|
|
|
|
|
FCCHandler handler = nID == IDM_SAVEAVI ? ENCODER_MJPEG : ENCODER_H264;
|
|
|
|
|
|
int code;
|
2025-11-29 23:22:55 +01:00
|
|
|
|
if (code = m_aviStream.Open(m_aviFile, m_BitmapInfor_Full, rate, handler)) {
|
|
|
|
|
|
MessageBox(CString("Create Video(*.avi) Failed:\n") + m_aviFile + "\r\n错误代码: " +
|
|
|
|
|
|
CBmpToAvi::GetErrMsg(code).c_str(), "提示");
|
|
|
|
|
|
m_aviFile = _T("");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
::SetTimer(m_hWnd, TIMER_ID, duration, NULL);
|
|
|
|
|
|
SysMenu->CheckMenuItem(nID, MF_CHECKED);
|
2025-11-23 10:57:52 +01:00
|
|
|
|
SysMenu->EnableMenuItem(nID == IDM_SAVEAVI ? IDM_SAVEAVI_H264 : IDM_SAVEAVI, MF_DISABLED);
|
2025-11-29 23:22:55 +01:00
|
|
|
|
}
|
2025-11-23 10:57:52 +01:00
|
|
|
|
break;
|
2025-11-29 23:22:55 +01:00
|
|
|
|
}
|
2025-11-28 20:53:28 +01:00
|
|
|
|
|
|
|
|
|
|
case IDM_SWITCHSCREEN: {
|
|
|
|
|
|
BYTE bToken[2] = { COMMAND_SWITCH_SCREEN };
|
2025-11-29 23:22:55 +01:00
|
|
|
|
m_ContextObject->Send2Client(bToken, sizeof(bToken));
|
2025-11-28 20:53:28 +01:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-29 23:22:55 +01:00
|
|
|
|
case IDM_MULTITHREAD_COMPRESS: {
|
2025-11-30 08:02:44 +01:00
|
|
|
|
static int threadNum = 0;
|
|
|
|
|
|
threadNum = 4 - threadNum;
|
2025-11-29 23:22:55 +01:00
|
|
|
|
BYTE bToken[2] = { CMD_MULTITHREAD_COMPRESS, (BYTE)threadNum };
|
|
|
|
|
|
m_ContextObject->Send2Client(bToken, sizeof(bToken));
|
2025-11-30 08:02:44 +01:00
|
|
|
|
SysMenu->CheckMenuItem(nID, threadNum ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
|
|
break;
|
2025-12-28 21:25:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
case IDM_FPS_10: case IDM_FPS_15: case IDM_FPS_20:
|
|
|
|
|
|
case IDM_FPS_25: case IDM_FPS_30: case IDM_FPS_UNLIMITED: {
|
|
|
|
|
|
int fps = 10 + (nID - IDM_FPS_10) * 5;
|
|
|
|
|
|
BYTE bToken[2] = { CMD_FPS, nID == IDM_FPS_UNLIMITED ? 255 : fps };
|
|
|
|
|
|
m_ContextObject->Send2Client(bToken, sizeof(bToken));
|
|
|
|
|
|
break;
|
2025-11-30 08:02:44 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
case IDM_TRACE_CURSOR: { // 跟踪被控端鼠标
|
|
|
|
|
|
m_bIsTraceCursor = !m_bIsTraceCursor; //这里在改变数据
|
|
|
|
|
|
SysMenu->CheckMenuItem(IDM_TRACE_CURSOR, m_bIsTraceCursor ? MF_CHECKED : MF_UNCHECKED);//在菜单打钩不打钩
|
|
|
|
|
|
m_bAdaptiveSize = !m_bIsTraceCursor;
|
|
|
|
|
|
ShowScrollBar(SB_BOTH, !m_bAdaptiveSize);
|
|
|
|
|
|
// 重绘消除或显示鼠标
|
|
|
|
|
|
OnPaint();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case IDM_BLOCK_INPUT: { // 锁定服务端鼠标和键盘
|
|
|
|
|
|
BOOL bIsChecked = SysMenu->GetMenuState(IDM_BLOCK_INPUT, MF_BYCOMMAND) & MF_CHECKED;
|
|
|
|
|
|
SysMenu->CheckMenuItem(IDM_BLOCK_INPUT, bIsChecked ? MF_UNCHECKED : MF_CHECKED);
|
|
|
|
|
|
|
|
|
|
|
|
BYTE bToken[2];
|
|
|
|
|
|
bToken[0] = COMMAND_SCREEN_BLOCK_INPUT;
|
|
|
|
|
|
bToken[1] = !bIsChecked;
|
|
|
|
|
|
m_ContextObject->Send2Client(bToken, sizeof(bToken));
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case IDM_GET_CLIPBOARD: { //想要Client的剪贴板内容
|
|
|
|
|
|
BYTE bToken = COMMAND_SCREEN_GET_CLIPBOARD;
|
|
|
|
|
|
m_ContextObject->Send2Client(&bToken, sizeof(bToken));
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case IDM_SET_CLIPBOARD: { //给他
|
|
|
|
|
|
SendServerClipboard();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case IDM_ADAPTIVE_SIZE: {
|
|
|
|
|
|
m_bAdaptiveSize = !m_bAdaptiveSize;
|
|
|
|
|
|
ShowScrollBar(SB_BOTH, !m_bAdaptiveSize);
|
|
|
|
|
|
SysMenu->CheckMenuItem(IDM_ADAPTIVE_SIZE, m_bAdaptiveSize ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CDialog::OnSysCommand(nID, lParam);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-23 10:57:52 +01:00
|
|
|
|
void CScreenSpyDlg::OnTimer(UINT_PTR nIDEvent)
|
|
|
|
|
|
{
|
2025-11-29 23:22:55 +01:00
|
|
|
|
if (!m_aviFile.IsEmpty()) {
|
|
|
|
|
|
LPCTSTR lpTipsString = _T("●");
|
2025-11-23 10:57:52 +01:00
|
|
|
|
|
2025-11-29 23:22:55 +01:00
|
|
|
|
m_aviStream.Write((BYTE*)m_BitmapData_Full);
|
2025-11-23 10:57:52 +01:00
|
|
|
|
|
2025-11-29 23:22:55 +01:00
|
|
|
|
// 提示正在录像
|
|
|
|
|
|
SetTextColor(m_hFullDC, RGB(0xff, 0x00, 0x00));
|
|
|
|
|
|
TextOut(m_hFullDC, 0, 0, lpTipsString, lstrlen(lpTipsString));
|
|
|
|
|
|
}
|
2025-12-22 23:01:19 +01:00
|
|
|
|
if (nIDEvent == 1 && m_bFullScreen && m_pToolbar) {
|
|
|
|
|
|
m_pToolbar->CheckMousePosition();
|
|
|
|
|
|
}
|
2025-11-29 23:22:55 +01:00
|
|
|
|
CDialog::OnTimer(nIDEvent);
|
2025-11-23 10:57:52 +01:00
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
|
|
|
|
|
BOOL CScreenSpyDlg::PreTranslateMessage(MSG* pMsg)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
#define MAKEDWORD(h,l) (((unsigned long)h << 16) | l)
|
|
|
|
|
|
switch (pMsg->message) {
|
|
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
|
|
case WM_LBUTTONUP:
|
|
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
|
|
case WM_RBUTTONUP:
|
|
|
|
|
|
case WM_LBUTTONDBLCLK:
|
|
|
|
|
|
case WM_RBUTTONDBLCLK:
|
|
|
|
|
|
case WM_MBUTTONDBLCLK:
|
|
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
|
|
case WM_MBUTTONUP:
|
|
|
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
|
|
case WM_MOUSEWHEEL: {
|
|
|
|
|
|
SendScaledMouseMessage(pMsg, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
|
|
case WM_KEYUP:
|
|
|
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
|
|
case WM_SYSKEYUP:
|
2025-12-22 23:01:19 +01:00
|
|
|
|
if (pMsg->message == WM_KEYDOWN && m_bFullScreen) {
|
|
|
|
|
|
// Ctrl+Alt+Home 退出全屏(备用)
|
|
|
|
|
|
if (pMsg->wParam == VK_HOME &&
|
|
|
|
|
|
(GetKeyState(VK_CONTROL) & 0x8000) &&
|
|
|
|
|
|
(GetKeyState(VK_MENU) & 0x8000)) {
|
|
|
|
|
|
LeaveFullScreen();
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (pMsg->wParam != VK_LWIN && pMsg->wParam != VK_RWIN) {
|
|
|
|
|
|
SendScaledMouseMessage(pMsg, true);
|
|
|
|
|
|
}
|
2025-12-25 18:49:10 +01:00
|
|
|
|
if (pMsg->message == WM_SYSKEYDOWN && pMsg->wParam == VK_F4) {
|
|
|
|
|
|
return TRUE; // 屏蔽 Alt + F4
|
|
|
|
|
|
}
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
|
|
|
|
|
|
return TRUE;// 屏蔽Enter和ESC关闭对话
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return CDialog::PreTranslateMessage(pMsg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::SendScaledMouseMessage(MSG* pMsg, bool makeLP)
|
|
|
|
|
|
{
|
2025-12-24 09:24:15 +01:00
|
|
|
|
if (!m_bIsCtrl || !m_bConnected)
|
2025-10-15 04:32:59 +08:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
MYMSG msg(*pMsg);
|
|
|
|
|
|
LONG x = LOWORD(pMsg->lParam), y = HIWORD(pMsg->lParam);
|
|
|
|
|
|
LONG low = m_bAdaptiveSize ? x * m_wZoom : x + m_ulHScrollPos;
|
|
|
|
|
|
LONG high = m_bAdaptiveSize ? y * m_hZoom : y + m_ulVScrollPos;
|
|
|
|
|
|
if (makeLP) msg.lParam = MAKELPARAM(low, high);
|
|
|
|
|
|
msg.pt.x = low;
|
|
|
|
|
|
msg.pt.y = high;
|
|
|
|
|
|
SendCommand(&msg);
|
2025-07-20 20:59:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID CScreenSpyDlg::SendCommand(const MYMSG* Msg)
|
2019-01-05 20:21:43 +08:00
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (!m_bIsCtrl)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (Msg->message == WM_MOUSEMOVE) {
|
|
|
|
|
|
auto now = clock();
|
|
|
|
|
|
auto time_elapsed = now - m_lastMouseMove;
|
|
|
|
|
|
int dx = abs(Msg->pt.x - m_lastMousePoint.x);
|
|
|
|
|
|
int dy = abs(Msg->pt.y - m_lastMousePoint.y);
|
|
|
|
|
|
int dist_sq = dx * dx + dy * dy;
|
2026-01-02 12:12:35 +01:00
|
|
|
|
|
|
|
|
|
|
bool fastMove = dist_sq > 50 * 50;
|
|
|
|
|
|
int minInterval = fastMove ? 33 : 16;
|
|
|
|
|
|
int minDistSq = fastMove ? 10 * 10 : 3 * 3;
|
|
|
|
|
|
if (time_elapsed < minInterval && dist_sq < minDistSq) {
|
2025-10-15 04:32:59 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_lastMouseMove = now;
|
|
|
|
|
|
m_lastMousePoint = Msg->pt;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const int length = sizeof(MSG64) + 1;
|
|
|
|
|
|
BYTE szData[length + 3];
|
|
|
|
|
|
szData[0] = COMMAND_SCREEN_CONTROL;
|
|
|
|
|
|
memcpy(szData + 1, Msg, sizeof(MSG64));
|
|
|
|
|
|
szData[length] = 0;
|
|
|
|
|
|
m_ContextObject->Send2Client(szData, length);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CScreenSpyDlg::SaveSnapshot(void)
|
|
|
|
|
|
{
|
2025-11-23 10:57:52 +01:00
|
|
|
|
auto path = GetScreenShotPath(this, m_IPAddress, "位图文件(*.bmp)|*.bmp|", "bmp");
|
|
|
|
|
|
if (path.empty())
|
2025-10-15 04:32:59 +08:00
|
|
|
|
return FALSE;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-11-23 10:57:52 +01:00
|
|
|
|
WriteBitmap(m_BitmapInfor_Full, m_BitmapData_Full, path.c_str());
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
return true;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-12-12 14:36:32 +01:00
|
|
|
|
VOID CScreenSpyDlg::UpdateServerClipboard(char* szBuffer, ULONG ulLength)
|
|
|
|
|
|
{
|
2025-12-21 00:27:40 +01:00
|
|
|
|
if (!::OpenClipboard(NULL))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
::EmptyClipboard();
|
|
|
|
|
|
|
|
|
|
|
|
// UTF-8 转 Unicode
|
|
|
|
|
|
int wlen = MultiByteToWideChar(CP_UTF8, 0, szBuffer, ulLength, nullptr, 0);
|
|
|
|
|
|
if (wlen > 0) {
|
|
|
|
|
|
// 分配 Unicode 缓冲区(+1 确保 null 结尾)
|
|
|
|
|
|
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, (wlen + 1) * sizeof(wchar_t));
|
|
|
|
|
|
if (hGlobal != NULL) {
|
|
|
|
|
|
wchar_t* pWideStr = (wchar_t*)GlobalLock(hGlobal);
|
|
|
|
|
|
if (pWideStr) {
|
|
|
|
|
|
MultiByteToWideChar(CP_UTF8, 0, szBuffer, ulLength, pWideStr, wlen);
|
|
|
|
|
|
pWideStr[wlen] = L'\0'; // 确保 null 结尾
|
|
|
|
|
|
GlobalUnlock(hGlobal);
|
|
|
|
|
|
|
|
|
|
|
|
if (SetClipboardData(CF_UNICODETEXT, hGlobal) == NULL) {
|
|
|
|
|
|
GlobalFree(hGlobal);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
GlobalFree(hGlobal);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CloseClipboard();
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID CScreenSpyDlg::SendServerClipboard(void)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (!::OpenClipboard(NULL)) //打开剪切板设备
|
|
|
|
|
|
return;
|
|
|
|
|
|
HGLOBAL hGlobal = GetClipboardData(CF_TEXT); //代表着一个内存
|
|
|
|
|
|
if (hGlobal == NULL) {
|
|
|
|
|
|
::CloseClipboard();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
int iPacketLength = GlobalSize(hGlobal) + 1;
|
|
|
|
|
|
char* szClipboardVirtualAddress = (LPSTR) GlobalLock(hGlobal); //锁定
|
|
|
|
|
|
LPBYTE szBuffer = new BYTE[iPacketLength];
|
|
|
|
|
|
|
|
|
|
|
|
szBuffer[0] = COMMAND_SCREEN_SET_CLIPBOARD;
|
|
|
|
|
|
memcpy(szBuffer + 1, szClipboardVirtualAddress, iPacketLength - 1);
|
|
|
|
|
|
::GlobalUnlock(hGlobal);
|
|
|
|
|
|
::CloseClipboard();
|
|
|
|
|
|
m_ContextObject->Send2Client((PBYTE)szBuffer, iPacketLength);
|
|
|
|
|
|
delete[] szBuffer;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
2019-01-10 19:35:03 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (m_bAdaptiveSize) return;
|
|
|
|
|
|
|
|
|
|
|
|
SCROLLINFO si = {sizeof(si)};
|
|
|
|
|
|
si.fMask = SIF_ALL;
|
|
|
|
|
|
GetScrollInfo(SB_HORZ, &si);
|
|
|
|
|
|
|
|
|
|
|
|
int nPrevPos = si.nPos;
|
|
|
|
|
|
switch(nSBCode) {
|
|
|
|
|
|
case SB_LEFT:
|
|
|
|
|
|
si.nPos = si.nMin;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_RIGHT:
|
|
|
|
|
|
si.nPos = si.nMax;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_LINELEFT:
|
|
|
|
|
|
si.nPos -= 8;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_LINERIGHT:
|
|
|
|
|
|
si.nPos += 8;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_PAGELEFT:
|
|
|
|
|
|
si.nPos -= si.nPage;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_PAGERIGHT:
|
|
|
|
|
|
si.nPos += si.nPage;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_THUMBTRACK:
|
|
|
|
|
|
si.nPos = si.nTrackPos;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
si.fMask = SIF_POS;
|
|
|
|
|
|
SetScrollInfo(SB_HORZ, &si, TRUE);
|
|
|
|
|
|
if (si.nPos != nPrevPos) {
|
|
|
|
|
|
m_ulHScrollPos += si.nPos - nPrevPos;
|
|
|
|
|
|
ScrollWindow(nPrevPos - si.nPos, 0, NULL, NULL);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CDialog::OnHScroll(nSBCode, nPrevPos, pScrollBar);
|
2019-01-10 19:35:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (m_bAdaptiveSize) return;
|
|
|
|
|
|
|
|
|
|
|
|
SCROLLINFO si = {sizeof(si)};
|
|
|
|
|
|
si.fMask = SIF_ALL;
|
|
|
|
|
|
GetScrollInfo(SB_VERT, &si);
|
|
|
|
|
|
|
|
|
|
|
|
int nPrevPos = si.nPos;
|
|
|
|
|
|
switch(nSBCode) {
|
|
|
|
|
|
case SB_TOP:
|
|
|
|
|
|
si.nPos = si.nMin;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_BOTTOM:
|
|
|
|
|
|
si.nPos = si.nMax;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_LINEUP:
|
|
|
|
|
|
si.nPos -= 8;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_LINEDOWN:
|
|
|
|
|
|
si.nPos += 8;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_PAGEUP:
|
|
|
|
|
|
si.nPos -= si.nPage;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_PAGEDOWN:
|
|
|
|
|
|
si.nPos += si.nPage;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SB_THUMBTRACK:
|
|
|
|
|
|
si.nPos = si.nTrackPos;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
si.fMask = SIF_POS;
|
|
|
|
|
|
SetScrollInfo(SB_VERT, &si, TRUE);
|
|
|
|
|
|
if (si.nPos != nPrevPos) {
|
|
|
|
|
|
m_ulVScrollPos += si.nPos - nPrevPos;
|
|
|
|
|
|
ScrollWindow(0, nPrevPos - si.nPos, NULL, NULL);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CDialog::OnVScroll(nSBCode, nPrevPos, pScrollBar);
|
2019-01-10 19:35:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::EnterFullScreen()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (!m_bFullScreen) {
|
|
|
|
|
|
// 1. 获取鼠标位置
|
|
|
|
|
|
POINT pt;
|
|
|
|
|
|
GetCursorPos(&pt);
|
2025-08-02 14:50:38 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// 2. 获取鼠标所在显示器
|
|
|
|
|
|
HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
|
|
|
|
|
|
MONITORINFO mi = { sizeof(mi) };
|
|
|
|
|
|
if (!GetMonitorInfo(hMonitor, &mi))
|
|
|
|
|
|
return;
|
2025-08-02 14:50:38 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
RECT rcMonitor = mi.rcMonitor;
|
2019-01-10 19:35:03 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// 3. 记录当前窗口状态
|
|
|
|
|
|
GetWindowPlacement(&m_struOldWndpl);
|
2019-01-10 19:35:03 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// 4. 修改窗口样式,移除标题栏、边框
|
|
|
|
|
|
LONG lStyle = GetWindowLong(m_hWnd, GWL_STYLE);
|
|
|
|
|
|
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_BORDER);
|
|
|
|
|
|
SetWindowLong(m_hWnd, GWL_STYLE, lStyle);
|
2025-03-30 18:03:01 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// 5. 隐藏滚动条
|
|
|
|
|
|
ShowScrollBar(SB_BOTH, !m_bAdaptiveSize); // 隐藏水平和垂直滚动条
|
2025-03-30 18:03:01 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// 6. 重新调整窗口大小并更新
|
|
|
|
|
|
SetWindowPos(&CWnd::wndTop, rcMonitor.left, rcMonitor.top, rcMonitor.right - rcMonitor.left,
|
|
|
|
|
|
rcMonitor.bottom - rcMonitor.top, SWP_NOZORDER | SWP_FRAMECHANGED);
|
2025-03-30 18:03:01 +08:00
|
|
|
|
|
2025-12-22 23:01:19 +01:00
|
|
|
|
if (!m_pToolbar) {
|
|
|
|
|
|
m_pToolbar = new CToolbarDlg(this);
|
|
|
|
|
|
m_pToolbar->Create(IDD_TOOLBAR_DLG, this);
|
|
|
|
|
|
int cx = GetSystemMetrics(SM_CXSCREEN);
|
|
|
|
|
|
int cy = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
|
|
m_pToolbar->SetWindowPos(&wndTopMost, 0, -40, cx, 40, SWP_HIDEWINDOW);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// 7. 标记全屏模式
|
|
|
|
|
|
m_bFullScreen = true;
|
2025-12-22 23:01:19 +01:00
|
|
|
|
|
2025-12-25 18:49:10 +01:00
|
|
|
|
SetTimer(1, 50, NULL);
|
2025-10-15 04:32:59 +08:00
|
|
|
|
}
|
2019-01-10 19:35:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-26 17:07:43 +08:00
|
|
|
|
// 全屏退出成功则返回true
|
2019-01-20 20:04:11 +08:00
|
|
|
|
bool CScreenSpyDlg::LeaveFullScreen()
|
2019-01-10 19:35:03 +08:00
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (m_bFullScreen) {
|
2025-12-22 23:01:19 +01:00
|
|
|
|
KillTimer(1);
|
|
|
|
|
|
if (m_pToolbar) {
|
|
|
|
|
|
m_pToolbar->DestroyWindow();
|
|
|
|
|
|
delete m_pToolbar;
|
|
|
|
|
|
m_pToolbar = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// 1. 恢复窗口样式
|
|
|
|
|
|
LONG lStyle = GetWindowLong(m_hWnd, GWL_STYLE);
|
|
|
|
|
|
lStyle |= (WS_CAPTION | WS_THICKFRAME | WS_BORDER);
|
|
|
|
|
|
SetWindowLong(m_hWnd, GWL_STYLE, lStyle);
|
2025-03-30 18:03:01 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// 2. 恢复窗口大小
|
|
|
|
|
|
SetWindowPlacement(&m_struOldWndpl);
|
|
|
|
|
|
SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
2025-03-30 18:03:01 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// 3. 显示滚动条
|
|
|
|
|
|
ShowScrollBar(SB_BOTH, !m_bAdaptiveSize); // 显示水平和垂直滚动条
|
2025-03-30 18:03:01 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// 4. 标记退出全屏
|
|
|
|
|
|
m_bFullScreen = false;
|
2025-03-30 18:03:01 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CMenu* SysMenu = GetSystemMenu(FALSE);
|
|
|
|
|
|
SysMenu->CheckMenuItem(IDM_FULLSCREEN, MF_UNCHECKED); //菜单样式
|
2025-03-30 18:03:01 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
2019-01-10 19:35:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::OnLButtonDown(UINT nFlags, CPoint point)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CDialog::OnLButtonDown(nFlags, point);
|
2019-01-10 19:35:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::OnLButtonUp(UINT nFlags, CPoint point)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CDialog::OnLButtonUp(nFlags, point);
|
2019-01-10 19:35:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CScreenSpyDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
return CDialog::OnMouseWheel(nFlags, zDelta, pt);
|
2019-01-10 19:35:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::OnMouseMove(UINT nFlags, CPoint point)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (!m_bMouseTracking) {
|
|
|
|
|
|
m_bMouseTracking = true;
|
|
|
|
|
|
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO));
|
|
|
|
|
|
}
|
2025-08-02 17:24:17 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CDialog::OnMouseMove(nFlags, point);
|
2019-01-10 19:35:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-02 17:24:17 +08:00
|
|
|
|
void CScreenSpyDlg::OnMouseLeave()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CWnd::OnMouseLeave();
|
2025-08-02 17:24:17 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_bMouseTracking = false;
|
|
|
|
|
|
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO));
|
2025-08-02 17:24:17 +08:00
|
|
|
|
}
|
2019-01-10 19:35:03 +08:00
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::OnKillFocus(CWnd* pNewWnd)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CDialog::OnKillFocus(pNewWnd);
|
2019-01-10 19:35:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::OnSize(UINT nType, int cx, int cy)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CDialog::OnSize(nType, cx, cy);
|
2025-07-20 20:59:16 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
// TODO: Add your message handler code here
|
|
|
|
|
|
if (!IsWindowVisible())
|
|
|
|
|
|
return;
|
2025-07-20 20:59:16 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
GetClientRect(&m_CRect);
|
|
|
|
|
|
m_wZoom = ((double)m_BitmapInfor_Full->bmiHeader.biWidth) / ((double)(m_CRect.Width()));
|
|
|
|
|
|
m_hZoom = ((double)m_BitmapInfor_Full->bmiHeader.biHeight) / ((double)(m_CRect.Height()));
|
2019-01-10 19:35:03 +08:00
|
|
|
|
}
|
2025-10-20 03:56:54 +08:00
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
|
|
|
|
|
|
{
|
2025-11-09 00:49:34 +08:00
|
|
|
|
CDialogBase::OnActivate(nState, pWndOther, bMinimized);
|
2025-10-20 03:56:54 +08:00
|
|
|
|
|
2025-11-09 00:49:34 +08:00
|
|
|
|
CWnd* pMain = AfxGetMainWnd();
|
|
|
|
|
|
if (!pMain)
|
|
|
|
|
|
return;
|
2025-10-20 03:56:54 +08:00
|
|
|
|
|
2025-11-09 00:49:34 +08:00
|
|
|
|
if (nState != WA_INACTIVE) {
|
|
|
|
|
|
// 通知主窗口:远程窗口获得焦点
|
|
|
|
|
|
::PostMessage(pMain->GetSafeHwnd(), WM_SESSION_ACTIVATED, (WPARAM)this, 0);
|
|
|
|
|
|
}
|
2025-10-20 03:56:54 +08:00
|
|
|
|
}
|
2025-12-23 15:16:01 +01:00
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::UpdateCtrlStatus(BOOL ctrl) {
|
|
|
|
|
|
m_bIsCtrl = ctrl;
|
|
|
|
|
|
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO));
|
|
|
|
|
|
}
|
2025-12-26 19:35:10 +01:00
|
|
|
|
|
|
|
|
|
|
// 将多个路径组合成单\0分隔的char数组
|
|
|
|
|
|
// 格式: "path1\0path2\0path3\0"
|
|
|
|
|
|
std::vector<char> BuildMultiStringPath(const std::vector<std::string>& paths)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::vector<char> result;
|
|
|
|
|
|
|
|
|
|
|
|
for (const auto& path : paths)
|
|
|
|
|
|
{
|
|
|
|
|
|
result.insert(result.end(), path.begin(), path.end());
|
|
|
|
|
|
result.push_back('\0');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CScreenSpyDlg::OnDropFiles(HDROP hDropInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_bIsCtrl && m_bConnected) {
|
|
|
|
|
|
UINT nFiles = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);
|
|
|
|
|
|
std::vector<std::string> list;
|
|
|
|
|
|
for (UINT i = 0; i < nFiles; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
|
|
DragQueryFile(hDropInfo, i, szPath, MAX_PATH);
|
|
|
|
|
|
list.push_back(szPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
std::string GetPwdHash();
|
|
|
|
|
|
std::string GetHMAC(int offset);
|
|
|
|
|
|
auto files = PreprocessFilesSimple(list);
|
|
|
|
|
|
auto str = BuildMultiStringPath(files);
|
|
|
|
|
|
BYTE* szBuffer = new BYTE[1 + 80 + str.size()];
|
|
|
|
|
|
szBuffer[0] = { COMMAND_GET_FOLDER };
|
|
|
|
|
|
std::string masterId = GetPwdHash(), hmac = GetHMAC(100);
|
|
|
|
|
|
memcpy((char*)szBuffer + 1, masterId.c_str(), masterId.length());
|
|
|
|
|
|
memcpy((char*)szBuffer + 1 + masterId.length(), hmac.c_str(), hmac.length());
|
|
|
|
|
|
memcpy(szBuffer + 1 + 80, str.data(), str.size());
|
2025-12-28 14:39:52 +01:00
|
|
|
|
auto md5 = CalcMD5FromBytes((BYTE*)str.data(), str.size());
|
|
|
|
|
|
m_pParent->m_CmdList.PutCmd(md5);
|
2025-12-26 19:35:10 +01:00
|
|
|
|
m_ContextObject->Send2Client(szBuffer, 81 + str.size());
|
2025-12-28 14:39:52 +01:00
|
|
|
|
Mprintf("【Ctrl+V】 从本地拖拽文件到远程: %s \n", md5.c_str());
|
2025-12-26 19:35:10 +01:00
|
|
|
|
SAFE_DELETE_ARRAY(szBuffer);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DragFinish(hDropInfo);
|
|
|
|
|
|
|
|
|
|
|
|
CDialogBase::OnDropFiles(hDropInfo);
|
|
|
|
|
|
}
|