- 在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() 取代
作者:dbzhang800