Qt Active Server的注册 对于Qt开发Active Server需要使用MSVC版Qt。mingw版无法用于开发Active Sever,只能通过Qt Active调用COM组件。
idc工具:D:\Qt\Qt5.5.1\5.5\msvc2013\bin
1 2 3 4 5 6 7 # 注册 idc.exe multipleax.dll /regserver idc.exe multipleax.dll -regserver # 反注册 idc.exe multipleax.dll /unregserver idc.exe multipleax.dll -unregserver
通过Qt Active Server,可以通过浏览器来显示应用,效果就像一个web应用。Active server可以编译成dll或exe的形式。
要为每个COM类提供属性,请使用Q_CLASSINFO
宏,它是Qt的元对象系统的一部分。
Key
Meaning of value
Version
类的版本号,默认值是1.0
Description
类的描述
ClassID
类的ID(COM中用来唯一确定一个类的方式)QAxFactory::classID
InterfaceID
接口ID(COM中用来唯一确定接口的方式) QAxFactory::interfaceID
EventsID
事件接口ID。 如果未指定,则没有信号作为COM事件公开
DefaultProperty
指定的属性表示此类的默认属性。IE浏览器。 按钮的默认属性是“text”
DefaultSignal
指定的信号表示此类的默认信号。IE浏览器。 按钮的默认信号将被“click”
LicenseKey
对象创建需要指定的许可证密钥。 密钥可以为空以要求许可机器。 默认情况下,类未获得许可。 另请参阅以下部分。
StockEvents
如果值为“yes”,则对象公开Stock事件。参阅QAxFactory::hasStockEvents ()
ToSuperClass
对象公开所有基类的接口,包括类名的值。参阅QAxFactory::exposeToSuperClass ()
Insertable
如果值为“yes”,则该类被注册为“Insertable”,并将列在OLE 2容器(例如:Microsoft Office)中。 默认情况下不设置此属性。
Aggregatable
如果值为“no”,则该类不支持聚合。 默认情况下,支持聚合
Creatable
如果值为“no”,则客户端无法创建类,并且只能通过另一个类的API获得(即,类是子类型)。
RegisterObject
如果值为“yes”,则此类的对象将使用OLE注册并可从运行对象表中访问(即,客户端可以连接到此类的已运行实例)。 仅在进程外服务器中支持此属性
MIME
该对象可以处理值中指定格式的数据和文件。 该值的格式为mime:extension:description。 多个格式由分号分隔
CoClassAlias
生成的IDL和注册表中使用的类名。对于存在于命名空间中的C ++类很有用 - 默认情况下,只删除“::”以使IDL编译。
Implemented Categories
逗号分隔的类别ID(CATID)UUID列表。 除了“control”,“insertable”等之外,用于指定其他容器功能的通用机制。典型的CATID包括CATID_InternetAware(“{0DE86A58-2BAA-11CF-A229-00AA003D7352}”),CATID_SafeForScripting(“{7DD95801-9882-11CF-” 9FA9-00AA006C42C4}“)以及用户定义的CATID值。
这里有两种方法,一种是进程内,另一种是进程外。进程内是把com组件编译成动态库的形式,进程外是指把com组件编译成可执行文件。
进程内COM组件 .pro
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 TEMPLATE = lib TARGET = multipleax CONFIG += warn_off dll QT += widgets axserver SOURCES = main.cpp HEADERS = ax1.h ax2.h RC_FILE = multipleax.rc DEF_FILE = multipleax.def QT_CI_JENKINS_HOME=$$(JENKINS_HOME) !isEmpty(QT_CI_JENKINS_HOME) { message("Qt CI environment detected, suppressing example registration" ) CONFIG += qaxserver_no_postlink }
QAxWidget1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #ifndef AX1_H #define AX1_H #include <QWidget> #include <QPainter> class QAxWidget1 : public QWidget{ Q_OBJECT Q_CLASSINFO ("ClassID" , "{1D9928BD-4453-4bdd-903D-E525ED17FDE5}" ) Q_CLASSINFO ("InterfaceID" , "{99F6860E-2C5A-42ec-87F2-43396F4BE389}" ) Q_CLASSINFO ("EventsID" , "{0A3E9F27-E4F1-45bb-9E47-63099BCCD0E3}" ) Q_PROPERTY (QColor fillColor READ fillColor WRITE setFillColor) public: explicit QAxWidget1 (QWidget *parent = nullptr) : QWidget (parent) , m_fillColor (Qt::red) { } QColor fillColor () const { return m_fillColor; } void setFillColor (const QColor &fc) { m_fillColor = fc; repaint(); } protected: void paintEvent (QPaintEvent *e) { QPainter paint (this) ; QRect r = rect(); r.adjust(10 , 10 , -10 , -10 ); paint.fillRect(r, m_fillColor); } private: QColor m_fillColor; }; #endif
QAxWidget2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 #ifndef AX2_H #define AX2_H #include <QWidget> #include <QPainter> class QAxWidget2 : public QWidget{ Q_OBJECT Q_CLASSINFO ("ClassID" , "{58139D56-6BE9-4b17-937D-1B1EDEDD5B71}" ) Q_CLASSINFO ("InterfaceID" , "{B66280AB-08CC-4dcc-924F-58E6D7975B7D}" ) Q_CLASSINFO ("EventsID" , "{D72BACBA-03C4-4480-B4BB-DE4FE3AA14A0}" ) Q_CLASSINFO ("ToSuperClass" , "QAxWidget2" ) Q_CLASSINFO ("StockEvents" , "yes" ) Q_CLASSINFO ("Insertable" , "yes" ) Q_PROPERTY (int lineWidth READ lineWidth WRITE setLineWidth) public: explicit QAxWidget2 (QWidget *parent = nullptr) : QWidget (parent) , m_lineWidth (1 ) { } int lineWidth () const { return m_lineWidth; } void setLineWidth (int lw) { m_lineWidth = lw; repaint(); } protected: void paintEvent (QPaintEvent *e) { QPainter paint (this) ; QPen pen = paint.pen(); pen.setWidth(m_lineWidth); paint.setPen(pen); QRect r = rect(); r.adjust(10 , 10 , -10 , -10 ); paint.drawEllipse(r); } private: int m_lineWidth; }; #endif
main.cpp
1 2 3 4 5 6 7 8 9 10 #include "ax1.h" #include "ax2.h" #include <QAxFactory> QT_USE_NAMESPACE QAXFACTORY_BEGIN ("{98DE28B6-6CD3-4e08-B9FA-3D1DB43F1D2F}" , "{05828915-AD1C-47ab-AB96-D6AD1E25F0E2}" ) QAXCLASS (QAxWidget1) QAXCLASS (QAxWidget2) QAXFACTORY_END ()
multipleax.def
1 2 3 4 5 6 7 EXPORTS DllCanUnloadNow PRIVATE DllGetClassObject PRIVATE DllRegisterServer PRIVATE DllUnregisterServer PRIVATE DumpIDL PRIVATE
multipleax.rc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include "winver.h" 1 TYPELIB "multipleax.rc" 1 ICON DISCARDABLE "multipleax.ico" VS_VERSION_INFO VERSIONINFO FILEVERSION 1 ,0 ,0 ,0 PRODUCTVERSION 1 ,0 ,0 ,0 FILEFLAGSMASK 0x3f L FILEOS 0x00040000 L FILETYPE 0x2 L FILESUBTYPE 0x0 L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904e4" BEGIN VALUE "CompanyName" , "The Qt Company Ltd." VALUE "FileDescription" , "Multiple Example (ActiveQt)" VALUE "FileVersion" , "1.0.0.0" VALUE "LegalCopyright" , "Copyright (C) 2015 The Qt Company Ltd." VALUE "InternalName" , "multipleax.dll" VALUE "OriginalFilename" , "multipleax.dll" VALUE "ProductName" , "Multiple Example (ActiveQt)" VALUE "ProductVersion" , "1.0.0.0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation" , 0x409 , 1252 END END
test.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <script language ="javascript" > function setColor ( form ) { Ax1 .fillColor = form.colorEdit .value ; } function setWidth ( form ) { Ax2 .lineWidth = form.widthEdit .value ; } </script > <p /> This is one QWidget subclass:<br /> <object ID ="Ax1" CLASSID ="CLSID:1D9928BD-4453-4bdd-903D-E525ED17FDE5" CODEBASE ="http://qt.nokia.com/demos/multipleax.cab" > [Object not available! Did you forget to build and register the server?] </object > <br /> <form > Fill Color: <input type ="edit" ID ="colorEdit" value = "red" /> <input type ="button" value = "Set" onClick ="setColor(this.form)" /> <input type ="button" value = "Hide" onClick ="Ax1.hide()" /> <input type ="button" value = "Show" onClick ="Ax1.show()" /> </form > <p /> This is another QWidget subclass:<br /> <object ID ="Ax2" CLASSID ="CLSID:58139D56-6BE9-4b17-937D-1B1EDEDD5B71" CODEBASE ="http://qt.nokia.com/demos/multipleax.cab" > [Object not available! Did you forget to build and register the server?] </object > <br /> <form > Line width: <input type ="edit" ID ="widthEdit" value = "1" /> <input type ="button" value = "Set" onClick ="setWidth(this.form)" /> </form >
注册使用
1 idc.exe multipleax.dll /regserver
注册成功后使用IE浏览器打开test.html
进程外COM组件 .pro
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 include (../shared.pri)TEMPLATE = app QT += axserver QT += widgets SOURCES += main.cpp RC_FILE = comapp.rc DEF_FILE = comapp.def QT_CI_JENKINS_HOME=$$(JENKINS_HOME) !isEmpty(QT_CI_JENKINS_HOME) { message("Qt CI environment detected, suppressing example registration" ) CONFIG += qaxserver_no_postlink }
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 #include <QApplication> #include <QAxFactory> #include <QTabWidget> #include <QScopedPointer> #include <QTimer> class Application ;class DocumentList ;class Document : public QObject{ Q_OBJECT Q_CLASSINFO ("ClassID" , "{2b5775cd-72c2-43da-bc3b-b0e8d1e1c4f7}" ) Q_CLASSINFO ("InterfaceID" , "{2ce1761e-07a3-415c-bd11-0eab2c7283de}" ) Q_PROPERTY (Application *application READ application) Q_PROPERTY (QString title READ title WRITE setTitle) public: explicit Document (DocumentList *list ) ; virtual ~Document(); Application *application () const ; QString title () const ; void setTitle (const QString &title) ; private: QScopedPointer <QWidget> m_page; }; class DocumentList : public QObject{ Q_OBJECT Q_CLASSINFO ("ClassID" , "{496b761d-924b-4554-a18a-8f3704d2a9a6}" ) Q_CLASSINFO ("InterfaceID" , "{6c9e30e8-3ff6-4e6a-9edc-d219d074a148}" ) Q_PROPERTY (Application* application READ application) Q_PROPERTY (int count READ count) public: explicit DocumentList (Application *application) ; int count () const ; Application *application () const ; public slots: Document *addDocument () ; Document *item (int index) const ; private: QList<Document *> m_list; }; class Application : public QObject{ Q_OBJECT Q_CLASSINFO ("ClassID" , "{b50a71db-c4a7-4551-8d14-49983566afee}" ) Q_CLASSINFO ("InterfaceID" , "{4a427759-16ef-4ed8-be79-59ffe5789042}" ) Q_CLASSINFO ("RegisterObject" , "yes" ) Q_PROPERTY (DocumentList* documents READ documents) Q_PROPERTY (QString id READ id) Q_PROPERTY (bool visible READ isVisible WRITE setVisible) public: explicit Application (QObject *parent = nullptr) ; DocumentList *documents () const ; QString id () const { return objectName(); } void setVisible (bool on) ; bool isVisible () const ; QTabWidget *window () const { return m_ui.data(); } public slots: void quit () ; private: QScopedPointer <DocumentList> m_docs; QScopedPointer <QTabWidget> m_ui; }; Document::Document(DocumentList *list ) : QObject(list ) { QTabWidget *tabs = list ->application()->window(); m_page.reset(new QWidget(tabs)); m_page->setWindowTitle(tr("Unnamed" )); tabs->addTab(m_page.data(), m_page->windowTitle()); m_page->show(); } Document::~Document() { } Application *Document::application () const { return qobject_cast<DocumentList *>(parent())->application(); } QString Document::title () const { return m_page->windowTitle(); } void Document::setTitle (const QString &t) { m_page->setWindowTitle(t); QTabWidget *tabs = application()->window(); int index = tabs->indexOf(m_page.data()); tabs->setTabText(index, m_page->windowTitle()); } DocumentList::DocumentList(Application *application) : QObject(application) { } Application *DocumentList::application () const { return qobject_cast<Application *>(parent()); } int DocumentList::count () const { return m_list.count(); } Document *DocumentList::item (int index) const { return m_list.value(index, nullptr); } Document *DocumentList::addDocument () { Document *document = new Document(this); m_list.append(document); return document; } Application::Application(QObject *parent) : QObject(parent), m_ui(new QTabWidget), m_docs(new DocumentList(this)) { setObjectName(QStringLiteral("From QAxFactory" )); } DocumentList *Application::documents () const { return m_docs.data(); } void Application::setVisible (bool on) { m_ui->setVisible(on); } bool Application::isVisible () const { return m_ui->isVisible(); } void Application::quit () { m_docs.reset(); m_ui.reset(); QTimer::singleShot(0 , qApp, &QCoreApplication::quit); } #include "main.moc" QAXFACTORY_BEGIN("{edd3e836-f537-4c6f-be7d-6014c155cc7a}" , "{b7da3de8-83bb-4bbe-9ab7-99a05819e201}" ) QAXCLASS(Application) QAXTYPE(Document) QAXTYPE(DocumentList) QAXFACTORY_END() int main (int argc, char *argv[]) { QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication app (argc, argv) ; app.setQuitOnLastWindowClosed(false ); if (QAxFactory::isServer()) return app.exec(); Application appobject; appobject.setObjectName(QStringLiteral("From Application" )); QAxFactory::startServer(); QAxFactory::registerActiveObject(&appobject); appobject.window()->setMinimumSize(300 , 100 ); appobject.setVisible(true ); QObject::connect(&app, &QGuiApplication::lastWindowClosed, &appobject, &Application::quit); return app.exec(); }
comapp.def
1 2 3 4 5 6 7 8 EXPORTS DllCanUnloadNow PRIVATE DllGetClassObject PRIVATE DllRegisterServer PRIVATE DllUnregisterServer PRIVATE DumpIDL PRIVATE
comapp.rc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include "winver.h" 1 TYPELIB "multipleax.rc" 1 ICON DISCARDABLE "comapp.ico" VS_VERSION_INFO VERSIONINFO FILEVERSION 1 ,0 ,0 ,0 PRODUCTVERSION 1 ,0 ,0 ,0 FILEFLAGSMASK 0x3f L FILEOS 0x00040000 L FILETYPE 0x2 L FILESUBTYPE 0x0 L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904e4" BEGIN VALUE "CompanyName" , "The Qt Company Ltd." VALUE "FileDescription" , "comapp (ActiveQt)" VALUE "FileVersion" , "1.0.0.0" VALUE "LegalCopyright" , "Copyright (C) 2015 The Qt Company Ltd." VALUE "InternalName" , "comapp" VALUE "OriginalFilename" , "comapp" VALUE "ProductName" , "comapp (ActiveQt)" VALUE "ProductVersion" , "1.0.0.0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation" , 0x409 , 1252 END END
注册使用
1 idc.exe comapp.exe /regserver