Click here to Skip to main content
13,090,418 members (52,996 online)
Click here to Skip to main content
Add your own
alternative version


140 bookmarked
Posted 24 Apr 2002

Creating an ActiveX button from a MFC owner-draw button

, 25 Apr 2002
Rate this:
Please Sign up or sign in to vote.
Basic steps to transform a MFC button in an activex control
<!-- Download Links --> <!-- Add the rest of your HTML here -->


There are many owner-draw button written using C++ and the MFC classes. There are also many ActiveX controls, mostly written in Visual Basic. While with C++ you can easily use both the MFC and the OCX controls, with Visual Basic you need to convert the MFC objects to an activex control. Unluckily, the class wizard doesn't cover all the messages and the events sent to an ActiveX control, and some messages are different, so most of the magic must be hand written.

Because sometimes a piece of code is more clear than the article itself, I included the porting of CxShadeButton to an ActiveX control, but it's just an example, in the article I will speak about a generic AxButtonCtrl.

The MFC Activex Control Wizard & the Class Wizard

With a couple of clicks, the Activex Control Wizard writes for us about 600 lines of commented code that probably we will never read. Just remember to select "BUTTON" in the combo-box where the wizard ask: "Which window class, if any, should this control subclass?", and the framework is ready.

Using the Class Wizard, you can add the member functions to process the basic messages:


Some of these messages are optional, but I'm thinking about a custom control, so there are good chances to handle more messages than a normal button.
The WM_DRAWITEM message is not in the list, it's not a mistake, and I will explain this later.


void AxuttonCtrl::PreSubclassWindow() 
	... //custom style initiaization code	

In this method you can copy the same code used in a MFC control; the difference is in the last 2 lines: the button is now derived from COleControl (in place of CButton). You must set the BS_OWNERDRAW style to paint the button with your custom graphics, and the BS_NOTIFY style if you need some special notification messages, like BN_DISABLE, BN_KILLFOCUS, ...


These messages sometime are not used by MFC controls, but in Visual Basic, the WYSIWYG philosophy requires that the developer can see the appearance while she/he builds the GUI.
The control receives the WM_CREATE message and creates the object with COleControl::OnCreate(lpCreateStruct), after this call the button exists, and you can use all the windows functions (CWnd members in MFC) to initialize the graphic objects.
The WM_SIZE message is sent after WM_CREATE, and when the button size has been changed; here you must build (or rebuild) the position and/or the dimensions of the graphic objects.

Keyboard & mouse messages

These messages are useful for the tooltips and the hover functionality, see later.

Drawing the button - Reflected window messages

The Class Wizard provides an AxButtonCtrl::OnDraw member for the drawing functions.

void AxButtonCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
	DoSuperclassPaint(pdc, rcBounds);

You can leave it as it is. Our button waits the WM_DRAWITEM message, but the mechanism with activex controls is slightly different: COleControl creates an extra window called "reflector", in the same position of the control window. The reflector intercepts certain window messages and sends them to the control with a different name. The reflected messages are:


Message sent by control Message reflected to control

For these messages you must add the message handlers manually: in the control class .H file, declare a handler function like this:

class AxButtonCtrl : public COleControl
LRESULT OnOcmCommand(WPARAM wParam, LPARAM lParam);
LRESULT OnOcmDrawItem(WPARAM wParam, LPARAM lParam);<br>...

In the control class .CPP file, add the ON_MESSAGE entries to the message map:

BEGIN_MESSAGE_MAP(AxButtonCtrl, COleControl)

And implement the member functions to process the reflected messages. The wParam and lParam parameters are the same as those of the original window message.

LRESULT AxButtonCtrl::OnOcmDrawItem(WPARAM wParam, LPARAM lParam)
	UINT nIDCtl = (UINT) wParam;
	... //drawing code as used in WM_DRAWITEM
	return 0;


The Class Wizard gives some stock handlers for the standard events, however the resulting functionality could be limited. If you add the "Click" event with the stock handler implementation, when someone clicks the button with the mouse, COleButton automatically calls the FireClick method, so you don't need to process the OCM_COMMAND message. But if the button has the focus and someone presses the space bar, the FireClick method is not called, although the button receives the BN_CLICKED notification through the OCM_COMMAND message.
In the end, use the custom event handler implementation, in this way you can control exactly the behavior of the button, without hidden calls or messages.

LRESULT AxButtonCtrl::OnOcmCommand(WPARAM wParam, LPARAM lParam)

	switch (wNotifyCode)
		// Fire click event when button is clicked

	return 0;


The MSDN article Q141871 (HOWTO: Add Tooltips to ActiveX Controls) describes the steps to implement tooltips. The resume: add the RelayEvent method and a CToolTipCtrl m_ttip member variable; create and activate the tooltip; in the handlers for WM_LBUTTONDOWN, WM_LBUTTONUP, and WM_MOUSEMOVE call RelayEvent to relay appropriate messages to the ToolTip control.

Hover functionality

You must use a bool m_tracking member variable to track the mouse position. When the mouse is over the button, the WM_MOUSEMOVE messages are sent, and here activate the tracking.

if (!m_tracking) {
   if (::_TrackMouseEvent(&t)) {
      m_tracking = true;

To detect when the mouse leaves, you must add this message handler in the control class .H file:


and in the control class .CPP file:

LRESULT AxButtonCtrl::OnMouseLeave(WPARAM, LPARAM)
    ASSERT (m_tracking);
    m_tracking = false;
    return 0;


This article treats how to convert an owner draw button in an ActiveX control, this is just the beginning, to build a complete control I should talk about automation, property sheet, and so on ..., but these topics are out of the scope of the article. For detailed informations about COM, please read these articles <p>


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

No Biography provided

You may also be interested in...


Comments and Discussions

Jokes.a Pin
baran6325-May-07 21:37
memberbaran6325-May-07 21:37 
GeneralGetStyle() Pin
blackbox795-Feb-06 16:41
memberblackbox795-Feb-06 16:41 
GeneralRe: GetStyle() Pin
blackbox797-Feb-06 11:16
memberblackbox797-Feb-06 11:16 
GeneralThank you Pin
Mr Pham7-Jan-06 18:52
memberMr Pham7-Jan-06 18:52 
GeneralU can find a lot of great C++ ebooks here Pin
Anonymous14-Aug-05 2:47
sussAnonymous14-Aug-05 2:47 
GeneralIt's very nice... Pin
ponyhe22-Apr-04 20:00
memberponyhe22-Apr-04 20:00 
GeneralRe: It's very nice... Pin
Anonymous4-May-05 8:20
sussAnonymous4-May-05 8:20 
GeneralExactly what I needed Pin
Gilles Diawara1-Apr-04 7:40
memberGilles Diawara1-Apr-04 7:40 
GeneralVery nice! .. but not complete Pin
okmot24-Mar-04 9:48
memberokmot24-Mar-04 9:48 
GeneralThank you Pin
anurak_aun19-Mar-03 1:40
memberanurak_aun19-Mar-03 1:40 
GeneralYou have the "Golden Touch"!! Pin
WREY12-Feb-03 8:02
memberWREY12-Feb-03 8:02 
GeneralRe: You have the "Golden Touch"!! Pin
Davide Pizzolato12-Feb-03 19:40
memberDavide Pizzolato12-Feb-03 19:40 
GeneralRe: You have the "Golden Touch"!! Pin
Anonymous8-Apr-03 4:56
sussAnonymous8-Apr-03 4:56 
GeneralUseful and intuitive article Pin
Trinh Minh Cuong25-Apr-02 4:58
memberTrinh Minh Cuong25-Apr-02 4:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.170813.1 | Last Updated 26 Apr 2002
Article Copyright 2002 by Davide Pizzolato
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid