एटीएल का उपयोग करने पर इंटरनेट पर कई ट्यूटोरियल हैं, और विशेष रूप से, इसकी मदद से COM घटक बनाने पर, जिसमें ActiveX / OLE नियंत्रण शामिल हैं, लेकिन उनमें से अधिकांश किसी कारण के लिए दृश्य स्टूडियो में माउस को विभिन्न दिलचस्प स्थानों में रखने की प्रक्रिया का वर्णन करते हैं, का उपयोग करते हुए उत्तरार्द्ध के चित्रमय उपकरण, और उनमें से कुछ काफी गहरी मात्रा में विकास पर्यावरण के आंतरिक रूप से उत्पन्न कोड को प्रभावित करते हैं। इंटरनेट के रूसी भाषी क्षेत्र में, स्थिति और भी खराब है - बहुत कम एटीएल सामग्री हैं, व्यावहारिक रूप से कोई नहीं (और न केवल एटीएल पर, बल्कि सामान्य रूप से कॉम घटकों के निर्माण पर भी), इसलिए मैंने इस कमी की भरपाई करने का फैसला किया।
खैर, आपको शायद एक संक्षिप्त विवरण के साथ शुरू करना चाहिए कि ActiveX घटक क्या हैं और ATL क्या है।
ActiveX OL, "ऑब्जेक्ट लिंकिंग और एंबेडिंग" का एक रीब्रांडिंग है, जो COM पर आधारित Microsoft की एक तकनीक है, जो कंपोनेंट ऑब्जेक्ट मॉडल - MS द्वारा आविष्कृत एक भाषा-स्वतंत्र घटक मॉडल है। OLE आपको Windows के अंतर्गत चलने वाली विभिन्न प्रोग्रामिंग भाषाओं में लिखे गए अलग-अलग कार्यक्रमों में अलग-अलग नियंत्रणों, दस्तावेज़ों या बस घटकों को एम्बेड करने की अनुमति देता है। ActiveX नियंत्रण, विशेष रूप से, इंटरनेट एक्सप्लोरर में "चिपकाया" जाने के लिए जाना जाता है, और IE के लिए सबसे प्रसिद्ध ऐसे घटकों में से एक है, उदाहरण के लिए, एडोब फ्लैश मॉड्यूल।
ActiveX घटक के इंटरफ़ेस को विंडोज के लिए कई प्रसिद्ध और लोकप्रिय कार्यक्रमों के साथ प्रदान किया जाता है, दोनों Microsoft से ही (विंडोज मीडिया प्लेयर, या, उदाहरण के लिए, Microsoft Office के प्रोग्राम, विशेष रूप से वर्ड, एक्सेल आदि में), और तीसरे पक्ष की कंपनियों से। (उपरोक्त फ्लैश, एडोब रीडर, एक ही एडोब के कई अन्य कार्यक्रम - उदाहरण के लिए फ़ोटोशॉप, अगर मुझे सही याद है)।
एक राय है कि प्रौद्योगिकी अप्रचलित हो रही है, या पहले से ही पुरानी है, लेकिन फिर भी, मुझे व्यक्तिगत रूप से लगता है कि इसे केवल निम्न-स्तरीय प्रोग्रामिंग और सिस्टम सेवाओं के क्षेत्र में निचोड़ा जा रहा है, और जबकि विंडोज कर्नेल सी में लिखा गया है, और कई सिस्टम सिस्टम COM का उपयोग करते हैं, और आधारित हैं COM इंटरफेस, यह निश्चित रूप से कहीं भी नहीं जाएगा।
अब ATL क्या है। ATL, एक्टिव टेम्प्लेट लाइब्रेरी Microsoft की एक प्रसिद्ध लाइब्रेरी है, जो C ++ में Winapi के साथ काम करने को सरल बनाती है। ATL में COM / OLE / ActiveX के साथ काम करने के लिए न केवल कक्षाएं / टेम्प्लेट शामिल हैं, बल्कि उदाहरण के लिए, GUI के निर्माण और प्रबंधन आदि के लिए कक्षाएं भी शामिल हैं।
ATL आमतौर पर Microsoft Visual Studio के पूर्ण संस्करणों के साथ आता है, लेकिन यदि आपके पास एक नहीं है, तो आप इस लाइब्रेरी को
Windows DDK से प्राप्त कर सकते हैं।
इसलिए, इस लेख में मैं एक सरल घटक बनाने की प्रक्रिया का वर्णन करूंगा जिसका उपयोग हम डायरेक्टएक्स 11 का उपयोग करते हुए वायरफ्रेम में एक कताई क्षेत्र को आकर्षित करने के लिए करेंगे, और जिसके दो तरीके होंगे - रन - गोले के रोटेशन की शुरुआत करें, और रोकें - रोटेशन बंद करें।

