Create an ActiveX control with ATL and MFC

xiaoxiao2021-03-06  31

Abstract: At present, MFC and ATL represent two frameworks, respectively, for different types of Windows-based development. The MFC represents a simple, consistent method of creating a separate Windows application; ATL provides a framework to implement the sample file code that Create a COM client and server. Both frames will be in their use of developing ActiveX. We will see how these two frameworks apply to create an ActiveX control - highlight its advantages and disadvantages, personally experience the process of creating a control - so that you can decide when to use a frame, when to use another. If you want to write ActiveX® controls with C , there are two popular frames, one is Microsoft® Foundation Classes (MFC) and the other is ATL. I will explain in depth to the support of the development of ActiveX controls to help you better decide which model is best for your development environment and demand. The full-form ActiveX control of the ActiveX control is based on the component object model COM, making the ActiveX control Basic principle of possible COM is an object's interface and its implementation and should be treated separately. As long as the COM object is consistent with the details of the interface, how to achieve it. The ActiveX control demonstrates the interface of a large number of ActiveX control package containers. Because the client code and control recognizes the external performance of these interfaces, you can write an ActiveX control and then put it into the package container. The package container will drive the control through a good definition, and these controls will make a proper response in their own way. At higher levels, an ActiveX control is a COM object that implements several primary ActiveX technology, including usually introduced COM interfaces, OLE embedded protocols, connection points, and property pages. At lower programming hierarchies, the ActiveX control only implements COM classes for certain types of interfaces. When some client code successfully queried one of these interfaces, it knows how to use an ActiveX control. An ActiveX control exposed interface is mainly divided into three categories. First, the ActiveX control is an embedded object; means that they have achieved most OLE documents, in-place activation, and embedded protocols. ActiveX controls to achieve the following interfaces: IOleObject, IPersistStorage, IDataObject, IOleInPlaceActiveObject, IOleInPlaceObject, IViewObject2 and IRunnableObject (this one is rarely used) second ActiveX controls typically support property pages, so the client side can modify the properties of the control. . Finally, ActiveX control usually uses COM's connection technology to implement the outgoing interface that the client can discover. To help compare the ATL and MFC frameworks, let's take a look at the same controls in each frame. This control monitors the message stream that creates its thread. The message flow control is a very good example because it demonstrates all the main aspects of an ActiveX control, including feeding interface, outgoing interface, attribute, permanent, and attribute pages. Let's start with the standard COM support from studying the two frameworks. The basic COM of the MFC support Microsoft builds MFC makes it easy to develop Windows® applications more than using SDK. With MFC, Microsoft then adds COM support for ready-to-store frames. This means that the MFC developers must keep the frame complete when more and more functions. At the same time, the Template does not support the Visual C ® compiler, so they have to incorporate the COM function into their classes by means of other means of non-template. Microsoft solves this problem by adding some virtual functions to the CCMDTARGET class and some macros, making the COM interface in the MFC.

COM support inside the MFC starts from CCmdTarget, Iunknown CCmdTarget class implements the interface, further comprising a member variable (m_dwRef) for a reference count and for 6 functions implement IUnknown :: InternalAddRef, InternalRelease, InternalQueryInterface, ExternalAddRef, ExternalRelease And ExternalQueryInterface .. Two versions of QueryInterface - Addref and Release support COM aggregation. InternaaDDREF, INTERNALEASE, and INTERNALQUERYINTERFACE complete the reference count and QueryInterface operation, and ExternalDRef, ExternalRelease, and ExternalQueryInterface proxy control aggregated objects (if this object is involved in aggregation). MFC uses nested class composite policies to implement COM interfaces. In the MFC, you want to implement the COM interface to derive from the ccmdtarget. Each interface implemented by CCMDTARGET is achieved by its own nested class. The MFC uses the macro begin_interface_part and end_interface_part to generate a nested class. Finally, the MFC implements the table driver QueryInterface. The working mechanism of the MFC interface mapping is basically the same as its message mapping: the message map of the MFC puts a Windows message and a function in a C class; the MFC interface mapping puts the GUID of an interface to represent this interface. The address of the VPTR is connected. Each CCMDTARGET-based class implementation COM interface adds an interface mapping by more macros: declare_interface_map, begin_interface_map, interface_part, and end_interface_map. To understand what these macros are in practice, please see Figure 1, which illustrates the MFC class that implements the ActiveX control, ColeControl. When you read the code, note that the ColeControl has a signature with each interface between a pair of begin_interface_part and end_interface_part macros, but also note that the ColeControl interface mapping table has 22 entries. In addition to the IUNKNOWN interface, the MFC also includes a standard implementation of IclassFactory. Once again, the MFC provides this support through several macros. MFC has two macros to provide class objects: declare_oleracte_ex and import_olecreate_ex.. In a CCMDTARGET-based class, use these macros to add a static member of a ColeObjectFactory type to that class. If you look at the definition of ColeObjectFactory in AfxDisp.h, you will see a nested class macro with the MFC in ColeObjectFactory to define a nested class to implement iClassFactory2. IclassFactory :: CREATEINSTANCE's MFC version uses MFC's dynamic creation mechanism (Declare_DyncReate, and Implement_DyncReate Macro to open this feature) to instantiate COM classes, so buying MFC COM support also means buying its dynamic creation mechanism. The last few basic COM support in the ActiveX control provided by MFC is support for iDispatch. Implementing a distribution interface is almost insignificant with Visual C and MFC. Implement a distribution interface in the MFC, just you need to use ClassWizard.

The automatic creation board in ClassWizard has a button for adding properties and the other for adding a method. In MFC, IDispatch supports from the CCMDTARGET class. The actual implementation of IDispatch's MFC is in a class called COLEDISPATCHIMPL, and COLLDISPATCHIMPL is derived from Idispatch, implements all 4 IDispatch functions: gettypeInfocount, gettypeinfo, getidsofnames, and invoke .. The class derived from the ccmdtarget is incremented by calling EnableAutomation, adding IDispatch VPTR to their interface map. When the customer calls the QueryInterface of IDispatch on the MFC-based ActiveX control, the ccmdtarget hands over the VPTR links to the ColedispatchImpl. Each time you use ClassWizard to join an automatic property or method to a class, you also add one of the distribution mapping tables in this class. A distribution map is a simple table that links DISPIDS (symbols for calling distribution members) and their represented names and and actually completed some C code that do this work. ColedispatchImpl calls and getIDSOFNames functions work by finding distribution members and distributing DISPIDs in class distribution mapping tables. MFC provides very good support for some COM-based advanced technologies such as OLE documents, OLE drag and drop, and auto operations, however, if you want to change the framework - For example, you want to distribute interface to double interface - you I have to get a big hand. On the other hand, ATL is more a COM center. ATL's basic COM support ATL's goal is to make developers don't have to override IUNKNOWN, IDISPATCH, ICLASSFACTORY, and other branches to turn regular DLL and EXE into COM-based DLL and EXE. From this perspective, ATL is a multi-frame frame that is thinner than MFC, and COM support is considered when designing and generating. It uses a template-based approach, by inheriting the template provided by the ATL, the developer can add a variety of COM functional pieces. The original COM support from ATL is from the support of IUNKNOWN. ATL's IUNKNOWN implementation is divided into two parts: CComObjectroTex classes to process reference counts for the iUnknown section; CComObjectRootBase class, used to process QueryInterface. CComObjectroTex is a template-based class that will linearize as its unique parameter. This is an example of how ATL acts uses templates to communicate algorithms as template parameters. ATL has two classes for processing reference counts for processing different linear models: CCOMSingLethreadModel and CCommultithreadModel. These classes have an increment and a decrement function. The difference between them is to increment and decrement with standard C operators ( and -); and CCOMMULTITHREADMODEL uses thread secure InterlocKedIncrement and InterlocKedDecrement functions to implement these two features. According to the template parameters used to instantiate CComObjectEx, it can run a given component type correctly. You will soon see an example of its usage. Like the MFC, ATL uses a table-based lookup mechanism to implement queryinterface .. CComObjectRootBase handles the QueryInterface function of the class through an interface map. Begin_ COM_MAP and END_COM_MAP macros define the beginning and end of an interface map.

However, unlike MFC, ATL provides 17 ways to form an interface map, for example, using the VPTRS such as IoleObjectImpl using a template-based interface from ATL. This includes VPTRs from the class from Tear-Off or by aggregation. In ATL, C class specifies the component model they want to use by inheriting CComobjectEx, specifying the components models they want (remember, the IUnknown support of MFC is built into the CCMDTARGET) becomes COM class. ATL's class object (and iClassFactory) support is also from templates, while MFC class objects support via ColeObjectFactory and some macro. ATL's class objects support from the CCOMCLASS / CCOMCLASSFACTORY family and CCMCREATOR class families. CCOMCOCLASS contains a class of GUID to define an error handling facility for COM classes. The CCMCREATOR class provides CreateInstance implementation for CCOMCLASSFACTORY. For MFC, you can pass a number of macros to make all this support is valid. The ATL includes Declare_Class_Factory, Declare_Class_Factory2, Declare_Class_Factory_Auto_thread, and Declare_Class_Factory_Singleton, etc., etc. to make a variety of specific types of plant support valid. Finally, ATL supports Idispatch's support from template classes, and its name is IDispatchImpl.. ATL is more support than the IDispatch support than MFC, and the support of IDispatch is more than the COM center. The MFC uses a Hand-Rolled iDispatch implementation, while ATL uses a more standard method to load type information of an interface and represent the standard type library compiler. Figure 2 shows a standard ATL-based control. The most worthless point is how the MFC and ATLs introduce the necessary various interfaces required to implement a control. The support of the MFC to the standard control interface is built in the Colecontrol class. You have given your control from the ColeControl and inherit all function calls at once. Note that ATL is inherited by template to introduce each functional piece one by one. This is a very important difference, because this means with ATL you can ignore some interface implementation templates (for example, make your control more streamlined) peel off undesirable features. For MFC, you can't complete the same action - no matter what you want, you will get all interfaces. About Example Application Here I will use an example of an ActiveX control monitoring message flow through a branch process, which shows the message flow diagram in real time. These two controls actually have the same functionality. They all submit charts to the screen. They are flowing into the interface so that the container can notify the control to start and stop the chart. They all support the color of the chart line and the length of the message interval as attributes. Finally, they all support the default event set, and the package container will be notified on the number of messages processed in a specific time period. Figure 3 shows these two controls. Figure 3 Monitoring ActiveX Control Messages Develop a control with MFC Develop an ActiveX control to use ActiveX ControlWizard in Visual Studio®. In order to start a new control, select New from the File menu, then select the MFC ActiveX control Wizard from the list of engineering types. First, ControlWizard requires you to decide how many controls are included in the DLL. Then you can choose how you intend to implement your control. The first options provided by ControlWizard generally applies to the DLL of the control. They include license support, source annotations, and online help.

Select License Make ControlWizard use begin_olefactory and end_olefactory (not Declare__olecreate).. Begin_olefactory and End_oleFactory macros cover VerifyUserLicense, and GetLicenseKey, thus providing license support for your control. Requesting ControlWizard includes comments to join all TODO annotations. Finally, requesting the ControlWizard including online help will create a template Help file source code for the DLL. Once you pass the first dialog, ControlWizard displays a dialog box to configure controls in the DLL. These configuration selections include the options visible when the control is run, allows the control to activate the option, so that the object can be inserted, giving the control of an option of an Abut box, making the control like a simple frame control as an option as a simple frame control . Figure 4 explains how different options affect the code generated by ControlWizard. ControlWizard has an option to implement controls as a standard Windows control, just like an edit box or a button. This is an interesting option. For example, if you choose to divide a button to divide your control into a subclass, the control's window is actually a button. At this point, PrecreateWindow intercepts the window of the control, use the Button window class when the control is created. ControlWizard allows you to choose some advanced options, including the window-free activation, so that your control has a complete device context, realizing no-shaking activation, so that your control is also accepting mouse messages in non-activated status, making your control asynchronous Load your own properties. Here has an outline of how each option affects the code generated by ControlWizard. Activated This option overwrites Colecontrol :: getControlFlags, attaching the WindowlessActivate flag to the control flag. Once this option is valid, the package container sends the input message to the IoleInplaceObjectWindowless interface of the control. This interface ColeControl's implementation distributes messages through your message mapping. You can handle messages like processing General Windows messages by simply adding a corresponding entrance to message mapping tables. The context of the free device has selected this option to override Colecontrol :: getControlFlags, close the ClipPainTDC bit, so that INTERSECTCLIPRECT calls are removed in the ColeControl onpaint function. If you are sure your control does not need to draw external drawings outside the customer area, this option is useful because there is an obvious speed increase after invalidation of the invocation of INTERSECTCLIPRECT. Jitter-free activation Selection This option overrides ColeControl :: getControlFlags, bringing the default control flag with the NoflickerActivate phases or. The control checks this flag when the control is activated to prevent the control from being swapped when the activation and inactive state are converted. If your control is the same as the appearance of the activation and inactive state, then this option is useful. Non-activated mouse pointers notify this option override ColeControl :: getControlFlags, which is attached to the PointerInactive bit. The iPointerInactive interface makes an object most of the time non-activation, but still participates in interactions with certain operations of the mouse, such as dragging and dropping. Optimized drawing code This option overrides Colecontrol :: getControlFlags, open the CanoptimizedRAW bit, checks this flag (through the ColeControl 'IsoptimizedDraw function) to determine if the control needs to restore the old object after completing the painting .

Asynchronous Load Properties This option adds the Stock ReadyState property and the Stock ReadyStateChange event to the control. This will make the control to load its properties asynchronously. For example, a lot of data loaded as one of its properties takes a long time to load, and lock the control. This STOCK property and event make this control immediately start loading the process. The package container uses this event and attribute judgment control to complete the load. When ControlWizard completes these things, you get the source code of the DLL containing this control (extension is .olx). The source code generated by Wizard includes a class from ColeControlModule (it is derived from cwinapp). This class contains the initialization code of the entire control module. Next, Wizard is based on Colecontrol representation of the source code for each control. Finally, Wizard generates some ODL code to establish type information. Once Wizard produces a control DLL, you face the task of perfecting this control. This means adding a rendering code, developing an introduction interface (method and attribute), the Rigging UP property page, showcase some events. However, when I explain how all this works, let's take a look at what to use ATL to create a control. Developing a control with ATL has an MFC-based control, you can get a trigger for developing ATL-based controls with ATL COM App Wizard. Use ATL to create controls to be two steps. Although the MFC's Control Wizard requires you to pre-determine how many controls you want to include in the DLL, ATL COM Wizard is simple to create a DLL - you can use the ATL object option to add controls from the INSERT menu. When you create a new ATL-based DLL, you can choose to mix MFC support. You can also choose to merge any Proxy / Stub code in the DLL of the control. This makes if someone wants to remotely control the code implemented by your control, you just have to release a file. Once an ATL-based DLL is generated, you can start adding a COM class. The INSERT New ATL Object menu strip makes this work easily. Select this menu item to display a dialog for creating any COM class, including unformatted COM objects, ActiveX controls, and part of the Microsoft Transaction Server component (part of Windows NT Server). When adding ATL-based controls to your project, ATL Object Wizard provides a greater range option than MFC Object Wizard. For novices, ATL makes you choose to use any existing linear model to implement your control. You can mark your class or single thread or unit thread. ATL Object Wizard limits the control you create a free or mixing thread because the control is usually the UI. If you create a single-threaded control, a customer of a tolerant control will always load it into the main, single-threaded unit (STA). As a result, only single-lanes running in the customer's process space will come into contact with your object, which eliminates the responsibility of your control status that you are not affected by concurrent interference. Also, because all instances of your object will only be contacted by a thread, you will not be worried about global data in the DLL. If your control is a cell thread, you also exempt most burden on the internal status of your control. However, you still have to protect global data in the DLL. why? First, imagine that your control is created by the customer's single-threaded. Now, the customer tries to create another copy of the control - but is from a cloud to the multi-threaded unit in the current process. By marking your object as a unit thread, COM is told that you want your control to protect from concurrent access. COM creates a new STA when it is loaded.

Now when the thread calls to your object, they can only access it through the unit boundary, and the remote layer will synchronize the call to this object. However, when a control is protected from concurrent access, the data shared by the control of the example (like the global data in the DLL) is fragile. This is because your global DLL data (for several object services, running in separate threads, respectively) will be contacted by those multi-threads. Although the MFC-based COM class is always aggregated (built-in support), ATL ObjectWizard makes you specify your control to support aggregation, just aggregated, or independent objects. According to your choice of aggregate options, ATL ObjectWizard uses a macro to perform aggregation policies. For example, an implementation of default COM classes is a polymerizable-object that will run both in a separate mode, as part of a polymerization. If you make your COM objects into aggregate, ObjectWizard adds the DECLARE_NOT_ AGGREGATABLE macro to your class definition. If you choose to be agable, ObjectWizard adds the DECLARE_OnLY_AGGREGATABLE macro to the class definition. Here is how macro works. The default object is created in a class called _creatorclass. _CREATORCLASS When the object mapped to the server range (this is part of the Object_Entry Macro), it becomes your COM class's creation mechanism. _CreatorClass is actually just a alias named CCMCREATOR2 class, which uses two classes customized from the CCMCREATOR class as a parameter. This special macro mode selected according to the aggregation type CcomCreator are used respectively CComObject, CComAggObject, CComFailCreator, or CcomPolyObject: #define DECLARE_NOT_AGGREGATABLE (x) public: / typedef CComCreator2 >, / CComFailCreator

> _CREATORCLASS;

#define DECLARE_AGGREGATABLE (x) public: / typedef CComCreator2 >, / CComCreator >> _CreatorClass; #define DECLARE_ONLY_AGGREGATABLE (x) public: / typedef CComCreator2

, /

CComCreator >> _CreatorClass; #define DECLARE_POLY_AGGREGATABLE (x) public: / typedef CComCreator > _CreatorClass; ATL ObjectWizard Attributes last page includes three check boxes COM support for exception handling (e.g., IsupportErrorInfo Interface), connection point, and free thread set (FTM). You can also add ISUPPORTERRORINFO to the inheritance list of the control, provide an implementation of ISUPPORTERRORINFO :: InterfaceSupportSerrorInfo. Open the connection point will add the iConnectionPointImpl template class to the inheritance list of the control. Polymerize your control to FTM causes the call between the unit (and the up and down of Windows 2000), if the two objects are located in the same process. However, you should not check this when writing controls, because when you use FTM, you violate the unit (and the context of Windows 2000) rules. In addition to the general options you can apply to all COM objects, ATL ObjectWizard provides several controls to create specific options. First, ATL ObjectWizard allows you to divide subclasses from a regular control (such as a button or an editing control). You can specify several other options for your space to make it more opaque, give it a more solid background, not visible at runtime, or your control is like a button. Below is an outline of the options provided by the control property page: an opaque and solid background If you want all the package containers without displaying the control boundary, select the "Opaque" check box, which is the status of the container passed to it. information. As a result, the control is explained that it will draw its full rectangle. Select this option to set the ViewStatus_opaque bit so that IVIEWOBJECTEXIMPL :: GetViewStatus indicates an opaque control to the package container. You may also want to choose a solid background. This option sets the ViewStatus_ SolidBkGnd bit so that GetViewStatus indicates that the control has a solid background. This option is not visible when running, making your controls are not visible at runtime. You can use invisible controls to complete some operations in the background, such as periodic excitation events. This option enables the control to flip the OLEMISC_INVISIBLEATRUNTIME bit after it is added to the registry. Imitation button This option makes your control like a button. At this point, the control will be displayed as the default button on the basis of the property DisplayAsDefault surrounding the package container. If the location of the control is marked as the default button, the control will appear as a thicker frame. Select this option to flip OLEMISC_ACTSLIKEBUTTON after it is added to the registry. Imitation Tag Select this option to make your control replace the internal label of the container. This makes the control after it adds to the registry in the registry. Mark Olemisc_ActslikeLabel. Adding a control on a superclass is added to select this option to make your control according to a standard WINDOW class division. The drop-down list contains a Windows defined Window class. When you choose one of these class names, add a CContainedWindow member variable to your control class. CContainedWindow :: Create is supercarbed with the Window class you specified. Specification DC Select this option to create a specificized device context when you call yourself. This standardizes the appearance of the control, but the efficiency is lowered.

The code generated by this option overwrites the onDrawadvanced method (instead of a regular OnDraw method). Insertable Select this option makes your controls in the Insert Object dialog box like Microsoft Excel and Word. Your control can be inserted into any application that supports embedded objects. Select this option to add an Insertable button in the registry key. Select this option for windowing forcing your control window, even in a package container that supports windowless objects. If you don't choose this option, your control will automatically adapt to the package container: in the package container that supports windowless, there is a window in the package container that does not support windowless objects. This will make the ccomcontrolbase :: m_bwindowonly flag set to True. ATL uses this flag to determine if you want to query the IoleInPlaceSItemWindowness interface of the package container during the control. ATL requires you to determine your object's stock properties in the stock property page, you can select the attributes such as CAPTION or Border Color, or select all the stock attributes at once by clicking >> Buttons. This will add an attribute to the property map of the control. After running the ATL COM App Wizard and ObjectWizard, you get a complete DLL that has all the branches necessary for COM DLL. The well-known exports displayed by this control include DllgetClassObject, DllcanunloadNow, DllregisterServer, and DllunregisterServer. In addition, you get an object that meets the main needs of COM - includes a mainstream interface and a class object. Once you have used a wizard to start a project, the next step is to make the control do something interesting. Usually the starting point is the translation code of the control. You get some visual feedback immediately. Let's take a look at how the translation of MFC-based control is what happens. Control translations MFC and ATL are similar in translation processing. In each frame, the class that implements the control has a virtual function called OnDraw. You just need to add your translation code into the onDraw function. However, in each frame, the ONDRAW function has different work. The MFC's OnDRAW is called in two context. The first context occurs when the control responds to a WM_PAINT message. At this time, the device context that passes to the OnDraw function represents a real device context. If the control is being required to render itself as a response to the customer call iViewObjectEx :: DRAW, the device context or a metad device context, or a regular device context. The following code illustrates how the MFC-based control is render: void cmfcmsgtraftctrl :: overdraw (cdc * pdc, const crect & rcbounds, const crect & rcinvalid) {// Todo: Use your own drawing code to replace the following code PDC- > FillRect (RcBounds, Cbrush :: fromHandle ((Hbrush) getStockObject (White_brush)); showgraph (* PDC, Const_cast

(rcbounds), NMESSAGESTOSHOW);

} The signature of the Colecontrol :: OnDRAW includes a rectangle representing the size of the control and a rectangle representing the illegal area of ​​the control. The MFC calls the control's onDraw function to respond to a WM_PAINT message. At this point, the onDraw function accepts a real device context to draw. The MFC also calls the onDraw function of the control to respond to one of the iViewObject :: DRAW. MFC's implementation calls ColeControl :: OnDrawMetafile, its default OnDrawMetafile calls ColeControl :: Ondraw. Of course, this suggests that the real-time translation of the control is the same as the metafile of the control, which is stored with the package container when designing. You can make the real-time translation of the control different from the translation of the design, which is achieved by overloading the ColeControl :: OndrawMetafile. You can force a redrawn by calling the InvaliDateControl method of your control. The translation mechanism of ATL is very similar to MFC. CCOMCONTROLBASE :: OnPaint builds an ATL_DRAWINFO structure, including creating a drawing device context. The ATL is then called the Ondrawadvanced function of the control. OnDrawadvanced generates meta files, then calls your control's onDraw method, which uses information in the ATL_DRAWINFO structure to know how to draw on the screen. Here is ATL_DRAWINFO structure: struct ATL_DRAWINFO {UINT cbSize; DWORD dwDrawAspect; LONG lindex; DVTARGETDEVICE * ptd; HDC hicTargetDev; HDC hdcDraw; LPCRECTL prcBounds; // the drawing in which a rectangular LPCRECTL prcWBounds; // WindowOrg and Ext if metafile BOOL bOptimize; Bool Bzoomed; bool zoomhimetric; sizel zoomnum; // zoomx = zoomnum.cx/zoomnum.cy sizel zoomden;}; ATL fills in this structure. When you are drawing on the screen, the most important domain you are interested is HDCDRAW and PRCBounds. If you are interested in drawing in a meta file, or you need to pay attention to scaling factors, then other domains is also important. The following code shows how the ATL-based message flow control is processed:

