Using the MFC wizard to create an ActiveX control is a very simple thing. In this article I will explain to you how to create an ActiveX button similar to a Windows XP style in VC .
Select the MFC ActiveX Control Wizard to create a new project and name it "xpbuttonex". There are two steps in the ActiveX Control Wizard. Select a control in the first dialog box, do not run the time license, source file annotation, and help files. In the second dialog box, select "Available" in the Insert Object dialog, there is an About dialog. When you want to call: "Which Window Class, if any, Should this Control Subclass?" Select "Button". Click to complete. The wizard will establish approximately 19 files, there are three classes: cxpbuttonexapp, cxpbuttonexctrl, and cxpbuttonexproppage.
Now open the class wizard and confirm that the currently selected is CXPButtonExctrl. Add message mapping for WM_CREATE, WM_LBUTTONDOWN, WM_LBUTTONUP, and WM_MOUSEMOVE. Right-click CXPButtoneXCtrl in the CLASS observation table, then add a virtual function: PRESUBCLASSWINDOW. Colecontrol :: PRESUBCLASSWINDOW () add statement at the PresubclassWindow function: ModifyStyle (0, BS_OWNERDRAW | BS_NOTIFY). Open XPButtonEx.h now, add the following member variables and functions:
PUBLIC:
CPEN * PBoundRypen;
CPEN * PinsideBoundrypenLeft;
CPEN * PINSIDEBOUNDRYPENTOP;
CPEN * PinsideBoundryPenright;
CPEN * PinsideBoundrypenbottom;
CPEN * POLDPEN;
CBRUSH * PFILLACTIVE;
CBRUSH * PFILLINACTIVE;
CBRUSH * POLDBRUSH;
BOOL M_BOVERCONTROL;
Void Dogradientfill (CDC * PDC, CRECT);
Void DrawInsideBorder (CDC * PDC, CRECT);
Open XPButtonex.cpp. Add the following code to the constructor cxpbuttonexctrl ():
m_boverControl = false;
PBoundrypen = New CPEN (PS_INSIDEFRAME | PS_SOLID, 1, RGB (0, 0, 0));
PinsideBoundrypenLeft = New CPEN (PS_INSIDEFRAME |
PS_SOLID, 3, RGB (250, 196, 88);
PinsideBoundrypenright = New CPEN (PS_INSIDEFRAME |
PS_SOLID, 3, RGB (251, 202, 106));
PinsideBoundrypenTop = New CPEN (PS_INSIDEFRAME |
PS_SOLID, 2, RGB (252, 210, 121));
PinsideBoundrypenbottom = New CPEN (PS_INSIDEFRAME |
PS_SOLID, 2, RGB (229, 151, 0));
Pfillactive = New CBRUSH (RGB (222, 223, 236);
PfillinActive = New CBRUSH (RGB (222, 223, 236));
Remove the object in the destructor ~ cxpbuttonexctrl (): PBoundrypen-> deleteObject ();
Pfillactive-> deleteObject ();
PfillinActive-> deleteObject ();
Poldpen-> deleteObject ();
Poldbrush-> deleteObject ();
PinsideBoundrypenLeft-> deleteObject ();
PinsideBoundrypenright-> deleteObject ();
PinsideBoundrypenbottom-> deleteObject ();
PinsideBoundrypentop-> deleteObject ();
Add the following function to XpButtonctL.cpp:
Void cxpbuttonexctrl :: DOGRADIENTFILL (CDC * PDC, CRECT)
{
CBRUSH * PBRUSH [64];
For (int i = 0; i <64; i )
PBRUSH [I] = New CBRUSH (RGB (253- (I / 2),
253- (I / 3),
253- (I / 4)))))))))
INT nwidth = (Rect.right) - (Rect.Left);
INT NHEIGHT = (Rect.bottom) - (Rect.top);
CRECT RCT;
For (i = Rect.top; i { Rct.seTRect (Rect.Left, I, NWIDTH 2, I 1); PDC-> FillRect (& RCT, PBRUSH [(I * 63) / NHEIGHT]); } For (i = 0; i <64; i ) Delete Pbrush [I]; } Void cxpbuttonexctrl :: drawinsideborder (CDC * PDC, CRECT) { Poldpen = PDC-> SelectObject (PinsideBoundrypenLeft); PDC-> MoveTo (Rect.Left, Rect.Bottom-3); PDC-> LINETO (Rect.Left, Rect.top 2); PDC-> SELECTOBJECT (PinsideBoundryPenright); PDC-> MoveTo (Rect.right-1, Rect.Bottom-3); PDC-> LINETO (Rect.right-1, Rect.top 2); PDC-> SELECTOBJECT (PinsideBoundrypenTop); PDC-> MoveTo (Rect.Left 2, Rect.top); PDC-> LINETO (Rect.right-2, Rect.Top); PDC-> SELECTOBJECT (PinsideBoundrypenbottom); PDC-> MoveTo (Rect.left 2, Rect.Bottom); PDC-> LineTo (Rect.right-2, Rect.Bottom); PDC-> SELECTOBJECT (POLDPEN); } Now return to OnoCmCommand (), and add the following Switch before returning 0 value: ... Switch (WNOTIFYCODE) { Case bn_clicked: // // The click evenet shop be fas Fired // when the button is copy.click event should be activated when the button is pressed FireClick (); Break; } We use the Boolean variable m_boverControll to track the mouse position. When the mouse is on the button, the button receives WM_MOUSEMOVE. Change the onmousemove code as follows: Void cxpbuttonexctrl :: ONMOUSEMOVE (UINT NFLAGS, CPOINT) { // Todo: Add your message Handler Code // Here and / or call default. ColeControl :: ONMOUSEMOVE (NFLAGS, POINT); IF (! m_bovercontrol) { m_boverControl = true; INVALIDATE (FALSE); TrackMouseEventTM; Tm.cbsize = sizeof (tm); Tm.dwflags = TME_LEVE; Tm.hwndtrack = this-> m_hwnd; :: _ TRACKMOUSEEVENT (& TM); } } Now, in order to detect when the mouse leaves the button, we must manually add the following message handle. Add: LResult Onmouseeleave (WPARAM, LPARAM); Add: on_Memage (WM_MouseLeave, OnMouseLeave) in XpButtonExctl.cpp. Add a function to XpButtonexctl.cpp: LResult CXPButtonexctrl :: OnMouseLeave (WPARAM, LPARAM) { m_boverControl = false; INVALIDATE (FALSE); Return 0; } Now, in order to draw a button, we need to manually add a handle for the OCM_DRAWITEM message. Add LRESUTTONEXCTL.H to add LResult OnoccrawItem (WPARAM WPARAM, LPARAM LPARAM). Add add on_message (OCM_DRAWITEM, ONOCMDRAWITEM) in XPButtonexctl.cpp. Add a function on xpbuttonex.cpp Add a function onOcmdrawItem: LResult CXPButtonexctrl :: OnoccrawItem (WPARAM WPARAM, LParam LPARAM) { Uint nidctl = (uint) wPARAM; LPDRAWITEMSTRUCT LPDRAWITEMSTRUCT = LPDRAWITEMSTRUCT) LPARAM; CDC * PDC = CDC :: fromHandle (LPDrawItemstruct-> HDC); CRECT RECT = LPDRAWITEMSTRUCT-> RCITEM; Uint state = lpdrawitemstruct-> itemstate; / / Draw the edge of the control Cpoint pt; Pt.x = 10; Pt.y = 10; Poldpen = PDC-> SELECTOBJECT (PBoundRypen); IF (State & ODS_SELECTED) PDC-> RoundRect (RECT, PT); Else PDC-> RoundRect (RECT, PT); PDC-> SELECTOBJECT (POLDPEN); // Reduce the draw area RECT.DEFLATERECT (CSIZE (CSISTEMETRICS), and getSystemMetrics); // If necessary to populate the internal color IF (m_boverControl) { Poldbrush = PDC-> SelectObject (Pfillactive); DOGRADIENTFILL (PDC, RECT); DrawInsideBorder (PDC, RECT); } Else { Poldbrush = PDC-> SelectObject (PfillInactive); DOGRADIENTFILL (PDC, RECT); } PDC-> SELECTOBJECT (POLDBRUSH); / / Draw a text IF (! m_title.isempty ()) { CSIZE EXTENT = PDC-> GetTextExtent (m_title / * strText * /); Cpoint Pt (Rect.centerpoint (). X - extent.cx/2, Rect.centerpoint (). y - extent.cy/2; IF (State & ODS_SELECTED) Pt.offset (1, 1); INT nmode = pdc-> setbkmode (transparent); CFont * PoldFont = SELECTSTOCKFONT (PDC); IF (State & ODS_DISABED) PDC-> DrawState (PT, Extent, m_title, DSS_DISABLED, True, 0, (Hbrush) NULL); Else PDC-> Textout (pt.x, pt.y, m_title); PDC-> SELECTOBJECT (POLDFONT); PDC-> setBkmode (nmode); } Return 0; } Now we will add two properties to our ActiveX Control. One is TILE and the other is font. Open the class wizard and select the Automation tab. Confirm that the selected class is CXPButtonex. Click the "Add Property" button. In the Add Property dialog, it gives it an external name (such as "Title") and select the type CString. Accept the default variables and functions. Click OK to close the class wizard dialog. . Add the following statement to the DOPROPEXCHANGE function Todo annotation in XpButtonexctl.cpp. PX_STRING (PPX, _T ("Title"), M_TITLE, _T ("CAPTION")); Now open the dialog template IDD_PROPPAGE_XPBUTTONEX to remove the TODO: ... declaration. Add an edit box IDC_TITLE, now open the class wizard, select the member variable label. Select Class CXPButtoneXProppage, select IDC_TITLE and click "Add Variable". In the Member Variable dialog box, give a member variable (such as m_title), category - value, variable type - cstring. Give Optional Property a name (such as title). Click OK to close the class wizard dialog. Now we can add a general property of font. Open class wizard Select Auto Control Tab. Confirm that the selected class name is CXPButtonex. Click the "Add Property" button. Select an external name (such as font) in the combo box. Click OK to close the class wizard dialog. Now we set a property page for Font. This is really simple because we can use the previously written property page. Open XPButtoneXCTL.cpp, find the following code: Begin_ProppageIDS (CDIEROLLCTRL, 1) ProppageId (CDIEROLLLPPAGE :: Guid) END_PROPPAGEIDS (CDIEROLLCTRL) Change the count to 2 here, add another PropPageID. Newly written code like this: Begin_ProppageIDS (CDIEROLLCTRL, 2) ProppageId (CDIEROLLLPPAGE :: Guid) PropPageId (CLSID_CFONTPROPPAGE) END_PROPPAGEIDS (CDIEROLLCTRL) Now our control is finally completed. Go to another ActiveX tester to test it!