I just stumbled across a backup of an old Web site, dating back to 1996. Back then I already had a personal homepage where I posted programming tricks. The one I picked for "reprint" is about COM / MFC programming - how to derive OCX controls from each other while maintaining a set of base properties etc. Here you go with a really antique piece of advice:
Create your basic OLE Control. Create a new Control using the Class Wizzard to add a new Control to your project OCX. Replace all occurencies of COleControl with your new base class (because DoPropExcange wouldn´t work correctly).
All the outlined tips & tricks work well, but there´s an exception: the release DLL of VC++ 1.51. The versions 32Bit Debug/Release and 16Bit Debug work fine, but the 16Bit Release DLL (oc25.dll) crashes with one of the controls I´ve developed. But this may also be a result of this special control I developed (I got compiler internal errors as well in release mode). I tried to track the bug, but couldn´t catch it. If someone has a good idea, here´s the DLL last entry point that was called before crash: 0015:00003f32 (oc25.dll)
COleControl::OnEnumVerbs enumerates all ON_OLEVERB Macros found in the message map. Because such entries exist in every COleControl derived class, they are duplicated (just doing the same). Therefore just put comments in the derived classes.
BEGIN_MESSAGE_MAP(CTestocx2Ctrl, CTestOCXCtrl) //{{AFX_MSG_MAP(CTestocx2Ctrl) ON_WM_RBUTTONUP() //}}AFX_MSG_MAP // ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties) END_MESSAGE_MAP()
This is done in the ODL file. Just copy the entries from the base class (CTestOCXCtrl) to the derived classes property dispatch interface (this time behind AFX_ODL_PROP)
//{{AFX_ODL_PROP(CTestOCXCtrl) [id(DISPID_BACKCOLOR), bindable, requestedit] OLE_COLOR BackColor; [id(DISPID_FORECOLOR), bindable, requestedit] OLE_COLOR ForeColor; //}}AFX_ODL_PROP
//{{AFX_ODL_PROP(CTestocx2Ctrl) //}}AFX_ODL_PROP [id(DISPID_BACKCOLOR), bindable, requestedit] OLE_COLOR BackColor; [id(DISPID_FORECOLOR), bindable, requestedit] OLE_COLOR ForeColor;
This is a "cool" hack when you do some pfreaking in the MFC Control sources: MFC passes requests with unknown DISPID´s to the base class, where, when found, these DISPID´s are built in the following way: DWORD dispid = MAKELONG(nIndex,nDeriveLevel)
Guess what you are doing in the ODL file: id[(MAKELONG(1,1))] for derivation level 1 and the original DISPID of 1 (see ODL file base class numbers). Of course MAKELONG won´t work in ODL file, so you have to hand-compute it: Derivation level 1/DISPID 0: 65536, Derivation level 2/DISPID 0: 131072. Just add your base class DISPID to this numbers - et voilá.
dispinterface _DTestOCX { //{{AFX_ODL_PROP(CTestOCXCtrl) [id(1)] short MyProperty; //}}AFX_ODL_PROP methods: //{{AFX_ODL_METHOD(CTestOCXCtrl) [id(2)] void DoTestOCX(); //}}AFX_ODL_METHOD [id(DISPID_ABOUTBOX)] void AboutBox(); };
dispinterface _DTestocx2 { properties: //{{AFX_ODL_PROP(CTestocx2Ctrl) //}}AFX_ODL_PROP [id(65537)] short MyProperty; methods: //{{AFX_ODL_METHOD(CTestocx2Ctrl) [id(1)] void DoTestOCX2(); //}}AFX_ODL_METHOD [id(65538)] void DoTestOCX(); [id(DISPID_ABOUTBOX)] void AboutBox(); };
The DISPID_ABOUTBOX is here duplicated, so only the derived classes Aboutbox is used. You could also use the base classes AboutBox(), when you remove the method call in the Dispatch map of derived classes´ implementation file..
Same HI/LO trick again.
Simple: Just remove all code from ::....::UpdateRegistry(...) [that´s the factory object meant here] and return TRUE. This class will never be seen again, but message dispatch, member ID´s and so on do work.
(don´t take the line for sure) Comment states duplicate name in dictionary. This assertion is caused by this "duplicate" entry in DoPropExchange:
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
Solution: Drop this line in the base class (if you are hiding it) or in the derived class (if depending on base class)