- 在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() 取代
本文深入探讨了QDesktopWidget类的特点及用途,特别是它如何与其他QWidget类不同,以及如何使用QPixmap::grabWindow()来捕获桌面内容。
717

被折叠的 条评论
为什么被折叠?



