Читать наложение игры DirectX

Я безуспешно работал над доступом к цветам пикселей в игре. Я исследовал и попробовал несколько методов, в том числе BitBlt, библиотеку SharpDX, дублирование рабочего стола (невозможно использовать из-за ограничений Windows 8) и GetPixel () (это сработало, но слишком медленно, чтобы быть полезным).

Ни один из них (кроме GetPixel ()) не работает из-за оверлея игры (возможно, я просто не обнаружил соответствующую функцию SharpDX / D3D).

Я просмотрел драйверы зеркал, но не смог найти достаточной документации для их использования или узнать, будут ли они работать.

Есть ли способ получить доступ к пикселям оверлея игры DirectX?


person asqapro    schedule 25.10.2013    source источник
comment
Оверлей - это особый вид поверхности в DirectX, Microsoft не предоставляет какого-либо общедоступного интерфейса для получения данных с поверхности наложения, нет другого способа, кроме перехвата!   -  person zdd    schedule 26.10.2013


Ответы (1)


Поскольку игры с Direct-x обычно имеют двойную буферизацию, существует 50% -ная вероятность, что GetPixel или Bitblt вообще будут работать. Если вам действительно нужны пиксели в реальном времени из игры, вы можете подключить ее с помощью dll / обхода и скормить пикселей в любое приложение, которое вы хотите, через общую память или какую-либо форму межпроцессного взаимодействия.

В качестве примечания: поскольку вы говорите, что GetPixel работает на вас, вы всегда можете попробовать следующее, чтобы сделать снимок экрана указанного окна и сохранить его .. Вам нужно будет установить ссылку на gdi32 и gdiplus

#include <windows.h>
#include <iostream>
#include <fstream>

typedef struct
{
    HBITMAP hBmp;
    int Width, Height;
    unsigned int* Pixels;
    unsigned short BitsPerPixel;
} BmpData;

bool ScreenShot(BmpData &Data, HDC DC)
{
    bool Result = false;
    memset(&Data, 0, sizeof(Data));
    HDC hdcMem = CreateCompatibleDC(DC);
    Data.Width = GetDeviceCaps(DC, HORZRES);
    Data.Height = GetDeviceCaps(DC, VERTRES);

    unsigned char* Pixels = NULL;
    unsigned short BitsPerPixel = 32;
    BITMAPINFO Info = {{sizeof(BITMAPINFOHEADER), Data.Width, -Data.Height, 1, BitsPerPixel, BI_RGB, 0, 0, 0, 0, 0}};

    Data.hBmp = CreateDIBSection(DC, &Info, DIB_RGB_COLORS, reinterpret_cast<void**>(&Pixels), NULL, 0);
    if(Data.hBmp)
    {
        HBITMAP hOld = reinterpret_cast<HBITMAP>(SelectObject(hdcMem, Data.hBmp));
        BitBlt(hdcMem, 0, 0, Data.Width, Data.Height, DC, 0, 0, SRCCOPY);
        SelectObject(hdcMem, hOld);
        Data.Height *= -1;
        Data.BitsPerPixel = BitsPerPixel;
        Data.Pixels = reinterpret_cast<unsigned int*>(Pixels);
        Result = true;
    }

    DeleteDC(hdcMem);
    return Result;
}

/*Portable way to save a bitmap =)*/
void SaveBitmap(const char* FilePath, const BmpData &Data)
{
    std::fstream hFile(FilePath, std::ios::out | std::ios::binary);
    if (!hFile.is_open())
    {
        printf("%s", "Error. Cannot Create Bitmap.");
        return;
    }

    unsigned int Trash = 0;
    unsigned short Planes = 1;
    unsigned int biSize = 40;
    unsigned short Type = 0x4D42;
    unsigned int compression = 0;
    unsigned int PixelsOffsetBits = 54;
    int Width = Data.Width;
    int Height = -Data.Height;
    unsigned short BitsPerPixel = Data.BitsPerPixel;
    unsigned int size = ((Width * BitsPerPixel + 31) / 32) * 4 * Height;
    unsigned int bfSize = 54 + size;
    Height *= -1;

    hFile.write(reinterpret_cast<char*>(&Type), sizeof(Type));
    hFile.write(reinterpret_cast<char*>(&bfSize), sizeof(bfSize));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(unsigned int));
    hFile.write(reinterpret_cast<char*>(&PixelsOffsetBits), sizeof(PixelsOffsetBits));
    hFile.write(reinterpret_cast<char*>(&biSize), sizeof(biSize));
    hFile.write(reinterpret_cast<char*>(&Width), sizeof(Width));
    hFile.write(reinterpret_cast<char*>(&Height), sizeof(Height));
    hFile.write(reinterpret_cast<char*>(&Planes), sizeof(Planes));
    hFile.write(reinterpret_cast<char*>(&BitsPerPixel), sizeof(BitsPerPixel));
    hFile.write(reinterpret_cast<char*>(&compression), sizeof(compression));
    hFile.write(reinterpret_cast<char*>(&size), sizeof(size));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(unsigned int));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(unsigned int));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(unsigned int));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(unsigned int));
    hFile.write(reinterpret_cast<char*>(Data.Pixels), size);
    hFile.close();
}

int main()
{
    HWND MyWindow = nullptr;  //Handle to the window that you want to screenshot..

    BmpData data;
    HDC Screen = GetDC(MyWindow); //Get a DC..
    ScreenShot(data, Screen);
    SaveBitmap("C:/Users/Brandon/desktop/Foo.bmp", data);
    DeleteDC(Screen);
    DeleteObject(data.hBmp);
}
person Brandon    schedule 25.10.2013
comment
К сожалению, скриншот не работает: /. Он по-прежнему делает черный снимок экрана (не захватывает оверлей). Начну изучать метод dll / обходной путь, спасибо за совет. - person asqapro; 26.10.2013