Qt 5.11 - Building ActiveX servers in Qt

क्यूटी में ActiveX सर्वर का निर्माण




qt

क्यूटी में ActiveX सर्वर का निर्माण

QAxServer मॉड्यूल ActiveQt ढांचे का हिस्सा है। इसमें तीन वर्ग होते हैं:

  • QAxFactory COM ऑब्जेक्ट्स के निर्माण के लिए एक कारखाने को परिभाषित करता है।
  • QAxBindable Qt विजेट और COM ऑब्जेक्ट के बीच एक इंटरफ़ेस प्रदान करता है।
  • QAxAggregated अतिरिक्त COM इंटरफ़ेस को लागू करने के लिए उप-वर्ग किया जा सकता है।

ActiveX नियंत्रण और COM ऑब्जेक्ट के कुछ उदाहरण कार्यान्वयन प्रदान किए जाते हैं।

विषय:

लाइब्रेरी का उपयोग करना

QAxServer लाइब्रेरी का उपयोग करके COM सर्वर में एक मानक Qt एप्लिकेशन को चालू करने के लिए, आपको अपनी .pro फ़ाइल में axserver चर में axserver जोड़ना होगा।

एक आउट-ऑफ-प्रोसेस निष्पादन योग्य सर्वर इस तरह से एक .pro फ़ाइल से उत्पन्न होता है:

TEMPLATE = app
QT  += axserver

RC_FILE  = qaxserver.rc
...

इन-प्रोसेस सर्वर बनाने के लिए, .pro फ़ाइल का इस तरह उपयोग करें:

TEMPLATE = lib
QT += axserver
CONFIG  += dll

DEF_FILE = qaxserver.def
RC_FILE  = qaxserver.rc
...

फ़ाइलें qaxserver.rc और qaxserver.def का हिस्सा हैं और उनका उपयोग उनके सामान्य स्थान ( .pro फ़ाइल में पथ निर्दिष्ट करें) से किया जा सकता है, या प्रोजेक्ट डायरेक्टरी में कॉपी किया जा सकता है। आप इन फ़ाइलों को तब तक संशोधित कर सकते हैं, जब तक कि इसमें कोई फ़ाइल प्रकार लाइब्रेरी प्रविष्टि के रूप में शामिल न हो, अर्थात। आप संस्करण जानकारी जोड़ सकते हैं या एक अलग टूलबॉक्स आइकन निर्दिष्ट कर सकते हैं।

axserver मॉड्यूल का उपयोग करने से qmake टूल का निर्माण सिस्टम में आवश्यक निर्माण चरणों को जोड़ने का कारण होगा:

  • qaxserver.lib बजाय qaxserver.lib खिलाफ बाइनरी लिंक करें
  • COM सर्वर के लिए IDL फ़ाइल जनरेट करने के लिए idc टूल को कॉल करें
  • MIDL टूल (कंपाइलर स्थापना का हिस्सा) का उपयोग करके IDL को एक प्रकार की लाइब्रेरी में संकलित करें
  • सर्वर बाइनरी के लिए बाइनरी संसाधन के रूप में परिणामी प्रकार की लाइब्रेरी को संलग्न करें (फिर से idc टूल का उपयोग करके)
  • सर्वर को पंजीकृत करें

पोस्ट-प्रोसेसिंग चरण को छोड़ने के लिए, qaxserver_no_postlink कॉन्फ़िगरेशन भी सेट करें।

इसके अतिरिक्त आप VERSION चर का उपयोग करके एक संस्करण संख्या निर्दिष्ट कर सकते हैं, उदाहरण के लिए

TEMPLATE = lib
VERSION = 2.5
...

निर्दिष्ट संस्करण संख्या का उपयोग पंजीकरण के समय पुस्तकालय के प्रकार और सर्वर के संस्करण के रूप में किया जाएगा।

आउट-ऑफ-प्रोसेस बनाम इन-प्रोसेस

चाहे आपका COM सर्वर एक स्टैंड-अलोन एक्ज़ीक्यूटेबल के रूप में चलना चाहिए या क्लाइंट प्रोसेस में एक साझा लाइब्रेरी के रूप में मुख्य रूप से COM ऑब्जेक्ट के प्रकार पर निर्भर करता है जिसे आप सर्वर में प्रदान करना चाहते हैं।

एक निष्पादन योग्य सर्वर को स्टैंड-अलोन एप्लिकेशन के रूप में चलाने में सक्षम होने का लाभ है, लेकिन COM क्लाइंट और COM ऑब्जेक्ट के बीच संचार में काफी उपरि जोड़ता है। यदि नियंत्रण में कोई प्रोग्रामिंग त्रुटि है, तो नियंत्रण को चलाने वाली केवल सर्वर प्रक्रिया क्रैश हो जाएगी, और क्लाइंट अनुप्रयोग संभवतः चलता रहेगा। सभी COM क्लाइंट निष्पादन योग्य सर्वर का समर्थन नहीं करते हैं।

एक इन-प्रोसेस सर्वर आमतौर पर छोटा होता है और इसमें स्टार्टअप का समय तेजी से होता है। क्लाइंट और सर्वर के बीच संचार सीधे आभासी फ़ंक्शन कॉल के माध्यम से किया जाता है और दूरस्थ प्रक्रिया कॉल के लिए आवश्यक ओवरहेड को पेश नहीं करता है। हालाँकि, यदि सर्वर क्रैश क्लाइंट अनुप्रयोग के रूप में अच्छी तरह से क्रैश होने की संभावना है, और हर कार्यक्षमता प्रक्रिया सर्वर के लिए उपलब्ध नहीं है (यानी COM के रनिंग ऑब्जेक्ट-टेबल में रजिस्टर)।

दोनों सर्वर प्रकार Qt का उपयोग या तो साझा लाइब्रेरी के रूप में कर सकते हैं, या सांख्यिकीय रूप से सर्वर बाइनरी में लिंक कर सकते हैं।

