简体   繁体   English

当窗口/屏幕上的任何内容发生变化时,Qt事件+屏幕截图

[英]Qt event when anything changed on the window/screen + Screenshot

I'm thinking of extending a QT4 application with some debug possibilities, to make it easier analyzing customer issues. 我正在考虑扩展QT4应用程序以及一些调试可能性,以便更轻松地分析客户问题。 The application already has a "Debug" mode, when this is enabled, a lot of log entries generated, which is hard to read. 应用程序已经具有“调试”模式,当启用此模式时,会生成大量日志条目,这很难读取。 What I would like to achive is taking a screenshot of the application, whenever something is changed on the GUI. 我想要实现的是在GUI上更改某些内容时截取应用程序的屏幕截图。 I know that it may take a lot of pictures, but generally Debug mode is not enabled for a long time. 我知道它可能需要很多图片,但通常调试模式很长时间都没有启用。 The problem is I cannot find such an event/signal. 问题是我找不到这样的事件/信号。 So I have two question: 所以我有两个问题:

  1. Is there such an event I could subscribe? 我可以订阅这样的活动吗? I mean, an event that is fired whenever anything changes on the screen. 我的意思是,只要屏幕上发生任何变化,就会触发一个事件。
  2. Can I take a screenshot of the application using Qt? 我可以使用Qt截取应用程序的屏幕截图吗?

Thanks in advance! 提前致谢!

I'd do it using an event filter and a QTimer, something like this: 我会使用事件过滤器和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();
}

Generally, when some widget changes Qt needs to repaint it, so the event you would be interested in is QEvent::Paint . 通常,当某些窗口小部件更改时,Qt需要重新绘制它,因此您感兴趣的事件是QEvent::Paint The problem here is that there will be tons of these events for widgets that overlap each other. 这里的问题是,对于彼此重叠的小部件,将有大量这些事件。 You can override QApplication::notify() to catch all paint events before they are even delivered to receivers. 您可以覆盖QApplication::notify()以在将所有绘制事件传递给接收者之前捕获它们。

As for making screenshots of Qt application - there are several similar questions here on SO, for example screenshot of a qt application from inside the application or Taking screenshot of a specific window - C++ / Qt 至于制作Qt应用程序的截图 - 这里有几个类似的问题,例如来自应用程序内部的qt应用程序的 截图截取特定窗口的截图 - C ++ / Qt

Here is also a thread discussing dumping widgets to images in paintEvent() . 这里还讨论了在paintEvent()中将小部件转储到图像的线程。

As for your second question, here is some of my old code that can take a screenshot of a window. 关于你的第二个问题, 这里有一些旧代码可以截取窗口的截图。 You can use this code like so: 您可以像这样使用此代码:

HDC WinDC = GetDC(HWND_OF_YOUR_WINDOW);
HBITMAP image = ScreenshotUtility::fromHDC(WinDC);

Then you can convert the HBITMAP to a Qt Pixmap object and work with it how you like: QPixmap pixmap = QPixmap::fromWinHBITMAP(image); 然后你可以将HBITMAP转换为Qt Pixmap对象并按照你喜欢的方式使用它: QPixmap pixmap = QPixmap::fromWinHBITMAP(image); .

EDIT: this is Windows-specific code, not sure what the equivalent on other systems may be. 编辑:这是特定于Windows的代码,不确定其他系统上的等效代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM