使用Direct3D获取屏幕内容

使用CreateCompatibleDC、CreateCompatibleBitmap、BitBlt等函数获取屏幕内容时,会导致屏幕的刷新频率降低,出现屏幕闪动的情况。

为避免出现上述问题,可以使用Direct3D提供的API来获取屏幕的内容,具体的代码如下:

#include <d3d9helper.h>
#pragma comment(lib,"d3d9.lib")

LPDIRECT3D9 g_pObjD3d = NULL;
IDirect3DDevice9 *g_pObjD3dDevice = NULL;
IDirect3DSurface9* g_pObjSurface = NULL;

int initDirect3D()
{
    DEVMODEA dm = { 0 };
    dm.dmSize = sizeof(DEVMODEA);
    EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
    int nScreenWidth = dm.dmPelsWidth;
    int nScreenHeight = dm.dmPelsHeight;
    HWND hDesktopWnd = GetDesktopWindow();

    g_pObjD3d = Direct3DCreate9(D3D_SDK_VERSION);
    if (g_pObjD3d == NULL)
    {
        return -1;
    }

    //设置呈现参数
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferCount = 1;
    d3dpp.BackBufferWidth = nScreenWidth;
    d3dpp.BackBufferHeight = nScreenHeight;
    d3dpp.hDeviceWindow = hDesktopWnd;

    //创建D3D的设备
    g_pObjD3d->CreateDevice(
        D3DADAPTER_DEFAULT,
        D3DDEVTYPE_HAL,
        hDesktopWnd,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING,
        &d3dpp,
        &g_pObjD3dDevice
    );

    if (g_pObjD3dDevice == NULL)
    {
        return -1;
    }

    if (D3D_OK != g_pObjD3dDevice->CreateOffscreenPlainSurface(nScreenWidth, nScreenHeight,
        D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
        &g_pObjSurface, NULL))
    {
        return -1;
    }

    return 0;
}

void termDirect3D()
{
    if (NULL != g_pObjSurface)
    {
        g_pObjSurface->Release();
        g_pObjSurface = NULL;
    }

    if (NULL != g_pObjD3dDevice)
    {
        g_pObjD3dDevice->Release();
        g_pObjD3dDevice = NULL;
    }

    if (NULL != g_pObjD3d)
    {
        g_pObjD3d->Release();
        g_pObjD3d = NULL;
    }
}

void GetDesktopImageByDx(unsigned char* buffer)
{
    DEVMODEA dm = { 0 };
    dm.dmSize = sizeof(DEVMODEA);
    EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
    int nScreenWidth = dm.dmPelsWidth;
    int nScreenHeight = dm.dmPelsHeight;

    g_pObjD3dDevice->GetFrontBufferData(0, g_pObjSurface);
    D3DLOCKED_RECT lockedRect;
    g_pObjSurface->LockRect(&lockedRect, NULL,
        D3DLOCK_NO_DIRTY_UPDATE |
        D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY);
    for (int i = 0; i < nScreenHeight; i++)
    {
        memcpy((BYTE*)buffer + i * nScreenWidth * 32 / 8,
            (BYTE*)lockedRect.pBits + i * lockedRect.Pitch,
            nScreenWidth * 32 / 8);
    }
    g_pObjSurface->UnlockRect();
}

 

posted @ 2023-02-21 11:05  竿钓蝉  阅读(86)  评论(0编辑  收藏  举报