पोस्ट-बिल्ड चरणों के दौरान विशिष्ट त्रुटियाँ

ActiveQt विशिष्ट कार्य-प्रसंस्करण चरणों के लिए सर्वर को कुछ आवश्यकताओं को पूरा करना है:

  • उजागर किए गए सभी नियंत्रणों को एक QApplication उदाहरण के अलावा कुछ भी नहीं बनाया जा सकता है
  • सर्वर के प्रारंभिक लिंक में एक अस्थायी प्रकार पुस्तकालय संसाधन शामिल है
  • सर्वर को चलाने के लिए आवश्यक सभी निर्भरताएं सिस्टम पथ में हैं (या कॉलिंग वातावरण द्वारा उपयोग किए जाने वाले पथ में; ध्यान दें कि विज़ुअल स्टूडियो के पास उपकरण में सूचीबद्ध पर्यावरण चर का अपना सेट है। विकल्प | निर्देशिकाएँ संवाद)।

यदि उन आवश्यकताओं को एक अयस्क से पूरा नहीं किया जाता है, तो निम्नलिखित त्रुटियों की अधिक संभावना है:

सर्वर निष्पादन योग्य क्रैश

IDL उत्पन्न करने के लिए ActiveX नियंत्रणों के रूप में उजागर किए गए विजेट्स को तत्काल बनाने की जरूरत है (निर्माता को कहा जाता है)। इस बिंदु पर, और कुछ नहीं बल्कि एक QApplication ऑब्जेक्ट मौजूद है। आपके विजेट निर्माणकर्ता को किसी भी अन्य वस्तुओं पर निर्भर नहीं होना चाहिए, जैसे कि यह अशक्त बिंदुओं की जांच करनी चाहिए।

अपने सर्वर को डिबग करने के लिए इसे -dumpidl outputfile के साथ चलाएं और जांचें कि यह कहां क्रैश हुआ है।

ध्यान दें कि नियंत्रण के किसी भी कार्य को नहीं कहा जाता है।

सर्वर निष्पादन योग्य नहीं एक मान्य Win32 अनुप्रयोग है

प्रकार लाइब्रेरी को संलग्न करने से सर्वर बाइनरी दूषित हो गया। यह विंडोज में एक बग है और केवल रिलीज बिल्ड के साथ होता है।

पहले लिंकिंग स्टेप को डमी टाइप लाइब्रेरी को एग्जीक्यूटेबल में लिंक करना होता है जिसे बाद में idc द्वारा बदला जा सकता है। उदाहरण के रूप में प्रदर्शित प्रोजेक्ट में एक प्रकार की लाइब्रेरी के साथ एक संसाधन फ़ाइल जोड़ें।

"DLL का पता लगाने में असमर्थ"

इंटरफ़ेस को उत्पन्न करने के लिए, और सर्वर को पंजीकृत करने के लिए सर्वर को चलाने के लिए बिल्ड सिस्टम को चलाने की आवश्यकता होती है। यदि एक डायनेमिक लिंक लाइब्रेरी सर्वर के विरुद्ध सर्वर लिंक नहीं करता है तो यह विफल हो सकता है (उदाहरण के लिए विजुअल स्टूडियो "निर्देशिकाएँ" विकल्प में निर्दिष्ट पर्यावरण सेटिंग्स का उपयोग करके सर्वर को कॉल करता है)। सुनिश्चित करें कि आपके सर्वर द्वारा आवश्यक सभी DLL और प्लगइन्स एक निर्देशिका में स्थित हैं जो पथ में त्रुटि संदेश बॉक्स में मुद्रित के रूप में सूचीबद्ध है (यह भी देखें विंडोज परिनियोजन उपकरण )।

"फाइल नहीं खोल सकता ..."

जब अंतिम क्लाइंट ने इसका उपयोग करना बंद कर दिया, तो ActiveX सर्वर ठीक से बंद नहीं हो सका। आमतौर पर एप्लिकेशन को समाप्त करने में लगभग दो सेकंड लगते हैं, लेकिन आपको प्रक्रिया को मारने के लिए कार्य प्रबंधक का उपयोग करना पड़ सकता है (उदाहरण के लिए जब कोई ग्राहक नियंत्रण को ठीक से जारी नहीं करता है)।

नियंत्रण तुरंत नहीं किया जा सकता है

इस स्थिति में, सर्वर को व्यवस्थापक के रूप में पंजीकृत करने में मदद मिल सकती है।

नियंत्रण लागू करना

Qt के साथ एक COM ऑब्जेक्ट को लागू करने के लिए, QObject या किसी भी मौजूदा QObject उपवर्ग का एक उपवर्ग बनाएँ। यदि वर्ग QWidget उपवर्ग है, तो COM ऑब्जेक्ट एक ActiveX नियंत्रण होगा।

#include <QWidget>

class MyActiveX : public QWidget
{
    Q_OBJECT

Q_OBJECT मैक्रो को विजेट ऑब्जेक्ट के बारे में जानकारी ActiveQt ढांचे को प्रदान करने के लिए आवश्यक है।

Q_CLASSINFO("ClassID", "{1D9928BD-4453-4bdd-903D-E525ED17FDE5}")
Q_CLASSINFO("InterfaceID", "{99F6860E-2C5A-42ec-87F2-43396F4BE389}")
Q_CLASSINFO("EventsID", "{0A3E9F27-E4F1-45bb-9E47-63099BCCD0E3}")

COM ऑब्जेक्ट के लिए COM पहचानकर्ता निर्दिष्ट करने के लिए Q_CLASSINFO () मैक्रो का उपयोग करें। ClassID और InterfaceID की आवश्यकता होती है, जबकि EventsID केवल तभी आवश्यक है जब आपके ऑब्जेक्ट में सिग्नल हों। इन पहचानकर्ताओं को उत्पन्न करने के लिए, सिस्टम टूल जैसे कि uuidgen या guidgen

आप अपनी प्रत्येक कक्षा के लिए अतिरिक्त विशेषताएँ निर्दिष्ट कर सकते हैं; विवरण के लिए कक्षा सूचना और ट्यूनिंग देखें।

Q_PROPERTY(int value READ value WRITE setValue)

ActiveX नियंत्रण के लिए गुण घोषित करने के लिए Q_PROPERTY () मैक्रो का उपयोग करें।

पैरेंट ऑब्जेक्ट लेने वाले एक मानक कंस्ट्रक्टर की घोषणा करें, और किसी भी QObject उपवर्ग के लिए फ़ंक्शन, सिग्नल और स्लॉट जैसे।

public:
    MyActiveX(QWidget *parent = 0)
    ...

    int value() const;

public slots:
    void setValue(int v);
    ...

signals:
    void valueChange(int v);
    ...

};

ActiveQt ढांचे में ActiveX गुण और विधियों के रूप में गुण और सार्वजनिक स्लॉट्स और ActiveX ईवेंट के रूप में संकेतों को उजागर किया जाएगा, और Qt डेटा प्रकारों और बराबर COM डेटा प्रकारों के बीच कनवर्ट किया जाएगा।

जानकारी का प्रकार

गुण के लिए समर्थित Qt डेटा प्रकार हैं:

Qt डेटा प्रकार COM संपत्ति
bool VARIANT_BOOL
QString BSTR
पूर्णांक पूर्णांक
uint अहस्ताक्षरित int
दोहरा दोहरा
qlonglong सीवाई
qulonglong सीवाई
QColor OLE_COLOR
QDate दिनांक
QDateTime दिनांक
QTime दिनांक
QFont IFontDisp *
QPixmap IPictureDisp *
QVariant VARIANT
QVariantList ( QList < QVariant > के समान) SAFEARRAY (संस्करण)
QStringList SAFEARRAY (BSTR)
QByteArray SAFEARRAY (बाइट)
QRect उपयोगकर्ता परिभाषित प्रकार
QSize उपयोगकर्ता परिभाषित प्रकार
QPoint उपयोगकर्ता परिभाषित प्रकार

क्यूटी डेटा प्रकार जो सिग्नल और स्लॉट में पैरामीटर के लिए समर्थित हैं, वे हैं:

Qt डेटा प्रकार COM पैरामीटर
bool [] VARIANT_BOOL
bool और [अंदर, बाहर] VARIANT_BOOL *
QString , const QString और [में] बीटीएस
QString और [में, बाहर] BSTR *
QString और [में, बाहर] BSTR *
पूर्णांक [में] int
पूर्णांक और [अंदर, बाहर] int
uint [में] अहस्ताक्षरित int
uint & [अंदर, बाहर] अहस्ताक्षरित int *
दोहरा [में] डबल
डबल और [में, बाहर] डबल *
QColor , Const QColor और [में] OLE_COLOR
QColor और [बाहर, बाहर] OLE_COLOR *
QDate , const QDate और [तिथि में
QDate और [अंदर, बाहर] DATE *
QDateTime , const QDateTime & [तिथि में
QDateTime और [अंदर, बाहर] DATE *
QFont , const QFont & [में] IFontDisp *
QFont और [में, बाहर] IFontDisp **
QPixmap , const QPixmap & [में] IPictureDisp *
QPixmap और [में, बाहर] IPictureDisp **
QList < QVariant >, const QList < QVariant > और [में] SAFEARRAY (VARIANT)
QList < QVariant > और [में, बाहर] SAFEARRAY (VARIANT) *
QStringList , const QStringList और [में] SAFEARRAY (BSTR)
QStringList और [में, बाहर] सुरक्षित (BSTR) *
QByteArray , const QByteArray और [में] SAFEARRAY (BYTE)
QByteArray और [में, बाहर] सुरक्षित (BYTE) *
QObject * [में] IDispatch *
QRect और [में, बाहर] संरचना QRect (उपयोगकर्ता परिभाषित)
QSize और [में, बाहर] संरचना QSize (उपयोगकर्ता परिभाषित)
QPoint और [में, बाहर] संरचना QPoint (उपयोगकर्ता परिभाषित)

समर्थित भी निर्यात किए गए एनम और झंडे हैं (देखें Q_ENUMS () और Q_FLAGS ())। इन-पैरामीटर प्रकार भी रिटर्न मान के रूप में समर्थित हैं।

ActiveQt ढांचे द्वारा किसी भी अन्य प्रकार के डेटा का उपयोग करने वाले गुणों और संकेतों / स्लॉट्स को अनदेखा किया ActiveQt है।

उप-वस्तुओं

COM ऑब्जेक्ट में कई उप-ऑब्जेक्ट हो सकते हैं जो COM ऑब्जेक्ट के एक उप तत्व का प्रतिनिधित्व कर सकते हैं। एक बहु-ऑब्जेक्ट स्प्रेड शीट एप्लिकेशन का प्रतिनिधित्व करने वाली एक COM ऑब्जेक्ट उदाहरण के लिए प्रत्येक फैल शीट के लिए एक उप-ऑब्जेक्ट प्रदान कर सकता है।

किसी भी QObject उपवर्ग को ActiveX में उप ऑब्जेक्ट के लिए उस प्रकार के रूप में उपयोग किया जा सकता है, जब तक कि यह QAxFactory लिए जाना जाता है। फिर प्रकार का उपयोग गुणों में किया जा सकता है, या किसी स्लॉट के रिटर्न प्रकार या पैरामीटर के रूप में।

संपत्ति की अधिसूचना

ActiveX क्लाइंट के लिए गुण को बाइंड करने योग्य बनाने के लिए, QAxBindable क्लास से कई इनहेरिटेंस का उपयोग करें:

#include <QAxBindable>
#include <QWidget>

class MyActiveX : public QWidget, public QAxBindable
{
    Q_OBJECT

प्रॉपर्टी राइट फ़ंक्शंस को लागू करते समय, QAxBindable क्लास की रिक्वेस्टप्रॉपर्टी चेंज () और प्रॉपर्टीचेंज्ड () फ़ंक्शंस को एक्टिवएक्स क्लाइंट्स को कंट्रोल प्रॉपर्टीज़ से बाइंड करने की अनुमति दें।

नियंत्रण कार्य करना

COM सिस्टम COM सिस्टम के लिए उपलब्ध कराने के लिए इसे सिस्टम रजिस्ट्री में पांच विशिष्ट पहचानकर्ताओं का उपयोग करके पंजीकृत होना चाहिए। ये पहचानकर्ता guidgen या uuidgen जैसे उपकरणों द्वारा प्रदान किए uuidgen । पंजीकरण जानकारी COM को अनुरोधित ActiveX नियंत्रण प्रदान करने वाली बाइनरी को स्थानीय बनाने की अनुमति देता है, मार्शेल दूरस्थ प्रक्रिया नियंत्रण को कॉल करती है और नियंत्रण द्वारा उजागर की गई विधियों और गुणों के बारे में जानकारी टाइप करती है।

COM ऑब्जेक्ट बनाने के लिए जब क्लाइंट इसके लिए पूछता है तो सर्वर को QAxFactory कार्यान्वयन का निर्यात करना चाहिए। ऐसा करने का आसान तरीका मैक्रोज़ के सेट का उपयोग करना है:

QAXFACTORY_BEGIN("{ad90301a-849e-4e8b-9a91-0a6dc5f6461f}",
                 "{a8f21901-7ff7-4f6a-b939-789620c03d83}")
    QAXCLASS(MyWidget)
    QAXCLASS(MyWidget2)
    QAXTYPE(MySubType)
QAXFACTORY_END()

यह MyWidget और MyWidget2 को COM ऑब्जेक्ट के रूप में निर्यात करेगा जिसे COM क्लाइंट द्वारा बनाया जा सकता है, और MySubType को एक प्रकार के रूप में पंजीकृत करेगा जो MyWidget और MyWidget2 गुणों और मापदंडों में उपयोग किया जा सकता है।

QAxFactory बताता है कि इस मैक्रो का उपयोग कैसे करें, और कस्टम कारखानों को कैसे लागू करें और कैसे उपयोग करें।

आउट-ऑफ-प्रोसेस निष्पादन योग्य सर्वरों के लिए आप QApplication ऑब्जेक्ट को तुरंत करने के लिए एक मुख्य () फ़ंक्शन को लागू कर सकते हैं और किसी भी सामान्य Qt एप्लिकेशन की तरह इवेंट लूप दर्ज कर सकते हैं। डिफ़ॉल्ट रूप से एप्लिकेशन एक मानक Qt अनुप्रयोग के रूप में शुरू होगा, लेकिन यदि आप कमांड लाइन पर- -activex पास करते हैं तो यह ActiveX सर्वर के रूप में शुरू होगा। एक मानक अनुप्रयोग इंटरफ़ेस बनाने या चलाने के लिए या स्टैंड-अलोन निष्पादन को रोकने के लिए QAxFactory::isServer () का उपयोग करें:

#include <QApplication>
#include <QAxFactory>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    if (!QAxFactory::isServer()) {
        // create and show main window
    }
    return app.exec();
}

यह हालांकि आवश्यक नहीं है क्योंकि ActiveQt एक मुख्य फ़ंक्शन का डिफ़ॉल्ट कार्यान्वयन प्रदान करता है। डिफ़ॉल्ट कार्यान्वयन QAxFactory::startServer () कहता है, एक QApplication उदाहरण बनाता है और निष्पादन () कहता है।

ActiveX सर्वर निष्पादन योग्य रन qmake बनाने के लिए makefile उत्पन्न करने के लिए, और किसी अन्य Qt अनुप्रयोग के लिए अपने संकलक के उपकरण का उपयोग करें। मेक प्रोसेस सिस्टम रजिस्ट्री में नियंत्रणों को भी पंजीकृत करेगा, जिसके परिणामस्वरूप -regserver कमांड लाइन विकल्प के साथ निष्पादन योग्य होगा।

यदि ActiveX सर्वर एक निष्पादन योग्य है, तो निम्न कमांड लाइन विकल्प समर्थित हैं:

विकल्प परिणाम
-regserver सिस्टम रजिस्ट्री में सर्वर को पंजीकृत करता है
-unregserver सिस्टम रजिस्ट्री से सर्वर को अपंजीकृत करता है
-activex ActiveX सर्वर के रूप में अनुप्रयोग प्रारंभ करता है
-dumpidl <file> -version xy सर्वर की IDL को निर्दिष्ट फ़ाइल में लिखता है। प्रकार लायब्रेरी में संस्करण xy होगा

सभी विंडोज सिस्टम पर उपलब्ध regsvr32 टूल का उपयोग करके इन-प्रोसेस सर्वर को पंजीकृत किया जा सकता है।

विशिष्ट संकलन-समय की समस्याएं

सूचीबद्ध कंपाइलर / लिंकर त्रुटियां Microsoft Visual C ++ 6.0 संकलक द्वारा जारी किए गए हैं।

"कोई अतिभारित फ़ंक्शन 2 पैरामीटर नहीं लेता है"

जब त्रुटि उस कोड में होती है जो QAXFACTORY_DEFAULT () मैक्रो का उपयोग करता है, तो विजेट क्लास में कोई कंस्ट्रक्टर नहीं था जिसे डिफ़ॉल्ट कारखाने द्वारा उपयोग किया जा सकता है। या तो एक मानक विजेट निर्माता जोड़ें या एक कस्टम कारखाने को लागू करें जिसे किसी की आवश्यकता नहीं है।

जब QAXFACTORY_EXPORT () मैक्रो का उपयोग करने वाले कोड में त्रुटि होती है, तो QAxFactory उपवर्ग में कोई उपयुक्त निर्माता नहीं था। एक सार्वजनिक वर्ग के निर्माता की तरह प्रदान करें

MyFactory(const QUuid &, const QUuid &);

अपने कारखाने वर्ग के लिए।

"सिंटैक्स त्रुटि: संख्या पर बुरा प्रत्यय"

विशिष्ट पहचानकर्ताओं को QAXFACTORY_EXPORT () या QAXFACTORY_DEFAULT () मैक्रो में स्ट्रिंग के रूप में पारित नहीं किया गया है।

"अनारक्षित बाहरी प्रतीक _ucm_instantiate"

सर्वर QAxFactory कार्यान्वयन को निर्यात नहीं करता है। QAXFACTORY_EXPORT लागू करने और निर्यात करने के लिए प्रोजेक्ट की कार्यान्वयन फ़ाइलों में से एक में QAXFACTORY_DEFAULT () मैक्रो का उपयोग करें, या डिफ़ॉल्ट फ़ैक्टरी का उपयोग करने के लिए QAXFACTORY_DEFAULT () मैक्रो का उपयोग करें।

"_ucm_initialize पहले से ही में परिभाषित ..."

सर्वर एक QAxFactory के एक से अधिक कार्यान्वयन का निर्यात करता है, या एक ही कार्यान्वयन को दो बार निर्यात करता है। यदि आप डिफ़ॉल्ट फ़ैक्टरी का उपयोग करते हैं, तो QAXFACTORY_DEFAULT () मैक्रो का उपयोग केवल एक बार परियोजना में किया जाना चाहिए। यदि कस्टम ActiveX नियंत्रण प्रदान करता है तो कस्टम QAxFactory कार्यान्वयन और QAXFACTORY_EXPORT () मैक्रो का उपयोग करें।

वितरण QAxServer बायनेरिज़

क्यूटी के साथ लिखे गए ActiveX सर्वर Qt को साझा लाइब्रेरी के रूप में उपयोग कर सकते हैं, या Qt को बाइनरी में स्टैटिकली लिंक किया है। दोनों तरीके बल्कि बड़े पैकेजों का उत्पादन करेंगे (या तो सर्वर बाइनरी खुद बड़े हो जाते हैं, या आपको क्यूटी डीएलएल को शिप करना होगा)।

स्टैंड-अलोन सर्वर स्थापित करना

जब आपका ActiveX सर्वर स्टैंड-अलोन अनुप्रयोग के रूप में भी चल सकता है, तो लक्ष्य सिस्टम पर निष्पादन योग्य स्थापित करने के बाद -regserver कमांड लाइन पैरामीटर के साथ निष्पादन योग्य सर्वर -regserver । उसके बाद सर्वर द्वारा दिए गए नियंत्रण ActiveX ग्राहकों के लिए उपलब्ध होंगे।

इन-प्रोसेस सर्वर स्थापित करना

जब आपका ActiveX सर्वर किसी इंस्टॉलेशन पैकेज का हिस्सा होता है, तो लक्ष्य प्रणाली पर नियंत्रण रजिस्टर करने के लिए Microsoft द्वारा प्रदान किए गए regsvr32 टूल का उपयोग regsvr32 । यदि यह उपकरण मौजूद नहीं है, तो DLL को अपनी इंस्टॉलर प्रक्रिया में लोड करें, DllRegisterServer सिंबल को हल करें और फ़ंक्शन को कॉल करें:

HMODULE dll = LoadLibrary("myserver.dll");
typedef HRESULT(__stdcall *DllRegisterServerProc)();
DllRegisterServerProc DllRegisterServer =
    (DllRegisterServerProc)GetProcAddress(dll, "DllRegisterServer");

HRESULT res = E_FAIL;
if (DllRegisterServer)
    res = DllRegisterServer();
if (res != S_OK)
    // error handling

इंटरनेट पर सर्वर वितरित करना

यदि आप वेब-पृष्ठों में अपने सर्वर में नियंत्रणों का उपयोग करना चाहते हैं, तो आपको अपने पृष्ठ को देखने के लिए उपयोग किए जाने वाले सर्वर को उपलब्ध कराने की आवश्यकता है, और आपको अपने पृष्ठ में सर्वर पैकेज के स्थान को निर्दिष्ट करने की आवश्यकता है।

किसी सर्वर का स्थान निर्दिष्ट करने के लिए, अपनी वेब साइट के OBJECT टैग में CODEBASE विशेषता का उपयोग करें। मान सर्वर फ़ाइल के लिए स्वयं को इंगित कर सकता है, अन्य फ़ाइल को सूचीबद्ध करने के लिए सर्वर को अन्य फ़ाइलों की सूची चाहिए (जैसे क्यूटी डीएलएल), या एक संकुचित सीएबी संग्रह।

INF और CAB फ़ाइलों को ActiveX और COM प्रोग्रामिंग के साथ-साथ MSDN लाइब्रेरी और विभिन्न अन्य ऑनलाइन संसाधनों के बारे में उपलब्ध लगभग हर पुस्तक में प्रलेखित किया गया है। उदाहरण में INF फ़ाइलें शामिल हैं जिनका उपयोग CAB अभिलेखागार बनाने के लिए किया जा सकता है:

[version]
    signature="$CHICAGO$"
    AdvancedINF=2.0
 [Add.Code]
    simpleax.exe=simpleax.exe
 [simpleax.exe]
    file-win32-x86=thiscab
    clsid={DF16845C-92CD-4AAB-A982-EB9840E74669}
    RegisterServer=yes

Microsoft से CABARC टूल आसानी से CAB अभिलेखागार उत्पन्न कर सकता है:

cabarc N simpleax.cab simpleax.exe simple.inf

INF फ़ाइलें Qt का एक स्थिर निर्माण मानती हैं, इसलिए अन्य DLL के लिए कोई निर्भरता INF फ़ाइलों में सूचीबद्ध नहीं हैं। DLL के आधार पर एक ActiveX सर्वर वितरित करने के लिए आपको निर्भरताएं जोड़ना होंगी, और संग्रह के साथ लाइब्रेरी फ़ाइलें प्रदान करनी होंगी।

नियंत्रणों का उपयोग करना

ActiveX नियंत्रणों का उपयोग करने के लिए, उदाहरण के लिए उन्हें वेब पेज में एम्बेड करने के लिए, <object> HTML टैग का उपयोग करें।

<object ID="MyActiveX1" CLASSID="CLSID:ad90301a-849e-4e8b-9a91-0a6dc5f6461f">
   ...
<\object>

नियंत्रण के गुणों को शुरू करने के लिए, उपयोग करें

<object ID=...>
    <param name="name" value="value">
<\object>

यदि वेब ब्राउज़र स्क्रिप्टिंग का उपयोग करता है तो जावास्क्रिप्ट, वीबीएसस्क्रिप्ट और नियंत्रण को स्क्रिप्ट करने के लिए उपयोग करता है। ActiveQt उदाहरणों में उदाहरण नियंत्रण के लिए प्रदर्शन HTML पृष्ठ शामिल हैं।

समर्थित और असमर्थित ActiveX ग्राहक

निम्नलिखित सक्रिय रूप से ActiveX नियंत्रणों और क्लाइंट अनुप्रयोगों के साथ हमारे स्वयं के experiements पर आधारित है, और पूर्ण नहीं के माध्यम से है।

समर्थित ग्राहक

ActiveQt साथ विकसित ActiveX नियंत्रणों के साथ ये मानक अनुप्रयोग काम करते हैं। ध्यान दें कि कुछ क्लाइंट केवल इन-प्रोसेस नियंत्रण का समर्थन करते हैं।

  • इंटरनेट एक्स्प्लोरर
  • Microsoft ActiveX नियंत्रण परीक्षण कंटेनर
  • Microsoft Visual Studio 6.0
  • Microsoft Visual Studio.NET/2003
  • Microsoft Visual Basic 6.0
  • MFC- और ATL- आधारित कंटेनर
  • Sybase PowerBuilder
  • ActiveQt आधारित कंटेनर

Microsoft Office अनुप्रयोग समर्थित हैं, लेकिन आपको "सम्मिलित करने योग्य" ऑब्जेक्ट के रूप में नियंत्रणों को पंजीकृत करने की आवश्यकता है। QAxFactory को QAxFactory::registerClass COM वर्ग में इस विशेषता को जोड़ने के लिए QAxFactory::registerClass करें, या Q_CLASSINFO मैक्रो का उपयोग करके अपनी कक्षा के लिए "सम्मिलित करने योग्य" वर्ग की जानकारी "हाँ" पर Q_CLASSINFO

असमर्थित ग्राहक

हम ActiveQt आधारित COM ऑब्जेक्ट को निम्न क्लाइंट अनुप्रयोगों के साथ काम करने में कामयाब नहीं हुए हैं।

  • बोरलैंड C ++ बिल्डर (संस्करण 5 और 6)
  • बोरलैंड डेल्फी

ठेठ रनटाइम त्रुटियां

सर्वर प्रतिक्रिया नहीं करता है

यदि सिस्टम सर्वर को शुरू करने में असमर्थ है (कार्य प्रबंधक के साथ जांचें कि क्या सर्वर एक प्रक्रिया चलाता है), सुनिश्चित करें कि कोई DLL सर्वर पर निर्भर करता है सिस्टम पथ (जैसे Qt DLL!) से गायब है। सर्वर बाइनरी की सभी निर्भरता देखने के लिए एक निर्भरता वॉकर का उपयोग करें।

यदि सर्वर चलता है (जैसे कार्य प्रबंधक एक प्रक्रिया को सूचीबद्ध करता है), तो अपने सर्वर को डीबग करने की जानकारी के लिए निम्न अनुभाग देखें।

ऑब्जेक्ट नहीं बनाया जा सकता है

यदि सर्वर को बिल्ड प्रक्रिया के दौरान सही तरीके से बनाया और पंजीकृत किया जा सकता है, लेकिन ऑब्जेक्ट को OLE / COM ऑब्जेक्ट व्यूअर एप्लिकेशन द्वारा initiliazed नहीं किया जा सकता है, तो सुनिश्चित करें कि कोई DLL सर्वर पर निर्भर नहीं करता है सिस्टम पथ (जैसे QQ DLL) से गायब है )। सर्वर बाइनरी की सभी निर्भरता देखने के लिए एक निर्भरता वॉकर का उपयोग करें।

