Special Edition Using Microsoft® Visual Studio for Enterprise Development

Previous chapterNext chapterContents


- 9 -
Using ActiveX Components in a Client/Server Environment

by Ronald W. Terry

Learn about the different types of ActiveX components typical in an n-tier client/server environment, where they're most effective, and how they're installed and registered.
Read about the utilities available to configure ActiveX components to run on remote machines by using the Remote Automation or DCOM transports.
Become familiar with the techniques in using ActiveX components with the Visual Basic development tool.
Learn the procedures for incorporating ActiveX components in a Visual C++ application.

Based on the Component Object Model, an ActiveX component exposes its objects for use by another unit of executable code. This implies a client/server relationship in that a client requests objects from the ActiveX server, which in turn performs services for the client. The client itself can be an ActiveX component, which in turn acts as a server and exposes objects to another client.

This relationship can be carried out on a single machine where the client and the server reside locally, or the client and server can be on separate machines in which the server is called a remote server. This chapter discusses the techniques of using the various types of ActiveX components in a client/server environment with the two most prominent client/server development tools today: Visual Basic and Visual C++. Visual Basic has been a highly successful front-end development tool dealing with capturing and displaying information for users. Although Visual C++ can equally develop the forms and dialog boxes that comprise a user interface, its niche in the client/server development environment has been in the business rules tier. This tier is comprised of objects with little or no user interface and with the primary task of performing the computationally intensive algorithms for data transformations. 

Understanding Techniques for Using Components

ActiveX components come in a wide variety of functionality that seems to be limited only by component developers' imaginations. From user interfaces that capture and display data in an elegant manner to complex behind-the-scenes business calculations, an ActiveX component can become a versatile building block in developing client/server applications.

As with any building block--whether it's a brick for a building or an object for a software application--it's not as important for you to learn the innermost workings or how the building block was produced to be an effective user. Instead, learning the behavior and limitations of the building block, along with being proficient with the techniques and tools used to adhere multiple blocks together, is of utmost importance in producing an effective composite structure.

The following sections focus on the different types of ActiveX components typical in a client/server application, their key characteristics, and in which tier they're most effective. The techniques of installing and registering components are also covered. How the component is registered in the Windows Registry determines where the component is located and the security factors involved for client access. You also see how to access remote components (executed on a separate machine) by using the Remote Automation and DCOM transports.

Component Types in a Client/Server Environment

You can categorize components used in a client/server environment into three types: ActiveX controls, ActiveX documents, and ActiveX code components. Figure 9.1 shows a typical three-tiered client/server application depicting where each type normally would be incorporated. The front-end or user-interface tier would be composed of forms and dialog boxes consisting of ActiveX controls. These controls would capture or display data for the user and pass/retrieve it to the business tier. The components on the business tier massage the data, perform calculations, and provide results back to the components in the user interface tier. Also, the business components can pass the data to the data tier. Components in the data tier contain the necessary logic to set and retrieve data from the database.

FIG. 9.1
ActiveX component types in a client/server environment.

These components can all reside on the client machine, creating what's known as a fat client, or be distributed among many machines. For instance, the user-interface tier would reside on the client machine, the business-tier objects would reside on a dedicated machine chosen for performance, and the data-tier objects would reside on the same machine as the database engine.

Deciding how the components will be distributed involves trade studies based on the environment in which they'll be used. Consider these key issues when distributing components:

The following sections explain in more detail the three different categories of ActiveX components and their uses. A how-to guide in installing and registering components for use by clients locally or remotely follows.

ActiveX Controls  ActiveX controls are components that provide some form of interface between users and the application, such as a text box or a command button. ActiveX controls are assembled on forms or dialog boxes and are part of the user-interface tier. They expose properties that can be set at design time to adjust the look and feel of the control. Properties can also be accessed at runtime, as well as the controls' methods and events, which allows controls to respond to different needs of the application as it's executing. ActiveX controls are the most common components. Although they're easily created with any of the Visual Studio development tools (as you've seen in earlier chapters), they're more commonly provided by third-party developers. ActiveX controls are in-process servers that are compiled into files with the extensions of .ocx (most common) or .dll. These files are copied to the client machine hard drive and expose functions that enable the control to register itself through the use of special utilities.

ActiveX Documents  ActiveX documents are special components hosted in document containers such as a web browser, Microsoft Office Binder, Visual Basic 5.0 IDE, or a container that you created. Through an additional set of interfaces supported by the ActiveX document, containers can provide a view port into the document's data. Unlike ActiveX controls, documents are displayed full frame in their host (see Figure 9.2) and can take control of their host to some extent. When a document is viewed, the document menus are merged with those of the containers to give users the impression that they're working with an application rather than a container.

FIG. 9.2
ActiveX documents can reside in many different containers. As shown here, a Word document can reside in Internet Explorer or Office Binder.

With the popularity of web-based applications, it's no wonder that the focus of implementing ActiveX documents was placed on web browsers. Although a container can be easily created by using the SHDOCVW.DLL file installed by Internet Explorer 4.0, working with documents is addressed in Chapter 11, "An Inside Look at Web-Based Applications," where ActiveX components in the Internet environment are addressed.

ActiveX Code Components  ActiveX code components, formerly referred to as OLE Automation servers, have little or no user interface. Code components are used primarily to implement business rules behind the scenes and can reside in all tiers of a client/server application. Client applications use objects created from the classes exposed by the components and manipulate them through the properties, methods, and events provided. Through the properties, methods, and events exposed to the client--collectively called the class interface--components are "glued" together to produce an application.

ActiveX code components can be packaged as in-process or out-of-process servers, with the former residing in files with the .dll extension and the latter in .exe files. Like ActiveX controls, code components expose self-registration functions and are accompanied by a type library (.tlb) file. Visual Basic and Visual C++ development tools use this type library file to obtain information on the components interface at design time.

How Components Are Installed and Registered

ActiveX components are normally installed by a setup program, provided with the application that uses the component, and placed in the System32 directory. If a component isn't associated with any setup program, simply copy the file containing the component to the hard drive. Locating files containing ActiveX components in one location (such as the System32 directory) is a good idea.

According to ActiveX standards, ActiveX components must be self-registering, which, for an in-process control or code component, means implementing and exporting the DllRegisterServer and DllUnregisterServer functions. If the components were installed with an application such as Visual Basic or Visual C++, they most likely were placed in the \Windows\System or System32 directory by their respective setup program and registered with the system Registry behind the scenes.

If the in-process component was developed locally or copied to the local machine without a setup program, the component will need to be registered manually. This is accomplished with the Regsvr32.exe command-line utility located in the \Windows\System or \System32 directory. Regsvr32 takes advantage of several command-line arguments (see Figure 9.3).

