如何在windows截屏的时候带上鼠标光标
2018-06-23 本文已影响0人
叶迎宪
https://www.codeproject.com/Articles/5051/Various-methods-for-capturing-the-screen 文章中提到,使用GDI或者DirectX方法截屏的时候,是不会有鼠标在截图之中的。要将鼠标补上,必须自己动手画。可以参考ffmpeg当中的gdigrab.c实现 https://github.com/FFmpeg/FFmpeg/blob/master/libavdevice/gdigrab.c
实现要点:
- 调用CreateDIBSection创建一个bitmap,用于将截屏图像放上去并且在上面使用GDI进行绘制
- 使用GetCursorInfo获得当前鼠标的信息,调用DrawIcon将鼠标光标画上去
HDC dcTemp; // 用于绘制鼠标的DC
HBITMAP hBmp; // 存放截图和用于绘制的bitmap
void *gdiBuffer; // 存放截图和绘制结果的缓存区
bool InitGDI()
{
HDC dcDesktop = ::GetDC(NULL);
dcTemp = ::CreateCompatibleDC(dcDesktop);
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
//prepare the bitmap attributes
BITMAPINFO bmInfo;
memset(&bmInfo.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmInfo.bmiHeader.biWidth = screenWidth;
bmInfo.bmiHeader.biHeight = -screenHeight;
bmInfo.bmiHeader.biPlanes = 1;
bmInfo.bmiHeader.biBitCount = 32;
bmInfo.bmiHeader.biCompression = BI_RGB;
gdiBuffer = NULL;
hBmp = CreateDIBSection(dcTemp, &bmInfo, DIB_RGB_COLORS,
&gdiBuffer, NULL, 0);
SelectObject(dcTemp, hBmp);
if (dcDesktop)
ReleaseDC(NULL, dcDesktop);
return true;
}
void DeinitGDI()
{
if (dcTemp)
DeleteDC(dcTemp);
if (hBmp)
DeleteObject(hBmp);
}
void PaintMousePointer()
{
CURSORINFO ci = { 0 };
ci.cbSize = sizeof(ci);
if (GetCursorInfo(&ci)) {
HCURSOR icon = CopyCursor(ci.hCursor);
ICONINFO info;
POINT pos;
info.hbmMask = NULL;
info.hbmColor = NULL;
if (ci.flags != CURSOR_SHOWING)
return;
if (!icon) {
/* Use the standard arrow cursor as a fallback.
* You'll probably only hit this in Wine, which can't fetch
* the current system cursor. */
icon = CopyCursor(LoadCursor(NULL, IDC_ARROW));
}
if (!GetIconInfo(icon, &info)) {
goto icon_error;
}
pos.x = ci.ptScreenPos.x - info.xHotspot;
pos.y = ci.ptScreenPos.y - info.yHotspot;
if (!DrawIcon(dcTemp, pos.x, pos.y, icon))
{
}
icon_error:
if (info.hbmMask)
DeleteObject(info.hbmMask);
if (info.hbmColor)
DeleteObject(info.hbmColor);
if (icon)
DestroyCursor(icon);
}
else {
}
}
HRESULT capture(IDirect3DDevice9* d3ddev9)
{
// ...省略截屏部分
if (lr.pBits)
{
uint8_t *dst_data[4] = { 0 };
int dst_linesize[4];
uint8_t *src_data[4] = { 0 };
int src_linesize[4];
struct SwsContext *sws_ctx = NULL;
AVFrame *frame = NULL;
int ret;
// 将截屏数据放入bitmap中
memcpy(gdiBuffer, lr.pBits, screenWidth * screenHeight * 4);
// 把鼠标画上去
PaintMousePointer();
// ...省略了中间部分
// 将bitmap的BGRA格式转换成YUV420P
src_data[0] = (uint8_t*)gdiBuffer;
src_linesize[0] = screenWidth * 4;
sws_scale(sws_ctx, src_data,
src_linesize, 0, screenHeight, dst_data, dst_linesize);
// ...省略了后面
}