<December 2019>
SunMonTueWedThuFriSat
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

On this page...

Search

Links

Member of...


ASP Insiders

MVP Visual Developer ASP/ASP.NET

Enter CodeZone

Blog Categories

Microsoft

Blogroll

Deutsche Resourcen

Management

Sign In
 

#  Wednesday, August 4, 2004

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:

Deriving Controls from each other

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).

Special Attention

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)

Avoid a second Properties menu command

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()

Showing stock properties in derived classes

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

Derived Control class:

//{{AFX_ODL_PROP(CTestocx2Ctrl)
//}}AFX_ODL_PROP
 [id(DISPID_BACKCOLOR), bindable, requestedit] OLE_COLOR BackColor;
 [id(DISPID_FORECOLOR), bindable, requestedit] OLE_COLOR ForeColor;

Taking custom prop´s and OLE methods to derived classes

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á.

Base class ODL
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();
};
Derived class ODL
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..

Event map derivation

Same HI/LO trick again.

Hiding base class from end-user

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.

Assertion failed in propset.cpp line 1169

(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)

Categories: this
Wednesday, August 4, 2004 2:41:41 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 



Comments are closed.

© Copyright 2019 Christoph Wille

newtelligence dasBlog 2.3.9074.18820
Subscribe to this weblog's RSS feed with SharpReader, Radio Userland, NewsGator or any other aggregator listening on port 5335 by clicking this button.   RSS 2.0|Atom 1.0  Send mail to the author(s)

 
Don't contact us via this (fleischfalle@alphasierrapapa.com) email address.