0
votes

I have been working on accessing a game's pixel colors, with little success. I have researched and attempted several methods, including BitBlt, the SharpDX library, Desktop Duplication (could not use due to Windows 8 limitations), and GetPixel() (this has worked, but it is far too slow to be useful).

None of these (except GetPixel()) work due to the game's Overlay (I possibly have just not discovered the appropriate SharpDX/ D3D function).

I have looked into mirror drivers, but I could not find sufficient documentation to utilize them, or know if they would work.

Is there any way to access the pixels of a DirectX game's Overlay?

1
Overlay is a special kind of surface in DirectX, Microsoft does not provide any public interface to get the data from Overlay surface, there is no way except hooking! - zdd

1 Answers

1
votes

Since direct-x games are usually double buffered, there is a 50% chance that GetPixel or Bitblt would work at all.. If you really need real-time pixels from the game, you can hook it with a dll/detour and feed the pixels to whatever application you want via sharedmemory or some form of inter-process communication.

As a side note, since you say that GetPixel works for you, you can always try the following for grabbing a screenshot of a specified window and saving it.. You'll need to link to gdi32 and 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);
}