To be an ActiveX control, your control must be a COM object, export DLLRegisterServer and DLLUnRegisterServer, and implement the IUnknown interface.
ActiveX controls are not limited to the Internet. An ActiveX control can also be used in any container, as long as the control supports the interfaces required by that container. Topics included in this article that describe how to create ActiveX controls for the Internet are:
You can use your existing controls on the Internet. However, there are steps you should take to make your code size smaller and to make your control properties download asynchronously.
The following tips will make your applications run better on the Internet.
For more information on increasing your control's performance, see ActiveX Controls: Optimization.
When creating a new control using AppWizard, you can choose to enable support for asynchronous monikers as well as other optimizations. To add support to download control properties asynchronously, follow these steps:
To create your project using the MFC ActiveX ControlWizard
In the Advanced ActiveX Features dialog box, select Loads Properties Asynchronously. Selecting this option sets up the ready state property and the ready state changed event for you.
You can also select other optimizations, such as Windowless Activation, which is described in ActiveX Controls: Optimization.
To create a class derived from CDataPathProperty
The code excerpt below is a simple example of progressively displaying data in an edit control. Note the use of flag BSCF_FIRSTDATANOTIFICATION to clear the edit control.
void CMyDataPathProperty::OnDataAvailable(DWORD dwSize, DWORD bscfFlag)
{
CListCtrl list_ctrl;
CEdit* edit=list_ctrl.GetEditControl();
if (bscfFlag & BSCF_FIRSTDATANOTIFICATION && edit->m_hWnd)
{
edit->SetSel(0, -1);
edit->Clear();
}
if (!dwSize)
return;
CString string;
LPTSTR str=string.GetBuffer(dwSize);
UINT nBytesRead=Read(str, dwSize);
if (!nBytesRead)
return;
string.ReleaseBuffer(nBytesRead);
edit->SetSel(-1, -1);
edit->ReplaceSel(string);
}
Note that you must include AFXCMN.H to use the CListCtrl class.
if (bscfFlag == BSCF_LASTDATANOTIFICATION)
{
GetControl()->InternalSetReadyState(READYSTATE_COMPLETE);
}
In the next procedure, you will be adding a property to your control to use the class you just derived.
To add a property using ClassWizard
EditControlText
, and select BSTR
as its type.
This adds the member variable, modifies the IDL, and adds the dispatch map and Get/Set functions.
CDataPathProperty
derived class to your ActiveX control class.
CMyDataPathProperty EditControlText;
BSTR CDataPathCtrl::GetDataPath()
{
CString strResult;
strResult = EditControlText.GetPath();
return strResult.AllocSysString();
}
void CDataPathCtrl::SetDataPath(LPCTSTR lpszNewValue)
{
Load(lpszNewValue, EditControlText);
SetModifiedFlag();
}
PX_DataPath(pPX, _T("DataPath"), EditControlText);
EditControlText.ResetData();
The previous example describes steps for deriving your control's property from CDataPathProperty. This is a good choice if you are downloading real-time data that frequently changes, and for which you do not need to keep all the data, but only the current value. An example is a stock ticker control.
You can also derive from CCachedDataPathProperty. In this case, the downloaded data is cached in a memory file. This is a good choice if you need to keep all the downloaded data — for example, a control that progressively renders a bitmap. In this case, the class has a member variable containing your data:
CMemFile m_Cache;
In your ActiveX control class, you can use this memory mapped file in OnDraw to display the data. In your ActiveX control CCachedDataPathProperty derived class, override the member function OnDataAvailable and invalidate the control, after calling the base class implementation.
COleControl OLEctrl;
void CMyCachedDataPathProperty::OnDataAvailable(DWORD dwSize, DWORD bscfFlag)
{
CCachedDataPathProperty:OnDataAvailable(dwSize, bscfFlag);
OLEctrl.InvalidateControl(NULL);
}
Downloading data over a network should be done asynchronously. The advantage of doing so is that if a large amount of data is transferred or if the connection is slow, the download process will not block other processes on the client.
Asynchronous monikers provide a way to download data asynchronously over a network. A Read operation on an Asynchronous moniker returns immediately, even if the operation has not been completed.
For example, if only 10 bytes are available and Read is called asynchronously on a 1K file, Read does not block, but returns with the currently available 10 bytes.
You implement asynchronous monikers using the CAsyncMonikerFile class. However, ActiveX controls can use the CDataPathProperty class, which is derived from CAsyncMonikerFile, to help implement asynchronous control properties.
The ASYNDOWN sample demonstrates how to set up an asynchronous loop using timers to read the data. ASYNDOWN is described in detail in the KB article "FILE: AsyncDown Demonstrates Asynchronous Data Download" (006415), and is available for download from the Microsoft Software Library. (For more information about downloading files from the Microsoft Software Library, please see the article How to Obtain Microsoft Support Files from Online Services (Q119591) in the Microsoft Knowledge Base.)
The basic technique used in ASYNDOWN is to set a timer in CDataPathProperty::OnDataAvailable to indicate when data is available. When the timer message is received, the application reads in 128-byte blocks of data and fills an edit control. If data is not available when the timer message is handled, the timer is turned off. OnDataAvailable turns on the timer if more data arrives later.
Here is an example of an object tag and attributes for inserting a control on a Web page.
<OBJECT
CLASSID="clsid:FC25B780-75BE-11CF-8B01-444553540000"
CODEBASE="/ie/download/activex/iechart.ocx"
ID=chart1
WIDTH=400
HEIGHT=200
ALIGN=center
HSPACE=0
VSPACE=0
>
<PARAM NAME="BackColor" value="#ffffff">
<PARAM NAME="ForeColor" value="#0000ff">
<PARAM NAME="url" VALUE="/ie/controls/chart/mychart.txt">
</OBJECT>
A W3C Working Draft is currently under review for the object tag. See the draft for details of object tags and attributes. A list of current W3C working drafts, including this one, can be found at:
http://www.w3.org/pub/WWW/TR
See Also Internet: Where Is..., ActiveX Controls on the Internet
If your OLE control was created with a version of Visual C++ prior to 4.2, there are steps you can take to improve its performance and enhance its functionality. For a detailed discussion of these changes, see ActiveX Controls: Optimization.
If you are adding asynchronous property support to an existing control, you will need to add the ready state property and the ReadyStateChange
event yourself. ClassWizard provides stock implementation of these. In the constructor for your control, add:
m_lReadyState = READYSTATE_LOADING;
You will update the ready state as your code is downloaded by calling COleControl::InternalSetReadyState. One place you could call InternalSetReadyState is from the OnProgress override of CDataPathProperty derived class.
Then, follow the steps in How do I create a new ActiveX control?