Important C and C Header Files

Chapter 26 - Getting Started with ActiveX Controls

Visual C++ 6: The Complete Reference
Chris H. Pappas and William H. Murray, III
  Copyright 1998 The McGraw-Hill Companies

ActiveX Controls
ActiveX controls can be placed alongside standard controls such as radio buttons, push buttons, checkboxes, and so on. Therefore, you might find a dialog box containing a few radio buttons, checkboxes, and an ActiveX control. ActiveX controls, however, are inherently more difficult to implement.
Unless a commercial vendor has supplied an ActiveX control, you, the programmer, will be responsible for the design and complete implementation of the control and its properties. The problem is now twofold. First, during the design phase you must create, write, and compile the code that draws the control and implements all of the control’s, methods, and so on. This code eventually becomes a tiny dynamic link library (see Appendix C for more information on DLLs) with an .OCX file extension. Second, the application that is to use the ActiveX control must now interface with the control’s methods, data, and so on. You also must properly design this interface.
A properly designed ActiveX control must be independent from the application in which it is used. In other words, it must be completely reentrant. Remember that an ActiveX control is really a separate dynamic link library that is not linked to any particular application. A separate instance for data for each use of the control is required for reentrance in a DLL. The only communications allowed between an application and an ActiveX control are via messages. Hence, an ActiveX control must be defined in a dynamic link library.
Control Design Criteria
When entering the design phase for an ActiveX control, several decisions must be made to create an ActiveX control as appealing and functional as possible.
First, you must decide how the ActiveX control will be drawn and displayed. Here, some talent will be required to produce ActiveX controls that are both functional and attractive.
Next, the ActiveX control should be designed to take advantage of changes in control properties resulting from the automation interface of the control. Note that for ActiveX controls, so designed, property pages will allow the user to change properties at run time. Arguments should be assigned ActiveX controls in order to control events, set their names, and determine when they should be fired. A control’s methods should be defined in terms of arguments and return types.
Finally, the persistence of a control’s various property states must be determined and implemented.
The COleControl Class
ActiveX controls are derived from MFC’s COleControl class. Examine the code in the next listing. This listing contains an edited portion of the AFXCTL.H header file. If you are interested in examining the full header file, you should be able to locate it in the MFC’s INCLUDE subdirectory. Be warned, however, that this file is approximately 30 pages in length.
// This is part of the MFC C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

//////////////////////////////////////////////////////////////
// AFXCTL.H - MFC OLE Control support
  .
  .
  .
//////////////////////////////////////////////////////////////
// Stock events

#define EVENT_STOCK_CLICK() \
 {afxEventStock,DISPID_CLICK,_T(“Click”),VTS_NONE},

#define EVENT_STOCK_DBLCLICK() \
 {afxEventStock,DISPID_DBLCLICK,_T(“DblClick”),VTS_NONE},

#define EVENT_STOCK_KEYDOWN() \
 {afxEventStock,DISPID_KEYDOWN,_T(“KeyDown”),VTS_PI2 VTS_I2},

#define EVENT_STOCK_KEYPRESS() \
 {afxEventStock,DISPID_KEYPRESS,_T(“KeyPress”),VTS_PI2},

#define EVENT_STOCK_KEYUP() \
 {afxEventStock,DISPID_KEYUP,_T(“KeyUp”),VTS_PI2 VTS_I2},

#define EVENT_STOCK_MOUSEDOWN() \
 {afxEventStock,DISPID_MOUSEDOWN,_T(“MouseDown”),\
   VTS_I2 VTS_I2 VTS_XPOS_PIXELS VTS_YPOS_PIXELS},

#define EVENT_STOCK_MOUSEMOVE() \
 {afxEventStock,DISPID_MOUSEMOVE,_T(“MouseMove”),\
   VTS_I2 VTS_I2 VTS_XPOS_PIXELS VTS_YPOS_PIXELS},

