日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

qt编写activex_Qt中使用ActiveX(一)

發(fā)布時(shí)間:2025/3/21 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 qt编写activex_Qt中使用ActiveX(一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

由于最近需要使用ActiveX,一般來(lái)說(shuō)可以使用微軟提供的MFC或者ATL框架來(lái)開發(fā),由于我個(gè)人對(duì)這部分內(nèi)容不是很熟悉,好在Qt也提供對(duì)于ActiveX的支持。本文主要記錄個(gè)人學(xué)習(xí)ActiveX的一些內(nèi)容,方便日后查閱。本文以Qt5(5.3.1)提供的ActiveX為參考,但是由于ActiveX這部分比較穩(wěn)定,因此Qt4應(yīng)該也是一樣的。

概述

Qt提供了QtActiveX模塊來(lái)支持微軟ActiveX的開發(fā),Qt的ActiveX和COM的開發(fā)支持兩種方式:

支持將已有的COM或者ActiveX空間引入到Qt的應(yīng)用程序中

支持將Qt應(yīng)用程序或者Qt的對(duì)象導(dǎo)出成COM對(duì)象或者ActiveX控件供他人使用

具體來(lái)說(shuō),Qt是通過(guò)ActiveXQt框架中的兩個(gè)模塊來(lái)支持上述所說(shuō)的兩種方式的:

使用QAxContainer模塊,通過(guò)QAxObject和QAxWidget分別支持COM對(duì)象和ActiveX控件的開發(fā),可以通過(guò)這兩個(gè)對(duì)象將外部的COM或者ActiveX組件接入到Qt應(yīng)用程序

使用QAxServer模塊,通過(guò)QAxAggregated、QAxBindable和QAxFactory類,通過(guò)了進(jìn)程內(nèi)和可執(zhí)行程序exe兩種方式的COM Server模式,用來(lái)將Qt寫的內(nèi)容導(dǎo)出為COM或者ActiveX供他人使用。

下圖簡(jiǎn)要的說(shuō)明了QtActiveX的作用

使用QtActiveX創(chuàng)建COM或ActiveX Server

在正式開始之前先對(duì)COM和ActiveX做一個(gè)簡(jiǎn)要的對(duì)比。COM(Component Object Model)是微軟提出的一種技術(shù),它定義了一種規(guī)范,通過(guò)COM可以輕松實(shí)現(xiàn)一種語(yǔ)言(如C#)調(diào)用另一種語(yǔ)言(如C++、VB等)開發(fā)的功能模塊。ActiveX是微軟主要針對(duì)互聯(lián)網(wǎng)客戶端設(shè)計(jì)的以COM為技術(shù)基礎(chǔ)的一種實(shí)現(xiàn),一般來(lái)說(shuō)二者并沒(méi)有本質(zhì)的區(qū)別,僅有一些概念上的差異,一般來(lái)說(shuō):

1. ActiveX一般包含一個(gè)窗體界面,COM對(duì)象一般并沒(méi)有界面

2. COM對(duì)象一般作為一個(gè)可調(diào)用的模塊來(lái)使用,ActiveX一般嵌入在網(wǎng)頁(yè)中使用

上述僅僅是一種使用上的慣例,但是并未強(qiáng)制一定這樣

使用Qt作COM和ActiveX的開發(fā)需要使用QAxServer模塊,這里面包含三個(gè)類:

1. QAxFactory定義了創(chuàng)建COM對(duì)象的工廠類

2. QAxBindable定義了COM對(duì)象與Qt對(duì)象之間的轉(zhuǎn)換關(guān)系,也就是說(shuō)Qt中的對(duì)象通過(guò)QAxBindable轉(zhuǎn)換為COM中的要素

3. QAxAggregated定義了COM組件接口

Qt作為Server支持的模式

COM組件在開發(fā)出來(lái)之后有多種形式,可以是一個(gè)dll,也可以是一個(gè)exe可執(zhí)行程序。可以在進(jìn)程中被加載(一般最常用的模式),可以作為外部進(jìn)程為其他進(jìn)程提供服務(wù),甚至可以是遠(yuǎn)程服務(wù)器上的進(jìn)程為本地集成提供服務(wù)。Qt ActiveX 提供了In-Process和out-of-process executable兩種方式的支持。簡(jiǎn)單來(lái)說(shuō)就是提供了一種 Dll供應(yīng)用程序調(diào)用也提供了一種可以作為運(yùn)行的exe,為其他應(yīng)用提供一些調(diào)用服務(wù)。

當(dāng)作為獨(dú)立exe時(shí)候,我們需要這樣編寫.pro文件:

TEMPLATE = app

QT += axserver

RC_FILE = qaxserver.rc當(dāng)作為進(jìn)程內(nèi)dll的時(shí)候,需要這樣寫.pro文件

TEMPLATE = lib

QT += axserver

CONFIG += dll

DEF_FILE = qaxserver.def

RC_FILE = qaxserver.rc

...但是我們不用去操心這些內(nèi)容,因?yàn)橐话阄覀兪怯孟驅(qū)?lái)生成Qt工程的,當(dāng)你勾選ActiveX Server模式的時(shí)候,向?qū)б呀?jīng)幫你寫好這些內(nèi)容了。