HRESULT CATLMsgTrafficCtl :: OnDraw (ATL_DRAWINFO & di) {RECT & rc = * (RECT *) di.prcBounds; HBRUSH hBrush = CreateSolidBrush (RGB (255, 255, 255)); FillRect (di.hdcDraw, & rc, hBrush); DeleteObject ( Hbrush); Rectangle (di.hdcdraw, rc.left, rc.top, rc.right, rc.bottom); showgraph (di.hdcdraw, rc, nMessagestoshow); return s_ok;} When you use ATL, you The device and GDI handle must be processed. In ATL, you call the fireviewchange function of your control to force the control of the control. Develop an inflow interface When developing an MFC-based ActiveX control, the default inflow interface is a distribution interface. Visual C and MFC make developing an inflow distribution interface is very simple - just use ClassWizard to generate methods and properties. Each time you use ClassWizard to add a new property or method, it is inserted into a distribution map to your control. MFC uses distribution maps to meet customer call requests. The disadvantage of the MFC is that adding a regular COM interface in your control is a boring process. This process includes COM macros using MFC to establish nested classes that implement interfaces. When developing the mainstream interface for your ATL-based COM control, class is the best means to add attributes and methods. When you generate code for the control, ATL ObjectWizard adds a default inflow interface. This can be a double-end interface, or a regular custom interface depends on the previously set project options. Visual Studio's class view shows you all classes and interfaces included in your project. You can add an attribute or method when you right-click on a definition of an interface. It is very convenient to use the class to define the interface, because each time you add a method or attribute, the class can update IDL, class source code, and header files. Not like MFC, which is very easy to add a regular COM interface to the control. In ATL, you just add new interface sample file connections (GOO) (a GUID, keyword object, and keyword interface). Category view will display new interfaces, you can continue to add new members. Adding an attribute An ActiveX control often contains properties, which are a member variable that describes the status of the control. The best way to add an attribute to an MFC-based control is to use the classwizard. ClassWizard automatically adds a member variable to you, map them to the default distribution interface. ClassWizard gives you two options: You can add a member variable, including a changing advertisement function, or you can add a pair of GET / SET functions, manually add member variables. In addition to adding your own custom properties to the control, ClassWizard adds inventory like adding background and titles. ClassWizard even adds a member variable for your class. There is a point different from an ATL-based control, you add a separate access program and variation factor function (PropGet, and ProPPUT functions for each attribute in the control. However, class is only defined interface functions. You have to add data members to the class, then simply implement these functions. ATL-based control also supports the stock attribute, ATL ControlWizard requires you to determine which STOCK properties are included in your control. Add at least one STOCK attribute to the control to inherit the control from the CstockPropIMPL class from ATL.

