QDesktopWidget 乱谈?

  • 在QWidget的众多派生类之中,QDesktopWidget比较特殊的一个(另一个比较特殊的是QAxWidget,定义了信号槽,却不使用Q_OBJECT这个宏)。

我们知道QDesktopWidget的作用就是获取和桌面相关的各种信息。恩,其实,它和QWidget没有多少共同点。

特殊之处?

class Q_WIDGETS_EXPORT QDesktopWidget : public QWidget
{
...
protected:
    void resizeEvent(QResizeEvent *e);
...
};

一般很少见到直接从QWidget派生的类,却没有实现自己的paintEvent()函数。这QDesktopWidget便是这样的一个。

grabWidget()

  • 如果你尝试使用 QPixmap::grabWidget()来抓取桌面,会发现什么都抓不到

QDesktopWidget只是桌面根窗口的一个封装器,而该桌面并不是你的进程的一部分。因此它不能通过常规QWidget的事件处理机制来接受任何事件。因此将QPixmap::grabWidget()应用到该窗口上并不能工作。

QPixmap::grabWidget()最终还是通过 paintEvent()函数内的操作进行绘制的。由于QDesktopWidget没有自己的paintEvent(),其父类QWidget的paintEvent()又是空的,故而...

注:

QPximap::grabWidget() 在Qt5中已被 QWidget::grab() 取代(因为QPixmap所在的QtGui模块不能依赖QWidget所在的QtWidgets模块)。

grabWindow()

如果要抓取桌面,需要用QPixmap::grabWindow(),与前者不同,该函数的参数是平台相关的句柄。而后是平台相关的代码根据该句柄抓取相应内容。

比如:在windows下,QDesktopWidget的句柄是通过系统的api函数GetDesktopWindow()获得,并没有创建一个新的窗口。

QWindowsWindow::WindowData
    WindowCreationData::create(const QWindow *w, const QRect &geometry, QString title) const
{
...
    if (desktop) {                        // desktop widget. No frame, hopefully?
        result.hwnd = GetDesktopWindow();
        result.geometry = frameGeometry(result.hwnd, true);
        if (QWindowsContext::verboseWindows)
            qDebug().nospace() << "Created desktop window " << w << result.hwnd;
        return result;
    }
...

而后

QPixmap QWindowsScreen::grabWindow(WId window, int x, int y, int width, int height) const
{
    RECT r;
    HWND hwnd = (HWND)window;
    GetClientRect(hwnd, &r);
...
    // Create and setup bitmap
    HDC display_dc = GetDC(0);
    HDC bitmap_dc = CreateCompatibleDC(display_dc);
    HBITMAP bitmap = CreateCompatibleBitmap(display_dc, width, height);
    HGDIOBJ null_bitmap = SelectObject(bitmap_dc, bitmap);

    // copy data
    HDC window_dc = GetDC(hwnd);
    BitBlt(bitmap_dc, 0, 0, width, height, window_dc, x, y, SRCCOPY | CAPTUREBLT);
...

注: 在Qt5中 QPixmap::grabWindow()将被 QScreen::grabWindow() 取代

参考


你可能感兴趣的:(Desktop)