Files
SimpleRemoter/server/2015Remote/ScreenSpyDlg.cpp

865 lines
22 KiB
C++
Raw Normal View History

// ScreenSpyDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "2015Remote.h"
#include "ScreenSpyDlg.h"
#include "afxdialogex.h"
#include <imm.h>
2025-02-06 03:34:57 +08:00
#include <WinUser.h>
// CScreenSpyDlg 对话框
enum
{
IDM_CONTROL = 0x1010,
2019-01-10 19:35:03 +08:00
IDM_FULLSCREEN,
IDM_SEND_CTRL_ALT_DEL,
IDM_TRACE_CURSOR, // 跟踪显示远程鼠标
IDM_BLOCK_INPUT, // 锁定远程计算机输入
IDM_SAVEDIB, // 保存图片
IDM_GET_CLIPBOARD, // 获取剪贴板
IDM_SET_CLIPBOARD, // 设置剪贴板
IDM_ADAPTIVE_SIZE,
};
IMPLEMENT_DYNAMIC(CScreenSpyDlg, CDialog)
#define ALGORITHM_DIFF 1
extern "C" void* x265_api_get_192() { return nullptr; }
extern "C" char* __imp_strtok(char* str, const char* delim) { return strtok(str, delim); }
CScreenSpyDlg::CScreenSpyDlg(CWnd* Parent, Server* IOCPServer, CONTEXT_OBJECT* ContextObject)
: DialogBase(CScreenSpyDlg::IDD, Parent, IOCPServer, ContextObject, 0)
{
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);// 禁用输入法
2019-01-10 19:35:03 +08:00
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;
ULONG ulBitmapInforLength = m_ContextObject->InDeCompressedBuffer.GetBufferLength() - 1;
m_BitmapInfor_Full = (BITMAPINFO *) new BYTE[ulBitmapInforLength];
m_ContextObject->InDeCompressedBuffer.CopyBuffer(m_BitmapInfor_Full, ulBitmapInforLength, 1);
m_bIsCtrl = FALSE;
m_bIsTraceCursor = FALSE;
}
VOID CScreenSpyDlg::SendNext(void)
{
BYTE bToken = COMMAND_NEXT;
m_ContextObject->Send2Client(&bToken, 1);
}
CScreenSpyDlg::~CScreenSpyDlg()
{
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);
}
void CScreenSpyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CScreenSpyDlg, CDialog)
ON_WM_CLOSE()
ON_WM_PAINT()
ON_WM_SYSCOMMAND()
2019-01-10 19:35:03 +08:00
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEWHEEL()
ON_WM_MOUSEMOVE()
ON_WM_MOUSELEAVE()
2019-01-10 19:35:03 +08:00
ON_WM_KILLFOCUS()
ON_WM_SIZE()
END_MESSAGE_MAP()
// CScreenSpyDlg 消息处理程序
BOOL CScreenSpyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetIcon(m_hIcon,FALSE);
CString strString;
strString.Format("%s - 远程桌面控制 %d×%d", m_IPAddress,
m_BitmapInfor_Full->bmiHeader.biWidth, m_BitmapInfor_Full->bmiHeader.biHeight);
SetWindowText(strString);
m_hFullDC = ::GetDC(m_hWnd);
m_hFullMemDC = CreateCompatibleDC(m_hFullDC);
m_BitmapHandle = CreateDIBSection(m_hFullDC, m_BitmapInfor_Full,
DIB_RGB_COLORS, &m_BitmapData_Full, NULL, NULL); //创建应用程序可以直接写入的、与设备无关的位图
SelectObject(m_hFullMemDC, m_BitmapHandle);//择一对象到指定的设备上下文环境
SetScrollRange(SB_HORZ, 0, m_BitmapInfor_Full->bmiHeader.biWidth); //指定滚动条范围的最小值和最大值
SetScrollRange(SB_VERT, 0, m_BitmapInfor_Full->bmiHeader.biHeight);//1366 768
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)");
SysMenu->AppendMenu(MF_STRING, IDM_SAVEDIB, "保存快照(&S)");
SysMenu->AppendMenu(MF_SEPARATOR);
SysMenu->AppendMenu(MF_STRING, IDM_GET_CLIPBOARD, "获取剪贴板(&R)");
SysMenu->AppendMenu(MF_STRING, IDM_SET_CLIPBOARD, "设置剪贴板(&L)");
SysMenu->AppendMenu(MF_SEPARATOR);
}
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);
2025-07-29 03:42:59 +08:00
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));
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()));
ShowScrollBar(SB_BOTH, !m_bAdaptiveSize);
SendNext();
2019-01-10 19:35:03 +08:00
return TRUE;
}
VOID CScreenSpyDlg::OnClose()
{
CancelIO();
// 等待数据处理完毕
if (IsProcessing()) {
ShowWindow(SW_HIDE);
return;
}
// 恢复鼠标状态
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor(NULL, IDC_ARROW));
DialogBase::OnClose();
}
VOID CScreenSpyDlg::OnReceiveComplete()
{
2019-01-10 19:35:03 +08:00
assert (m_ContextObject);
auto cmd = m_ContextObject->InDeCompressedBuffer.GetBYTE(0);
switch(cmd)
{
case TOKEN_FIRSTSCREEN:
{
2019-01-10 19:35:03 +08:00
DrawFirstScreen();
break;
}
case TOKEN_NEXTSCREEN:
{
DrawNextScreenDiff(false);
break;
}
case TOKEN_KEYFRAME: {
if (!m_bIsFirst) {
DrawNextScreenDiff(true);
}
break;
}
2019-01-10 19:35:03 +08:00
case TOKEN_CLIPBOARD_TEXT:
{
Buffer str = m_ContextObject->InDeCompressedBuffer.GetMyBuffer(1);
UpdateServerClipboard(str.c_str(), str.length());
break;
}
default: {
TRACE("CScreenSpyDlg unknown command: %d!!!\n", int(cmd));
}
}
}
VOID CScreenSpyDlg::DrawFirstScreen(void)
{
m_bIsFirst = FALSE;
//得到被控端发来的数据 将他拷贝到HBITMAP的缓冲区中这样一个图像就出现了
m_ContextObject->InDeCompressedBuffer.CopyBuffer(m_BitmapData_Full, m_BitmapInfor_Full->bmiHeader.biSizeImage, 1);
PostMessage(WM_PAINT);//触发WM_PAINT消息
}
VOID CScreenSpyDlg::DrawNextScreenDiff(bool keyFrame)
{
//该函数不是直接画到屏幕上,而是更新一下变化部分的屏幕数据然后调用
//OnPaint画上去
//根据鼠标是否移动和屏幕是否变化判断是否重绘鼠标,防止鼠标闪烁
BOOL bChange = FALSE;
ULONG ulHeadLength = 1 + 1 + sizeof(POINT) + sizeof(BYTE); // 标识 + 算法 + 光标 位置 + 光标类型索引
#if SCREENYSPY_IMPROVE
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;
}
#else
m_FrameID++;
#endif
LPVOID FirstScreenData = m_BitmapData_Full;
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;
}
// 光标类型发生变化
2019-01-20 20:04:11 +08:00
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
SetClassLongPtrA(m_hWnd, GCLP_HCURSOR, (ULONG_PTR)m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex));
#else
SetClassLongA(m_hWnd, GCL_HCURSOR, (LONG)m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex));
#endif
}
// 屏幕是否变化
if (NextScreenLength > 0)
{
bChange = TRUE;
}
2025-02-06 03:34:57 +08:00
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;
}
}
#if SCREENSPY_WRITE
if (!WriteBitmap(m_BitmapInfor_Full, m_BitmapData_Full, "YAMA", frameID)) {
TRACE("WriteBitmap [%d] failed!!!\n", frameID);
}
#endif
if (bChange)
{
PostMessage(WM_PAINT);
}
}
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;
}
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,
2019-01-20 20:04:11 +08:00
m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex),
0,0,
0,
NULL,
DI_NORMAL | DI_COMPAT
);
}
VOID CScreenSpyDlg::DrawTipString(CString strString)
{
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);
2019-01-10 19:35:03 +08:00
DrawText (m_hFullDC, strString, -1, &Rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER);
SetBkColor(m_hFullDC, BackgroundColor);
SetTextColor(m_hFullDC, OldBackgroundColor);
}
void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CMenu* SysMenu = GetSystemMenu(FALSE);
switch (nID)
{
case IDM_CONTROL:
{
m_bIsCtrl = !m_bIsCtrl;
2019-01-10 19:35:03 +08:00
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));
2019-01-10 19:35:03 +08:00
break;
}
case IDM_FULLSCREEN: // 全屏
2019-01-10 19:35:03 +08:00
{
EnterFullScreen();
SysMenu->CheckMenuItem(IDM_FULLSCREEN, MF_CHECKED); //菜单样式
break;
}
case IDM_SAVEDIB: // 快照保存
{
SaveSnapshot();
break;
}
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);
2025-07-29 03:42:59 +08:00
SysMenu->CheckMenuItem(IDM_ADAPTIVE_SIZE, m_bAdaptiveSize ? MF_CHECKED : MF_UNCHECKED);
break;
}
}
CDialog::OnSysCommand(nID, lParam);
}
BOOL CScreenSpyDlg::PreTranslateMessage(MSG* pMsg)
{
#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:
if (pMsg->wParam == VK_F11 && LeaveFullScreen()) // F11: 退出全屏
return TRUE;
if (pMsg->wParam != VK_LWIN && pMsg->wParam != VK_RWIN)
{
SendScaledMouseMessage(pMsg, true);
}
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) {
if (!m_bIsCtrl)
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);
}
VOID CScreenSpyDlg::SendCommand(const MYMSG* Msg)
{
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;
if (time_elapsed < 200 && dist_sq < 18 * 18) {
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);
}
BOOL CScreenSpyDlg::SaveSnapshot(void)
{
CString strFileName = m_IPAddress + CTime::GetCurrentTime().Format("_%Y-%m-%d_%H-%M-%S.bmp");
CFileDialog Dlg(FALSE, "bmp", strFileName, OFN_OVERWRITEPROMPT, "位图文件(*.bmp)|*.bmp|", this);
if(Dlg.DoModal () != IDOK)
return FALSE;
WriteBitmap(m_BitmapInfor_Full, m_BitmapData_Full, Dlg.GetPathName().GetBuffer());
return true;
}
VOID CScreenSpyDlg::UpdateServerClipboard(char *szBuffer,ULONG ulLength)
{
if (!::OpenClipboard(NULL))
return;
::EmptyClipboard();
HGLOBAL hGlobal = GlobalAlloc(GPTR, ulLength);
if (hGlobal != NULL) {
char* szClipboardVirtualAddress = (LPTSTR) GlobalLock(hGlobal);
memcpy(szClipboardVirtualAddress,szBuffer,ulLength);
GlobalUnlock(hGlobal);
if(NULL==SetClipboardData(CF_TEXT, hGlobal))
GlobalFree(hGlobal);
}
CloseClipboard();
}
VOID CScreenSpyDlg::SendServerClipboard(void)
{
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-10 19:35:03 +08:00
void CScreenSpyDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (m_bAdaptiveSize) return;
2019-01-10 19:35:03 +08:00
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);
}
void CScreenSpyDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (m_bAdaptiveSize) return;
2019-01-10 19:35:03 +08:00
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);
}
void CScreenSpyDlg::EnterFullScreen()
{
if (!m_bFullScreen)
{
// 1. 获取鼠标位置
POINT pt;
GetCursorPos(&pt);
// 2. 获取鼠标所在显示器
HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
MONITORINFO mi = { sizeof(mi) };
if (!GetMonitorInfo(hMonitor, &mi))
return;
RECT rcMonitor = mi.rcMonitor;
2019-01-10 19:35:03 +08:00
// 3. 记录当前窗口状态
2019-01-10 19:35:03 +08:00
GetWindowPlacement(&m_struOldWndpl);
// 4. 修改窗口样式,移除标题栏、边框
LONG lStyle = GetWindowLong(m_hWnd, GWL_STYLE);
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_BORDER);
SetWindowLong(m_hWnd, GWL_STYLE, lStyle);
// 5. 隐藏滚动条
ShowScrollBar(SB_BOTH, !m_bAdaptiveSize); // 隐藏水平和垂直滚动条
// 6. 重新调整窗口大小并更新
SetWindowPos(&CWnd::wndTop, rcMonitor.left, rcMonitor.top, rcMonitor.right - rcMonitor.left,
rcMonitor.bottom - rcMonitor.top, SWP_NOZORDER | SWP_FRAMECHANGED);
// 7. 标记全屏模式
2019-01-10 19:35:03 +08:00
m_bFullScreen = true;
}
}
// 全屏退出成功则返回true
2019-01-20 20:04:11 +08:00
bool CScreenSpyDlg::LeaveFullScreen()
2019-01-10 19:35:03 +08:00
{
if (m_bFullScreen)
{
// 1. 恢复窗口样式
LONG lStyle = GetWindowLong(m_hWnd, GWL_STYLE);
lStyle |= (WS_CAPTION | WS_THICKFRAME | WS_BORDER);
SetWindowLong(m_hWnd, GWL_STYLE, lStyle);
// 2. 恢复窗口大小
2019-01-10 19:35:03 +08:00
SetWindowPlacement(&m_struOldWndpl);
SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
// 3. 显示滚动条
ShowScrollBar(SB_BOTH, !m_bAdaptiveSize); // 显示水平和垂直滚动条
// 4. 标记退出全屏
2019-01-10 19:35:03 +08:00
m_bFullScreen = false;
CMenu* SysMenu = GetSystemMenu(FALSE);
SysMenu->CheckMenuItem(IDM_FULLSCREEN, MF_UNCHECKED); //菜单样式
2019-01-20 20:04:11 +08:00
return true;
2019-01-10 19:35:03 +08:00
}
2019-01-20 20:04:11 +08:00
return false;
2019-01-10 19:35:03 +08:00
}
void CScreenSpyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
CDialog::OnLButtonDown(nFlags, point);
}
void CScreenSpyDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
CDialog::OnLButtonUp(nFlags, point);
}
BOOL CScreenSpyDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
return CDialog::OnMouseWheel(nFlags, zDelta, pt);
}
void CScreenSpyDlg::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bMouseTracking)
{
m_bMouseTracking = true;
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO));
}
2019-01-10 19:35:03 +08:00
CDialog::OnMouseMove(nFlags, point);
}
void CScreenSpyDlg::OnMouseLeave()
{
CWnd::OnMouseLeave();
m_bMouseTracking = false;
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO));
}
2019-01-10 19:35:03 +08:00
void CScreenSpyDlg::OnKillFocus(CWnd* pNewWnd)
{
CDialog::OnKillFocus(pNewWnd);
}
void CScreenSpyDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
if (!IsWindowVisible())
return;
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
}