CstockPropiMPL is an implementation, optimization of iDispatch to display the Stock property of the ActiveX control, which contains the GET and PUT functions compatible with Idispatch for each standard stock attribute. ControlWizard also adds a data member representing the Stock property to the control, for example, if you add a background color's stock property, ControlWizard adds a data member named M_clrbackColor to your class. CstockPropimple adds an implementation for the GET and PUT functions of all standard stock properties. All of these functions are expected to see the right member variables in your class (M_ClrBackColor corresponding to the background color). The compiler will block on the GET and PUT functions that the stock attribute is not included. The implementation process hopes to see member variables in your class. In order to eliminate compiler errors, CCOMControlBase adds a joint structure that includes the name of all members of the GET and PUT functions that STOCK. However, adding data members to control the name in the federal type, the cstoppropiMPL class uses controls in its GET and PUT functions. If you have forgotten the use of ControlWizard, you can always add relevant code - - That is, inherit from CstockPropiMPL, then add member variables to the properties you want to display. The attribute continuation mechanism of the attribute continuous MFC is very intuitive and easy to understand. From a programming point of view, all you have to do is fill in the DOPEXCHANGE function already provided by ControlWizard. DOPROPEXCHANGE moves the status of the control properties from some member variables to the continuous media. The MFC has three attribute continuous mechanisms, built into Colecontrol: IPersistPropertybag, IPersistStorage, and IPersistStream [init]. All of these continuity mechanisms are encapsulated in the CPropExchange class of the MFC, and CARCHIVE is very similar to the CARCHIVE when you need a Serialize a document. The client chooses to use one of the three interfaces to maintain an object. Regardless of which continuity mechanism is used, the execution is in the DOPEXCHANGE function of the control. The following code shows how to control MFCMsgTraffic color and save it up interval attribute: void CMFCMsgTrafficCtrl :: DoPropExchange (CPropExchange * pPX) {ExchangeVersion (pPX, MAKELONG (_wVerMinor, _wVerMajor)); COleControl :: DoPropExchange (pPX ); PX_COLOR (PPX, "GraphlineColor", M_GraphLineColor; PX_LONG (PPX, "Graphinterval", M_INTERVAL);} MFC includes several PX_ functions to transfer data between controls and storage media, they are:

PX_Short PX_UShort PX_Long PX_ULong PX_Color PX_Bool PX_String PX_Currency PX_Float PX_Double PX_Blob PX_Font PX_Picture PX_IUnknown PX_VBXFontConvert PX_DataPath management control properties in ATL continued involves two steps. The first step is to add the ATL implementation you want to the continuous interface that customers can use. ATL includes class IPersistRORGEIMPL, IPERSISTREAMINITIMPL, and IPERSISTPROPERTYBAGIMPL, which implements three main COM continuous mechanisms. The second step is to insert attributes in the property map of the control. When a customer requests to save or load an ATL-based control, the ATL checks the property mapping table, outputs the properties of the control to the storage medium, or input from the storage medium. The property mapping table is a property name, a table of Dispids, sometimes including a property page GUID. The ATL traversal word table finds which attributes that continue and continues to the appropriate media. Figure 5 shows an ATLMSGTRAFFIC control that inherits a continuous interface implementation and an attribute map. Properties page ActiveX controls often provide a property page to help developers when developers put controls in various containers. Playing a message flow control in a developer of a dialog may want to configure the various aspects of the control, the sampling interval of the control, or the color of the drawing line. For example, when the control is placed in a dialog box, Visual Studio displays a prominent dialog when you get the properties of the control by right mouse. The working process will be explained here. Visual Studio request control In a dialog frame (Visual Studio ISPAGYPAGES interface request control provides a list of a property page), the property page is displayed in Visual Studio, but a COM interface provided by the control, keep connecting to the control connection . Whenever you have completed the property editing and close the dialog from Visual Studio, it will require the properties in the property page update control. When you generate an MFC control, Wizard gives you a dialog template and a class that represents the default property page derived from ColePropertyPage. Visual Studio makes it easy to implement the properties of a control and the properties in this property page. When you use the ControlWizard's Automation Tab to add an attribute to your MFC-based control, you give an external name. This name is an external client (including the property page) to identify this property. You can develop property pages in accordance with any other dialog box - add controls to dialog templates to link dialog members variables and controls. ControlWizard adds DDX / DDV code to exchange data between dialog controls and member variables. However, when you associate member variables and dialog controls, ControlWizard gives you an opportunity that you can use external property names for member variables for dialog boxes. This name is a string that is typed when you add a property to the control. When the property page needs to be applied to the control (for example, when pressing the Apply button), the property page uses the control's IDSPATCH interface and the external name to modify the properties of the control. In the MFC, you can add a new attribute through ClassWizard, add a new dialog template to the project, let ClassWizard create a class - To make sure to be born from the ColePropertyPage. Then, in order to enable the new attribute page to be accessed by the outside, it is added to the property page mapping of the control (two macros in the .cpp file in the control).

