5

次のコード (C++ Win32) を作成して、ゲーム ウィンドウ画面をキャプチャし、画像からピクセル カラー配列を取得しました。関数 autoB() が仕事をします。

次に、結果の配列をウィンドウに描画して、何が得られたかを視覚的に確認します。

問題は、このプログラムがコンピューターを起動した後、最初にゲームから取得した最初のスクリーンショットを「キャッシュ」した後に一度だけ動作し、常に同じピクセル配列を取得することです。プログラムを閉じて再起動しても、同じスクリーンショットが表示されます。

ゲームは 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;

}

スクリーンショットを変更する唯一の方法は、ゲームを再起動することです。次に、最初のスクリーンショットがキャプチャされ、ゲーム ウィンドウで何が起こっているかに関係なく、何度も表示されます。

4

2 に答える 2

1

同じピクセルが返されていますか?それとも、デバッグ ウィンドウの画面に同じ画像が表示されているだけですか? 元のイメージ コピー コードは問題ないように見えますが、「デバッグ」コードでは、SetPixel() を直接呼び出していても、InvalidateRect()Windows に新しい WM_PAINT メッセージを送信させるために呼び出す必要があります。そうしないと、新しいビットが実際にキャプチャされた (描画されていない) にもかかわらず、おそらく古い画像を見ているだけです。

于 2012-06-25T22:26:17.663 に答える