#define EVENT_STOCK_MOUSEUP() \
 {afxEventStock,DISPID_MOUSEUP,_T(“MouseUp”),\
   VTS_I2 VTS_I2 VTS_XPOS_PIXELS VTS_YPOS_PIXELS},

#define EVENT_STOCK_ERROREVENT() \
 {afxEventStock,DISPID_ERROREVENT,_T(“Error”),\
VTS_I2 VTS_PBSTR VTS_SCODE VTS_BSTR VTS_BSTR VTS_I4 VTS_PBOOL},

#define EVENT_STOCK_READYSTATECHANGE() \
{afxEventStock,DISPID_READYSTATECHANGE,_T(“ReadyStateChange”),\
   VTS_I4},
  .
  .
  .
//////////////////////////////////////////////////////////////
// Stock properties

#define DISP_PROPERTY_STOCK(theClass,szExternalName,dispid,
                           pfnGet,pfnSet,vtPropType) \
 {_T(szExternalName),dispid,NULL,vtPropType,\
   (AFX_PMSG)(void (theClass::*)(void))&pfnGet,\
   (AFX_PMSG)(void (theClass::*)(void))&pfnSet,
   0,afxDispStock},\

#define DISP_STOCKPROP_APPEARANCE() \
 DISP_PROPERTY_STOCK(COleControl,"Appearance",
 DISPID_APPEARANCE,\
   COleControl::GetAppearance,COleControl::SetAppearance,
   VT_I2)

#define DISP_STOCKPROP_BACKCOLOR() \
 DISP_PROPERTY_STOCK(COleControl,"BackColor",
 DISPID_BACKCOLOR,\
   COleControl::GetBackColor,COleControl::SetBackColor,
   VT_COLOR)

#define DISP_STOCKPROP_BORDERSTYLE() \
 DISP_PROPERTY_STOCK(COleControl,"BorderStyle",
 DISPID_BORDERSTYLE,\
   COleControl::GetBorderStyle,COleControl::SetBorderStyle,
   VT_I2)

#define DISP_STOCKPROP_CAPTION() \
 DISP_PROPERTY_STOCK(COleControl,"Caption",DISPID_CAPTION,\
   COleControl::GetText,COleControl::SetText,VT_BSTR)

#define DISP_STOCKPROP_ENABLED() \
 DISP_PROPERTY_STOCK(COleControl,"Enabled",DISPID_ENABLED,\
   COleControl::GetEnabled,COleControl::SetEnabled,VT_BOOL)

#define DISP_STOCKPROP_FONT() \
 DISP_PROPERTY_STOCK(COleControl,"Font",DISPID_FONT,\
   COleControl::GetFont,COleControl::SetFont,VT_FONT)
  .
  .
  .
//////////////////////////////////////////////////////////////
// Stock methods

#define DISP_FUNCTION_STOCK(theClass,szExternalName,dispid,
                           pfnMember,vtRetVal,vtsParams) \
 {_T(szExternalName),dispid,vtsParams,vtRetVal,\
   (AFX_PMSG)(void (theClass::*)(void))&pfnMember
,
   (AFX_PMSG)0,0,\
   afxDispStock},\

#define DISP_STOCKFUNC_REFRESH() \
 DISP_FUNCTION_STOCK(COleControl,"Refresh",DISPID_REFRESH,\
     COleControl::Refresh,VT_EMPTY,VTS_NONE)

#define DISP_STOCKFUNC_DOCLICK() \
 DISP_FUNCTION_STOCK(COleControl,"DoClick",DISPID_DOCLICK,\
     COleControl::DoClick,VT_EMPTY,VTS_NONE)
  .
  .
  .
 // Firing events
 void AFX_CDECL FireEvent(DISPID dispid,BYTE* pbParams,...);

 // Firing functions for stock events
 void FireKeyDown(USHORT* pnChar,short nShiftState);
 void FireKeyUp(USHORT* pnChar,short nShiftState);
 void FireKeyPress(USHORT* pnChar);
 void FireMouseDown(short nButton,short nShiftState,
   OLE_XPOS_PIXELS x,OLE_YPOS_PIXELS y);
 void FireMouseUp(short nButton,short nShiftState,
   OLE_XPOS_PIXELS x,OLE_YPOS_PIXELS y);
 void FireMouseMove(short nButton,short nShiftState,
   OLE_XPOS_PIXELS x,OLE_YPOS_PIXELS y);
 void FireClick();
 void FireDblClick();
 void FireError(SCODE scode,LPCTSTR lpszDescription,
                UINT nHelpID = 0);
 void FireReadyStateChange();
  .
  .
  .
 // Type library
 BOOL GetDispatchIID(IID* pIID);

 // Connection point container
 virtual LPCONNECTIONPOINT GetConnectionHook(REFIID iid);
 virtual BOOL GetExtraConnectionPoints(CPtrArray* pConnPoints);

 // Events
 static const AFX_DATA AFX_EVENTMAP_ENTRY _eventEntries[];
 virtual const AFX_EVENTMAP* GetEventMap() const;
 static const AFX_DATA AFX_EVENTMAP eventMap;
 const AFX_EVENTMAP_ENTRY* GetEventMapEntry(LPCTSTR pszName,
   DISPID* pDispid) const;
 void FireEventV(DISPID dispid,BYTE* pbParams,
                 va_list argList);

 
// Stock events
 void KeyDown(USHORT* pnChar);
 void KeyUp(USHORT* pnChar);
 void ButtonDown(USHORT iButton,UINT nFlags,CPoint point);
 void ButtonUp(USHORT iButton,UINT nFlags,CPoint point);
 void ButtonDblClk(USHORT iButton,UINT nFlags,CPoint point);
  .
  .
  .
 // Stock properties
 OLE_COLOR m_clrBackColor;      // BackColor
 OLE_COLOR m_clrForeColor;      // ForeColor
 CString m_strText;             // Text/Caption
 CFontHolder m_font;            // Font
 HFONT m_hFontPrev;             // Prev select font object
 short m_sAppearance;           // Appearance
 short m_sBorderStyle;          // BorderStyle
 BOOL m_bEnabled;               // Enabled
 long m_lReadyState;            // ReadyState
  .
  .
  .
// Message Maps
protected:
 //{{AFX_MSG(COleControl)
 afx_msg void OnKeyDown(UINT nChar,UINT nRepCnt,UINT nFlags);
 afx_msg void OnKeyUp(UINT nChar,UINT nRepCnt,UINT nFlags);
 afx_msg void OnChar(UINT nChar,UINT nRepCnt,UINT nFlags);
 afx_msg void OnMouseMove(UINT nFlags,CPoint point);
 afx_msg void OnLButtonDown(UINT nFlags,CPoint point);
 afx_msg void OnLButtonUp(UINT nFlags,CPoint point);
 afx_msg void OnLButtonDblClk(UINT nFlags,CPoint point);
 afx_msg void OnMButtonDown(UINT nFlags,CPoint point);
 afx_msg void OnMButtonUp(UINT nFlags,CPoint point);
 afx_msg void OnMButtonDblClk(UINT nFlags,CPoint point);
 afx_msg void OnRButtonDown(UINT nFlags,CPoint point);
 afx_msg void OnRButtonUp(UINT nFlags,CPoint point);
 afx_msg void OnRButtonDblClk(UINT nFlags,CPoint point);
 afx_msg void OnInitMenuPopup(CMenu*,UINT,BOOL);
 afx_msg void OnMenuSelect(UINT nItemID,UINT nFlags,
                           HMENU hSysMenu);
 afx_msg LRESULT OnSetMessageString(WPARAM wParam,
                                    LPARAM lParam);
 afx_msg void OnEnterIdle(UINT nWhy,CWnd* pWho);
 afx_msg void OnCancelMode();
 afx_msg void OnPaint(CDC* pDC);
 afx_msg BOOL OnEraseBkgnd(CDC* pDC);
 afx_msg void OnSysKeyDown(UINT nChar,UINT nRepCnt,
                           UINT nFlags);
 afx_msg void OnSysKeyUp(UINT nChar,UINT nRepCnt,
                         UINT nFlags);
 afx_msg int  OnMouseActivate(CWnd *pDesktopWnd,
                              UINT nHitTest,UINT message);
 afx_msg LRESULT OnSetText(WPARAM wParam,LPARAM lParam);
 afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct);
 afx_msg void OnDestroy();
 afx_msg  void OnKillFocus(CWnd* pNewWnd);
 afx_msg void OnSetFocus(CWnd* pOldWnd);
 afx_msg void OnNcPaint();
 afx_msg void OnNcCalcSize(BOOL bCalcValidRects,
                           NCCALCSIZE_PARAMS* lpncsp);
 afx_msg UINT OnNcHitTest(CPoint point);
 afx_msg void OnNcLButtonDown(UINT nHitTest,CPoint point);
 afx_msg BOOL OnSetCursor(CWnd* pWnd,UINT nHitTest,
                          UINT message);
 afx_msg UINT OnGetDlgCode();
 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
 afx_msg void OnSize(UINT nType,int cx,int cy);
 afx_msg void OnMove(int x,int y);
 afx_msg void OnShowWindow(BOOL bShow,UINT nStatus);
 //}}AFX_MSG
 afx_msg LRESULT OnOcmCtlColorBtn(WPARAM wParam,
                                  LPARAM lParam);
 afx_msg LRESULT OnOcmCtlColorDlg(WPARAM wParam,
                                  LPARAM lParam);
 afx_msg LRESULT OnOcmCtlColorEdit(WPARAM wParam,
                                   LPARAM lParam);
 afx_msg LRESULT OnOcmCtlColorListBox(WPARAM wParam,
                                      LPARAM lParam);
 afx_msg LRESULT OnOcmCtlColorMsgBox(WPARAM wParam,
                                     LPARAM lParam);
 afx_msg LRESULT OnOcmCtlColorScrollBar(WPARAM wParam,
                                        LPARAM lParam);
 afx_msg LRESULT OnOcmCtlColorStatic(WPARAM wParam,
                                     LPARAM lParam);
 DECLARE_MESSAGE_MAP()

 // button handler helpers
 void OnButtonUp(USHORT nButton,UINT nFlags,CPoint point);
 void OnButtonDown(USHORT nButton,UINT nFlags,CPoint point);
 void OnButtonDblClk(USHORT nButton,UINT nFlags,
                     CPoint point);
// Interface Maps
public:
 // IPersistStorage
 BEGIN_INTERFACE_PART(PersistStorage,IPersistStorage)
   INIT_INTERFACE_PART(COleControl,PersistStorage)
   STDMETHOD(GetClassID)(LPCLSID);
   STDMETHOD(IsDirty)();
   STDMETHOD(InitNew)(LPSTORAGE);
   STDMETHOD(Load)(LPSTORAGE);
   STDMETHOD(Save)(LPSTORAGE,BOOL);
   STDMETHOD(SaveCompleted)(LPSTORAGE);
   STDMETHOD(HandsOffStorage)();
 END_INTERFACE_PART_STATIC(PersistStorage)
  .
  .
  .
 // IOleInPlaceObject
 BEGIN_INTERFACE_PART(OleInPlaceObject,
                      IOleInPlaceObjectWindowless)
   INIT_INTERFACE_PART(COleControl,OleInPlaceObject)
   STDMETHOD(GetWindow)(HWND*);
   STDMETHOD(ContextSensitiveHelp)(BOOL);
   STDMETHOD(InPlaceDeactivate)();
   STDMETHOD(UIDeactivate)();
   STDMETHOD(SetObjectRects)(LPCRECT,LPCRECT);
   STDMETHOD(ReactivateAndUndo)();
   STDMETHOD(OnWindowMessage)(UINT msg,WPARAM wParam,
                              LPARAM lparam,
     LRESULT* plResult);
   STDMETHOD(GetDropTarget)(IDropTarget **ppDropTarget);
 END_INTERFACE_PART(OleInPlaceObject)
 // IOleInPlaceActiveObject
 BEGIN_INTERFACE_PART(OleInPlaceActiveObject,
                      IOleInPlaceActiveObject)
   INIT_INTERFACE_PART(COleControl,OleInPlaceActiveObject)
   STDMETHOD(GetWindow)(HWND*);
   STDMETHOD(ContextSensitiveHelp)(BOOL);
   STDMETHOD(TranslateAccelerator)(LPMSG);
   STDMETHOD(OnFrameWindowActivate)(BOOL);
   STDMETHOD(OnDocWindowActivate)(BOOL);
   STDMETHOD(ResizeBorder)(LPCRECT,LPOLEINPLACEUIWINDOW,
                           BOOL);
   STDMETHOD(EnableModeless)(BOOL);
 END_INTERFACE_PART(OleInPlaceActiveObject)
  .
  .
  .
