Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SSW_8_11.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
5.22 Mб
Скачать

Interaction Between Controls with Windows and ActiveX Control Containers

When a control is used within a control container, it uses two mechanisms to communicate: it exposes properties and methods, and it fires events. The following figure demonstrates how these two mechanisms are implemented.

The above figure also illustrates how other OLE interfaces (besides automation and events) are handled by controls.

All of a control's communication with the container is performed by COleControl. To handle some of the container's requests, COleControl will call member functions that are implemented in the control class. All methods and some properties are handled in this way. Your control's class can also initiate communication with the container by calling member functions of COleControl. Events are fired in this manner.

Active and Inactive States of an ActiveX Control

A control has two basic states: active and inactive. Traditionally, these states were distinguished by whether or not the control had a window. An active control had a window; an inactive control did not. With the introduction of windowless activation, this distinction is no longer universal, but still applies to many controls.

When a windowless control goes active, it invokes mouse capture, keyboard focus, scrolling, and other window services from its container. You can also provide mouse interaction to inactive controls, as well as create controls that wait until activated to create a window.

When a control with a window becomes active, it is able to interact fully with the control container, the user, and Windows. The figure below demonstrates the paths of communication between the ActiveX control, the control container, and the operating system.

Windows Message Processing in a Windowed ActiveX Control

The ability to serialize data, sometimes referred to as persistence, allows the control to write the value of its properties to persistent storage. Controls can then be re-created by reading the object's state from the storage.

Note that a control is not responsible for obtaining access to the storage medium. Instead, the control's container is responsible for providing the control with a storage medium to use at the appropriate times.

13.6 Optimization of ActiveX Controls

When you install Visual C++, the MFC ActiveX control classes and retail and debug ActiveX control run-time DLLs are automatically installed if ActiveX controls are selected in Setup (they are selected by default). For more information on Test Container, see the article Test Container.

By default, the ActiveX control classes and tools are installed in the following subdirectories under \Program Files\DevStudio:

  • \VC\Bin

Contains the executable for Test Container, TstCon32.exe, as well as its Help file

  • \SharedIDE\Bin

Contains RegSvr32.exe

  • \SharedIDE\Bin\IDE

Contains the executable for the ActiveX ControlWizard

  • \SharedIDE\Help

Contains Help files for the ActiveX control development tools

  • \VC\MFC\Include

Contains the include files needed to develop ActiveX controls with MFC

  • \VC\MFC\Src

Contains the source code for specific ActiveX control classes in MFC

  • \VC\MFC\Lib

Contains the libraries required to develop ActiveX controls with MFC

  • \VC\Samples\MFC\Controls (on the installation CD, not installed)

Contains a set of ActiveX control samples. Information about these samples is available online; search for "sample"

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.

Making Your Existing Controls Internet-Friendly

You don't need to do anything special; you can use your existing controls on the Internet. However, there are steps you can 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.

  • Be asynchronous. Download code and properties in the background.

  • Don't block other programs.

  • Become user-interface active as quickly as possible.

  • Be efficient.

  • Keep code size small.

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

  1. Click New on the File menu, and click the Projects tab.

  2. On the Projects tab, click MFC ActiveX ControlWizard and name your project.

  3. In Step 2 of the MFC ActiveX ControlWizard, click the Advanced button.

In the Advanced ActiveX Features dialog box, click Loads Properties Asynchronously. Choosing 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.

  1. In the Advanced ActiveX Features dialog box, click OK.

  2. Choose Finish to create the project.

To create a class derived from CDataPathProperty

  1. Create a class derived from CDataPathProperty.

  2. In each of your source files that includes the header file for your control, add the header file for this class before it.

  3. In this class, override OnDataAvailable. This function is called whenever data is available for display. As data becomes available, you can handle it any way you choose, for example by progressively rendering it.

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

{

CEdit& edit=GetEditControl();

if (grfBSCF & 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);

}

  1. When your control's overall state changes, for example, from loading to initialized or user interactive, call the member function COleControl::InternalSetReadyState. If your control has only one data path property, you can add code on BSCF_LASTDATANOTIFICATION to notify the container that your download is complete.

GetControl().InternalSetReadyState(READYSTATE_COMPLETE);

  1. Override OnProgress. In OnProgress, you are passed a number showing the maximum range and a number showing how far along the current download is. You can use these numbers to display status such as percent complete to the user.

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

  1. In the MFC ClassWizard dialog box, click the Automation tab and make sure your control's derived class is selected.

  2. Choose Add Property, and in the Add Property dialog box select Get/Set methods.

  3. Type a variable name in the External name box, for example, m_dppEditControlText, and select BSTR as its type.

This adds the member variable, modifies the IDL, and adds the dispatch map and Get/Set functions.

  1. Declare a member variable of your CDataPathProperty derived class to your ActiveX control class.

CMyDataPathProperty m_dppEditControlText;

  1. Implement the Get/Set member functions. For the Get function, return the string. For Set, load the property and call SetModifiedFlag.

BSTR CDataPathCtrl::GetDataPath()

{

CString strResult;

strResult = m_dppEditControlText.GetPath();

return strResult.AllocSysString();

}

void CDataPathCtrl::SetDataPath(LPCTSTR lpszNewValue)

{

Load(lpszNewValue, m_dppEditControlText);

SetModifiedFlag();

}

  1. In DoPropExchange, add the following line:

PX_DataPath(pPX, _T("DataPath"), m_dppEditControlText);

  1. Override ResetData to notify the property to reset its control by adding this line:

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

void CMyCachedDataPathProperty::OnDataAvailable(DWORD dwSize, DWORD grfBSCF)

{ CCachedDataPathProperty:OnDataAvailable(dwSize, grfBSCF);

GetControl().Invalidate();.

}

Updating an Existing OLE Control to use new ActiveX Control Features

If the 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.

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.

Displaying a Control on a Web Page

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>

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]