다음 코드 (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