यदि सर्वर चलता है, तो अपने सर्वर को डीबग करने की जानकारी के लिए निम्न अनुभाग देखें।

डिबगिंग रनटाइम त्रुटियां

Visual Studio में इन-प्रोसेस सर्वर को डीबग करने के लिए, सर्वर प्रोजेक्ट को सक्रिय प्रोजेक्ट के रूप में सेट करें, और प्रोजेक्ट सेटिंग्स में क्लाइंट "डिबग सत्र के लिए निष्पादन योग्य" निर्दिष्ट करें (जैसे ActiveX टेस्ट कंटेनर का उपयोग करें)। यदि आप डिबग संस्करण स्थापित करते हैं, तो आप अपने कोड में ब्रेकपॉइंट सेट कर सकते हैं, और ActiveQt और Qt कोड में भी कदम ActiveQt सकते हैं।

एक निष्पादन योग्य सर्वर को डीबग करने के लिए, एप्लिकेशन को डीबगर में चलाएं और कमांड लाइन पैरामीटर- -activex साथ शुरू करें। फिर अपना क्लाइंट शुरू करें और अपने ActiveX नियंत्रण का एक उदाहरण बनाएं। ActiveX नियंत्रण बनाने के लिए प्रयास कर रहा क्लाइंट अगले क्लाइंट के लिए मौजूदा प्रक्रिया का उपयोग करेगा।