Not like the ActiveX ControlWizard of the MFC, ATL COM App Wizard does not add the default properties page to the DLL. This means you have to do this yourself. Fortunately, another Wizard can add ATL-based DLL to the property page. Just choose INSERT ATL Object and then find the property page object. Wizard adds a dialog template and a C class to a property page together with all the necessary COM GOOs. It is your business to make them do. Unfortunately, the Wizard driver feature of the ATL property page is worse than the MFC-based property page, you have to manually complete the application and display operation. This means providing the APPLY and SHOW functions to your property page class. The Apply function is just the status of the control in the dialog box, traverses the interface pointer list of the pointing control, using the interface pointer to modify the control properties. The show function typically extracts the status of the control, and then organizes the control of the dialog box. The following code shows how the ATL-based property page is processed by the Apply function:

STDMETHOD (Apply) (void) {long nInterval = GetDlgItemInt (IDC_EDITINTERVAL); ATLTRACE (_T ( "CMainPropPage :: Apply / n")); for (UINT i = 0; i QueryInterface (IID_IATLMsgTrafficCtl, (void **) & pATLMsgTrafficCtl); if (pATLMsgTrafficCtl) {pATLMsgTrafficCtl-> put_Interval (nInterval); pATLMsgTrafficCtl-> Release ();}} m_bDirty = FALSE; return S_OK;} is based ATL The control provides a second step in a property page is to ensure that the CLSID of the property page appears in the property map of the control, and the attribute continuous code listed in Figure 5 provides an example of it. Message mapping indicates that the control of the control, is managed by the standard color property page. Sampling interval of controls is managed by the primary attribute page of the control. WINDOW Messages MFC and ATL have a lot of common in they handle Window messages, using message mapping, have WiZARDS to generate code processing Window messages. In the MFC, the message mapping can be added to any CCMDTARGET derived class, and then you can use ClassWizard to create the event processor for your control. Figure 6 shows how the MFC-based control is processed to process the WM_ TIMER message. In addition, the MFC provides a macro that handles commands and control notices. Like the MFC, the ATL handles the Window message through the message mapping, as long as your class is derived from CWindowImpl, and contains the ATL message map macro, you can use the class to create an event processor. Figure 7 shows how the ATL message flow control processes the WM_TIMER message. ATL uses the Message_Handler Macro to map the standard Window message to a C class. This macro is simple to generate a table that associates a WINDOW message and a member function of the class. In addition to regular messages, message mapping can also handle other types of events. Figure 8 shows various macros that can participate in the message mapping. The comparison to which the connection and events to be performed is how the MFC and ATL are processed by the connection point and event set. To manage connection points and event sets, a COM class is required to implement IconnectionPointContainer, then create a method that provides a pointer to iConnectionPoint to the customer. MFC's master class, ColeControl, has built-in IconnectionPointContainer, and the MFC provides a connection point via the connection mapping. The MFC has defined the default event set of connection points and controls for iPropertynNotifyink. In order to improve the default event set based on MFC-based control, you will use the ClassWizard's ActiveX Event Tab as long as it is easy. When you use ClassWizard to add an event, Visual Studio updates your control .odl file, describe the outgoing event for the potential package container. In addition, Visual Studio adds a function to your class, you can call it in turn to motivate events to the bag container. Figure 9 demonstrates an event trigger mechanism for an MFC-based control.

The event trigger function based on the MFC-based control is only some simple wrappers for one Idispatch pointer provided by the package container to establish a connection point in it and the control. Establish an event in ATL-based controls. In an ATL-based control, you start with the event of the control. IDL file. Then you have established a compilation project file for the type library. Figure 10 shows an event set of ATL-based controls described in IDL. One, type library compile, you can click on the class in class, right-click on the class, then select Implement Connection Point, let the class will create a callback agent for you. Visual Studio pops up a dialog box listing all accessible event interfaces in the control type library. You choose those you want to call the agent, Visual Studio write a proxy. Figure 11 shows a callback agent based on ATL-based message flow control. The callback agent generated by Visual Studio represents a C friendly function set and is called by the client implemented. The MFC's IconNnectionPointContainer implementation is hard distributed to ColeControl, and each connection is processed by a connection mapping, while the implementation of the ATL is handled by multiple inheritance. Your control class inherits iConnectionPointContainerImpl and a class-dependent agent. If you start a project, choose "Supports Connection Points", ObjectWizard adds IconnectionPointContainerImpl to you. If you forget the tag check box, you can write it. This code shows how the connection point mechanism is added to a control. Class ATL_NO_VTABLE CATLMSGTRAFFICCTL: {•• PubliciConnectionPointContainerImpl

,

Public cproxy_datlmsgtrafficevents

转载请注明原文地址:https://www.9cbs.com/read-81569.html

New Post(0)