Our intention in showing this partial listing was not to explain each section of the listing in detail, but to provide you with a reference as we introduce some new terms used with ActiveX controls. You’ll find several of the captions for those sections set in a bold font.
Events
Events are actions or responses that are triggered by the control’s reaction to an action on the control—for example, a keypress or mouse button click. KeyUp and KeyDown are examples of stock events.
Since your class will be derived from Microsoft’s COleControl class, it will be able to use a new map that enables messages. These messages or events are sent to the application using the control. This application is called the control container. The application or container will receive information about an event when something happens to the control. This event could be as simple as clicking the mouse within the control. Using event parameters can provide additional information. Examine the message map area of the previous listing.
A control communicates with its application (container) by firing events. ActiveX provides stock and custom events to be used by your control. See the sections marked stock events in the previous listing. Stock events are handled by the COleControl as a default. Custom events might be used to signal the application (container) when a control event occurs, such as receiving a message.
Methods and Properties
The control must expose a set of methods (functions) and properties (interface) to the application using the control in order to make an ActiveX control interactive. Methods are control functions that permit external code to alter characteristics of the control. Typical characteristics include appearance, properties, or behavior. Control properties, on the other hand, include the color, text, font, and other elements used in the control. Methods and properties form the basic mechanism whereby the application (container) communicates with the control. This communication allows the appearance and values of the control to be changed. The developer, while using Microsoft’s ClassWizard, defines methods and properties. Find the section defining stock methods in the previous listing. Stock methods are implemented automatically by the COleControl class. The programmer can add custom methods if additional custom features are needed by the control.
A primary interface to the control allows early bound access to the control’s methods and properties. Here, object methods are exposed as methods, and properties as get/set method pairs. IDispatch is used for late bound access. The application using the control (container) decides which type of binding is provided the user. IProvideClassInfo returns a CoClass TypeInfo, which describes the control.
ActiveX controls also provide extended properties, methods, and events. Usually this is control-specific information needed only by the application (container).
Persistence
Controls support persistence to streams through IPersistStream and persistence to storage through IPersistStorage. Both implementations can be found in the interface maps section of the previous listing. IPersistStorage is necessary for continued support of compound document applications (containers). IPersistStream allows embedded controls to be saved to streams, where feasible.
Persistence permits the ActiveX control to read or write property values to and from a file or stream. An application (container) can use persistence to store property values for the control. These values can then be retrieved if a new instance of the control is created.
An example, not shown in the previous listing, is the parameter PX_Blob that is used to exchange a control property that stores Binary Large Object (BLOB) data. In a similar manner, PX_Bool is used to exchanges a control property of type BOOL.

Books24x7.com, Inc 2000 –  


Visual C++ 6(c) The Complete Reference
Visual Studio 6: The Complete Reference
ISBN: B00007FYGA
EAN: N/A
Year: 1998
Pages: 207

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net