कक्षा सूचना और ट्यूनिंग

प्रत्येक COM वर्ग के लिए विशेषताएँ प्रदान करने के लिए, Q_CLASSINFO मैक्रो का उपयोग करें, जो Qt के मेटा ऑब्जेक्ट सिस्टम का हिस्सा है।

कुंजी मूल्य का अर्थ
संस्करण कक्षा का संस्करण (1.0 डिफ़ॉल्ट है)
विवरण कक्षा का वर्णन करने वाला एक तार।
कक्षा आईडी वर्ग आईडी। यदि आप निर्दिष्ट नहीं हैं तो आपको QAxFactory::classID को फिर से QAxFactory::classID करना होगा।
InterfaceID इंटरफ़ेस आईडी। यदि आप निर्दिष्ट नहीं हैं तो आपको QAxFactory::interfaceID को फिर से QAxFactory::interfaceID करना होगा।
EventsID घटना इंटरफ़ेस आईडी। निर्दिष्ट नहीं होने पर कोई संकेत COM ईवेंट के रूप में सामने नहीं आते हैं।
DefaultProperty निर्दिष्ट संपत्ति इस वर्ग की डिफ़ॉल्ट संपत्ति का प्रतिनिधित्व करती है। अर्थात। एक पुश बटन की डिफ़ॉल्ट संपत्ति "पाठ" होगी।
DefaultSignal निर्दिष्ट संकेत इस वर्ग के डिफ़ॉल्ट संकेत का प्रतिनिधित्व करता है। अर्थात। एक पुश बटन का डिफ़ॉल्ट संकेत "क्लिक" होगा।
लाइसेंस कुंजी ऑब्जेक्ट निर्माण के लिए निर्दिष्ट लाइसेंस कुंजी की आवश्यकता होती है। लाइसेंस मशीन की आवश्यकता के लिए कुंजी खाली हो सकती है। डिफ़ॉल्ट रूप से कक्षाएं लाइसेंस प्राप्त नहीं हैं। निम्न अनुभाग भी देखें।
StockEvents यदि मूल्य "हां" है तो वस्तुएं स्टॉक घटनाओं को उजागर करती हैं। देखें QAxFactory::hasStockEvents ()
ToSuperClass ऑब्जेक्ट सभी सुपर-कक्षाओं की कार्यक्षमता को उजागर करते हैं और मूल्य में वर्ग के नाम को शामिल करते हैं। देखें QAxFactory::exposeToSuperClass ()
insertable यदि मान "हाँ" है, तो कक्षा "इंसर्टेबल" होने के लिए पंजीकृत है और इसे ओएलई 2 कंटेनरों में सूचीबद्ध किया जाएगा (अर्थात। Microsoft कार्यालय)। यह विशेषता डिफ़ॉल्ट रूप से सेट नहीं की गई है।
Aggregatable यदि मान "नहीं" है तो वर्ग एकत्रीकरण का समर्थन नहीं करता है। डिफ़ॉल्ट रूप से एकत्रीकरण समर्थित है।
creatable यदि मान "नहीं" है, तो वर्ग क्लाइंट द्वारा नहीं बनाया जा सकता है, और केवल किसी अन्य वर्ग के एपीआई के माध्यम से उपलब्ध है (यानी वर्ग एक उप-प्रकार है)।
RegisterObject यदि मान "हाँ" है, तो इस वर्ग की वस्तुएं OLE के साथ पंजीकृत हैं और रनिंग ऑब्जेक्ट टेबल (यानी क्लाइंट इस वर्ग के पहले से चल रहे उदाहरण से कनेक्ट कर सकते हैं) से सुलभ हैं। यह विशेषता केवल आउट-ऑफ-प्रोसेस सर्वर में समर्थित है।
माइम ऑब्जेक्ट मूल्य में निर्दिष्ट प्रारूप के डेटा और फ़ाइलों को संभाल सकता है। मूल्य में प्रारूप माइम है: विस्तार: विवरण। एकाधिक स्वरूपों को एक अर्धविराम द्वारा अलग किया जाता है।
CoClassAlias उत्पन्न IDL और रजिस्ट्री में प्रयुक्त क्लासनाम। यह esp है। सी ++ वर्गों के लिए उपयोगी जो एक नाम स्थान में रहते हैं - डिफ़ॉल्ट रूप से, ActiveQt को संकलित करने के लिए "::" को हटा देता है।
कार्यान्वित श्रेणियाँ अल्पविराम से अलग श्रेणी आईडी (CATID) यूयूआईडी की सूची। "कंट्रोल", "इंसर्टेबल" आदि के अलावा अतिरिक्त कंटेनर क्षमताओं को निर्दिष्ट करने के लिए सामान्य तंत्र, CATID_InternetAware ("{0DE86A58-2BAA-11CF-A229-00AA003D7352}"), CATID_SafeForScripting ("{7D9501] शामिल हैं। 9FA9-00AA006C42C4} ") साथ ही उपयोगकर्ता द्वारा परिभाषित CATID मान।

