我編寫了下面的代碼(C++ Win32)來捕獲遊戲窗口屏幕並從圖像中獲取像素顏色數組。函數autoB()完成這項工作。用BitBlt捕獲程序窗口總是返回相同的圖像
然後我將結果數組繪製到我的窗口中,以便直觀地檢查我得到的結果。
問題是這個程序在我啓動計算機之後只能運行一次,在第一次「緩存」從遊戲中獲得的第一個截圖後,我總是得到相同的像素數組。即使我關閉並重新啓動程序,我也會得到相同的屏幕截圖。
遊戲並未使用DirectX在屏幕上繪圖,而且我總是可以使用Alt + PrtSc截取屏幕截圖。
任何幫助理解爲什麼發生這種方式表示讚賞。
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;
}
更改屏幕截圖的唯一方法是重新啓動遊戲。然後再次捕獲第一張截圖,無論遊戲窗口中發生了什麼,都會一遍又一遍地顯示。
'autoB'是否過早返回? –
不,它沒有。如果我在sp = NUll之後添加MessageBox,每次調用函數時都會看到它。 – user1481126