Compile C ++ code with better reusability -- band object and comtoys (8)

Source: Internet
Author: User

Compile/Zhao Xiangning

Original: Paul dilascia

MSJ November 1999 & December 1999

Keywords: bands object, desk bands, info/Comm bands, explorer bar, and tool bands.

This document assumes that you are familiar with C ++, COM, and IE.

Download the source code of this article: mybands.zip (KB)
Testeditsrch.zip (75kb)

Part 1: Introduction to band objects
Part 2: bandobj class hierarchy and mybands service program Registration
Part 3: go deep into the band and unveil the band.
Part 4: problems encountered in using the band object
Part 5: build your own COM programming platform comtoys
Part 6: design and construct comtoys
Part 7: class implementation

Part 8 factory and registration and US weaknesses

Factory and Registration

So far, our discussion has not touched on an important detail, that is, the creation of objects. Because it is relatively simple to design and implement. The class factory and registration discussed in the first four sections are quite broad. It describes how bandobj registers COM objects using the DLL entries listed in the resource script file and the class factory that uses the ATL register. To comtoys, I just moved the code from bandobj to comtoys. Comtoys uses ctmodule, ctfactory, and a special file dllentry. cpp to process object creation, registration, and DLL entries. Ctmodule is a typical "module class", just like the cwinapp of MFC or the ccommodule of ATL. Among them, virtual functions such as ongetclassobject and ondllregisterserver can be reloaded. However, you must include (# include) The dllentry. cpp that implements the DLL entry.

 extern "C" STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid,                           LPVOID* ppv) {   MFCENTRY;   return CTModule::GetModule()->     OnGetClassObject(rclsid, riid, ppv); }      

Such as dllregisterserver, dllcanunloadnow and other functions. Ctmodule: getmodule is similar to afxgetapp. It returns one and only one full ctmodule object. Therefore, all the work of dllentry. cpp is to convert external hard functions into virtual functions that are easier to overload. As for the MFC application, comtoys has a ctmfcmodule for the MFC Application class of COM, which inherits from the ctmodule and colecontrolmodule. Ongetclassobject and other operations are implemented in the ctmfcmodule class, and corresponding MFC functions are called to complete the work. The reason for separating these things is to try to put the processing in code that does not rely on MFC. Figure 18 shows the relationship between the MFC class and the non-MFC class:


Figure 18 Relationship Between MFC and non-MFC classes

For the implementation of the class factory, comtoys depends on the MFC imitation class: ctfactory. Ctmodule: onregisterserver calls a static function, ctfactory: onregisterall, which has the ctfactory: onregister called for each class factory. When the ctfactory is created. One of the parameters that must be specified is the resource ID. By default, ctfactory: onregister searches for script file resources with the same ID and calls the ATL Registrar to run it. But first it needs to call another virtual function: oninitregistryvariables to initialize common register variables, such as % CLSID % and % classname % ., the following is a list of variables defined by comtoys in ctcomobjfactory: oninitregistryvariables:

%CLSID%          = class ID (GUID) (COleObjectFactory::m_clsid)%MODULE%         = full pathname of DLL%Title%          = title (resource substring 0)%ClassName%      = human-readable COM class name (resource substring 1)%ProgID%         = ProgID (resource substring 2)%ThreadingModel% = "", "Apartment", "Free", or "Both" (m_nThreadingModel)      

You can overload oninitregistryvariables to add your own register variable. These methods are the same as those of the previous sections, but the current code is abstracted from the band object and enters comtoys. In the end, when registering and deregistering, all you need to do is write a registration script and put it as a resource into the resource file so that its ID is the same as that of the COM class.

IDR_MYCOMCLASS REGISTRY DISCARDABLE "MyComClass.rgs"      

It should be noted that the ctfactory has a headache: it should have implemented iclassfactory, but it does not. That's because I haven't had time to take care of it. So far, all the com classes I have created are related to MFC, and I have been using coleobjectfactory, which is very useful. Therefore, I derived cbandobjfactory from coleobjectfactory and ctfactory. If you need a non-MFC factory, you can implement an iclassfactory for the ctfactory. But now there is ctfactory, coleobjectfactory, and so on. ctfactory provides all the things required for registration and is easy to use. Coleobjectfactory provides the iclassfactory interface and the connection with dllgetclassobject. When a process such as Windows Resource Manager (Explorer) wants to create its own COM object instance, assume that it is creating mybands. the band object in DLL -- it calls the cocreateinstance function. This function reads the registry to determine which DLL to load and then calls dllgetclassobject (in dllentry. in CPP), it then calls the ctmodule: ongetclassobject. Because bandobj is an MFC-based object, it uses ctmfcmodule, and its ongetclassobject function calls the afxdllgetclassobject function of MFC. MFC search factory list and other processing. Someone may ask: where is the class factory created? Generally, declare_olecreate and implement_olecreate are used to create a class factory in MFC. These macros declare and instantiate a static coleobjectfactory object in the form of cmycomclass: class factory. However, neither bandobj nor comtoys in the previous four sections use declare/implement_olecreate. Therefore, to create your own class factory, you must call New for dynamic creation:

// In initinstance, new ctbandobjfactory (myguid, runtime_class (cmycomclass), idr_mainframe );

When a new ctfactory is created, comtoys adds it to the master list. MFC does the same for coleobjectfactory. In other words, as I explained in a few sections, you don't have to do anything specifically to let MFC or comtoys know about your class factory. You only need to create one. You do not have to delete the class factory. The ctmodule is automatically completed in exitinstance. If you prefer to create a static global class using the old-fashioned method-but you must set m_bautodel = false in your class factory constructor. The main reason for avoiding declare/implement_olecreate is that after doing so, I can derive my own class factory in the ideal way. In the bandobj example, you must create a class factory. as you have done in several sections, you still need to call addbandclass. To process object creation, all you need to do is to derive your own class factory from ctfactory and coleobjectfactory and remember the # include file dllentry. cpp. The rest is done by comtoys. To enable self-registration of COM objects, you have to write a resource script (RGS file) for registration and add it as a registry resource with the same ID as the class factory to the. RC file. For details about the RGS file, download the source code.

Weaknesses in the US

When I first realized comtoys, I encountered a small obstacle. What if the methods of the two com interfaces have the same name and signature? Although this rarely happens, it does. For example, both ipersiststream and ipersistfile have isdirty. If it is written as follows:

DECLARE_IPersistFile();DECLARE_IPersistStream();      

Isdirty is declared twice. Although it can be corrected manually, this problem is always disturbing. To do this manually, you must re-type A Lot Of implement_ipersiststream code, which is annoying. To avoid this, I introduced a function-level macro.

// Ipersistfile-the entire interface implement_ipersistfile (cmyclass, ctpersistfile); // ipersiststream-each independent function // functions (); Aggregate (cmyclass, ctpersiststream); Aggregate (cmyclass, ctpersiststream); implement_ipersiststream_getsizemax (cmyclass, ctpersiststream );

Here again demonstrates the advantages of magic mi ruler. There is only one isdirty which is applied to two interfaces: ipersistfile and ipersiststream. Isn't that the expected result? If you really want two interfaces to have the same function and different implementations, you can use the common C ++ syntax to fully limit the method name: cmycomclass: ipersiststream :: isdirty and cmycomclass: ipersistfile: isdirty. But with this function-level macro, at least you don't have to repeat it-or even know its implementation. Function-level macros also provide a way to overload the standard implementation for one or more interface methods, I think it is best to derive your own implementation class-ctmypersiststream or another class (to be continued)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.