使用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(); }