FIG. 9.3
The Regsvr32 utility's command-line arguments.

To register an ActiveX in-process component, simply choose Run from the Start menu and enter the following:

Regsvr32.exe <DLL or OCX File Name>

Similarly, to unregister the component, enter the following:

Regsvr32.exe <DLL or OCX File Name> /u


TIP: If you're registering in-process ActiveX components often, associate DLL and OCX files with the Regsvr32 utility. By doing so, you can just double-click a DLL or OCX file in Explorer to automatically launch the Regsver32 utility with the file as the command-line argument.

To associate a DLL or OCX with the Regsvr32 utility, locate the file in Explorer. Right-click the file, and then choose Open With. In the dialog box that appears, click Other and select Regsvr32 to open the component file with the Regsvr32 utility and subsequently register the component. If the Always Use This Program to Open This File checkbox is selected, all files with the same extension are associated with the utility.


For out-of-process servers, the components are automatically registered by executing the server.

Components and Remote Automation

ActiveX clients and out-of-process ActiveX servers communicate via a proxy/stub mechanism automatically supplied by COM. Distributed COM (DCOM) extends this mechanism across a network, allowing the out-of-process code component to be instantiated and executed on a remote machine and thus distributing the computational load across multiple machines.

DCOM shipped with Windows NT 4.0, and a service pack is available to provide DCOM for Windows 95. For machines not running Windows NT 4.0 or Windows 95 with the DCOM upgrade, Remote Automation is available to provide the same functionality as DCOM. Remote Automation was introduced before DCOM and shipped with Visual Basic 4.0. Although DCOM is slowly taking over the role Remote Automation held, Remote Automation is still supported by Visual Basic 5.0's Enterprise Edition for backward compatibility and for situations in which the client process resides on a 16-bit machine.

The following steps are necessary to implement a remote server. Use of DCOM is assumed and, where different, Remote Automation is indicated.

1. Install and register the server on the remote machine (the remote server must be an out-of-process ActiveX code component) by simply copying the executable to the server machine and executing it.

2. Configure the access and launch privileges for the component that uses the Racmgr32.exe or dcomcnfg.exe (DCOM only) utility. (Both utilities are discussed later in this section.)

3. Register the server on the client machine by copying the executable to the client machine and executing it. At this point, however, the component is configured as a local server.
4. On the client machine, configure the remote component to run remotely by using the Racmgr32.exe or dcomcnfg.exe (DCOM only) utility.

5. Install and register Autprx16.dll or Autprx32.dll on the client and server machines (Remote Automation). These files are located in the \Windows\System or \System32 directory of the development machine and were installed with Visual Basic.

6. Install and run the Automation Manager (Autmgr32.exe) on the server machine (Remote Automation). This file was also installed in the \Windows\System or \System32 directory with Visual Basic.

7. Run the client application.

Figure 9.4 shows the Racmgr32 utility, which is found in the Visual Basic program group. The Remote Automation Control Manager window consists of a list of the classes in your Windows Registry as potential ActiveX components. Two tabbed pages appear on the right: one to configure client access, and the other to configure server connection. The Client Access page is for configuring the remote server's access privileges, which is performed on the server machine.

FIG. 9.4
The Racmgr32 utility is used on the server machine to configure client access to remote components.

Remote Automation provides four levels of access security:

When invoking the Remote Automation Control Manager on the client machine, click the Server Connection tab. The Server Connection page has two option buttons and three drop-down boxes that you can use to configure the network connection (see Figure 9.5). When you're selecting a class for the first time, the connection icon toward the top of the page will indicate Local. To change this to Remote, right-click the class or the icon and select Remote. However, the type of remote transport and network connection still needs to be configured.

FIG. 9.5
The Server Connection page of the Racmgr32 utility is used on the client machine to configure the connection to out-of-process ActiveX components.

In the Remote Transport section, choose Distributed COM or Remote Automation. If you choose DCOM, notice that only the Network Address drop-down box is enabled (DCOM uses its own network protocol and security). All three drop-down boxes become enabled with the Remote Automation selection. Figure 9.6 shows a sample entry for the selected remote server by using Remote Automation.

FIG. 9.6
The MyRemoteServer.Server connection. This component will be accessed on the network machine named REMCOMP with the TCP/IP protocol.

Because the Racmgr32.exe utility is extremely easy to use, you can quickly configure component servers. You can select the local connection and run the client application, and the local component will be used. Then select Remote along with Remote Automation, and the component will be accessed from the specified network machine by using Remote Automation. Finally, keep the selection at Remote and select DCOM, and the component will be accessed on the remote machine by using the DCOM protocol. It's as easy as that.

Another utility is provided for DCOM-enabled machines (Windows NT 4.0 and Windows 95 with DCOM upgrade) that facilitates configuring DCOM access. You can find this utility, dcomcnfg.exe, in the Windows \System32 directory. Executing this application displays the dialog box shown in Figure 9.7.

FIG. 9.7
The dcomcnfg.exe utility is used to configure the properties and security of components running under DCOM.

This dialog box consists of three tabbed pages:

Use dcomcnfg.exe to configure a component to run on a remote machine with the DCOM transport.


NOTE: Make sure that the component is installed and registered on the remote machine and registered on the local machine.

Follow these steps:

1. From the Applications page, select the component you want to run remotely and click Properties.

2. Click the Location tab.

3. Select the Run Application on the Following Computer checkbox and provide the machine name of the remote server.

4. Choose OK twice to save the configuration and exit the utility.

Likewise, to configure a remote server, follow these steps with the dcomcnfg utility:

1. From the Applications page, select the server component you want to configure and click Properties.

2. Make sure that the Run Application on This Computer checkbox is selected on the Location page.

3. Use the Security page if you want the component to have a different security configuration from the default (as defined on the Default Security page of the Distributed COM Configuration Properties dialog box).

4. Use the Identity page to set the account under which the component will run.

5. Choose OK twice to save the configuration and exit the utility.

Now that you've seen the different types of components and how they're installed and registered, it's time to cover how they're glued together into a working application. For client/server applications, the most popular tools for performing this task are Visual Basic and Visual C++, both part of the Visual Studio suite. The rest of this chapter is devoted to using ActiveX components with these two development tools.

To learn the techniques of using ActiveX controls and code components, you'll develop a simple dialog box-based application first with Visual Basic and then with Visual C++. This application will prompt for an URL and, on the user's request, navigate to the web site and display the associated web page. The following controls and components (installed on your machine when the Visual Studio development tools were installed) will be used:

The two controls, Microsoft Rich Text Box and Sheridan 3-D Command Button, will be discussed first in the "ActiveX Controls" section. Then, the Internet Explorer Automation object will be incorporated to provide the web-navigation capability that will be covered in the "ActiveX Code Components" section.

Using Components with Visual Basic

After you use an ActiveX component within Visual Basic, you'll come to appreciate the ease at which you can rapidly build component-based applications with this highly successful development tool. What's more, after you work with a particular component and become familiar with the basic steps of incorporating one into a Visual Basic project, using other components will become second nature to you.

You use ActiveX controls by selecting the control from the toolbox and placing it on a form. You can set the control's design-time properties to adjust the look and feel. Properties and methods can also be accessed programmatically. Event-handler functions are incorporated into the form's code to provide logic that needs to be executed in response to a particular event from a control.

Using ActiveX code components requires declaring a variable that's an object of the component. When a call is made to instance the object, properties and methods can then be accessed.

These procedures are discussed in detail in the following sections. Now create a project for the sample application. With Visual Basic running, choose File, New Project from the menu, and select Standard exe.

ActiveX Controls

Using an ActiveX control involves these general steps, explained in more detail in the following sections:

1. Load the control into the current project.

2. Access the control's properties and methods.

3. Handle events fired by the control.

Loading the Control  To use an ActiveX control in a project, you need to add the control to the toolbox. Choose Project, Components from the menu to open the Components dialog box. In the list of controls registered with the Windows Registry, select a control and click OK. An icon representing the control appears in the toolbox. If the control you're interested in doesn't appear in the list box but the .ocx file is installed on your machine (the control may not be registered), click the Browse button on the Components dialog box. In the Add ActiveX Control dialog box, locate the .ocx file and select it to load the control into the project. With the control added to the toolbox, you can use it just like any other control provided with Visual Basic.

Follow these steps to load the Microsoft Rich Textbox and Sheridan 3D Command Button controls into your sample application:

1. Choose Project, Components from the menu to open the Components dialog box.

2. Select the Microsoft Rich Textbox Control 5.0 item.

3. Select the Sheridan 3D Controls item.

4. Click OK. Six new icons appear in the toolbox. Five of the icons represent the Sheridan 3D controls (of which the Command Button is a member); the sixth one represents the Microsoft Rich Textbox (see Figure 9.8).

FIG. 9.8
The toolbox reflects the components loaded into the projects.

You can now assemble the controls on your form.

Place a Microsoft Rich Textbox and a Sheridan 3D Command Button on the form of your sample application. Also place a common label control next to the text box. Your project should look like Figure 9.9.

FIG. 9.9
The Microsoft Rich Textbox and Sheridan 3D ActiveX controls positioned on the main form.

Accessing Properties and Methods  With the control loaded, the properties and methods exposed by the component are most easily viewed with the Object Browser (see Figure 9.10). The list on the left contains the classes or components that are part of the type library selected in the top drop-down box. Selecting the component will cause its properties, methods, and events to appear in the right list. The pane at the bottom of the dialog box displays information about the item selected in either list--a convenient way to familiarize yourself with a component before using it in code.

FIG. 9.10
Use the Object Browser to review an ActiveX component's properties and methods.

Another way to display control properties that are available at design time is through the Properties window, which normally appears between the Project and Form Layout windows at the right of the IDE. You can use the Properties window to set component properties at design time. Selecting the property displays information about it in the bottom pane of the window. With the property selected, the value can be entered in the column directly to the right of it.

For the example, you'll want to set the Caption properties for the Label and CommandButton controls. Also, you'll need to set the Text property of the TextBox control to a blank string:

1. Select the Label control on the form. In the Properties window, locate the Caption property and change the value from Label1 to URL:.

2. In a similar fashion, change the CommandButton's Caption property to Navigate.

3. Select the Rich Textbox control and remove the Rich Text string from the Text property in the Properties window. Your project should now resemble Figure 9.11.

FIG. 9.11
The final appearance of the sample application with the appropriate properties set.

Properties and methods of an ActiveX control can be accessed programmatically. An object of a control is identified by the (Name) property in the Properties window. For example, to obtain the text value of the Rich Textbox identified by the name RichTextBox1, the following code segment would be added:

Dim sText As String
sText = RichTextBox1.Text

Setting the text value is accomplished with this statement:

RichTextBox1.Text = "Hello World"

Methods are accessed in the same manner. For example, if you wanted to invoke the LoadFile function of the Rich Textbox, the following code would be inserted:

Dim sFile As String = "MyFile.rtf"
RichTextBox1.LoadFile(sFile)

This code would load an .rtf file into a RichTextBox control.

Run the sample application. Notice that the only operation that can be performed is entering text into the text box. What you really want to happen is the application navigating to the entered URL at the user's command. You'll use the click event fired by the Sheridan 3D Command Button to tell the program to access the text in the text box and navigate to the URL. This leads to a discussion of handling events from ActiveX controls with Visual Basic.

Handling Events  ActiveX controls will fire events predefined by the control's developer, notifying the client process of important events. ActiveX controls provided by vendors usually provide information to be displayed with Visual Basic help documenting what events they fire. You can view exposed events from a control loaded into the project in various ways:

FIG. 9.12
Viewing the Sheridan 3D Command Button's Click event.

View the form's code in the Code window. From the left drop-down list, you can select a control or code component to associate code with. The right drop-down list provides the events raised by the component. Selecting an event provides an event prototype in the code section of the form (as seen for the Command Button's Click event in Figure 9.13). It's within this subroutine you provide the necessary logic to be executed when this event is fired.

FIG. 9.13
The Command Button event handler prototype inserted into the form's code.

Returning to the sample application, enter the bold line of code in the Command Button Click event:

Private Sub SSCommand1_Click()
        MsgBox RichTextBox1.Text
End Sub

Run the application, type some text into the text box, and click the Navigate button. Did the text in the text box appear in the message box?

You'll now want to add web-navigation capability to your application via the Internet Explorer component. Using ActiveX code components is the next topic of discussion.

ActiveX Code Components

Using ActiveX code components involves the following steps, which are covered in more detail in the following sections:

1. Load the component into the current project.

2. Instantiate an object of the component class.

3. Access properties and methods of the component.

4. Handle events raised by the component.

Loading the Code Component  Code components aren't child windows like controls. Subsequently, they're not dropped onto forms from the toolbox. However, you can load code components into the project, similar to a control. This pulls the type library information into the project, allowing you to view the component's properties and methods. To add a code component, choose Project, References from the menu. The list box in the References dialog box contains ActiveX components registered with the Windows Registry. Selecting a component allows its properties and methods to be accessed at design time.

If the component doesn't appear in the list box, click the Browse button to open the Add Reference dialog box. Locate the file containing the type library information and select it to register the type library with the Registry and provide access to the properties and methods exposed by the component.

Follow these steps to load the Internet Explorer code component into your sample project:

1. Choose Project, References from the menu.

2. Select the Microsoft Internet Controls item to load the type library from the shdocvw.dll file.

3. Click OK.

Accessing Properties and Methods  With the code components type library loaded, the properties and methods exposed by the component are most easily viewed through the Object Browser, the same as for ActiveX controls. To view the Internet Explorer code component properties and methods, do the following:

1. Choose View, Object Browser from the menu.

2. From the top drop-down list, select the SHDocVw library.

3. In the left list box, select the InternetExplorer item. The properties, methods, and events appear in the right list box.

4. Note the class name in the bottom pane. You'll need this, along with the Application property, when making a call to create a running object.

ActiveX components are created and manipulated programmatically. These are the basic steps in using a code component within Visual Basic code:

1. Declare a variable of type Object.

2. Create and return a reference to the ActiveX object.

3. Access properties and methods with the . member selector.

4. Release the reference to the object by setting the object variable to Nothing.

To incorporate the Internet Explorer component into your example, follow these steps:

1. With the form's code displayed in the Code window, add the following to the declarations section:
Dim m_oInternetExplorer As Object
2. In the form's load event handler, insert the following:
Private Sub Form_Load()
    Set m_oInternetExplorer = CreateObject("InternetExplorer.Application")
End Sub
3. In the command button's click event, add this code:
Private Sub SSCommand1_Click()
    m_oInternetExplorer.Navigate (RichTextBox1.Text)
    m_oInternetExplorer.Visible = True
End Sub
4. In the form's unload event, insert the necessary code to release the reference to the object:
Private Sub Form_Unload(Cancel As Integer)
    Set m_oInternetExplorer = Nothing
End Sub
5. Make an executable file by choosing File, Make <project name>.exe.

6. Make sure that Internet service is up and running. Run the application, type a valid URL, and click Navigate. You should see the Internet Explorer launch with the appropriate web page displayed.

Handling Events  Some ActiveX code components will raise events similar to ActiveX controls. Visual Basic allows you to provide event handling for ActiveX components with the WithEvents keyword used in the dimension statement. This tells Visual Basic up front that you want to handle events exposed by the component. To see how to use the WithEvents keyword, handle the Quit event from Internet Explorer and place the reference releasing code there, as follows:

1. Change the declaration statement to read as follows:
Dim WithEvents m_oInternetExplorer As InternetExplorer
This tells Visual Basic that you want to handle the events raised by the InternetExplorer class.

2. Notice the m_oInternetExplorer item in the left drop-down list. Select it to list all the events raised by the InternetExplore component in the right drop-down list.

3. Select the Quit event from the right drop-down list.

4. In the Quit event-handler function, add the following message box and relocate the object release code:
Private Sub m_oInternetExplorer_Quit(Cancel As Boolean)
    m_oInternetExplorer.Visible = False
    MsgBox "Exiting Internet Explorer"
    Set m_oInternetExplorer = Nothing
End Sub
5. Relocate the object creation code to the command button's click event:
Private Sub SSCommand1_Click()
    Set m_oInternetExplorer = CreateObject("InternetExplorer.Application")
    m_oInternetExplorer.Navigate (RichTextBox1.Text)
    m_oInternetExplorer.Visible = True
End Sub
6. Make an executable, and run the application as before.

Distributing Applications

You would create an executable of your application that uses ActiveX components as you would for any application. Your application, however, will require the .ocx and .dll files that package the components used to be distributed and registered on the target machine. Just as Visual Basic uses the registered .ocx and .dll files, your application also will use them and will generate a runtime error if the file isn't found. Therefore, your application's installation procedure should copy all files that package the components as well as automatically register them.


NOTE: If you're using components obtained from a third party, consulting the accompanying documentation regarding distribution licenses is always a good idea.

When you're ready to distribute your application, you should use Visual Basic's Application Setup Wizard to create the installation program.


NOTE: If your application will use remote server components and you want the servers registered without copying the executable to the target machine, ensure that a .vbr file exists for each server. A .vbr file is created when the server project (ActiveX executable) is compiled with the Remote Server Files option selected on the Component page from the Project Properties dialog box (Project, Project Properties).

To create an installation program, follow these steps:

1. Start the Setup Wizard by choosing Start, Programs, Microsoft Visual Basic, and Application Setup Wizard. Click Next in the first setup dialog box.

2. The next dialog box prompts for the project for which to build a setup application (see Figure 9.14). Complete this dialog box as follows:

FIG. 9.14
The Select Projects and Options dialog box of the Setup Wizard.

3. Click Next.

4. If your project references a type library (.tlb) file, the Setup Wizard asks whether this refers to a Remote Automation sever (see Figure 9.15). In this case, the MyRemoteServer.TLB file does in fact represent a remote server, so choose Yes. You're then reminded to manually add the .vbr file to the ActiveX Server Components list (which you'll see shortly).

FIG. 9.15
When the Setup Wizard finds reference to a type library file, it asks whether this refers to a Remote Automation component.

5. In this example, the Setup Wizard found two files with no dependencies (see Figure 9.16). Select the files that you're certain have no dependent files and click Next.

FIG. 9.16
If the Setup Wizard finds files with missing dependencies, it asks for verification that no dependency information is available.

6. The next screen in the Setup Wizard provides a means to select the method of distribution, be it a floppy disk, single directory, or disk directories. In this example, the Single Directory option is selected. Click Next; the Setup Wizard asks for the directory.

7. Provide the directory location and click Next again.

A dialog box appears, listing the ActiveX servers that the Setup Wizard has determined are used in your application. As shown in Figure 9.17, only the local server is listed. Recall from step 3 that you need to add the remote server manually.

FIG. 9.17
The Setup Wizard's ActiveX Server Components dialog box provides the means to add remote servers to the setup program.

8. Click the Add Remote button to bring up a dialog box that lets you search for the .vbr file containing the registration information for your remote server. After locating the file, the wizard prompts for required information for Remote Automation or DCOM access. In this example, DCOM is selected and the name of the computer where the remote server will be executed is provided (see Figure 9.18).

FIG. 9.18
The Setup Wizard's Remote Connection Details dialog box prompts for the necessary remote transport and connection information.


NOTE: Selecting DCOM as the remote transport disables the Network Protocol and Authentication Level drop-down boxes because DCOM has its own protocol and security. If you use Remote Automation, however, you would have to supply this information.
9. Enter the required information and click OK. The remote server appears in the ActiveX Server Components list box (see Figure 9.19). Click Next.

FIG. 9.19
The ActiveX Server Components dialog box, showing the addition of a remote server.

10. You're now asked to confirm the dependency on any ActiveX controls. Ensure that the files shown are the ones used in the application and select their checkboxes. Click Next.

11. A summary appears of all the files that should be shipped with your application. You can include additional files by clicking Add, or remove files from the distribution by deselecting their checkbox. Click Next.

12. The Setup Wizard has all the necessary information it needs to create a setup program. You're asked if you want to save this setup as a template to be run again on this project. Click Finish; the wizard copies the files to the distribution directory, compresses them, and creates the Setup.exe file that will be invoked on the client machine.

Using Components with Visual C++

As mentioned earlier, when you become comfortable with using one component, using others of the same type becomes second nature. Using ActiveX components with Visual C++ is no exception. After you use an ActiveX control with the resource editor or use a code component programmatically, you'll use the same techniques repeatedly with each and every ActiveX component you use.

Using ActiveX controls in Visual C++ is similar to that of Visual Basic when you become familiar with Visual C++'s resource editor. With the control loaded into the project, an icon representing the control appears on the editor toolbar for "dropping" onto dialog boxes and forms in a similar manner. Visual C++ exposes design-time tools that enable viewing and setting control properties, as well as a test container that allows a control to be tested and its behavior monitored before you incorporate it into applications.

ActiveX code components, on the other hand, are incorporated a little differently in Visual C++ in that they aren't loaded into the project for early binding, as was the case in Visual Basic. To use an ActiveX code component, a container class must be created to encapsulate the interface provided by the component. Before Visual C++ 5.0, this was accomplished by the ClassWizard, which created source code that was included into your project that implemented the container class. With Visual C++ 5.0, special support for COM has been added to the compiler. By using the new #import directive to import a type library, the preprocessor generates the C++ header file describing the interface and a second file containing the implementation, thus eliminating the need to maintain container source code as before.

Creating an MFC Application with ActiveX Support

Now is a good time to open the project in which you'll be working with the components. You'll be developing the same sample application as you did with Visual Basic in the earlier discussion. Follow these steps to create a dialog box-based MFC application:

1. Choose File, New from the menu to open the New dialog box.

2. From the Projects page, select MFC AppWizard (exe). Provide the project name and location in the text boxes on the right. Click OK.

3. Select the Dialog Based option and default on the Language drop-down list. Click Next.

4. In the MFC AppWizard - Step 2 of 4 dialog box, select Automation Support and ensure that ActiveX Controls Support is also selected. By selecting Automation support, your application can use Automation objects exposed by other programs or expose its own Automation objects to other ActiveX clients. With the ActiveX Controls support selected, your application is created with the necessary logic to be an ActiveX controls container. Click Next.

5. Accept the default options on MFC AppWizard - Step 3 of 4 dialog box. Allowing the AppWizard to generate source file comments is helpful if you're new to developing in Visual C++. These comments indicate where in the source code you'll need to provide some form of functionality. By choosing to link to the MFC library dynamically (the second set of options on the dialog box), your program will make calls to the MFC library at runtime. This selection minimizes the size of your executable. Click Next.

6. The last AppWizard dialog box appears (see Figure 9.20). You should have three classes in the list box. Selecting a class in the list displays in the text boxes information regarding the base class and the associated implementation files that will be generated. Click Finish to have the AppWizard create the project and insert the implementation files. You're then presented with a dialog box summarizing the project. Click OK.

FIG. 9.20
The last dialog box of the MFC AppWizard summarizes the classes that will be added to your project.

7. Now you can compile your application, even though it has no functionality. Choose Build, Build <project name>.exe from the menu. After the project finishes compiling, choose Build, Execute <project name>.exe from the menu. You should see a dialog box similar to the one shown in Figure 9.21. Because no functionality has been added yet, clicking either command button will halt the execution and return the developer studio to design mode. Click one of the buttons.

FIG. 9.21
Execution of the skeleton project.

8. Your sample application won't need the two command buttons or the TODO caption supplied by the AppWizard. Invoke the resource editor by double-clicking the dialog box resource file in Resource View. You should see the contents of Figure 9.22 onscreen.

FIG. 9.22
Editing the dialog box resource with the resource editor.

9. Remove the two command buttons and the caption by selecting them and pressing Delete.

You're now ready to proceed with adding the ActiveX controls that will be used in the application. Save your project.

ActiveX Controls

Using an ActiveX control within Visual C++ involves the following steps, which are discussed in detail in the following sections:

1. Load the control into the project by creating a class to wrap the control's interface.

2. Identify the control's properties and methods, and set the design-time properties.

3. Establish a member variable representing an object of the control's wrapper class.

Loading the Control  To load a control into a project, use the Component Gallery (choose Project, Add to Project, Components and Controls from the menu). The Component Gallery stores shortcuts as well as Registry information about registered controls. If you've installed and registered an ActiveX control and it doesn't appear in the Component Gallery, you must create the shortcut yourself. In Explorer, use the right mouse button to drag the .ocx file containing the control to the Registered ActiveX Controls folder. Choose Create Shortcut(s) Here from the pop-up menu.

To load the two ActiveX controls into your application, follow these steps:

1. Choose Project, Add to Project, Components and Controls from the menu to bring up the Component Gallery dialog box. Double-click the Registered ActiveX Controls folder to display its contents.

2. Locate and select the Microsoft Rich Text control (version 5.0).

3. Click Insert, and then click OK in the message box that asks you to verify your selection.

4. The Confirm Classes dialog box appears, listing all the classes (with their implementation files) associated with the ActiveX control that will be inserted into your project. Click OK.

5. Repeat steps 1 through 4 for the Sheridan 3D Command Button control.

6. If you now view the resource editor (as in Figure 9.23), notice the addition of two icons on the resource editor's toolbar.

FIG. 9.23
The project's resource editor's toolbar after loading the Microsoft Rich Textbox and Sheridan 3D Command Button controls.

7. Select the Microsoft Rich Textbox control from the toolbar and place it on the dialog box.

8. Select the Sheridan 3D Command Button control and place it on the dialog box. Your dialog box should look like Figure 9.24.

FIG. 9.24
The dialog box resource after placing the Microsoft Rich Textbox and Sheridan 3D Command Button controls on it.


NOTE: The label control to the left of the text box is placed on the dialog box in the same way. You can change the label's caption by right-clicking the label and then choosing Properties. On the General page, enter the new caption in the appropriate text box.