當(dāng)使用QAxServer開發(fā)dll時(shí),實(shí)際工程編譯鏈接過(guò)程中會(huì)涉及到以下的過(guò)程:

1. 應(yīng)用程序?qū)?huì)鏈接到qtserver.lib而不是qtmain.lib

2. idc工具會(huì)被調(diào)用,產(chǎn)生IDL文件(接口描述語(yǔ)言的接口描述文件)

3.調(diào)用MIDL工具編譯IDL文件到類型庫(kù)

4.調(diào)用idc工具將類型庫(kù)附到server的二進(jìn)制代碼中

5. 注冊(cè)dll

另外在.Pro文件中可以添加一個(gè)版本信息,這個(gè)版本信息會(huì)作類型庫(kù)和server dll的版本號(hào),添加方式使用VERSION變量即可:

TEMPLATE = lib

VERSION = 2.5

...

COM進(jìn)程外和進(jìn)程內(nèi)使用方式的比較

進(jìn)程外的使用方式是將COM寫成一個(gè)exe可執(zhí)行文件,當(dāng)它運(yùn)行的時(shí)候其他程序可以調(diào)用它提供的接口來(lái)開發(fā),這樣做如果某個(gè)調(diào)用它的程序出了bug,那么只有該程序會(huì)崩潰,其他調(diào)用不收影響,提供了更好的隔離性。缺點(diǎn)是需要更長(zhǎng)的啟動(dòng)時(shí)間與跨進(jìn)程通信的一些額外負(fù)擔(dān)。

進(jìn)程內(nèi)的使用方式就很簡(jiǎn)單了,調(diào)用過(guò)程僅僅是通過(guò)類似虛函數(shù)這樣的調(diào)用,需要加載的時(shí)間短、效率比較高。

開發(fā)Server的過(guò)程

為了使用Qt實(shí)現(xiàn)COM對(duì)象,我們必須使用一個(gè)QObject的子類,如果該子類是QWidget的子類,那么這個(gè)COM對(duì)象就是一個(gè)ActiveX控件。代碼如下:

#include

class MyActiveX : public QWidget

{

Q_OBJECT只里面Q_OBJECT宏不能少,它提供了關(guān)于類MyActiveX的一些元數(shù)據(jù)信息, 接下來(lái)繼續(xù)添加ActiveX的一些信息

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_CLASSINFO定義了COM組件的一些信息,這里面ClassID和InterfaceID是必須的,當(dāng)你需要使用COM中的事件時(shí),EventsID就需要添加進(jìn)來(lái)。里面的128位的字符串使用GUID.exe工具生成(微軟提供的一個(gè)小工具,可以生成全球唯一的標(biāo)識(shí)符,可以在系統(tǒng)文件夾或者visual Studio的工具菜單中找到),工具提供了多種模式,可以選擇需要的模式復(fù)制添加到代碼中:

除了上述基本必要的信息之外(ClassID實(shí)際上被寫入注冊(cè)表中,當(dāng)控件被使用的時(shí)候會(huì)搜索注冊(cè)表找到里面該COM控件dll的位置并加載,可以使用regedit.exe在HKEY_CLASSES_ROOT中找到很多已經(jīng)注冊(cè)的COM組件信息),Qt還提供了Q_CLASSINFO更多的內(nèi)容,如下表所示:

名稱

值和含義

Version

類的版本號(hào),默認(rèn)值是1.0

Description

類的描述

ClassID

類的ID(COM中用來(lái)唯一確定一個(gè)類的方式)

InterfaceID

接口ID(COM中用來(lái)唯一確定接口的方式)

EventsID

事件ID

DefaultProperty

默認(rèn)屬性

DefaultSignal

默認(rèn)的時(shí)間

LicenseKey

類的許可號(hào),默認(rèn)未開啟,如果開啟使用類需要許可號(hào)

StockEvents

TODO:???

ToSuperClass

暴露父類的接口

Insertable

設(shè)置"yes"后可以被列到OLE2容器中,默認(rèn)未設(shè)置

Aggregatable

默認(rèn)是"yes",COM支持聚合

Creatable

設(shè)置為“no”調(diào)用者不能使用該類

RegisterObject

僅能用在進(jìn)程外方式的COM中

MIME

該COM控件支持的文件格式描述

CoClassAlias

類的名稱在IDL中被修改為CoClassAlias指定的名字

繼續(xù)上面的代碼,接下來(lái)可以添加一些屬性到COM組件中,可以使用另一個(gè)宏Q_PROPERTY

Q_PROPERTY(int value READ value WRITE setValue)之后可以像寫Qt程序那樣來(lái)完成。

public:

MyActiveX(QWidget *parent = 0)

...

int value() const;

public slots:

void setValue(int v);

...

signals:

void valueChange(int v);

...

};Qt的ActiveX框架會(huì)將Qt類中的要素轉(zhuǎn)換為COM中的標(biāo)準(zhǔn)要素供其他調(diào)用者使用,具體來(lái)說(shuō):