ध्यान दें कि कुंजी और मान दोनों ही संवेदनशील हैं।

निम्नलिखित एक वर्ग के संस्करण 2.0 की घोषणा करता है जो केवल अपने स्वयं के एपीआई को उजागर करता है, और Microsoft Office अनुप्रयोगों के "ऑब्जेक्ट सम्मिलित करें" संवाद में उपलब्ध है।

class MyActiveX : public QWidget
{
    Q_OBJECT
    Q_CLASSINFO("Version", "2.0")
    Q_CLASSINFO("ClassID", "{7a4cffd8-cbcd-4ae9-ae7e-343e1e5710df}")
    Q_CLASSINFO("InterfaceID", "{6fb035bf-8019-48d8-be51-ef05427d8994}")
    Q_CLASSINFO("EventsID", "{c42fffdf-6557-47c9-817a-2da2228bc29c}")
    Q_CLASSINFO("Insertable", "yes")
    Q_CLASSINFO("ToSuperClass", "MyActiveX")
    Q_PROPERTY(...)

public:
    MyActiveX(QWidget *parent = 0);

    ...
};

लाइसेंसीकृत अवयवों का विकास करना

यदि आप उन घटकों का विकास करते हैं, जिन्हें आप नियंत्रित करना चाहते हैं, तो उन घटकों को त्वरित करने में सक्षम हैं। चूंकि सर्वर बाइनरी को किसी भी क्लाइंट मशीन पर भेज दिया और पंजीकृत किया जा सकता है, इसलिए किसी के लिए भी संभव है कि वह अपने सॉफ़्टवेयर में उन घटकों का उपयोग करे।

