Anonymous
Как создать наложение, невидимое на скриншоте, с помощью DirectComposition и Direct2D в C++?
Сообщение
Anonymous » 31 май 2024, 23:27
Я пытаюсь создать наложение на C++, которое не отображается на снимках экрана. Оверлей должен быть виден пользователю, но не запечатлен на снимке экрана (что также будет выполняться кодом). Я читал, что это возможно с помощью DirectComposition и Direct2D, но мне не удалось добиться желаемого эффекта.
Текущее поведение : наложение отображается на экран, но он также фиксируется на снимках экрана.
Желаемое поведение : я хочу, чтобы наложение было видно на экране, но не фиксировалось на снимках экрана. p>
Вот код, с которым я работаю:
Код: Выделить всё
#include
#include
#include
#include
#include
#include
#pragma comment(lib, "dcomp.lib")
#pragma comment(lib, "d2d1.lib")
void OverlayThreadFunction() {
const wchar_t CLASS_NAME[] = L"DirectCompWindowClass";
WNDCLASSW wc = {};
wc.lpfnWndProc = DefWindowProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = CLASS_NAME;
wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND);
RegisterClassW(&wc);
HWND hwnd = CreateWindowExW(
WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT,
CLASS_NAME,
L"DirectComposition Overlay",
WS_POPUP | WS_VISIBLE,
0, 0, 100, 100,
// 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), (for fullscreen)
nullptr, nullptr, GetModuleHandle(NULL), nullptr
);
if (!hwnd) {
return;
}
// Set window transparency
SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 0, LWA_COLORKEY);
// Initialize DirectComposition
IDCompositionDevice *pDCompDevice = nullptr;
HRESULT hr = DCompositionCreateDevice(nullptr, __uuidof(IDCompositionDevice),
reinterpret_cast(&pDCompDevice));
if (FAILED(hr)) {
return;
}
IDCompositionTarget *pDCompTarget = nullptr;
hr = pDCompDevice->CreateTargetForHwnd(hwnd, TRUE, &pDCompTarget);
if (FAILED(hr)) {
return;
}
IDCompositionVisual *pDCompVisual = nullptr;
hr = pDCompDevice->CreateVisual(&pDCompVisual);
if (FAILED(hr)) {
return;
}
// Initialize Direct2D
ID2D1Factory *pD2DFactory = nullptr;
hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory);
if (FAILED(hr)) {
return;
}
ID2D1HwndRenderTarget *pRT = nullptr;
D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties();
D2D1_HWND_RENDER_TARGET_PROPERTIES hwndProps = D2D1::HwndRenderTargetProperties(hwnd, D2D1::SizeU(
GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)));
hr = pD2DFactory->CreateHwndRenderTarget(props, hwndProps, &pRT);
if (FAILED(hr)) {
return;
}
ID2D1SolidColorBrush *pBrush = nullptr;
hr = pRT->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red, 1.0f), &pBrush);
if (FAILED(hr)) {
return;
}
pDCompVisual->SetContent(pRT);
// Set the visual as the root of the composition target
hr = pDCompTarget->SetRoot(pDCompVisual);
if (FAILED(hr)) {
return;
}
// Commit the composition
hr = pDCompDevice->Commit();
if (FAILED(hr)) {
return;
}
// Draw overlay
pRT->BeginDraw();
pRT->Clear(D2D1::ColorF(D2D1::ColorF::Black, 0.0f)); // Fully transparent background
pRT->FillRectangle(D2D1::RectF(100, 100, 400, 300), pBrush); // Solid red rectangle
pRT->EndDraw();
MSG msg = {};
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Clean up
pBrush->Release();
pRT->Release();
pD2DFactory->Release();
pDCompVisual->Release();
pDCompTarget->Release();
pDCompDevice->Release();
}
bool SaveBitmap(HBITMAP hBitmap, const char *filename) {
BITMAP bmp;
GetObject(hBitmap, sizeof(BITMAP), &bmp);
LONG height = (bmp.bmHeight > 0) ? -bmp.bmHeight : bmp.bmHeight;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmp.bmWidth;
bi.biHeight = height;
bi.biPlanes = 1;
bi.biBitCount = 32; // Change this to 24 if your bitmap doesn't have alpha channel
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
DWORD dwBmpSize = ((bmp.bmWidth * bi.biBitCount + 31) / 32) * 4 * abs(height);
// Add the size of the headers to the size of the bitmap to get the total file size
DWORD dwSizeofDIB = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmpSize;
// Offset to where the actual bitmap bits start.
bmfHeader.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + (DWORD) sizeof(BITMAPINFOHEADER);
// Size of the file
bmfHeader.bfSize = dwSizeofDIB;
// bfType must always be BM for Bitmaps
bmfHeader.bfType = 0x4D42; //BM
// Create the file
std::ofstream file(filename, std::ios::out | std::ios::binary);
if (!file) {
std::cerr
Подробнее здесь: [url]https://stackoverflow.com/questions/78561418/how-to-create-a-screenshot-invisible-overlay-using-directcomposition-and-direct2[/url]
1717187231
Anonymous
Я пытаюсь создать наложение на C++, которое не отображается на снимках экрана. Оверлей должен быть виден пользователю, но не запечатлен на снимке экрана (что также будет выполняться кодом). Я читал, что это возможно с помощью DirectComposition и Direct2D, но мне не удалось добиться желаемого эффекта. [b]Текущее поведение[/b]: наложение отображается на экран, но он также фиксируется на снимках экрана. [b]Желаемое поведение[/b]: я хочу, чтобы наложение было видно на экране, но не фиксировалось на снимках экрана. p> Вот код, с которым я работаю: [code]#include #include #include #include #include #include #pragma comment(lib, "dcomp.lib") #pragma comment(lib, "d2d1.lib") void OverlayThreadFunction() { const wchar_t CLASS_NAME[] = L"DirectCompWindowClass"; WNDCLASSW wc = {}; wc.lpfnWndProc = DefWindowProc; wc.hInstance = GetModuleHandle(NULL); wc.lpszClassName = CLASS_NAME; wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND); RegisterClassW(&wc); HWND hwnd = CreateWindowExW( WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT, CLASS_NAME, L"DirectComposition Overlay", WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, // 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), (for fullscreen) nullptr, nullptr, GetModuleHandle(NULL), nullptr ); if (!hwnd) { return; } // Set window transparency SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 0, LWA_COLORKEY); // Initialize DirectComposition IDCompositionDevice *pDCompDevice = nullptr; HRESULT hr = DCompositionCreateDevice(nullptr, __uuidof(IDCompositionDevice), reinterpret_cast(&pDCompDevice)); if (FAILED(hr)) { return; } IDCompositionTarget *pDCompTarget = nullptr; hr = pDCompDevice->CreateTargetForHwnd(hwnd, TRUE, &pDCompTarget); if (FAILED(hr)) { return; } IDCompositionVisual *pDCompVisual = nullptr; hr = pDCompDevice->CreateVisual(&pDCompVisual); if (FAILED(hr)) { return; } // Initialize Direct2D ID2D1Factory *pD2DFactory = nullptr; hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory); if (FAILED(hr)) { return; } ID2D1HwndRenderTarget *pRT = nullptr; D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(); D2D1_HWND_RENDER_TARGET_PROPERTIES hwndProps = D2D1::HwndRenderTargetProperties(hwnd, D2D1::SizeU( GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN))); hr = pD2DFactory->CreateHwndRenderTarget(props, hwndProps, &pRT); if (FAILED(hr)) { return; } ID2D1SolidColorBrush *pBrush = nullptr; hr = pRT->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red, 1.0f), &pBrush); if (FAILED(hr)) { return; } pDCompVisual->SetContent(pRT); // Set the visual as the root of the composition target hr = pDCompTarget->SetRoot(pDCompVisual); if (FAILED(hr)) { return; } // Commit the composition hr = pDCompDevice->Commit(); if (FAILED(hr)) { return; } // Draw overlay pRT->BeginDraw(); pRT->Clear(D2D1::ColorF(D2D1::ColorF::Black, 0.0f)); // Fully transparent background pRT->FillRectangle(D2D1::RectF(100, 100, 400, 300), pBrush); // Solid red rectangle pRT->EndDraw(); MSG msg = {}; while (GetMessage(&msg, nullptr, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } // Clean up pBrush->Release(); pRT->Release(); pD2DFactory->Release(); pDCompVisual->Release(); pDCompTarget->Release(); pDCompDevice->Release(); } bool SaveBitmap(HBITMAP hBitmap, const char *filename) { BITMAP bmp; GetObject(hBitmap, sizeof(BITMAP), &bmp); LONG height = (bmp.bmHeight > 0) ? -bmp.bmHeight : bmp.bmHeight; BITMAPFILEHEADER bmfHeader; BITMAPINFOHEADER bi; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bmp.bmWidth; bi.biHeight = height; bi.biPlanes = 1; bi.biBitCount = 32; // Change this to 24 if your bitmap doesn't have alpha channel bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; DWORD dwBmpSize = ((bmp.bmWidth * bi.biBitCount + 31) / 32) * 4 * abs(height); // Add the size of the headers to the size of the bitmap to get the total file size DWORD dwSizeofDIB = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmpSize; // Offset to where the actual bitmap bits start. bmfHeader.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + (DWORD) sizeof(BITMAPINFOHEADER); // Size of the file bmfHeader.bfSize = dwSizeofDIB; // bfType must always be BM for Bitmaps bmfHeader.bfType = 0x4D42; //BM // Create the file std::ofstream file(filename, std::ios::out | std::ios::binary); if (!file) { std::cerr Подробнее здесь: [url]https://stackoverflow.com/questions/78561418/how-to-create-a-screenshot-invisible-overlay-using-directcomposition-and-direct2[/url]