首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何用Qt API制作包含鼠标光标的截图?

如何用Qt API制作包含鼠标光标的截图?
EN

Stack Overflow用户
提问于 2012-04-17 11:47:56
回答 3查看 1.7K关注 0票数 2

我希望屏幕截图中有鼠标光标,但QT -- QPixmap::grabWindow()中的grab API只能在没有光标的情况下创建屏幕截图。

我可以自己在图片中绘制光标,但我必须获取光标图片,截图中的光标将保持不变的光标图片。太难看了。有没有更好的解决方案?

EN

回答 3

Stack Overflow用户

发布于 2012-04-17 19:28:46

根据QPixmap::grabWindow文档,它不会捕获鼠标光标,

我认为你需要确定鼠标的位置,然后自己画光标。您可以使用QCursor cursor() const接口从QWidget获取QCursor。

而QCursor有QPixmap pixmap ()接口,你可以用这个Pixmap来绘制鼠标光标。

如果我不能正确理解您的问题,很抱歉。

票数 4
EN

Stack Overflow用户

发布于 2020-03-07 22:47:48

以下是跨平台的解决方案:

代码语言:javascript
运行
复制
#include <assert.h>
#include <QCursor>
#include <QPainter>

#ifdef Q_OS_LINUX
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xfixes.h>
#else // Q_OS_WINDOWs
#include <Windows.h>
#include <wingdi.h>
#pragma comment (lib, "User32.lib")
#pragma comment (lib, "Gdi32.lib")
#include <QtWinExtras>
#endif

namespace imageutil {

#ifdef Q_OS_LINUX

/* WebCore/plugins/qt/QtX11ImageConversion.cpp */
QImage qimageFromXImage(XImage* xi) {
    QImage::Format format = QImage::Format_ARGB32_Premultiplied;
    if (xi->depth == 24)
        format = QImage::Format_RGB32;
    else if (xi->depth == 16)
        format = QImage::Format_RGB16;

    QImage image = QImage(reinterpret_cast<uchar*>(xi->data), xi->width, xi->height, xi->bytes_per_line, format).copy();

    // we may have to swap the byte order
    if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
            || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst)) {

        for (int i = 0; i < image.height(); i++) {
            if (xi->depth == 16) {
                ushort* p = reinterpret_cast<ushort*>(image.scanLine(i));
                ushort* end = p + image.width();
                while (p < end) {
                    *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
                    p++;
                }
            } else {
                uint* p = reinterpret_cast<uint*>(image.scanLine(i));
                uint* end = p + image.width();
                while (p < end) {
                    *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
                         | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
                    p++;
                }
            }
        }
    }

    // fix-up alpha channel
    if (format == QImage::Format_RGB32) {
        QRgb* p = reinterpret_cast<QRgb*>(image.bits());
        for (int y = 0; y < xi->height; ++y) {
            for (int x = 0; x < xi->width; ++x)
                p[x] |= 0xff000000;
            p += xi->bytes_per_line / 4;
        }
    }

    return image;
}

#endif // Q_OS_LINUX

QPixmap takeScreenShot(const QRect& area) {
    QRect screen; /* interested display area */
    QImage qimage; /* result image */

#ifdef Q_OS_LINUX
    QPoint cursorPos;

    Display* display = XOpenDisplay(nullptr);
    Window root = DefaultRootWindow(display);

    XWindowAttributes gwa;
    XGetWindowAttributes(display, root, &gwa);

    const auto goodArea = QRect(0, 0, gwa.width, gwa.height).contains(area);
    if (!goodArea) {
        screen = QRect(0, 0, gwa.width, gwa.height);
        cursorPos = QCursor::pos();
    } else {
        screen = area;
        cursorPos = QCursor::pos() - screen.topLeft();
    }

    XImage* image = XGetImage(display, root, screen.x(), screen.y(), screen.width(), screen.height(), AllPlanes, ZPixmap);
    assert(nullptr != image);

    qimage = qimageFromXImage(image);

    /* draw mouse cursor into QImage
     * https://msnkambule.wordpress.com/2010/04/09/capturing-a-screenshot-showing-mouse-cursor-in-kde/
     * https://github.com/rprichard/x11-canvas-screencast/blob/master/CursorX11.cpp#L31
     * */
    {
        XFixesCursorImage* cursor = XFixesGetCursorImage(display);
        cursorPos -= QPoint(cursor->xhot, cursor->yhot);
        std::vector<uint32_t> pixels(cursor->width * cursor->height);
        for (size_t i = 0; i < pixels.size(); ++i)
            pixels[i] = cursor->pixels[i];
        QImage cursorImage((uchar*)(pixels.data()), cursor->width, cursor->height, QImage::Format_ARGB32_Premultiplied);
        QPainter painter(&qimage);
        painter.drawImage(cursorPos, cursorImage);
        XFree(cursor);
    }

    XDestroyImage(image);
    XDestroyWindow(display, root);
    XCloseDisplay(display);

#elif defined(Q_OS_WINDOWS)
    HWND hwnd = GetDesktopWindow();
    HDC hdc = GetWindowDC(hwnd);
    HDC hdcMem = CreateCompatibleDC(hdc);

    RECT rect = { 0, 0, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES) };
    const auto goodArea = QRect(rect.left, rect.top, rect.right, rect.bottom).contains(area);
    if (!goodArea) {
        screen = QRect(rect.left, rect.top, rect.right, rect.bottom);
    } else {
        screen = area;
    }

    HBITMAP hbitmap(nullptr);
    hbitmap = CreateCompatibleBitmap(hdc, screen.width(), screen.height());
    SelectObject(hdcMem, hbitmap);
    BitBlt(hdcMem, 0, 0, screen.width(), screen.height(), hdc, screen.x(), screen.y(), SRCCOPY);

    /* draw mouse cursor into DC
     * https://stackoverflow.com/a/48925443/5446734
     * */
    CURSORINFO cursor = { sizeof(cursor) };
    if (GetCursorInfo(&cursor) && cursor.flags == CURSOR_SHOWING) {
        RECT rect;
        GetWindowRect(hwnd, &rect);
        ICONINFO info = { sizeof(info) };
        GetIconInfo(cursor.hCursor, &info);
        const int x = (cursor.ptScreenPos.x - rect.left - rect.left - info.xHotspot) - screen.left();
        const int y = (cursor.ptScreenPos.y - rect.left - rect.left - info.yHotspot) - screen.top();
        BITMAP bmpCursor = { 0 };
        GetObject(info.hbmColor, sizeof(bmpCursor), &bmpCursor);
        DrawIconEx(hdcMem, x, y, cursor.hCursor, bmpCursor.bmWidth, bmpCursor.bmHeight,
                   0, nullptr, DI_NORMAL);
    }

    qimage = QtWin::imageFromHBITMAP(hdc, hbitmap, screen.width(), screen.height());
#endif // Q_OS_LINUX

    return QPixmap::fromImage(qimage);
}

} // namespace imageutil

别忘了添加到qmake:

代码语言:javascript
运行
复制
win32: QT += winextras
unix:!macx: LIBS += -lX11 -lXext -lXfixes
票数 2
EN

Stack Overflow用户

发布于 2013-01-11 02:06:17

仅当光标为像素图时,QPixmap::pixmap才有效。当当前游标是标准游标时,不起作用。一些想法总是可以得到一个包含实际光标的像素图?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10184784

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档