层次结构范例 (ActiveQt)

The Hierarchy example is shows how to write an in-process ActiveX control. The control is a QWidget subclass with child widgets that are accessible as sub-types.

class QParentWidget : public QWidget
{
    Q_OBJECT
    Q_CLASSINFO("ClassID", "{d574a747-8016-46db-a07c-b2b4854ee75c}");
    Q_CLASSINFO("InterfaceID", "{4a30719d-d9c2-4659-9d16-67378209f822}");
    Q_CLASSINFO("EventsID", "{4a30719d-d9c2-4659-9d16-67378209f823}");
public:
    explicit QParentWidget(QWidget *parent = nullptr);
    QSize sizeHint() const override;
public slots:
    void createSubWidget(const QString &name);
    QSubWidget *subWidget(const QString &name);
private:
    QVBoxLayout *m_vbox;
};
					

QParentWidget class provides slots to create a widget with a name, and to return a pointer to a named widget. The class declaration uses Q_CLASSINFO() to provide the COM identifiers for this class.

QParentWidget::QParentWidget(QWidget *parent)
: QWidget(parent),
  m_vbox(new QVBoxLayout(this))
{
}
					

The constructor of QParentWidget creates a vertical box layout. New child widgets are automatically added to the layout.

void QParentWidget::createSubWidget(const QString &name)
{
    QSubWidget *sw = new QSubWidget(this, name);
    m_vbox->addWidget(sw);
    sw->setLabel(name);
    sw->show();
}
					

createSubWidget 槽创建新的 QSubWidget with the name provided in the parameter, and sets the label to that name. The widget is also shown explicitly.

QSubWidget *QParentWidget::subWidget(const QString &name)
{
    return findChild<QSubWidget *>(name);
}
					

subWidget 槽使用 QObject::findChild() function and returns the first child of type QSubWidget that has the requested name.

class QSubWidget : public QWidget
{
    Q_OBJECT
    Q_PROPERTY(QString label READ label WRITE setLabel)
    Q_CLASSINFO("ClassID", "{850652f4-8f71-4f69-b745-bce241ccdc30}");
    Q_CLASSINFO("InterfaceID", "{2d76cc2f-3488-417a-83d6-debff88b3c3f}");
    Q_CLASSINFO("ToSuperClass", "QSubWidget");
public:
    QSubWidget(QWidget *parent = nullptr, const QString &name = QString());
    void setLabel(const QString &text);
    QString label() const;
    QSize sizeHint() const override;
protected:
    void paintEvent(QPaintEvent *e) override;
private:
    QString m_label;
};
					

QSubWidget class has a single string-property label , and implements the paintEvent to draw the label. The class uses again Q_CLASSINFO to provide the COM identifiers, and also sets the ToSuperClass attribute to QSubWidget , to ensure that only no slots of any superclasses (i.e. QWidget ) are exposed.

QSubWidget::QSubWidget(QWidget *parent, const QString &name)
: QWidget(parent)
{
    setObjectName(name);
}
void QSubWidget::setLabel(const QString &text)
{
    m_label = text;
    setObjectName(text);
    update();
}
QString QSubWidget::label() const
{
    return m_label;
}
QSize QSubWidget::sizeHint() const
{
    QFontMetrics fm(font());
    return QSize(fm.horizontalAdvance(m_label), fm.height());
}
void QSubWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setPen(palette().text().color());
    painter.drawText(rect(), Qt::AlignCenter, m_label);
}
					

实现为 QSubWidget class is self-explanatory.

#include "objects.h"
#include <QAxFactory>
QAXFACTORY_BEGIN("{9e626211-be62-4d18-9483-9419358fbb03}", "{75c276de-1df5-451f-a004-e4fa1a587df1}")
    QAXCLASS(QParentWidget)
    QAXTYPE(QSubWidget)
QAXFACTORY_END()
					

The classes are then exported using a QAxFactory . QParentWidget is exported as a full class (which can be created ), while QSubWidget is only exported as a type, which can only be created indirectly through APIs of QParentWidget .

要构建范例必须先构建 QAxServer 库。然后运行 qmake 和 make 工具在 activeqt/hierarchy .

demonstration 要求 WebBrowser 支持 ActiveX 控件,并启用脚本。

<script language="javascript">
function createSubWidget( form )
{
    ParentWidget.createSubWidget( form.nameEdit.value );
}
function renameSubWidget( form )
{
    var SubWidget = ParentWidget.subWidget( form.nameEdit.value );
    if ( !SubWidget ) {
        alert( "No such widget " + form.nameEdit.value + "!" );
        return;
    }
    SubWidget.label = form.labelEdit.value;
    form.nameEdit.value = SubWidget.label;
}
function setFont( form )
{
    ParentWidget.font = form.fontEdit.value;
}
</script>
<p>
This widget can have many children!
</p>
<object ID="ParentWidget" CLASSID="CLSID:d574a747-8016-46db-a07c-b2b4854ee75c"
CODEBASE="http://www.qt-project.org/demos/hierarchy.cab">
[Object not available! Did you forget to build and register the server?]
</object><br />
<form>
<input type="edit" ID="nameEdit" value="<enter object name>" />
<input type="button" value="Create" onClick="createSubWidget(this.form)" />
<input type="edit" ID="labelEdit" />
<input type="button" value="Rename" onClick="renameSubWidget(this.form)" />
<br />
<input type="edit" ID="fontEdit" value="MS Sans Serif" />
<input type="button" value = "Set Font" onClick="setFont(this.form)" />
</form>
					

范例工程 @ code.qt.io