Web Browser Example (ActiveQt)

该代码演示了Qt应用程序如何使用信号,插槽和dynamicCall()函数与嵌入式ActiveX控件进行通信。


  class MainWindow : public QMainWindow, public Ui::MainWindow
  {
      Q_OBJECT
  public:
      MainWindow();
      ~MainWindow();

  public slots:
      void navigate(const QString &address);
      void on_WebBrowser_TitleChange(const QString &title);
      void on_WebBrowser_ProgressChange(int a, int b);
      void on_WebBrowser_CommandStateChange(int cmd, bool on);
      void on_WebBrowser_BeforeNavigate();
      void on_WebBrowser_NavigateComplete(const QString &address);

      void on_actionGo_triggered();
      void on_actionNewWindow_triggered();
      void on_actionAddBookmark_triggered();
      void on_actionAbout_triggered();
      void on_actionAboutQt_triggered();
      void on_actionFileClose_triggered();

  private:
      inline const QString address() const
          { return addressEdit->text().trimmed(); }
      QList<Location> bookmarks() const;
      QAction *addLocation(const Location &location, QMenu *menu);
      inline void addBookmark(const Location &location)
          { bookmarkActions << addLocation(location, BookmarksMenu); }

      QProgressBar *pb;
      QLineEdit *addressEdit;
      QList<QAction *> bookmarkActions;
      QList<QAction *> historyActions;
      QSignalMapper locationActionMapper;
  };

The MainWindow class declares a QMainWindow based user interface, using the Ui::MainWindow class generated by Qt Designer. A number of slots are implemented to handle events from the various user interface elements, including the WebBrowser object, which is a QAxWidget hosting the Microsoft Web Browser control.


  MainWindow::MainWindow()
  {
      setupUi(this);

      addressEdit = new QLineEdit;
      tbAddress->insertWidget(actionGo, new QLabel(tr("Address")));
      tbAddress->insertWidget(actionGo, addressEdit);

      connect(addressEdit, SIGNAL(returnPressed()), actionGo, SLOT(trigger()));
      connect(actionBack, SIGNAL(triggered()), WebBrowser, SLOT(GoBack()));
      connect(actionForward, SIGNAL(triggered()), WebBrowser, SLOT(GoForward()));
      connect(actionStop, SIGNAL(triggered()), WebBrowser, SLOT(Stop()));
      connect(actionRefresh, SIGNAL(triggered()), WebBrowser, SLOT(Refresh()));
      connect(actionHome, SIGNAL(triggered()), WebBrowser, SLOT(GoHome()));
      connect(actionSearch, SIGNAL(triggered()), WebBrowser, SLOT(GoSearch()));

      pb = new QProgressBar(statusBar());
      pb->setTextVisible(false);
      pb->hide();
      statusBar()->addPermanentWidget(pb);

      connect(&locationActionMapper, SIGNAL(mapped(QString)), this, SLOT(navigate(QString)));

      QSettings settings(QSettings::IniFormat, QSettings::UserScope,
                         QCoreApplication::organizationName(), QCoreApplication::applicationName());
      const QByteArray restoredGeometry = settings.value(QLatin1String(geometryKey)).toByteArray();
      if (restoredGeometry.isEmpty() || !restoreGeometry(restoredGeometry)) {
          const QRect availableGeometry = QApplication::desktop()->availableGeometry(this);
          const QSize size = (availableGeometry.size() * 4) / 5;
          resize(size);
          move(availableGeometry.center() - QPoint(size.width(), size.height()) / 2);
      }
      const QString restoredVersion = settings.value(QLatin1String(versionKey)).toString();
      QList<Location> bookmarks = readBookMarks(settings);
      if (bookmarks.isEmpty() || restoredVersion.isEmpty())
          bookmarks = defaultBookmarks();
      for (const Location &bookmark : qAsConst(bookmarks))
          addBookmark(bookmark);
  }

