美文网首页
如何在windows截屏的时候带上鼠标光标

如何在windows截屏的时候带上鼠标光标

作者: 叶迎宪 | 来源:发表于2018-06-23 16:56 被阅读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

    实现要点:

    1. 调用CreateDIBSection创建一个bitmap,用于将截屏图像放上去并且在上面使用GDI进行绘制
    2. 使用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);
    
            // ...省略了后面
    }
    
    

    相关文章

      网友评论

          本文标题:如何在windows截屏的时候带上鼠标光标

          本文链接:https://www.haomeiwen.com/subject/nkqdyftx.html