Xlib 应用被覆盖遮挡或者移出屏幕时,获取窗口截图

https://www.cnblogs.com/chaichengxun/p/15409996.html这篇文章里已经讲过,如果应用窗口位于屏幕外或者被遮挡,xlib不能获取完整的应用窗口截屏,如下

今天就来解决这个问题。

用到的头文件:

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>

用到的库:

-lXlib -lXcomposite -lXrender

代码:

复制代码
static Display *xdisplay = 0;

Display *disp()
{
    if (!xdisplay)
        xdisplay = XOpenDisplay(NULL);

    return xdisplay;
}

XImage* GetDrawableThumbnail(Drawable src_drawable,
                             Visual* visual,
                             int src_width,
                             int src_height) {
    XRenderPictFormat* format = XRenderFindVisualFormat(disp(),
                                                        visual);
    if (!format) {
        cout <<"XRenderFindVisualFormat() failed";
        return NULL;
    }

    XRenderPictureAttributes pa;
    pa.subwindow_mode = IncludeInferiors;
    Picture src = XRenderCreatePicture(disp(),
                                       src_drawable,
                                       format,
                                       CPSubwindowMode,
                                       &pa);
    if (!src) {
        cout << "XRenderCreatePicture() failed";
        return NULL;
    }

    Pixmap dst_pixmap = XCreatePixmap(disp(),
                                      src_drawable,
                                      src_width,
                                      src_height,
                                      format->depth);
    if (!dst_pixmap) {
        cout << "XCreatePixmap() failed";
        XRenderFreePicture(disp(), src);
        return NULL;
    }
    Picture dst = XRenderCreatePicture(disp(), dst_pixmap, format, 0, NULL);
    if (!dst) {
        cout << "XRenderCreatePicture() failed";
        XFreePixmap(disp(), dst_pixmap);
        XRenderFreePicture(disp(), src);
        return NULL;
    }

    XRenderColor transparent = {0};
    XRenderFillRectangle(disp(),
                         PictOpSrc,
                         dst,
                         &transparent,
                         0,
                         0,
                         src_width,
                         src_height);

    XTransform xform = { {
                             { XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0) },
                             { XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0) },
                             { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }
                         } };
    XRenderSetPictureTransform(disp(), src, &xform);
    XRenderSetPictureFilter(disp(), src, FilterBest, NULL, 0);
    XRenderComposite(disp(),
                     PictOpSrc,
                     src,
                     None,
                     dst,
                     0,
                     0,
                     0,
                     0,
                     0,
                     0,
                     src_width,
                     src_height);
    XImage* image = XGetImage(disp(),
                              dst_pixmap,
                              0,
                              0,
                              src_width,
                              src_height,
                              AllPlanes, ZPixmap);
    return image;
}
复制代码

将XImage转换成QPixmap:

复制代码
void AppListSelDlg::GetPixmap(unsigned long win, QPixmap &pixmap)
{
    Display *display_ = disp();

    XCompositeRedirectWindow(display_, win, CompositeRedirectAutomatic);
    Pixmap src_pixmap = XCompositeNameWindowPixmap(display_, win);
    if (!src_pixmap) {
        printf("XCompositeNameWindowPixmap() failed");
        return;
    }

    XWindowAttributes attr;
    if (!XGetWindowAttributes(display_, win, &attr)) {
        printf( "XGetWindowAttributes() failed");
        XFreePixmap(display_, src_pixmap);
        return ;
    }

    XImage* pImage = XCompcap::GetDrawableThumbnail(src_pixmap,
                                          attr.visual,
                                          attr.width,
                                          attr.height);

    QImage image = QImage((const uchar *)(pImage->data), pImage->width, pImage->height, pImage->bytes_per_line, QImage::Format_RGB32);
    pixmap = QPixmap::fromImage(image);
    XDestroyImage(pImage);
    XFreePixmap(display_, src_pixmap);
}
复制代码

 

看一下实际效果:

 

 

可以看出,虽然终端遮挡住了文件夹,但是获取到的图像仍然是完整的图像。

posted @   柴承训  阅读(832)  评论(3编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示
主题色彩