使用 BitBlt 捕获程序窗口总是返回相同的图像 [英] Capturing a program window with BitBlt always returns the same image

查看:22
本文介绍了使用 BitBlt 捕获程序窗口总是返回相同的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了以下代码(C++ Win32)来捕获游戏窗口屏幕并从图像中获取像素颜色数组.函数 autoB() 完成这项工作.

I wrote the following code (C++ Win32) to capture a game window screen and get pixel color array from the image. Function autoB() does the job.

然后我将结果数组绘制到我的窗口中,以直观地检查我得到了什么.

Then I draw the result array into my window to visually check what I got.

问题是这个程序在我启动计算机后只运行一次,在第一次缓存"从游戏中截取的第一个屏幕截图后,我总是得到相同的像素数组.即使我关闭并重新启动程序,我也会得到相同的屏幕截图.

The problem is that this program works only once after I start the computer, after the first time it "caches" the first screenshot taken from the game and I always get the same array of pixels. Even if I close and restart the program I get the same screenshot.

游戏没有使用 DirectX 在屏幕上绘图,我总是可以使用 Alt+PrtSc 截取屏幕截图.

The game is not using DirectX to draw on the screen and I'm always able to take screenshots using Alt+PrtSc.

对于理解为什么会这样发生的任何帮助表示赞赏.

Any help in understanding why it's happening this way is appreciated.

int getPixels(HDC *eClientHdcMem, HBITMAP *eClientBmp, unsigned char **lp) {

BITMAP bmpScreen;   
    BITMAPINFOHEADER bi;

GetObject(*eClientBmp, sizeof(BITMAP), &bmpScreen);

LONG bW = bmpScreen.bmWidth, bH = bmpScreen.bmHeight;

bi.biSize = sizeof(BITMAPINFOHEADER);    
bi.biWidth = bW;    
bi.biHeight = -bH;  
bi.biPlanes = 1;    
bi.biBitCount = 32;    
bi.biCompression = BI_RGB;    
bi.biSizeImage = 0;  
bi.biXPelsPerMeter = 0;    
bi.biYPelsPerMeter = 0;    
bi.biClrUsed = 0;    
bi.biClrImportant = 0;

DWORD dw = ((bW * bi.biBitCount + 31) / 32) * 4 * bH;
*lp = new unsigned char[dw];

return GetDIBits(*eClientHdcMem, *eClientBmp, 0, (UINT)bH, *lp, (BITMAPINFO *)&bi, DIB_RGB_COLORS);

}

void autoB() {
HWND hwnd;
HDC hDC0 = NULL, eClientHdcMem = NULL;
HBITMAP eClientBmp = NULL;
BITMAP bmp = {0};
unsigned char *lp = NULL, *sp = NULL;
WINDOWINFO wi;
wi.cbSize = sizeof(WINDOWINFO);
RECT vp;
int vpW, vpH;
long iW, iH;

if (!(hwnd = FindWindow(NULL,TEXT("Client")))) return;
if (!(hDC0 = GetDC(hwnd))) return;

GetWindowInfo(hwnd,&wi);
vp = wi.rcClient;
vpW = vp.right - vp.left;
vpH = vp.bottom - vp.top;

if (!(eClientBmp = CreateCompatibleBitmap(hDC0, vpW, vpH))) return;
if (!(eClientHdcMem = CreateCompatibleDC(hDC0))) return;
SelectObject(eClientHdcMem, eClientBmp);

BitBlt(eClientHdcMem, 0, 0, vpW, vpH, hDC0, 0, 0, SRCCOPY);

int res = getPixels(&eClientHdcMem, &eClientBmp, &lp);

DeleteObject(eClientBmp);
DeleteObject(eClientHdcMem);

    // begin testing
HDC sts = GetDC(hStats);
HBITMAP stsBmp = CreateCompatibleBitmap(sts, vpW, vpH);
HBITMAP stsBmpOld = (HBITMAP)SelectObject(sts, stsBmp);
unsigned char r,g,b;
for(unsigned int i=0;i<vpW;i++) {
    for(unsigned int j=0;j<vpH;j++) {
        r = lp[(vpW*j+i) * 4 + 2];
        g = lp[(vpW*j+i) * 4 + 1];
        b = lp[(vpW*j+i) * 4 + 0];
        SetPixel(sts,i,j,RGB(r,g,b));
    }
}
SelectObject(sts, stsBmpOld);
DeleteObject(stsBmp);
DeleteObject(stsBmpOld);
ReleaseDC(hStats,sts);
    // end testing

DeleteDC(eClientHdcMem);
ReleaseDC(hwnd,hDC0);

delete [] lp;
lp = NULL;
delete [] sp;
sp = NULL;

}

更改截图的唯一方法是重新启动游戏.然后,第一个屏幕截图被捕获并会一遍又一遍地显示,无论游戏窗口中发生了什么.

The only way to change the screenshot is to restart the game. Then again, the first screenshot is captured and will be displayed over and over again regardless of what's happening in the game window.

推荐答案

您确定要返回相同的像素,还是只是在调试窗口的屏幕上看到相同的图像?原始图像复制代码看起来不错,但是在您的调试"代码中,即使您直接调用 SetPixel(),您仍然需要调用 InvalidateRect() 以导致 Windows 发送新的 WM_PAINT 消息.如果您不这样做,您可能只是在查看旧图像,即使确实已捕获(但未绘制)新位.

Are you sure you're getting back the same pixels, or are you just seeing the same image on your screen in your debug window? The original image copy code looks OK, but in your "debug" code, even though you are calling SetPixel() directly, you still need to call InvalidateRect() to cause Windows to send a new WM_PAINT message. If you're not doing that, you're probably just looking at the old image, even though the new bits have indeed been captured (but not drawn).

这篇关于使用 BitBlt 捕获程序窗口总是返回相同的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