using Visual Studio 2017, vc141, the following code should got a screenshot from front game window but now it return a black and blank image.
only issue with games(tried OpenGL and Vulkan, ogl return black, vulkan return white)
before upgrade to windows 10 1703, it works on windows 10 1607 and windows 7 sp1
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
code:
BOOL ScreenShot(cv::Mat *img, HWND hWnd = NULL) {
HBITMAP hBitmap;
HDC hdcSys = GetDC(hWnd);
HDC hdcMem = CreateCompatibleDC(hdcSys);
void *ptrBitmapPixels;
BITMAPINFO bi;
HDC hdc;
RECT rect;
if (!GetWindowRect(hWnd, &rect) || (hWnd == NULL)) {
return FALSE;
}
ZeroMemory(&bi, sizeof(BITMAPINFO));
LONG lWidth = rect.right - rect.left;
LONG lHeight = rect.bottom - rect.top;
bi.bmiHeader.biSize = sizeof(BITMAPINFO);
bi.bmiHeader.biWidth = lWidth;
bi.bmiHeader.biHeight = -lHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
hdc = GetDC(hWnd);
hBitmap = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, &ptrBitmapPixels, NULL, 0);
SelectObject(hdcMem, hBitmap);
*img = cv::Mat(lHeight, lWidth, CV_8UC4, ptrBitmapPixels, 0);
BitBlt(hdcMem, 0, 0, lWidth, lHeight, hdcSys, 0, 0, SRCCOPY);
//DeleteObject(hBitmap);
DeleteDC(hdcMem);
ReleaseDC(hWnd, hdcSys);
ReleaseDC(hWnd, hdc);
return TRUE;
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
/*...*/
HotKeyId = GlobalAddAtom(L"DBKGNDSCREENSHOT");
RegisterHotKey(hWnd, HotKeyId, NULL, VK_F10);
/*...*/
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
/*...*/
case WM_HOTKEY:
if (wParam == HotKeyId) {
cv::Mat t;
HWND MainHWND;
MainHWND = GetForegroundWindow();
ScreenShot(&t, MainHWND);
cv::imshow("1", t);
}
break;
/*...*/
}
and still black even PrintWindow(at least we got a titlebar)
PrintWindow(hWnd, hdcMem, 0);
//BitBlt(hdcMem, 0, 0, lWidth, lHeight, hdcSys, 0, 0, SRCCOPY);
I send this program to my friend (without any modify, his OS=win7 x64), but he got the correct result.
so what should I do?
BitBlt
call be made before the call tocv::Mat
? – HarmsGetClientRect
instead ofGetWindowRect
. Otherwise your bitmap will be larger than the actual contents of hdcSys and hdcMem. – HarmsBitBlt
. If it returnsFALSE
, then when does a subsequent call toGetLastError()
return? – Harms