将屏幕绘图翻译成屏幕的另一部分

时间:2018-01-03 08:03:07

标签: c++ windows graphics

是否有可能使所有人都画到一个区域" A"被翻译成一个区域" B"?

例如绘制到区域(0,0)(100,100)并将其显示在区域(200,200)(300,300)中。

1 个答案:

答案 0 :(得分:2)

问题实际上是使用标记的。这可能是针对Win32和GDI(我很遗憾几乎没有经验)。因此,以下可能被视为概念证明:

我无法抗拒使用QWindowQPixmap来实现这个想法/概念。

概念是:

  1. 全屏打开一个窗口(即没有装饰)

  2. 制作快照并将其存储在内部(在我的情况下为a)

  3. 在窗口中显示内部图像(用户无法注意到差异)

  4. 执行一个循环,其中pixmap被修改并定期重新显示(取决于或不取决于用户输入)。

  5. 这就是我在Qt中的表现:

    1. 我打开QWindow并将其全屏显示。 (最大尺寸可能会使窗口全屏显示,但仍然会有装饰(带有系统菜单的标题栏等),这是无意的。)

    2. 在绘制任何内容之前,此窗口的快照已完成。使用QScreen::grabWindow()在Qt中这很容易。抓取的内容将返回QPixmap并存储为我的派生Window类的成员。

    3. 视觉输出只绘制存储的成员QPixmap

    4. 我使用QTimer来强制QPixmap的定期更改。为了使示例代码尽可能短,我没有努力改变瓦片。相反,我只是滚动像素图复制一小部分,向上移动其余部分,再次在底部插入小条纹。

    5. 示例代码qWindowRoll.cc

      #include <QtWidgets>
      
      class Window: public QWindow {
        private:
          // the Qt backing store for window
          QBackingStore _qBackStore;
          // background pixmap
          QPixmap _qPixmap;
      
        public:
          // constructor.
        Window():
          QWindow(),
          _qBackStore(this)
          {
            showFullScreen();
          }
          // destructor.
          virtual ~Window() = default;
          // disabled:
          Window(const Window&) = delete;
          Window& operator=(const Window&) = delete;
      
          // do something with pixmap
          void changePixmap()
          {
            enum { n = 4 };
            if (_qPixmap.height() < n) return; // not yet initialized
            const QPixmap qPixmapTmp = _qPixmap.copy(0, 0, _qPixmap.width(), n);
            //_qPixmap.scroll(0, -n, 0, n, _qPixmap.width(), _qPixmap.height() - n);
            { QPainter qPainter(&_qPixmap);
              qPainter.drawPixmap(
                QRect(0, 0, _qPixmap.width(), _qPixmap.height() - n),
                _qPixmap,
                QRect(0, n, _qPixmap.width(), _qPixmap.height() - n));
              qPainter.drawPixmap(0, _qPixmap.height() - n, qPixmapTmp);
            }
            requestUpdate();
          }
      
        protected: // overloaded events
      
          virtual bool event(QEvent *pQEvent) override
          {
            if (pQEvent->type() == QEvent::UpdateRequest) {
              paint();
              return true;
            }
            return QWindow::event(pQEvent);
          }
      
          virtual void resizeEvent(QResizeEvent *pQEvent)
          {
            _qBackStore.resize(pQEvent->size());
            paint();
          }
      
          virtual void exposeEvent(QExposeEvent*) override
          {
            paint();
          }
      
          // shoot screen
          // inspired by http://doc.qt.io/qt-5/qtwidgets-desktop-screenshot-screenshot-cpp.html
          void makeScreenShot()
          {
            if (QScreen *pQScr = screen()) {
              _qPixmap = pQScr->grabWindow(winId());
            }
          }
      
        private: // internal stuff
          // paint
          void paint()
          {
            if (!isExposed()) return;
            QRect qRect(0, 0, width(), height());
            if (_qPixmap.width() != width() || _qPixmap.height() != height()) {
              makeScreenShot();
            }
            _qBackStore.beginPaint(qRect);
            QPaintDevice *pQPaintDevice = _qBackStore.paintDevice();
            QPainter qPainter(pQPaintDevice);
            qPainter.drawPixmap(0, 0, _qPixmap);
            _qBackStore.endPaint();
            _qBackStore.flush(qRect);
          }
      
      };
      
      int main(int argc, char **argv)
      {
        QApplication app(argc, argv);
        // setup GUI
        Window win;
        win.setVisible(true);
        // setup timer
        QTimer qTimer;
        qTimer.setInterval(50); // 50 ms -> 20 Hz (round about)
        QObject::connect(&qTimer, &QTimer::timeout,
          &win, &Window::changePixmap);
        qTimer.start();
        // run application
        return app.exec();
      }
      

      我在Windows 10上使用Qt 5.9.2编译和测试。这就是它的外观:

      Snapshot sequence of qWindowRoll

      注意:在我的桌面上,滚动很流畅。我手动制作了4张快照并在GIMP中组成了一个GIF - 因此图像看起来有点卡顿。