The Initial CBullsEye Class Declaration Listing 11.5 shows the initial wizard-generated class declaration for the CBullsEye control class. We have to make a number of changes to the class before it meets all the requirements described at the beginning of the chapter. For example, we need to add a few more base classes to obtain all the required control functionality. Also, presently the control supports no properties except the stock properties I selected via the wizard dialog boxes. Plus, there is quite of bit of implementation code to write to make the control draw and behave as a bull's eye. I'll get to all that, but first let's look at the initial source code. I've reformatted the source code slightly from the original wizard-generated source code to group related functionality and to add a few comments (see Listing 11.5). Listing 11.5. The Initial Wizard-Generated CBullsEye Class // CBullsEye class ATL_NO_VTABLE CBullsEye : // COM object support public CComObjectRootEx<CComSingleThreadModel>, // Class object support public CComCoClass<CBullsEye, &CLSID_BullsEye>, // Default dual interface for control. // Requests for properties preprocessed by // stock property base class public CStockPropImpl<CBullsEye, IBullsEye>, // Error info support for default dual interface public ISupportErrorInfo, // Basic "lite" control implementation public CComControl<CBullsEye> public IOleControlImpl<CBullsEye>, public IOleObjectImpl<CBullsEye>, public IOleInPlaceActiveObjectImpl<CBullsEye>, public IOleInPlaceObjectWindowlessImpl<CBullsEye>, public IViewObjectExImpl<CBullsEye>, // "Lite" control persistence implementation public IPersistStreamInitImpl<CBullsEye>, // Full control additional implementation #ifndef _WIN32_WCE // Support for OLE Embedding public IDataObjectImpl<CBullsEye>, #endif public IPersistStorageImpl<CBullsEye>, // Support for property pages public ISpecifyPropertyPagesImpl<CBullsEye>, // Support for fast activation public IQuickActivateImpl<CBullsEye>, // Connection point implementation public IConnectionPointContainerImpl<CBullsEye>, public CProxy_IBullsEyeEvents<CBullsEye>, public IProvideClassInfo2Impl<&CLSID_BullsEye, &__uuidof(_IBullsEyeEvents), &LIBID_BullsEyeControlLib>, // Selection of IPropertyNotifySink adds additional // connection point for property change notifications public IPropertyNotifySinkCP<CBullsEye>, #ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the // control to be loaded correctly public IObjectSafetyImpl<CBullsEye, INTERFACESAFE_FOR_UNTRUSTED_CALLER>, #endif { public: CBullsEye() { } DECLARE_REGISTRY_RESOURCEID(IDR_BULLSEYE) DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE | OLEMISC_CANTLINKINSIDE | OLEMISC_INSIDEOUT | OLEMISC_ACTIVATEWHENVISIBLE | OLEMISC_SETCLIENTSITEFIRST ) BEGIN_COM_MAP(CBullsEye) // Default dual interface to control COM_INTERFACE_ENTRY(IBullsEye) COM_INTERFACE_ENTRY(IDispatch) // Error info support for default dual interface COM_INTERFACE_ENTRY(ISupportErrorInfo) // Basic "lite" control implementation COM_INTERFACE_ENTRY(IOleControl) COM_INTERFACE_ENTRY(IOleObject) COM_INTERFACE_ENTRY(IOleInPlaceActiveObject) COM_INTERFACE_ENTRY(IOleInPlaceObject) COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY(IViewObjectEx) COM_INTERFACE_ENTRY(IViewObject2) COM_INTERFACE_ENTRY(IViewObject) // "Lite" control persistence implementation COM_INTERFACE_ENTRY(IPersistStreamInit) COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit) // Full control additional implementation // Support for OLE Embedding #ifndef _WIN32_WCE COM_INTERFACE_ENTRY(IDataObject) #endif COM_INTERFACE_ENTRY(IPersistStorage) // Support for property pages COM_INTERFACE_ENTRY(ISpecifyPropertyPages) // Support for fast activation COM_INTERFACE_ENTRY(IQuickActivate) // Support for connection points COM_INTERFACE_ENTRY(IConnectionPointContainer) COM_INTERFACE_ENTRY(IProvideClassInfo) COM_INTERFACE_ENTRY(IProvideClassInfo2) #ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the // control to be loaded correctly COM_INTERFACE_ENTRY_IID(IID_IObjectSafety, IObjectSafety) #endif END_COM_MAP() // Initially, the control's stock properties are the only // properties supported via persistence and property pages. BEGIN_PROP_MAP(CBullsEye) PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4) PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4) #ifndef _WIN32_WCE PROP_ENTRY("BackColor", DISPID_BACKCOLOR, CLSID_StockColorPage) #endif PROP_ENTRY("BackStyle", DISPID_BACKSTYLE, CLSID_NULL) PROP_ENTRY("Enabled", DISPID_ENABLED, CLSID_NULL) #ifndef _WIN32_WCE PROP_ENTRY("ForeColor", DISPID_FORECOLOR, CLSID_StockColorPage) #endif END_PROP_MAP() BEGIN_CONNECTION_POINT_MAP(CBullsEye) // Property change notifications CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink) // Our default connection point CONNECTION_POINT_ENTRY(__uuidof(_IBullsEyeEvents)) END_CONNECTION_POINT_MAP() // Initially the control passes all Windows messages // to the base class BEGIN_MSG_MAP(CBullsEye) CHAIN_MSG_MAP(CComControl<CBullsEye>) DEFAULT_REFLECTION_HANDLER() END_MSG_MAP() // ISupportsErrorInfo STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid) { // Implementation deleted for clarity... } // IViewObjectEx DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE) // IBullsEye public: HRESULT OnDraw(ATL_DRAWINFO& di) { // Sample drawing code omitted for clarity } // Storage for values of stock properties OLE_COLOR m_clrBackColor; LONG m_nBackStyle; BOOL m_bEnabled; OLE_COLOR m_clrForeColor; // Stock property change notification functions void OnBackColorChanged() { ATLTRACE(_T("OnBackColorChanged\n")); } void OnBackStyleChanged() { ATLTRACE(_T("OnBackStyleChanged\n")); } void OnEnabledChanged() { ATLTRACE(_T("OnEnabledChanged\n")); } void OnForeColorChanged() { ATLTRACE(_T("OnForeColorChanged\n")); } }; | The Initial IBullsEye Interface Listing 11.6 is the initial wizard-generated IDL description for the IBullsEye interface. The wizard generates the interface containing any stock properties you've specified. We need to add all the custom properties for the control, as well as any stock and custom methods that the control supports. Listing 11.6. The Initial Wizard-Generated IDL for the IBullsEye Interface [ object, uuid(B4FBD008-B03D-4F48-9C5B-4A981EB6A515), dual, nonextensible, helpstring("IBullsEye Interface"), pointer_default(unique) ] interface IBullsEye : IDispatch{ [propput, bindable, requestedit, id(DISPID_BACKCOLOR)] HRESULT BackColor([in]OLE_COLOR clr); [propget, bindable, requestedit, id(DISPID_BACKCOLOR)] HRESULT BackColor([out,retval]OLE_COLOR* pclr); [propput, bindable, requestedit, id(DISPID_BACKSTYLE)] HRESULT BackStyle([in]long style); [propget, bindable, requestedit, id(DISPID_BACKSTYLE)] HRESULT BackStyle([out,retval]long* pstyle); [propput, bindable, requestedit, id(DISPID_FORECOLOR)] HRESULT ForeColor([in]OLE_COLOR clr); [propget, bindable, requestedit, id(DISPID_FORECOLOR)] HRESULT ForeColor([out,retval]OLE_COLOR* pclr); [propput, bindable, requestedit, id(DISPID_ENABLED)] HRESULT Enabled([in]VARIANT_BOOL vbool); [propget, bindable, requestedit, id(DISPID_ENABLED)] HRESULT Enabled([out,retval]VARIANT_BOOL* pbool); }; | The Initial _IBullsEyeEvents Dispatch Interface The initial _IBullsEyeEvents dispatch interface is empty (see Listing 11.7). We need to add the BullsEye custom events to the dispinterface. When a control supports any of the stock events, you add them to the event interface as well. Listing 11.7. The Initial Wizard-Generated IDL for the _IBullsEyeEvent Dispatch Interface [ uuid(58D6D8CB-765D-4C59-A41F-BBA8C40F7A14), helpstring("_IBullsEyeEvents Interface") ] dispinterface _IBullsEyeEvents { properties: methods: }; | |