Fives. COM_INTERFACE_ENTRY_AGGREGATE (IID, PUNK)
This section will be introduced to the macro used to aggregate objects in ATL. Please refer to other reference books for the concept of gathering objects.
Let's take a look at this macro test now:
Class Cagg: Public IDispatchiMPL
CAGG is a gathering class, which does not differ from the general ATL component, just notice that do not join DECLARE_NO_AGGREGATABLE in its class definition.
class COuter: public CChainBase, public IDispatchImpl
The COUTER contains the aggregated component CAGG, which contains several differences:
(1) Join Com_Interface_entry_aggregate (IID_IAGG, M_PUNKAGG.P) macro.
#define com_interface_entry_aggregate (IID, PUNK) / {& IID, / (DWORD) OFFSTOF (_CommapClass, punk), / _dlegate},
Offsetof We have seen in the previous section, you can guess it is the position in PUNK in the class. That is, M_Punkagg is in the position of the COUTER.
(2) Join the macro Declare_Get_Controlling_unkNown (), which is defined as:
#define declare_get_controlling_unknown () public: / virtual iUnknown * getControllingunknown () () () () () () () ()
We don't have to continue to go abroad, you can see this function will return to the component's iUnknown pointer from literally.
(3) Add a member variable in the COUTER: ccomptr
(4) Heavy loaded FinalConstruct, FinalRelease
HRESULT COuter :: FinalConstruct () {IUnknown * pUnkOuter = GetControllingUnknown (); HRESULT hRes = CoCreateInstance (CLSID_CAgg, pUnkOuter, CLSCTX_ALL, IID_IUnknown, (void **) & m_pUnkAgg); return hRes;} void COuter :: FinalRelease () {m_pUnkAgg .Release (); .....} FinalConstruct will be called after creating component couter, so you will create a gathering component here. In principle, the aggregation component can be created only when needed, but can also be created along with the components that contain it. There is no special place for the creation of the aggregation components, just pay attention to it will query the IUnknown pointer and return to m_punkagg. External components will operate the components via the M_PUnkagg operation. Also note that Punkouter as a parameter of CocreateInstance, which will cause CCOMAGGGOBJECT
Run Pouter-> queryinterface (IID_IAGG, (Void **) & PAGG1)
Function Stack 1:
9.atl :: atlinternalQueryinterface (...) 8.atl :: ccomobjectrootbase :: innalqueryinterface (...) 7.cagg :: _ internalQueryinterface (...) 6.atl :: ccomaggobject
Explanation:
1-5: These steps have been called many times because of this macro definition using _Delegate, so CComObjectRootBase :: _ delegate (...).
Static HRESULT _DELEGATE (Void * PV, Refiid IID, Void ** PPVObject, DWORD DW) {HRESULT HRES = E_NOINTERFACE; IUNKNOWN * P = * (iUnknown **) ((DWORD) PV DW); if (p! = null HRES = P-> Queryinterface (IID, PPVObject); Return Hres;} The meaning of the second sentence we have seen in the previous section, the last result p = couter :: m_punkagg.
6: As we just expected, call now ccomaggobject
STDMETHOD (REFIID IID, VOID ** PPVObject) {// If the query is iUnknown, then .... else hres = m_contained._internalQueryinterface (IID, PPVObject); Return HRES;}
Just as we expected, it will be handed over to it. (This code seems to be seen in the previous section, huh, huh)
7-9: Like the same section, it will be handed over to CAGG :: _ InternalQueryInterface (...), and the remaining work will be done by CAGG. The final returned pointer is actually the interface pointer of the CCOMCONTAINEDOBJECT
Run PAGG1-> Queryinterface (IID_IAGG, (Void **) & PAGG2)
Function Stack 2:
9.cagg :: _ InternalQueryinterface (...) 8.atl :: ccomaggobject
Explanation:
1-9: Browse the entire stack, with the stack two of our previous section, because it is used to include objects. The role of the object has gone a proxy, he first handed the query to the external object (step 1, 2), when the external object is found to query the interface of the aggregated component (IAGG), The query is returned to the pointer to the aggregated component (M_PUnkagg, step 7, pay attention to this is not a real aggregation component), M_PUnkagg will hand over the query to the included object (step 8), including the object and give the query That's that the external object finds that the external object is found to query the interface of the external component, it is very simple, and directly queries. This prevents inconsistencies of external components and aggregated component query operations. Hey, the truth is really troublesome, but it is ok, it is very similar to the macro of the previous section. Related source code can be found in the previous section.