Using ActiveX Controls

advertisement
Using ActiveX Controls
1. An ActiveX control is really a separate program which runs separately
but manages the appearance of a window within your program. It is
registered in the Windows Registry as an ActiveX control.
2. Visual Studio checks the Registry and allows you to put ActiveX controls
in your program using the dialog editor, just like ordinary controls.
3. MFC supports the communication between your program and the
ActiveX control, so that you don’t have to add code for that purpose.
This makes using ActiveX controls in an MFC program as easy as using
ordinary controls.
4. The interface to an ActiveX control is precisely defined. It consists of
properties and methods. Properties have symbolic names that are
matched to integer indices. For each property XXX, there is a SetXXX
method and a GetXXX method. For example, for the BackColor
property, there would be a SetBackColor method and a GetBackColor
method. A method, like a function, has a symbolic name, required
parameters, and a return value.
5. In your program, a C++ class will represent the control, and the member
functions of that class call the methods of the control.
6. A program using an ActiveX control is called a “container”. The control
does not send messages to the container like an ordinary control would
do. Instead it “fires events”. An event is a function defined in the
container; to “fire” an event means to call this function. For example,
there might be an event called Click which the control fires when the
mouse is clicked in its window.
7. The code for an ActiveX control is usually in a DLL, but the filename
extension is often .ocx. A single such file can contain several controls.
These files are typically kept in the system directory so that the system
can find them easily.
8. Before an ActiveX control can be used it must be registered. Actually, it
registers itself when a certain function exported by the DLL is called.
This can be done using the Regsvr32 utility that comes with Windows,
mentioning the control name on the command line.
Now let’s build a program that uses an ActiveX control. Create a new MFC
project. Make it SDI, and in the application properties, go to Generated
Classes and make the view class inherit from CFormView. That way our
main window will be a dialog (“form”). Once the project is created, go to
Resource View and click your Form dialog to open it in the resource editor.
We want to put a Calendar Control on the form. Don’t be confused by the
fact that there is something labeled Month Calendar Control on the Dialog
Editor toolbar. That is a different control, not a Calendar Control 10.0. To
get a Calendar Control 10.0, right click your dialog and choose Insert
ActiveX Control. Select a Calendar Control 10.0. It will be created at such
a tiny size that it is almost unrecognizable. You have to make it bigger—
then you will see this:
You can build and run this program now. The calendar works—it is a
complete program in its own right.
Some of the control’s properties are design-time properties. That means you
can change them at compile time. Right click your control and select
Properties. You’ll see a property sheet like this one:
Just like with any other control you can specify the ID number. Try
changing some of the other properties and then running your program.
Even though this control looks attractive, and even though you can
customize its size and appearance, it’s not much use so far—you need to
make your program communicate with it, for example to let the user choose
a date on which he will send you money. Communication with the control
can go two ways: Either the control can fire an event, which your program
can handle as it would handle a message, or, if you want to tell the control
something, you call one of its methods. Let’s do the former first, as it is
easier.
Class Wizard lets you map ActiveX control events the same way you map
Windows messages and commands from controls. Right-click your view
class in Class View, select Properties, and click the button with the lightning
flash icon, whose tool-tip says Events. You should see a list with an item
for your calendar control. Expand that node and you should see this:
This shows the events you can “map”. You do this exactly as you would
“map” a message. Let’s add some very simple handlers just to see if the
control is communicating to our program. The following handlers just make
“beeps” of different pitches and durations when the user changes the month
or the year.
void CActiveXDemoView::AfterUpdateCalendar1()
{ Beep(256,100);
}
void CActiveXDemoView::NewMonthCalendar1()
{ Beep(512,100);
}
void CActiveXDemoView::NewYearCalendar1()
{ Beep(512,300);
}
What user actions fire which of these events?
If we want to tell the calendar control something (e.g. to set the date to a
dynamically generated value), then we need to have a class corresponding to
the calendar control. This can be done through Project | Add Class, but
there is an easier way: just right-click the control and choose Add variable.
You can add a variable of category control. This can be used to call the
methods of the control, just as you called ListBox::AddString earlier in the
semester. Try that. Afterwards, you can check that a new class has been
added to your project:
Instead of calling some of the calendar controls methods, we will move on to
another example:
Adding a Web Browser to your program
A calendar is fine, but how about adding a Web browser to your program?
Go back to the dialog editor and right-click, and choose Insert ActiveX
Control. This time, select Microsoft Web Browser. Like the calendar, it
first appears at a ridiculously small size, and in the upper left. You will have
to enlarge your dialog to make room for a reasonably large browser control.
1. Right-click your dialog, and add a member variable m_browser
corresponding to this class. (It's a member of the view class.)
2. Add the following code to OnInitialUpdate:
COleVariant noArg;
m_browser.Navigate("www.cs.sjsu.edu/faculty/beeson",
&noArg,&noArg,&noArg,&noArg);
This sets an initial URL for the browser.
3. Run the program: the contents of the specified page are displayed (if
you have an Internet connection).
4. You have the functionality of Internet Explorer available. To make a real
web browser, you could add an edit box where the user can type a URL and
a Go button that calls the Navigate method as above. You could use an
array or a CArray to hold the recently visited locations, and add Back and
Forward buttons that would call Navigate to the next or previous element of
this array. Would you like a browser that lets you view two URLs
simultaneously in two different windows? Just add two of these browser
controls to your program.
Working with WebBrowser Events
The WebBrowser control fires a number of different events to notify an
application of user- and browserr-generated activity. The events are
implemented using the DWebBrowserEvents2 interface. When the control
is about to navigate to a new location, it fires a BeforeNavigate2 event that
specifies the URL or path of the new location and any other data that will be
transmitted to the Internet server through the HTTP transaction. The data
can include the HTTP header, HTTP post data, and the URL of the referrer.
BeforeNavigate2 also includes a cancel flag that you can set to FALSE to
cancel the navigation. The WebBrowser control fires the
NavigateComplete2 event after it has navigated to a new location. This
event includes the same information as BeforeNavigate2, but
NavigateComplete2 does not include the cancel flag.
When the WebBrowser control is about to begin a download operation, it
fires the DownloadBegin event. The control fires a number of
ProgressChange events as the operation progresses, and then it fires the
DownloadComplete event after completing the operation. Applications
typically use these three events to indicate the progress of the download
operation, often by displaying a progress bar. An application would show the
progress bar in response to DownloadBegin, update the progress bar in
response to ProgressChange, and hide it in response to
DownloadComplete. When an application calls the Navigate method with
the Flags parameter set to navOpenInNewWindow, the WebBrowser control
fires the NewWindow2 event before navigating to the new location. The
event includes information about the new location and a flag that indicates
whether the application or the control is to create the new window. Set this
flag to TRUE if your application will create the window or to FALSE if the
WebBrowser control should create it.
Some Final Remarks
If you have a modal dialog containing an ActiveX control, you may want to
lock it in memory so it doesn’t have to be loaded each time the modal dialog
appears. This is done by adding the following line of code to your
overridden OnInitDialog after the base class call:
AfxOleLockControl(m_calendar.GetClsid()); here m_calendar is a member
variable of your dialog class corresponding to the control, that is, its type is
the C++ wrapper class for the control. This line of code is only meant to
prevent delay in the appearance of the dialog due to loading the control into
memory again.
ActiveX controls can be added to an HTML file, in which case Internet
Explorer will use them. Netscape with a suitable plugin can do so also. But
they will only work on a Windows machine, so it’s not much use if you
want to make a web page that Mac and Unix users can see.
If you want to use an ActiveX control, such as the Web Browser control, in
your view window rather than in a dialog box, then you must add the control
dynamically. That’s where you would use Project | Add Class to create a
class corresponding to your control. Add a data member of this type to the
class corresponding to the window you want to contain the control. Map the
WM_CREATE message for the container window and call the control
class’s Create function. In the container window class, you must manually
add the event message handlers and prototypes, including the
BEGIN_EVENTSINK_MAP and END_EVENTSINK_MAP macros (which
are written for you automatically when you add an ActiveX control to a
dialog box). This is a difficult business and not for the weak or the fainthearted.
Download