लाइसेंसिंग घटकों को विभिन्न प्रकार की तकनीकों का उपयोग करके किया जा सकता है, उदाहरण के लिए नियंत्रण बनाने वाला कोड एक लाइसेंस कुंजी प्रदान कर सकता है, या जिस मशीन पर नियंत्रण को चलाने की आवश्यकता होती है उसे लाइसेंस दिया जाना चाहिए।

लाइसेंस के रूप में एक क्यूटी वर्ग को चिह्नित करने के लिए Q_CLASSINFO () मैक्रो का उपयोग करके एक "लाइसेंसकी" निर्दिष्ट करें।

class MyLicensedControl : public QWidget
{
    Q_OBJECT
    Q_CLASSINFO("LicenseKey", "<key string>")
    ...
};

कुंजी को एक मशीन पर MyLicensedControl का एक उदाहरण बनाने में सक्षम होना आवश्यक है जो स्वयं लाइसेंस प्राप्त नहीं है। लाइसेंस प्राप्त डेवलपर अब अपने आवेदन के साथ सर्वर बाइनरी का पुनर्वितरण कर सकता है, जो "लाइसेंसकेय" के मूल्य का उपयोग करके नियंत्रण बनाता है, जबकि एप्लिकेशन के उपयोगकर्ता लाइसेंस कुंजी के बिना नियंत्रण नहीं बना सकते हैं।

यदि नियंत्रण के लिए एक एकल लाइसेंस कुंजी पर्याप्त नहीं है (अर्थात। आप विभिन्न डेवलपर्स को अलग-अलग लाइसेंस कुंजी प्राप्त करना चाहते हैं) तो आप यह इंगित करने के लिए एक खाली कुंजी निर्दिष्ट कर सकते हैं कि नियंत्रण के लिए लाइसेंस की आवश्यकता होती है, और QAxFactory::validateLicenseKey () को सत्यापित करने के लिए। एक लाइसेंस प्रणाली पर मौजूद है (यानी, लाइसेंस फ़ाइल के माध्यम से)।

अधिक इंटरफेस

ActiveQt सर्वर द्वारा ActiveQt गए ActiveX नियंत्रण ActiveQt विनिर्देशों को लागू करने के लिए COM इंटरफेस का एक न्यूनतम सेट का समर्थन करते हैं। जब ActiveX वर्ग QAxBindable वर्ग से विरासत में मिलता है तो यह अतिरिक्त COM इंटरफ़ेस भी लागू कर सकता है।

QAxAggregated का एक नया उपवर्ग बनाएँ और अतिरिक्त COM इंटरफ़ेस कक्षाओं को उप-वर्ग के लिए कई वंशानुक्रम का उपयोग करें।

class AxImpl : public QAxAggregated, public ISomeCOMInterface
{
public:
    AxImpl() {}

    long queryInterface(const QUuid &iid, void **iface);

    // IUnknown
    QAXAGG_IUNKNOWN

    // ISomeCOMInterface
    ...
}

अतिरिक्त COM इंटरफ़ेस का समर्थन करने के लिए QAxAggregated::queryInterface () फ़ंक्शन को फिर से लागू करें।

long AxImpl::queryInterface(const QUuid &iid, void **iface)
{
    *iface = 0;
    if (iid == IID_ISomeCOMInterface)
        *iface = (ISomeCOMInterface *)this;
    else
        return E_NOINTERFACE;

    AddRef();
    return S_OK;
}

चूंकि ISomeCOMInterface का एक उपवर्ग है, इसलिए आपको QueryInterface() , AddRef() , और Release() फ़ंक्शन लागू करने होंगे। ऐसा करने के लिए अपनी कक्षा परिभाषा में QAXAGG_IUNKNOWN मैक्रो का उपयोग करें। यदि आप मैन्युअल रूप से IUnknown फ़ंक्शन को कार्यान्वित करते हैं, तो QAxAggregated::controllingUnknown () फ़ंक्शन, जैसे वापस लौटाए गए इंटरफ़ेस पॉइंटर को कॉल प्रतिनिधि करें

HRESULT AxImpl::QueryInterface(REFIID iid, void **iface)
{
    return controllingUnknown()->QueryInterface(iid, iface);
}

अपने QAxAggregated::queryInterface कार्यान्वयन में स्वयं QAxAggregated::queryInterface इंटरफ़ेस का समर्थन न करें।

COM इंटरफ़ेस की विधियों को लागू करें, और QAxAggregated::object () का उपयोग करें यदि आपको नियंत्रण को लागू करने के लिए QObject उपवर्ग को कॉल करने की QObject

अपने QAxBindable उपवर्ग में, QAxBindable::createAggregate () को QAxAggregated उपवर्ग का एक नया ऑब्जेक्ट वापस करने के लिए QAxAggregated

class MyActiveX : public QWidget, public QAxBindable
{
    Q_OBJECT

public:
    MyActiveX(QWidget *parent);

    QAxAggregated *createAggregate()
    {
        return new AxImpl();
    }
};

ActiveQt भी देखें