window/screen + 屏幕截图上发生任何更改时的 Qt 事件
Qt event when anything changed on the window/screen + Screenshot
我正在考虑扩展具有一些调试可能性的 QT4 应用程序,以便更轻松地分析客户问题。该应用程序已经有一个 "Debug" 模式,当启用它时,会生成很多日志条目,很难阅读。
我想要实现的是在 GUI 上发生更改时截取应用程序的屏幕截图。我知道可能会拍很多照片,但一般都是长时间不开启Debug模式。问题是我找不到这样的event/signal。所以我有两个问题:
- 有这样的活动我可以订阅吗?我的意思是,一个事件是
每当屏幕上发生任何变化时都会触发。
- 我可以使用 Qt 截取应用程序的屏幕截图吗?
提前致谢!
关于你的第二个问题,here是我的一些旧代码,可以截图一个window。您可以像这样使用此代码:
HDC WinDC = GetDC(HWND_OF_YOUR_WINDOW);
HBITMAP image = ScreenshotUtility::fromHDC(WinDC);
然后您可以将 HBITMAP 转换为 Qt Pixmap 对象并按您喜欢的方式使用它:QPixmap pixmap = QPixmap::fromWinHBITMAP(image);
.
编辑:这是 Windows 特定的代码,不确定其他系统上的等效代码是什么。
一般来说,当一些widget改变时Qt需要重新绘制它,所以你会感兴趣的事件是QEvent::Paint
。这里的问题是,对于彼此重叠的小部件,将会有大量这些事件。您可以覆盖 QApplication::notify()
以在所有绘制事件交付给接收者之前捕获它们。
关于制作Qt应用程序的屏幕截图-SO上有几个类似的问题,例如screenshot of a qt application from inside the application or Taking screenshot of a specific window - C++ / Qt
Here 也是讨论将小部件转储到 paintEvent()
中图像的线程。
我会使用事件过滤器和 QTimer 来完成,就像这样:
class MyEventFilter : public QObject
{
public:
MyEventFilter() : _screenshotPending(false) {/* empty */}
virtual bool eventFilter(QObject * o, QEvent * e)
{
if (e->type() == QEvent::Paint)
{
if (_screenshotPending == false)
{
// we'll wait 500mS before taking the screenshot
// that way we aren't trying to take 1000 screenshots per second :)
_screenshotPending = true;
QTimer::singleShot(500, this, SLOT(TakeAScreenshot()));
}
}
return QObject::eventFilter(o, e);
}
public slots:
void TakeAScreenshot()
{
_screenshotPending = false;
// add the standard Qt code for taking a screenshot here
// see $QTDIR/examples/widgets/desktop/screenshot for that
}
private:
bool _screenshotPending; // true iff we've called QTimer::singleShot() recently
};
int main(int argc, char ** argv)
{
MyEventFilter filter;
QApplication app(argc, argv);
app.installEventFilter(&filter);
[...]
return app.exec();
}
我正在考虑扩展具有一些调试可能性的 QT4 应用程序,以便更轻松地分析客户问题。该应用程序已经有一个 "Debug" 模式,当启用它时,会生成很多日志条目,很难阅读。 我想要实现的是在 GUI 上发生更改时截取应用程序的屏幕截图。我知道可能会拍很多照片,但一般都是长时间不开启Debug模式。问题是我找不到这样的event/signal。所以我有两个问题:
- 有这样的活动我可以订阅吗?我的意思是,一个事件是 每当屏幕上发生任何变化时都会触发。
- 我可以使用 Qt 截取应用程序的屏幕截图吗?
提前致谢!
关于你的第二个问题,here是我的一些旧代码,可以截图一个window。您可以像这样使用此代码:
HDC WinDC = GetDC(HWND_OF_YOUR_WINDOW);
HBITMAP image = ScreenshotUtility::fromHDC(WinDC);
然后您可以将 HBITMAP 转换为 Qt Pixmap 对象并按您喜欢的方式使用它:QPixmap pixmap = QPixmap::fromWinHBITMAP(image);
.
编辑:这是 Windows 特定的代码,不确定其他系统上的等效代码是什么。
一般来说,当一些widget改变时Qt需要重新绘制它,所以你会感兴趣的事件是QEvent::Paint
。这里的问题是,对于彼此重叠的小部件,将会有大量这些事件。您可以覆盖 QApplication::notify()
以在所有绘制事件交付给接收者之前捕获它们。
关于制作Qt应用程序的屏幕截图-SO上有几个类似的问题,例如screenshot of a qt application from inside the application or Taking screenshot of a specific window - C++ / Qt
Here 也是讨论将小部件转储到 paintEvent()
中图像的线程。
我会使用事件过滤器和 QTimer 来完成,就像这样:
class MyEventFilter : public QObject
{
public:
MyEventFilter() : _screenshotPending(false) {/* empty */}
virtual bool eventFilter(QObject * o, QEvent * e)
{
if (e->type() == QEvent::Paint)
{
if (_screenshotPending == false)
{
// we'll wait 500mS before taking the screenshot
// that way we aren't trying to take 1000 screenshots per second :)
_screenshotPending = true;
QTimer::singleShot(500, this, SLOT(TakeAScreenshot()));
}
}
return QObject::eventFilter(o, e);
}
public slots:
void TakeAScreenshot()
{
_screenshotPending = false;
// add the standard Qt code for taking a screenshot here
// see $QTDIR/examples/widgets/desktop/screenshot for that
}
private:
bool _screenshotPending; // true iff we've called QTimer::singleShot() recently
};
int main(int argc, char ** argv)
{
MyEventFilter filter;
QApplication app(argc, argv);
app.installEventFilter(&filter);
[...]
return app.exec();
}