Greg2FS
asked on
Screen capture CreateDIBSection doesn't capture LayeredWindow
Hello, I am trying to capture a screen shot using this code:
But I layered windows doesn't appear inside the shot, it is like them were invisible, only the desktop and other windows are captured.
Using "print screen" I get a full screen shot including layered window, then how can I correct that ?
Thanks
...
HWND hwnd=0;
hdc = GetWindowDC(hwnd);
memdc = CreateCompatibleDC(hdc);
...
hbmp = CreateDIBSection(hdc, &bmpinfo, DIB_PAL_COLORS, &pBits, NULL, 0)
SelectObject(memdc, hbmp);
...
But I layered windows doesn't appear inside the shot, it is like them were invisible, only the desktop and other windows are captured.
Using "print screen" I get a full screen shot including layered window, then how can I correct that ?
Thanks
ASKER
Sorry I didn't know exactly what does the job of taking the screenshot, but my code was longer and it seems that the code you link does exactly the same: the screenshot is taken but my layered window is not captured...
No problem.
If you need the screenshots, you need to take the code from the article:
Win32: Capture an image
https://www.experts-exchange.com/A_1739.html
If you need the screenshots, you need to take the code from the article:
Win32: Capture an image
https://www.experts-exchange.com/A_1739.html
ASKER
I tried this code and said it does the same thing as mine.
Yes. You are right. GetDC from the desktp does not help for the window with the WS_EX_LAYERED.
For a test, I took the screenshot of the layered window itself.
For a test, I took the screenshot of the layered window itself.
#include <Windows.h>
BOOL Capture(HDC, LPRECT, LPCWSTR);
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
HDC hDC;
RECT rect;
hWnd = FindWindow(NULL, L"Semi-Transparent Window");
SetForegroundWindow(hWnd);
::GetWindowRect(hWnd, &rect);
ScreenToClient(hWnd, (LPPOINT)&rect);
ScreenToClient(hWnd, (LPPOINT)&rect.right);
hDC = GetDC(hWnd);
Capture(hDC, &rect, L"capture.bmp");
return 0;
}
BOOL Capture(HDC hDC, LPRECT lpRect, LPCWSTR lpszFile)
{
BITMAPINFO bmi = { 0 };
LPBYTE pBits = NULL;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = lpRect->right - lpRect->left;
bmi.bmiHeader.biHeight = lpRect->bottom - lpRect->top;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
HBITMAP hBitmap = CreateDIBSection(hDC, &bmi,
DIB_RGB_COLORS, (LPVOID*)&pBits, NULL, 0);
HDC hMemDC = CreateCompatibleDC(hDC);
HGDIOBJ hOld = SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0,
lpRect->right - lpRect->left,
lpRect->bottom - lpRect->top,
hDC, lpRect->left, lpRect->top, SRCCOPY);
SelectObject(hMemDC, hOld);
DeleteDC(hMemDC);
DWORD nImageSize = ((((bmi.bmiHeader.biWidth *
bmi.bmiHeader.biBitCount)
+ 31) & ~31) >> 3)
* bmi.bmiHeader.biHeight;
BITMAPFILEHEADER header = { 0 };
header.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
(DWORD)sizeof(BITMAPINFOHEADER);
header.bfSize = nImageSize + sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER);
header.bfType = 0x4D42;
HANDLE hFile = CreateFile(lpszFile, GENERIC_WRITE,
0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD nWritten = 0;;
WriteFile(hFile, (LPVOID)&header,
sizeof(BITMAPFILEHEADER),
&nWritten, NULL);
WriteFile(hFile, (LPVOID)&bmi,
sizeof(BITMAPINFOHEADER),
&nWritten, NULL);
WriteFile(hFile, (LPVOID)pBits, nImageSize,
&nWritten, NULL);
CloseHandle(hFile);
}
return TRUE;
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Yes just using SRCCOPY|CAPTUREBLT works !
ASKER
Thanks
:)
I've already made a short example for you.
You are welcome.
I've already made a short example for you.
You are welcome.
#include <Windows.h>
BOOL Capture(HDC, LPRECT, LPCWSTR);
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow)
{
HWND hWnd = GetDesktopWindow();
HDC hDC = GetDC(hWnd);
RECT rect = { 100, 100, 500, 500 };
HDC hDCMem = ::CreateCompatibleDC(hDC);
HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, 500, 500);
HBITMAP hBmpOld = (HBITMAP)::SelectObject(hDCMem, hBitmap);
BOOL bRet = ::BitBlt(hDCMem, 0, 0, 500, 500, hDC, 100, 100, SRCCOPY | CAPTUREBLT);
Capture(hDCMem, &rect, L"capture.bmp");
::SelectObject(hDCMem, hBmpOld);
::DeleteObject(hBitmap);
::DeleteDC(hDCMem);
return 0;
}
BOOL Capture(HDC hDC, LPRECT lpRect, LPCWSTR lpszFile)
{
BITMAPINFO bmi = { 0 };
LPBYTE pBits = NULL;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = lpRect->right - lpRect->left;
bmi.bmiHeader.biHeight = lpRect->bottom - lpRect->top;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
HBITMAP hBitmap = CreateDIBSection(hDC, &bmi,
DIB_RGB_COLORS, (LPVOID*)&pBits, NULL, 0);
HDC hMemDC = CreateCompatibleDC(hDC);
HGDIOBJ hOld = SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0,
lpRect->right - lpRect->left,
lpRect->bottom - lpRect->top,
hDC, lpRect->left, lpRect->top, CAPTUREBLT | SRCCOPY);
SelectObject(hMemDC, hOld);
DeleteDC(hMemDC);
DWORD nImageSize = ((((bmi.bmiHeader.biWidth *
bmi.bmiHeader.biBitCount)
+ 31) & ~31) >> 3)
* bmi.bmiHeader.biHeight;
BITMAPFILEHEADER header = { 0 };
header.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
(DWORD)sizeof(BITMAPINFOHEADER);
header.bfSize = nImageSize + sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER);
header.bfType = 0x4D42;
HANDLE hFile = CreateFile(lpszFile, GENERIC_WRITE,
0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD nWritten = 0;;
WriteFile(hFile, (LPVOID)&header,
sizeof(BITMAPFILEHEADER),
&nWritten, NULL);
WriteFile(hFile, (LPVOID)&bmi,
sizeof(BITMAPINFOHEADER),
&nWritten, NULL);
WriteFile(hFile, (LPVOID)pBits, nImageSize,
&nWritten, NULL);
CloseHandle(hFile);
}
return TRUE;
}
capture.bmp
CreateDIBSection creates a DIB section. It does not capture any screen. Mainly, it is a way to create HBITMAP. pBits - this is the array of the pixels.
Sorry if I simplified too much.
In this EE article "Win32: Capture an image" (https://www.experts-exchange.com/A_1739.html) you can find the code that works. There is an example that takes screenshots from the desktop.
About the layered window (if your need):
Win32: Semi-Transparent Window: https://www.experts-exchange.com/A_1783.html
(There is the screenshot as an evidence for you).