सबसे पहले, हमें अपने मॉड्यूल के इंटरफेस के साथ आने की जरूरत है, लाइब्रेरी, इंटरफेस और कंपोनेंट क्लास के लिए एक GUID के साथ आएं, और यह सब, हमेशा की तरह MIDL, Microsoft इंटरफ़ेस डेफिनिशन लैंग्वेज में लिखें।
[ uuid(1E4E47F3-21AF-407C-9544-59C34C81F3FA), version(1.0), helpstring("MyActiveX 1.0 Type Library") ] library MyActiveXLib { importlib("stdole32.tlb")
इस मामले को एक फ़ाइल में सहेजें और MyActiveX.idl पर कॉल करें
जैसा कि आप देख सकते हैं, हमने दो इंटरफेस की परिभाषा और साथ ही साथ COM वर्ग का वर्णन दर्ज किया है जो हमारे इंटरफेस को लागू करता है। पहला, IMyControl, हमारे पास वास्तव में घटक का इंटरफ़ेस है, और दूसरा हमारे नियंत्रण में होने वाली घटनाओं के बारे में बाहरी दुनिया को सतर्क करने के लिए आवश्यक है। हमने कोई ईवेंट रिकॉर्ड नहीं किया है, और हम उन्हें अपने उदाहरण में नहीं करेंगे, इसलिए यह इंटरफ़ेस खाली है।
हमारी कक्षा द्वारा लागू किया गया इंटरफ़ेस तथाकथित दोहरे इंटरफेस को संदर्भित करता है। इसका मतलब यह है कि इसका उपयोग न केवल उन भाषाओं से किया जा सकता है जो देशी कोड के साथ संवाद कर सकते हैं, लेकिन, तदनुसार, वर्चुअल विधि तालिकाओं के माध्यम से COM घटकों के साथ संवाद कर सकते हैं, लेकिन आईडीपीच इंटरफ़ेस का उपयोग करके स्क्रिप्टिंग भाषाओं से भी।
अगला, हमें C ++ के लिए हेडर फ़ाइल में IMyControl और _IMyControlEvents की परिभाषाएँ लिखना होगा - MyControl.hpp
#ifndef __MY_CONTROL_HPP__ #define __MY_CONTROL_HPP__ #include <windows.h> typedef interface IMyControl IMyControl; MIDL_INTERFACE("2B26D028-4DA6-4D69-9513-D0CA550949D1") IMyControl : IDispatch { public: virtual HRESULT STDMETHODCALLTYPE Run() = 0; virtual HRESULT STDMETHODCALLTYPE Stop() = 0; }; MIDL_INTERFACE("E7D13B5A-0A09-440A-81EA-C9E3B0105DB0") _IMyControlEvents : public IDispatch { }; DEFINE_GUID(IID_IMyControl,0x2B26D028,0x4DA6,0x4D69,0x95,0x13,0xD0,0xCA,0x55,0x09,0x49,0xD1); DEFINE_GUID(LIBID_MyActiveXLib,0x1E4E47F3,0x21AF,0x407C,0x95,0x44,0x59,0xC3,0x4C,0x81,0xF3,0xFA); DEFINE_GUID(DIID__IMyControlEvents,0xE7D13B5A,0x0A09,0x440A,0x81,0xEA,0xC9,0xE3,0xB0,0x10,0x5D,0xB0); DEFINE_GUID(CLSID_MyControl,0x5747094E,0x84FB,0x47B4,0xBC,0x0C,0xF8,0x9F,0xB5,0x83,0x89,0x5F); #endif __MY_CONTROL_HPP__
MIDL_INTERFACE मैक्रो "संरचना __declspec (novtable) __declspec (uuid (इंटरफ़ेस के लिए GUID स्ट्रिंग))" जैसे कुछ में फैलता है। Microsoft ने अपने सी ++ कंपाइलर में COM को आसानी से एकीकृत किया है, और यह कम से कम साधारण सी ++ कक्षाओं और संरचनाओं के साथ, एमएसवीसी ++ से COM इंटरफेस और घटकों के साथ काम करने की अनुमति देता है (और यह भविष्य में विशेष रूप से अच्छी तरह से देखा जाएगा)।
मैक्रो DEFINE_GUID, बदले में, मैक्रो INITGUID की परिभाषा के आधार पर विस्तारित किया जाता है - एक की अनुपस्थिति में, यह एक विशिष्ट नाम के साथ GUID प्रकार का बाहरी चर घोषित करता है। INITGUID के मामले में, यह इसे इनिशियलाइज़ भी करता है।
अब आपको _Module चर को परिभाषित करना चाहिए, जो ATL से CComModule वर्ग के अंतर्गत आता है।
MyActiveX.hpp पर एक अलग हेडर फ़ाइल में चर की घोषणा लिखें
#ifndef __MY_ACTIVE_X_HPP__ #define __MY_ACTIVE_X_HPP__ #include <windows.h> #include <atlbase.h> extern CComModule _Module; #endif // __MY_ACTIVE_X_HPP__
CComModule एक वर्ग है जो COM मॉड्यूल की कार्यक्षमता को लागू करता है, विशेष रूप से, घटक वर्गों को पंजीकृत करना, एक COM सर्वर को प्रारंभ करना, और इसी तरह की अन्य चीजें।
रजिस्ट्री में COM-सर्वर को पंजीकृत करने के लिए (और COM रजिस्ट्री के माध्यम से काम करता है), हम एक reg-फाइल लिख सकते हैं, या मैन्युअल रूप से रजिस्ट्री में संबंधित प्रविष्टियां बना सकते हैं, लेकिन हम regsvr32.exe प्रोग्राम का भी उपयोग कर सकते हैं, जो विंडोज का हिस्सा है, और स्वचालित है पंजीकरण, घटक का उपयोग करके। इसके लिए, यह आवश्यक है कि हमारा पुस्तकालय कुछ कार्यों का निर्यात करे, और विशेष रूप से, DllRegisterServer और DllUnregisterServer।
CComModule स्वचालित पंजीकरण की पूरी प्रक्रिया को सरल करता है, और आपको इसे उपरोक्त निर्यात किए गए पुस्तकालय कार्यों में उपयुक्त विधियों को कॉल करने के लिए कम करने की अनुमति देता है, लेकिन इसके लिए घटक को लागू करने वाले dll संसाधन अनुभाग में पंजीकरण स्क्रिप्ट का होना आवश्यक है। हम फ़ाइल को नाम देते हैं, जिसे हम बाद में संसाधनों में जोड़ते हैं, MyControl.rgs, और निम्नलिखित पाठ को वहां जोड़ें:
HKCR { MyActiveX.MyControl.1 = s 'MyControl Class' { CLSID = s '{5747094E-84FB-47B4-BC0C-F89FB583895F}' } MyActiveX.MyControl = s 'MyControl Class' { CLSID = s '{5747094E-84FB-47B4-BC0C-F89FB583895F}' CurVer = s 'MyActiveX.MyControl.1' } NoRemove CLSID { ForceRemove {5747094E-84FB-47B4-BC0C-F89FB583895F} = s 'MyControl Class' { ProgID = s 'MyActiveX.MyControl.1' VersionIndependentProgID = s 'MyActiveX.MyControl' ForceRemove 'Programmable' InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' } ForceRemove 'Control' ForceRemove 'Insertable' ForceRemove 'ToolboxBitmap32' = s '%MODULE%, 101' 'MiscStatus' = s '0' { '1' = s '139665' } 'TypeLib' = s '{1E4E47F3-21AF-407C-9544-59C34C81F3FA}' 'Version' = s '1.0' } } }
पंजीकरण स्क्रिप्ट के सबसे महत्वपूर्ण भाग हैं CLSID, यानी हमारे घटक के वर्ग के GUID, ProgID, अर्थात्। मानव-पठनीय सीएलएसआईडी प्रतिनिधित्व, और थ्रेडिंगमॉडल हमारे घटक का मल्टीथ्रेडिंग मॉडल है, जो इस मामले में अपार्टमेंट में स्थापित किया गया है, जिसका अर्थ है कि हमारा नियंत्रण केवल उस धागे से एक्सेस किया जा सकता है जिसमें इसे बनाया गया था, और सभी बाहरी कॉल, जिसमें प्रक्रिया के बाहर भी शामिल है। (या किसी अन्य कंप्यूटर से - DCOM के माध्यम से) COM रनटाइम के माध्यम से क्रमबद्ध और सिंक्रनाइज़ किया जाएगा।
वैसे, सीरियलाइज़ेशन के बारे में, जो कि, या बल्कि, मार्शलिंग के बारे में है। सिद्धांत रूप में, हमारे घटकों और संकेतकर्ताओं की विधि कॉल को इसके इंटरफेस में क्रमबद्ध करने के लिए, हमें इसके साथ एक अलग पुस्तकालय, तथाकथित प्रॉक्सी-डीएल के समानांतर रखना चाहिए, जो क्लाइंट एप्लिकेशन (यदि यह किसी अन्य कंप्यूटर पर है) में लोड किया जाएगा और वह प्रक्रिया जहां हमारा COM घटक लोड होता है।
Microsoft का MIDL कंपाइलर एक प्रॉक्सी लाइब्रेरी के लिए कोड उत्पन्न कर सकता है, या, जैसा कि इस मामले में, प्रॉक्सी / स्टब में कहा जाएगा, लेकिन हमारे मामले में इसे करना आसान है - चूंकि डेटा प्रकार अधिक या कम मानक हैं, इसलिए हम अंतर्निहित मार्शलिंग का उपयोग कर सकते हैं रनटाइम OLE। इस स्थिति के लिए, हमें अपनी IDL फ़ाइल से तथाकथित प्रकार की लाइब्रेरी (टाइप लाइब्रेरी, tlb) को संकलित करने की आवश्यकता है, फिर से MIDL कंपाइलर, midl.exe (Windows SDK और VS दोनों के साथ शामिल) का उपयोग करके, और इसे अपने घटक पर स्थापित करें यह। इसके अलावा, हम आगे भी पूरी बात को सरल कर सकते हैं और DLL संसाधन अनुभाग में संकलित प्रकार की लाइब्रेरी को शामिल कर सकते हैं, जो हम करेंगे।
हमारे मॉड्यूल के संसाधनों के लिए हेडर फ़ाइल:
#ifndef __RESOURCE_H__ #define __RESOURCE_H__ #define IDB_MAIN_ICON 101 #define IDR_MYCONTROL 102 #define IDS_SHADER 103 #define SHADER_RESOURCE 256 #endif
IDR_MYCONTROL - पंजीकरण स्क्रिप्ट का संसाधन आईडी।
IDB_MAIN_ICON - बीएमपी प्रारूप में, हमारे घटक के लिए 16x16 आइकन। मैंने व्यक्तिगत रूप से इस फ़ाइल के लिए MS DirectX SDK से डायरेक्टएक्स आइकन लिया।
IDS_SHADER और SHADER_RESOURCE - संसाधन का प्रकार और क्षेत्र के प्रकार जिसमें ड्राइंग कोड के लिए शेडर कोड होता है।
संसाधन फ़ाइल ही, MyActiveX.rc है:
#include <windows.h> #include "Resource.h" LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 1 TYPELIB "MyActiveX.tlb" IDR_MYCONTROL REGISTRY "MyControl.rgs" IDB_MAIN_ICON BITMAP "DirectX.bmp" IDS_SHADER SHADER_RESOURCE "MyActiveX.fx" VS_VERSION_INFO VERSIONINFO FILEVERSION 1,0,0,0 PRODUCTVERSION 1,0,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x4L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", "MyActiveX component module\0" VALUE "FileVersion", "1, 0, 0, 0\0" VALUE "InternalName", "MyActiveX\0" VALUE "LegalCopyright", "Copyright 2012 (C) Dmitry Ignatiev <lovesan.ru at gmail.com>\0" VALUE "OriginalFilename", "MyActiveX.dll\0" VALUE "ProductName", "MyActiveX component module\0" VALUE "ProductVersion", "1, 0, 0, 0\0" VALUE "OLESelfRegister", "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END
अब हम सीधे अपने नियंत्रण के कार्यान्वयन के लिए आगे बढ़ते हैं।
वर्ग CMyControl को कॉल करें, और हेडर फ़ाइल CMyControl.hpp बनाएं
#ifndef __CMY_CONTROL_HPP__ #define __CMY_CONTROL_HPP__ #include <atlbase.h> #include <atlcom.h> #include <atlctl.h> #include "Resource.h" #include "MyActiveX.hpp" #include "MyControl.hpp" class DECLSPEC_UUID("5747094E-84FB-47B4-BC0C-F89FB583895F") CMyControl : public CComObjectRootEx<CComSingleThreadModel>, public CStockPropImpl<CMyControl, IMyControl, &IID_IMyControl, &LIBID_MyActiveXLib>, public CComControl<CMyControl>, public IPersistStreamInitImpl<CMyControl>, public IPersistPropertyBagImpl<CMyControl>, public IObjectSafetyImpl<CMyControl, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>, public IOleControlImpl<CMyControl>, public IOleObjectImpl<CMyControl>, public IOleInPlaceActiveObjectImpl<CMyControl>, public IViewObjectExImpl<CMyControl>, public IOleInPlaceObjectWindowlessImpl<CMyControl>, public IConnectionPointContainerImpl<CMyControl>, public IPersistStorageImpl<CMyControl>, public ISpecifyPropertyPagesImpl<CMyControl>, public IQuickActivateImpl<CMyControl>, public IDataObjectImpl<CMyControl>, public IProvideClassInfo2Impl<&CLSID_MyControl, &DIID__IMyControlEvents, &LIBID_MyActiveXLib>, public IPropertyNotifySinkCP<CMyControl>, public CComCoClass<CMyControl, &CLSID_MyControl> { public: DECLARE_REGISTRY_RESOURCEID(IDR_MYCONTROL) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CMyControl) COM_INTERFACE_ENTRY(IMyControl) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IViewObjectEx) COM_INTERFACE_ENTRY(IViewObject2) COM_INTERFACE_ENTRY(IViewObject) COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY(IOleInPlaceObject) COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY(IOleInPlaceActiveObject) COM_INTERFACE_ENTRY(IOleControl) COM_INTERFACE_ENTRY(IOleObject) COM_INTERFACE_ENTRY(IPersistStreamInit) COM_INTERFACE_ENTRY(IPersistPropertyBag) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit) COM_INTERFACE_ENTRY(IConnectionPointContainer) COM_INTERFACE_ENTRY(ISpecifyPropertyPages) COM_INTERFACE_ENTRY(IQuickActivate) COM_INTERFACE_ENTRY(IPersistStorage) COM_INTERFACE_ENTRY(IDataObject) COM_INTERFACE_ENTRY(IProvideClassInfo) COM_INTERFACE_ENTRY(IProvideClassInfo2) END_COM_MAP() BEGIN_PROP_MAP(CMyControl) END_PROP_MAP() BEGIN_CONNECTION_POINT_MAP(CMyControl) CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink) END_CONNECTION_POINT_MAP() BEGIN_MSG_MAP(CMyControl) MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) MESSAGE_HANDLER(WM_CREATE, OnCreate) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) MESSAGE_HANDLER(WM_SIZE, OnSize) MESSAGE_HANDLER(WM_TIMER, OnTimer) CHAIN_MSG_MAP(CComControl<CMyControl>) END_MSG_MAP() DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE) CMyControl(); ~CMyControl(); STDMETHOD(Run)(); STDMETHOD(Stop)(); HRESULT OnDraw(ATL_DRAWINFO& di); private: LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); CMyControl(const CMyControl& copy); class CMyControlImpl; CMyControlImpl *_impl; }; #endif // __CMY_CONTROL_HPP__
जैसा कि आप देख सकते हैं, कक्षा की परिभाषा काफी बड़ी हो गई है।
ActiveX नियंत्रण को लागू करने के लिए, हमारी कक्षा, वास्तव में, IDispatch से शुरू होने वाले कई COM इंटरफेस की एक बड़ी संख्या को लागू करना चाहिए, लेकिन चूंकि हम ATL का उपयोग करते हैं, इसलिए विशेष वर्गों से विरासत के लिए प्रक्रिया को बहुत सरल किया जाता है जिनके नाम "Impl" में समाप्त होते हैं। ", जो, एक तथ्य के रूप में, एक मानक रूप में इंटरफेस के लिए आवश्यक कार्यक्षमता को भी लागू करता है।
हमारे CMyControl के तीन सबसे महत्वपूर्ण आधार वर्ग CComObjectRootEx हैं, जो विशेष रूप से, हमारी कक्षा की वस्तुओं की संदर्भ गणना, CComCoClass, जो क्लास फैक्ट्री (IClassFactory) को लागू करता है, और CComControl है, जो बदले में CWindowImpl (एक वर्ग है कि HWDD को लपेटता है) , और यह कि अंतर्निहित ActiveX नियंत्रणों के लिए आवश्यक अधिकांश कार्यक्षमता को लागू करता है।
क्लास बॉडी में सबसे महत्वपूर्ण मैक्रोज़:
DECLARE_REGISTRY_RESOURCEID - उस संसाधन की आईडी को इंगित करता है जिसमें घटक पंजीकरण स्क्रिप्ट स्थित है।
BEGIN_COM_MAP + END_COM_MAP - IUnogn इंटरफ़ेस (जो COM इंटरफ़ेस के पदानुक्रम के शीर्ष पर है) के क्वेरीइंटरफेस विधि को लागू करता है, जो आपको ऑब्जेक्ट के विभिन्न इंटरफ़ेस (और COM_INTERFACE_ENTRY में से एक विकल्प का संकेत देता है) के लिंक प्राप्त करने की अनुमति देता है।
BEGIN_CONNECTION_POINT_MAP और संबंधित END नियंत्रण घटनाओं के साथ अलर्ट से जुड़े इंटरफेस के कार्यान्वयन के लिए आवश्यक हैं।
BEGIN_MSG_MAP, MESSAGE_HANDLER और END_MSG_MAP - C ++ कक्षाओं के तरीकों के लिए विंडोज-विंडो संदेशों की मैपिंग लागू करें।
जब भी नियंत्रण प्रणाली को एक संदेश मिलता है, हम हर बार ऑनड्रॉव विधि को रिड्राईजिंग की आवश्यकता के बारे में कॉल करेंगे। इसके अलावा, नियंत्रण को फिर से व्यवस्थित करने को टाइमर पर बुलाया जाएगा।
हमारे घटक की सभी कार्यक्षमता, और विशेष रूप से, Direct3D के साथ काम करना, निजी वर्ग CMyControlImpl द्वारा लागू किया जाता है, pimpl पैटर्न के अनुसार, फ़ाइल CMyControl.cpp में। मैं इसका विस्तार से वर्णन नहीं करूंगा, मैं केवल यह ध्यान दूंगा कि CMyControl के निर्माता में ही आंतरिक संपत्ति m_bWindowOnly को TRUE पर सेट करना आवश्यक है - इसका मतलब यह होगा कि हमारा घटक ग्राफिक अनुप्रयोगों में विशेष रूप से एम्बेडिंग का समर्थन करता है।
इसके अलावा, यह ध्यान देने योग्य है कि COM इंटरफेस के लिए लिंक की गिनती को नियंत्रित करने के लिए घटक के कार्यान्वयन में, एटीएल से स्मार्ट पॉइंटर CComPtr के टेम्पलेट वर्ग को सक्रिय रूप से उपयोग किया जाता है, बहुत बढ़ावा से intrusive_ptr के समान है।
अब हम MyActiveX.cpp फ़ाइल बनाएंगे, जिसमें हम वर्ग और इंटरफेस के GUID को परिभाषित करेंगे, _Module चर, और ActiveL मॉड्यूल के लिए आवश्यक DLL और निर्यात किए गए फ़ंक्शन के प्रवेश बिंदु को भी लागू करते हैं:
#include <windows.h> #include <atlbase.h> #include "MyActiveX.hpp" #include "CMyControl.hpp" const IID IID_IMyControl = {0x2B26D028,0x4DA6,0x4D69,{0x95,0x13,0xD0,0xCA,0x55,0x09,0x49,0xD1}}; const IID LIBID_MyActiveXLib = {0x1E4E47F3,0x21AF,0x407C,{0x95,0x44,0x59,0xC3,0x4C,0x81,0xF3,0xFA}}; const IID DIID__IMyControlEvents= {0xE7D13B5A,0x0A09,0x440A,{0x81,0xEA,0xC9,0xE3,0xB0,0x10,0x5D,0xB0}}; const CLSID CLSID_MyControl= {0x5747094E,0x84FB,0x47B4,{0xBC,0x0C,0xF8,0x9F,0xB5,0x83,0x89,0x5F}}; CComModule _Module; BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_MyControl, CMyControl) END_OBJECT_MAP() extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { if(DLL_PROCESS_ATTACH == dwReason) { _Module.Init(ObjectMap, hInstance, &LIBID_MyActiveXLib); DisableThreadLibraryCalls(hInstance); } else if(DLL_PROCESS_DETACH == dwReason) _Module.Term(); return TRUE; } STDAPI DllCanUnloadNow(void) { return (_Module.GetLockCount()==0) ? S_OK : S_FALSE; } STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { return _Module.GetClassObject(rclsid, riid, ppv); } STDAPI DllRegisterServer(void) { return _Module.RegisterServer(TRUE); } STDAPI DllUnregisterServer(void) { return _Module.UnregisterServer(TRUE); }
डीएल को संकलित करने से पहले, हम यह निर्धारित करते हैं कि हमारे मॉड्यूल डी-फाइल में कौन से कार्य करता है:
LIBRARY "MyActiveX.dll" EXPORTS DllCanUnloadNow PRIVATE DllGetClassObject PRIVATE DllRegisterServer PRIVATE DllUnregisterServer PRIVATE
विंडोज एसडीके का उपयोग करके निर्माण के लिए मेकफिल सहित सभी परियोजना स्रोत कोड, लेख के अंत में लिंक पर, गिटब पर प्रदान किया जाता है। लेकिन पहले, एक घटक को एम्बेड करने के कुछ उदाहरण:
एक HTML पृष्ठ में एम्बेड करें
<html> <head> <title>Test page for MyControl ActiveX object</title> <script type="text/javascript"> var running = false; function OnClick() { var ctl = document.getElementById("MyControl"); var btn = document.getElementById("btn"); if(running) { ctl.Stop(); running = false; btn.value = "Run"; } else { ctl.Run(); running = true; btn.value = "Stop"; } } </script> </head> <body> <center> <input type=button value="Run" id="btn" style="display:block; padding: 3px 20px;" onclick="OnClick();"/> <object id="MyControl" style="width:500px; height:500px;" classid="CLSID:5747094E-84FB-47B4-BC0C-F89FB583895F"> </object> </center> </body> </html>

Windows.Forms पर किसी अनुप्रयोग में एम्बेड करना
using System; using System.Windows.Forms; namespace MyControl { class MyControl : AxHost { public MyControl() : base("5747094E-84FB-47B4-BC0C-F89FB583895F") { } public void Run() { dynamic ax = GetOcx(); ax.Run(); } public void Stop() { dynamic ax = GetOcx(); ax.Stop(); } } class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Form f = new Form(); f.Text = "My control"; f.StartPosition = FormStartPosition.CenterScreen; f.Width = 640; f.Height = 480; MyControl c = new MyControl(); c.Dock = DockStyle.Fill; c.BeginInit(); Button b = new Button(); b.Dock = DockStyle.Top; b.Text = "Run/Stop"; bool running = false; b.Click += (s, e) => { if (running) { c.Stop(); running = false; } else { c.Run(); running = true; } }; f.Controls.Add(b); f.Controls.Add(c); f.ShowDialog(); } } }

स्रोत कोड:
github.com/Lovesan/MyActiveX