1. ?Qt類中的屬性和公有的插槽函數(shù)(slots)會(huì)被轉(zhuǎn)換為COM中的屬性和方法

2. ?Qt類中的信號(hào)(signals)會(huì)被轉(zhuǎn)換成為COM組件中的事件

另外其他的數(shù)據(jù)類型轉(zhuǎn)換之間的對(duì)應(yīng)關(guān)系如下圖所示:

1. Qt中屬性的數(shù)據(jù)類型與COM中數(shù)據(jù)類型的轉(zhuǎn)換關(guān)系如下:

Qt數(shù)據(jù)類型

COM 屬性數(shù)據(jù)類型

bool

VARIANT_BOOL

QString

BSTR

int

int

uint

unsigned int

double

double

qlonglong

CY

qulonglong

CY

QColor

OLE_COLOR

QDate

DATE

QDateTime

DATE

QTime

DATE

QFont

IFontDisp*

QPixmap

IPixtureDisp*

QVariant

VARIANT

QVariantList

SAFEARRAY(VARIANT)

QStringList

SAFEARRAY(BSTR)

QByteArray

SAFEARRAY(BYTE)

QRect

User defined type

QSize

User defined type

QPoint

User defined type

2. Qt中信號(hào)和插槽函數(shù)的形式參數(shù)數(shù)據(jù)類型

Qt數(shù)據(jù)類型

對(duì)應(yīng)COM的數(shù)據(jù)類型

bool

[in] VARIANT_BOOL

bool&

[in,out] VARIANT_BOOL*

QString, const Qtring&

[in] BSTR

QString&

[in, out] BSTR*

QStinrg&

[in, out] BSTR*

int

[in] int

int&

[in, out]int

uint

[in,out]unsigned int

uint&

[int, out] unsigned int*

double

[in] double

QColor, const QColor&

[in] OLE_COLOR

QColor&

[in,out] OLE_COLOR*

QDate, const QDate&

[in] DATE

QDate&

[in,out]DATE*

QDateTime, const QDateTime&

[in] DATE

QDateTime&

[in,out]DATE*

QFont, const QFont&

[in] IFontDisp*

QFont&

[in,out]IFontDisp**

QPixmap, const QPixmap&

[in]IPictureDisp*

QPixmap&

[in,out]IPictureDisp**

QList

[in]SAFEARRAY(VARIANT)

QList&

[in,out]SAFEARRAY(VARIANT)*

QObject*

[in] IDispatch*

此外QActiveX也可以通過(guò)Q_ENUMS和Q_FLAGS將枚舉變量導(dǎo)出,如果使用了非上表中的類型來(lái)作為信號(hào)和插槽函數(shù)的參數(shù)類型,那么Qt ActiveX框架不會(huì)轉(zhuǎn)換這些參數(shù)。

發(fā)布COM控件

為了讓Qt編寫的代碼可以作為一個(gè)COM組件被使用,必須提供獲取COM對(duì)象的方法,在Qt中使用QAxFactory來(lái)完成,最簡(jiǎn)單的方法是使用下面的宏:

QAXFACTORY_BEGIN("{ad90301a-849e-4e8b-9a91-0a6dc5f6461f}",

"{a8f21901-7ff7-4f6a-b939-789620c03d83}")

QAXCLASS(MyWidget)

QAXCLASS(MyWidget2)

QAXTYPE(MySubType)

QAXFACTORY_END()上面這段代碼把MyWidget和MyWidget2導(dǎo)出為可供外部調(diào)用的COM對(duì)象,并注冊(cè)MySubType類型可供MyWidget和MyWidget2中的屬性和參數(shù)使用。

進(jìn)程外COM控件的編寫

對(duì)于進(jìn)程外可執(zhí)行的COM組件,我們需要執(zhí)行一個(gè)main函數(shù)來(lái)實(shí)例化一個(gè)QApplication,和一般的Qt程序類似。

#include

#include

int main(int argc, char *argv[])

{

QApplication app(argc, argv);

if (!QAxFactory::isServer()) {

// create and show main window

}

return app.exec();

}

總結(jié)

以上是生活随笔為你收集整理的qt编写activex_Qt中使用ActiveX(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。