TIP: To reposition controls in the dialog box, drag them with the mouse or, with the control selected, use the arrow keys. Likewise, you can resize the control with the arrow keys while holding down the Shift key.

With the ActiveX controls loaded into the project and placed in the dialog box resource, you now can use the properties, methods, and events exposed by each.

Accessing Properties and Methods  The ActiveX control's developer designated certain properties to be accessed at design time. You can view these properties and set their values from the control's property page displayed by the resource editor. To access the property page of the Sheridan 3D Command Button control in your application, do the following:

1. With the resource editor in view, right-click the Command Button control. Choose Properties; a dialog box such as the one in Figure 9.25 appears.

FIG. 9.25
The property sheet for the Sheridan 3D Command Button.

2. The properties are grouped into categories on each page. Display each page to get a feel for what properties the control's developer exposed at design time. Notice that you also can access all properties from the different categories on the All page.

3. On the General page, change the Caption property to Navigate. Play around with the other properties to see how creative you can get with this control's appearance.

The properties for the Microsoft Rich Text control are accessed in the same way. It's a good idea to go ahead and view what properties are exposed by this control for future reference, but you won't need to change any values for this application. You will, however, need to access the Text property of the Microsoft Rich Text control at runtime.

If you remember back to when the controls were inserted via the Component Gallery, several classes were generated and placed into your project. These wrapper classes wrap the interfaces to the controls and have member functions for all properties and methods. You can view these member functions through the Class View or by editing the class implementation file. To view the member functions for the Microsoft Rich Text control wrapper class, follow these steps:

1. With the Class View page displayed in the left pane of the Developer Studio, expand the view of the CRichText class. You'll see a complete list of all member functions that can be used to communicate with the control. You can see a subset of these member functions that begin with the prefixes Get and Set, which are accessor and modifier functions, respectively, that allow you to retrieve and set the control's property values at runtime.

2. Locate the GetText() member function from the expanded list in the Class View. Right-click the function and choose Go To Definition. The implementation file (RichText.cpp) containing the definition (or implementation) of this particular accessor function opens. You should now be viewing the following code in the right pane of the developer studio:
CString CRichText::GetText()
{
    CString result;
    InvokeHelper(DISPID_TEXT, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL);
    return result;
}
You'll call this function later in the sample application to obtain the Text property from the text box.

To make use of the properties and methods exposed by an ActiveX control at runtime, the dialog box class needs a data member that's an object of the control's wrapper class. The ClassWizard provides the support for adding data members of type <control wrapper class> to the dialog box class. You'll want to add a data member of type CRichText to your dialog box to have access to the text property by following these steps:

1. With the dialog box resource in view, right-click the Microsoft Rich Text control and choose ClassWizard.

2. On the Member Variables page is a list of control IDs and their respective data member names, if any (see Figure 9.26). Select the IDC_RICHTEXTCTRL1 ID and click the Add Variable button.

FIG. 9.26
Adding member variables with the MFC ClassWizard.

3. Complete the member variable name in the Add Member Variable dialog box. You use this name in your code to reference the object of the control's wrapper class. Click OK to display the data member assigned to the IDC_RICHTEXTCTRL1 ID. Click OK again, and the ClassWizard will add the boldface lines of code to the dialog box class's interface file (see Listing 9.1).

Listing 9.1  Adding a Member Variable

// InterNavVCPPDlg.h : header file
//
//{{AFX_INCLUDES()
#include "richtext.h"
//}}AFX_INCLUDES
#if !defined(AFX_INTERNAVVCPPDLG_H__FF98D69A_FFDE_11D0_83C1_000000000000__INCLUDED_)
#define AFX_INTERNAVVCPPDLG_H__FF98D69A_FFDE_11D0_83C1_000000000000__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CInterNavVCPPDlgAutoProxy;
/////////////////////////////////////////////////////////////////////////////
// CInterNavVCPPDlg dialog
class CInterNavVCPPDlg : public CDialog
{
    DECLARE_DYNAMIC(CInterNavVCPPDlg);
    friend class CInterNavVCPPDlgAutoProxy;
// Construction
public:
    CInterNavVCPPDlg(CWnd* pParent = NULL);    // standard constructor
    virtual ~CInterNavVCPPDlg();
// Dialog Data
    //{{AFX_DATA(CInterNavVCPPDlg)
    enum { IDD = IDD_INTERNAVVCPP_DIALOG };
    CRichText m_oRichText;
    //}}AFX_DATA
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CInterNavVCPPDlg)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //}}AFX_VIRTUAL
.
.
.
#endif // !defined(AFX_INTERNAVVCPPDLG_H__FF98D69A_FFDE_11D0_83C1_000000000000__INCLUDED_)
The ClassWizard also adds the following boldface line of code to the implementation file:
void CInterNavVCPPDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CInterNavVCPPDlg)
    DDX_Control(pDX, IDC_RICHTEXTCTRL1, m_oRichText);
    //}}AFX_DATA_MAP
}
4. Invoke the GetText() member function (or any another function, for that matter) of the Microsoft Rich Text control and obtain the value of the text property:
CString strText;
strText = m_oRichText.GetText();

Handling Events  The ClassWizard maps an ActiveX control's events to dialog box class handler functions. The wizard displays all the events that the control can fire. By selecting the events you want your dialog box class to handle, the ClassWizard will place the class into an event sink map that connects the event to its handler function. If you went ahead and compiled and executed the sample application, you would see the dialog box appear and be able to enter an URL into the text control. But that's about all the functionality the application has at this point. What you really want the program to do is navigate to the URL when you click the Navigate button. Clicking the Command Control button fires an event. The dialog box class handles the event by providing a member function that gets invoked when the event is fired. It's within this member function that you'll want to incorporate the necessary logic to retrieve the text from the text control and navigate to the URL.

Because the navigation logic will be handled by the Internet Explorer component (which is covered later in the "ActiveX Code Components" section), an intermediate step will be followed. When the event is handled, logic is put into place to receive the text from the text control and display it in a message box.

To handle the click event, follow these steps:


NOTE: This procedure is the same for mapping all events for all ActiveX controls.
1. With the dialog box resource in view, right-click the button control and choose Events to display a dialog box containing all the event types the control can fire (see Figure 9.27).

FIG. 9.27
The events fired by the Sheridan 3D Command Button.

2. Select the Click event from the left list, and then click the Add and Edit button. You're prompted for the name of the member function that will be mapped to the event. Click OK to accept the default name.

3. You're launched into the implementation file where the handler function prototype has been created by the ClassWizard. Enter the following code inside the function:
void CInterNavVCPPDlg::OnClickSscommand1()
{
    CString sDisplay;
    sDisplay = "The URL You Entered: " + m_oRichText.GetText();
    AfxMessageBox(sDisplay);
}
4. Compile and run the program. Type any text into the text box and click Navigate. The message box should display what was typed.

You also can view and directly maintain the message/event map through the ClassWizard dialog box. Follow these steps:

1. Choose View, ClassWizard from the menu. On the Message Maps page, you should see what's shown in Figure 9.28. The two side-by-side list boxes in the middle of the dialog box contain the objects and events for the class displayed in the upper-right drop-down list.

FIG. 9.28
The MFC ClassWizard's Message Maps page is used to add and maintain event handlers.

2. Select the command button's ID (IDC_SSCOMMAND1) in the Object IDs list. The events for this control appear in the list on the right.

3. Select the event for which you want to add a handler function and click the Add Function button. Accept or change the handler function name and proceed to add logic into the function's implementation.

ActiveX Code Components

Using an ActiveX code component in a Visual C++ project is similar to using ActiveX controls in that a class that wraps the components interface is inserted into a project. It's this wrapper class in which the rest of your application accesses the properties and methods the component developer exposed. What's different is that the ActiveX code component isn't inserted into the project through the Component Gallery, and the component isn't visually edited with the resource editor.

Various techniques are available for loading and using ActiveX code components within Visual C++. To learn these techniques, you'll add the Internet Explorer Automation object to the sample application that you created earlier in the "ActiveX Controls" section to provide the web navigation functionality this application needs.

Now is a good time to become familiar with the interface to the Internet Explorer component. To obtain information about the component (or any registered component), use the OLE/COM Object Viewer utility provided with Visual C++. This utility will display Registry as well as type library information about the selected component. To view the Internet Explorer component, do the following:

1. Choose Tools, OLE/COM Object Viewer from the menu.

2. From the left list, expand the Automation Objects folder and locate the Internet Explorer entry. Select the entry to see the Registry information (see Figure 9.29).

FIG. 9.29
The Internet Explorer automation object's Registry entry as viewed by the OLE/COM Object Viewer.

3. The most pertinent information to obtain from this is the ProgID entry. You'll use this value (InternetExplorer.Application.1) in your code to create a running object. Also, the location of the type library is found in the TypeLib/{CLSID}/1.0/0/win32 entry, which for this case is C:\WINNT\System32\shdocvw.dll.

4. In the OLE/COM Object Viewer window, choose File, View TypeLib from the menu and locate the type library file (C:\WINNT\System32\shdocvw.dll).

5. Expand the interface IWebBrowserApp entry in the left pane to see all the member functions implemented in the interface in the right pane (see Figure 9.30). It's these member functions that you'll create support for in the wrapper class inserted in your project.

There are two ways to create and insert a wrapper class for an ActiveX code component in Visual C++:

FIG. 9.30
The IWebBrowserApp interface implementation.

The ClassWizard  Provided an ActiveX code component's type library, the ClassWizard will generate a class that encapsulates each interface listed in the library. The member functions of these classes are tailored to access each property and method included in the library. To create and insert a class for the Internet Explorer component, follow these steps:

1. Choose View, ClassWizard from the menu. Click the Add Class button and select the From a Type Library option.

2. Locate and open the type library file (in this case, C:\WINNT\System32\shdocvw.dll). You should be presented with the Confirm Classes dialog box, which lists the classes that the ClassWizard will generate.

3. Select only the IWebBrowserApp class and click OK.

4. Click OK again to exit the ClassWizard. Notice an IWebBrowserApp class in the Class View, along with the shdocvw.h and shdocvw.cpp files in the File View that contain the implementation.

The #import Directive  A new feature introduced with Visual C++ 5.0 is compiler support for COM. By using the #import directive with a type library file, the preprocessor generates two header files: one describing the interface to the wrapper class and the other containing the implementation. What's nice is that no source code is added to your project, which subsequently means less code to maintain. The syntax for using the #import directive is

 #import <filename> [attributes]
using namespace <library name>;

<filename> is the name of the file containing the type library information. This file can be any of the following or any other file format that the LoadTypeLib API can understand:


NOTE: Refer to Visual C++'s online documentation for a description of all the available attributes.

To prevent name collisions between the imported component and your existing code, the compiler defines a namespace identified by the type library name. A namespace is a declarative region that attaches an additional identifier to any names declared inside it. To identify a member of a namespace, the scope resolution operator is used:

<namespace>::<member>

To avoid typing the scope resolution throughout your code, the using namespace line directly after the #import line is incorporated and includes the library name.

To incorporate the Internet Explorer component into your application by using the #import directive, follow these steps:

1. Insert the following lines of code into the dialog box class's header file:
#import "C:\WINNT\System32\shdocvw.dll" rename("tagREADYSTATE", "tagIEREADYSTATE")
using namespace SHDocVw;


NOTE: You need to rename tagREADYSTATE to tagIEREADYSTATE to prevent a name collision inside the compiler-generated implementation files.
2. In the class declaration section, declare the following data member:
IWebBrowserAppPtr m_oIWebBrowserAppPtr;
This creates an object of the smart pointer class that encapsulates the interface.

Classes Created by the ClassWizard  If you used the ClassWizard to incorporate the code component into your project, you'll be creating an object of the class that was derived from the COleDispatchDriver class. Member functions inherited from this class provide the means of instantiating the COM object and retrieving and releasing its dispatch interface. The following are the basic steps of using a class derived from COleDispatchDriver:


NOTE: Assume that IChildClass, a class created by the ClassWizard, exists for these steps.
1. Declare a data member of type IChildClass.

2. Call the COleDispatchDriver::CreateDispatch function to load the server program and retrieve the IDispatch pointer. This increments the object's reference count by 1.

3. When you're finished with the component, release IDispatch and decrement the reference count by calling the COleDispatchDriver::ReleaseDispatch() function.

In the sample application, the ClassWizard created and inserted IWebBrowserApp into your project. You use the Internet Explorer component in your application as follows:

1. In the header file for the dialog box class (InterNavVCPPDlg.h, in this case), insert the three boldface lines of code shown in Listing 9.2.

Listing 9.2  Adding the Internet Explorer Component as an IWebBrowserApp Object

// InterNavVCPPDlg.h : header file
//
//{{AFX_INCLUDES()
#include "richtext.h"
//}}AFX_INCLUDES
#include "shdocvw.h"     //Contains the declaration of the IWebBrowserApp class
#if !defined(AFX_INTERNAVVCPPDLG_H__FF98D69A_FFDE_11D0_83C1_000000000000__INCLUDED_)
#define AFX_INTERNAVVCPPDLG_H__FF98D69A_FFDE_11D0_83C1_000000000000__INCLUDED_
.
.
.
// Implementation
protected:
    CInterNavVCPPDlgAutoProxy* m_pAutoProxy;
    HICON m_hIcon;
    VARIANT vDummy;                      //Argument for                 
                                         //IWebBrowserApp::Navigate()
    IWebBrowserApp m_oInternetExplorer;  //Declaration IWebBrowserApp object
    BOOL CanExit();
.
.
.

#endif // !defined(AFX_INTERNAVVCPPDLG_H__FF98D69A_FFDE_11D0_83C1_000000000000__INCLUDED_)
2. In the implementation file for the dialog box class, insert the following boldface lines into the dialog box class's constructor:
CInterNavVCPPDlg::CInterNavVCPPDlg(CWnd* pParent /*=NULL*/)
: CDialog(CInterNavVCPPDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CInterNavVCPPDlg)
        // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_pAutoProxy = NULL;
    //Initial the dummy argument that will be passed to the
    //IWebBrowserApp::Navigate function
    vDummy.vt = VT_EMPTY;
    //Create an instance of the InternetExplorer.Application object
    //and retrieve its dispatch interface
    m_oInternetExplorer.CreateDispatch("InternetExplorer.Application.1");
}
3. Insert the following boldface line of code into the dialog box class's destructor:
CInterNavVCPPDlg::~CInterNavVCPPDlg()
{
    // If there is an automation proxy for this dialog, set
    //  its back pointer to this dialog to NULL, so it knows
    //  the dialog has been deleted.
    if (m_pAutoProxy != NULL)
        m_pAutoProxy->m_pDialog = NULL;
    //Release the dispatch interface and decrement the object's
    //reference count
    m_oInternetExplorer.ReleaseDispatch();
}
4. Change the code inside the command button's click event handler function to call the IWebBrowserApp::Navigate and IWebBrowserApp::SetVisible member functions:
void CInterNavVCPPDlg::OnClickSscommand1()
{
    m_oInternetExplorer.Navigate(m_oRichText.GetText(),
                              &vDummy,
                       &vDummy,
                       &vDummy,
                       &vDummy);
    m_oInternetExplorer.SetVisible(TRUE);
}
5. Compile and run the application, making sure that you have Internet service provided to you. Type a valid URL in the text box and click the Navigate button. Internet Explorer should be launched and the respective web page brought into view.

Classes Created by the #import Directive  If you've used the #import directive to create your dispatch interface wrapper class, you'll be using the _com_ptr_t template class to access the component's members. _com_ptr_t, known as a smart pointer, encapsulates a raw interface pointer and handles the creating, reference adding, and releasing of the component object automatically. The _com_ptr_t class is hidden in the _COM_SMARTPTR_TYPEDEF macro located in the .tlh file created by the #import directive. For example, in the shdocvw.tlh file, the following macro is found for the IWebBrowserApp interface:

COM_SMARTPTR_TYPEDEF(IWebBrowserApp, __uuidof(IWebBrowserApp));

This will get expanded by the compiler to the following:

typedef _com_ptr_t<_com_IIID<IWebBrowserApp, __uuidof(IWebBrowserApp)>
    IWebBrowserAppPtr;

You'll use this class, IWebBrowserAppPtr, in your code to use the Internet Explorer component.

Returning to the sample application, follow these steps to incorporate the Internet Explorer component:

1. In the header file for the dialog box class (InterNavVCPPDlg.h, in this case), insert the four boldface lines of code shown in Listing 9.3.

Listing 9.3  Adding the Internet Explorer Component as an IWebBrowserAppPtr Object

// InterNavVCPPDlg.h : header file
//
//{{AFX_INCLUDES()
#include "richtext.h"
//}}AFX_INCLUDES
#import "C:\WINNT\System32\shdocvw.dll" rename ("tagREADYSTATE", "tagIEREADYSTATE")
using namespace SHDocVw;
#if !defined(AFX_INTERNAVVCPPDLG_H__FF98D69A_FFDE_11D0_83C1_000000000000__INCLUDED_)
#define AFX_INTERNAVVCPPDLG_H__FF98D69A_FFDE_11D0_83C1_000000000000__INCLUDED_
.
.
.
// Implementation
protected:
    CInterNavVCPPDlgAutoProxy* m_pAutoProxy;
    HICON m_hIcon;
    VARIANT vDummy;                         //Argument for
                                            //IWebBrowserApp::Navigate()
    IWebBrowserAppPtr m_oInternetExplorer;  //Declaration IWebBrowserApp object
    BOOL CanExit();
.
.
.
n
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately  //before the previous line.
#endif // !defined(AFX_INTERNAVVCPPDLG_H__FF98D69A_FFDE_11D0_83C1_000000000000__INCLUDED_)
2. In the implementation file for the dialog box class, insert the following boldface lines into the dialog box class's constructor:
CInterNavVCPPDlg::CInterNavVCPPDlg(CWnd* pParent /*=NULL*/)
: CDialog(CInterNavVCPPDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CInterNavVCPPDlg)
        // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_pAutoProxy = NULL;
    //Initial the dummy argument that will be passed to the
    //IWebBrowserApp::Navigate function
    vDummy.vt = VT_EMPTY;
    //Create an instance of the InternetExplorer.Application object
    //and retrieve its dispatch interface
    m_oInternetExplorer.CreateInstance("InternetExplorer.Application.1");
}


NOTE: When an object of the _com_ptr_t class leaves scope, the Release method of the interface pointer is called automatically. There's no need to explicitly release the reference as was the case for the class derived from COleDispatchDriver.
3. Change the code inside the command button's click event handler function to call the IWebBrowserApp::Navigate and IWebBrowserApp::SetVisible member functions:
void CInterNavVCPPDlg::OnClickSscommand1()
{
    m_oInternetExplorer ->Navigate((LPCSTR)m_oRichText.GetText(),,
                                &vDummy,
                         &vDummy,
                         &vDummy,
                         &vDummy);
    m_oInternetExplorer ->PutVisible(TRUE);
}
4. Compile and run the application.

From Here...

In this chapter, you've been introduced to the types of ActiveX components typical in a client/server environment. Also, you've learned the techniques to install and register ActiveX components to be accessed on a local or remote machine. You've also seen the steps necessary in incorporating ActiveX components into Visual Basic and Visual C++ applications.


Previous chapterNext chapterContents


© Copyright, Macmillan Computer Publishing. All rights reserved.