The constructor initializes the user interface, installs a progress bar on the status bar, and loads the bookmarks.


  void MainWindow::on_WebBrowser_TitleChange(const QString &title)
  {
      // This is called multiple times after NavigateComplete().
      // Add new URLs to history here.
      setWindowTitle("Qt WebBrowser - " + title);
      const QString currentAddress = address();
      const QString historyAddress = historyActions.isEmpty() ?
          QString() : locationFromAction(historyActions.last()).address;
      if (currentAddress.isEmpty() || currentAddress == "about:blank" || currentAddress == historyAddress)
          return;
      historyActions << addLocation(Location(title, currentAddress), HistoryMenu);
      if (historyActions.size() > 10)
          delete historyActions.takeFirst();
  }

  void MainWindow::on_WebBrowser_ProgressChange(int a, int b)
  {
      if (a <= 0 || b <= 0) {
          pb->hide();
          return;
      }
      pb->show();
      pb->setRange(0, b);
      pb->setValue(a);
  }

  void MainWindow::on_WebBrowser_CommandStateChange(int cmd, bool on)
  {
      switch (cmd) {
      case 1:
          actionForward->setEnabled(on);
          break;
      case 2:
          actionBack->setEnabled(on);
          break;
      }
  }

  void MainWindow::on_WebBrowser_BeforeNavigate()
  {
      actionStop->setEnabled(true);
  }

  void MainWindow::on_WebBrowser_NavigateComplete(const QString &url)
  {
      actionStop->setEnabled(false);
      const bool blocked = addressEdit->blockSignals(true);
      addressEdit->setText(url);
      addressEdit->blockSignals(blocked);
  }

  void MainWindow::on_actionGo_triggered()
  {
      navigate(address());
  }

Different slots handle the signals emitted by the WebBrowser object.

Connections that don't require any coding, i.e. connecting the back action to the GoBack() slot, have already been made in Qt Designer.


  void MainWindow::on_actionGo_triggered()
  {
      navigate(address());
  }


  void MainWindow::navigate(const QString &url)
  {
      WebBrowser->dynamicCall("Navigate(const QString&)", url);
  }

  void MainWindow::on_actionNewWindow_triggered()
  {
      MainWindow *window = new MainWindow;
      window->show();
      if (addressEdit->text().isEmpty())
          return;
      window->addressEdit->setText(addressEdit->text());
      window->actionStop->setEnabled(true);
      window->on_actionGo_triggered();
  }

  void MainWindow::on_actionAbout_triggered()
  {
      QMessageBox::about(this, tr("About WebBrowser"),
                  tr("This Example has been created using the ActiveQt integration into Qt Designer.\n"
                     "It demonstrates the use of QAxWidget to embed the Internet Explorer ActiveX\n"
                     "control into a Qt application."));
  }

  void MainWindow::on_actionAboutQt_triggered()
  {
      QMessageBox::aboutQt(this, tr("About Qt"));
  }

  void MainWindow::on_actionFileClose_triggered()
  {
      close();
  }

  #include "main.moc"

  int main(int argc, char ** argv)
  {
      QApplication a(argc, argv);
      QCoreApplication::setApplicationVersion(QT_VERSION_STR);
      QCoreApplication::setApplicationName("Active Qt Web Browser");
      QCoreApplication::setOrganizationName("QtProject");
      MainWindow w;
      const QStringList arguments = QCoreApplication::arguments();
      const QString url = arguments.size() > 1 ?
          arguments.at(1) : QString::fromLatin1(qtUrl);
      w.navigate(url);
      w.show();
      return a.exec();
  }

The rest of the implementation is not related to ActiveQt - the actions are handled by different slots, and the entry point function starts the application using standard Qt APIs.

To build the example you must first build the QAxContainer library. Then run your make tool in examples/activeqt/webbrowser and run the resulting webbrowser.exe.

Files: