Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Schongar P.VBScript unleashed.1997

.pdf
Скачиваний:
46
Добавлен:
23.08.2013
Размер:
1.59 Mб
Скачать

we mentioned, barring any redistribution which isn't explicitly mentioned in the VBScript binary licensing agreement, it's free! Otherwise, you take the next step, the one that requires the involvement of the Microsoft legal department.

Source Code

Porting VBScript to another platform, or doing other things that require you to get at the very innards of VBScript itself, will require the VBScript runtime source code, which can be modified, tweaked, or mucked about with however you see fit. As you could probably guess, there are a large number of restrictions that get placed on you when you decide to go this route. If you develop a new technology, get a patent, or benefit in any number of ways from your hard work, Microsoft does too. In fact, if you look at the licensing, they become your partner. Not a "let's split it 50-50" partner, but rather a partner with as much ownership as you over what you've created and the rights to redistribute, sell, relicense, or otherwise make a tidy sum off your work. And did we mention that any profit they make is solely theirs?

Ownership considerations aside, VBScript Source Code licensing is not a common option. It's much more likely that your needs can be served by either porting your own scripting language or by using the VBScript binary licensing arrangement to take advantage of the binary convenience and price difference.

Putting It All Together-Microsoft's "Spruuids" Example

While different reasons exist for putting together a scripting host, the folks at Microsoft thought a game would be a neat way to demonstrate it all. "Spruuids" is one of the examples included in the ActiveX Developer's Kit, but it's in kit form, and some assembly is required to make it work. If you have the ActiveX SDK, or if you obtain it from Microsoft, you'll have all the files and sample code you need to get a jump start on creating your own host. Although it's not possible to cover everything that's done in the Spruuids sample, we'll look at a few pieces of it so that you can get an idea of what the creators of this whole hosting thing had in mind.

First, depending on the version of your ActiveX Developer's Kit, you may or may not be easily able to find the sample. In earlier editions, references were included in the online Infoviewer text, but later editions hid the reference a little deeper. If you have sample code installed, you'll find everything you really need in the Samples/AXScript/ Spruuids/Src directory. If you don't have the sample code, try getting hold of the latest ActiveX Developer's Kit from http://www.microsoft.com/activex, or through a subscription to the Microsoft Developer's Network

(any level).

The first stop on the tour is the README file found in the Src directory. This provides the outline of what performs what task so that you can skip over the pieces that you don't want to know about yet and jump to the heart of the matter. The three files to pay close attention to for their relation to ActiveX script hosting are:

Game.h, the ActiveX scripting header file

VBSGuids.h, which contains the registered CLASSID of VBScript

Game.cpp, the heart of the ActiveX scripting code

NOTE

If you did check the Readme.txt file, and then looked at that list, you might be a bit confused. According to the Readme file, there's supposed to be an ActivScp.h file that serves as the ActiveX scripting header file. That may have been true in a previous release, but in recent releases, Game. h has taken its place and contains the header information for IActiveScriptSite. In the rush to get the ActiveX Developer's Kit out the door in answer to the demands for it, that's a small change that was overlooked and might be corrected by the time you get your development kit.

Inside Game.h, it's pretty easy to spot the section that deals with ActiveX scripting supportMicrosoft puts a big comment line before and after the section, as shown in Listing 22.5.

Listing 22.5. Contents of Game.h header file.

1:// ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####

2:// *** IActiveScriptSite methods ***

3:STDMETHOD(GetLCID)(LCID *plcid);

4:STDMETHOD(GetItemInfo)(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown

**ppiunkItem, ITypeInfo **ppti);

5:STDMETHOD(GetDocVersionString)(BSTR *pszVersion);

6:STDMETHOD(RequestItems)(void);

7:STDMETHOD(RequestTypeLibs)(void);

8:STDMETHOD(OnScriptTerminate)(const VARIANT *pvarResult, const EXCEPINFO

*pexcepinfo);

9:STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState);

10:STDMETHOD(OnScriptError)(IActiveScriptError *pscripterror);

11:STDMETHOD(OnEnterScript)(void);

12:STDMETHOD(OnLeaveScript)(void);

13:// *** IActiveScriptSiteWindow methods ***

14:STDMETHOD(GetWindow)(HWND *phwnd);

15:STDMETHOD(EnableModeless)(BOOL fEnable);

16:// ##### END ACTIVEX SCRIPTING SUPPORT #####

This provides the hooks that Game.cpp is going to need, and that we've explored before. Since the idea of the program is to have a user interface (it is a game, after all), IActiveScriptingWindow is included, to allow interaction with the UI windows.

The contents of VBSGuids.h is really one item-the Globally Unique Identifier (GUID or Class ID) of the VBScript engine itself-{B54f3741-5B07-11cf-A4B0-00AA004A55E8}. Try saying that two times fast.

Inside Game.cpp is the heart and soul of the interactions, but if you tear it apart you'll see it's not really that mysterious. Neat, yes. Fun, yes. But not overwhelming. Again, it's going to require a real knowledge of C++ programming to get an idea of what's going on, but picking out the pieces that enable the ActiveX scripting support is about as easy as it getsthey're delineated, as shown in Listing 22.6.

Listing 22.6. What ActiveX scripting sections of Game.cpp look like.

1:// ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####

2:// Add the Game as a Named Item & load its code

3:g_clineOffset = 0;

4:hr = pgame->ParseFile(g_pszCodeFile, L"Game");

5:if (hr)

6:{

7:MessageBox(g_papp->m_hwndDlg, s_pszError ? s_pszError : "Unspecified

Error", "Spruuids", MB_OK | MB_ICONEXCLAMATION);

8:return hr;

9:}

10:// ##### END ACTIVEX SCRIPTING SUPPORT #####

Future Hosts

Developers are already starting to build ActiveX scripting hosts for a variety of purposes. When Netscape didn't jump at providing ActiveX scripting support, NCompass Labs created the ScriptActive plug-in, which serves as a scripting host that builds seamless VBScript support right into Netscape Navigator. It's a perfect example of how extensibility on all fronts can provide quite an opportunity for developers. What will the next scripting hosts be? Anything from ActiveX plug-n-play components all the way to complete tools built around ActiveX scripting as their internal scripting language for access to functions. The possibilities are endless.

The big question is how many other languages will follow suit, and whether the extensibility of ActiveX scripting hosts will overpower or just complement existing JavaScript development. All that remains to be seen is who builds what people want, and how soon they do it.

Chapter 23

Conversions and Calculations

by Evangelos Petroutsos

CONTENTS

Metric Conversions

The User Interface

The TabStrip Control

Implementing the Conversions Utility

Programming the Application

A Financial Calculator

The User Interface

A Math Calculator

The User Interface

Programming the Application

Improving the Calculator

Further Improvements

Review

The last part of the book contains a collection of examples you will find useful both in learning VBScript and applying it to your projects. These examples demonstrate key features of the language, some of them rather trivial and others more advanced. All the examples in this section were designed to show how to handle common situations in application development with a language like VBScript, as well as how to use some of the more advanced ActiveX controls. Converting metric units, for instance, is a trivial operation that can be carried out with a single multiplication. The Conversions utility of the next section, however, deploys an elaborate user interface based on the TabStrip control. In the discussion of the examples, you will see how this control is used in building a user interface. Even if you're not interested in learning how to write calculators, in the following chapters you will certainly find useful and practical information and VBScript programming techniques.

The first example of this chapter discusses a unit conversion utility. As simple as the actual conversions may be, the program was designed so that you can easily expand it to perform additional conversions. The second example is a financial calculator. Again, the main topic isn't the actual code for calculating monthly payments, but how to manipulate dates programmatically, a common task in financial calculations. The last example in this chapter is a math calculator. You will see the basics for developing a calculator that performs the basic arithmetic operations, and you learn how to simulate a hand-held calculator. Again, this application was designed so that it can be easily expanded, and you will see how to enhance the basic calculator by making it capable of manipulating hexadecimal numbers.

Metric Conversions

The first example presents a utility that converts metric units. The actual calculations are trivial, but the example provides a few programming issues to explore. The first issue is the user interface. As you can see in Figure 23.1, the

Conversions utility deploys a sophisticated user interface based on the TabStrip control. You could have designed this application in many different ways, but the one suggested here has distinctive advantages.

Figure 23.1 : The Conversions utility lets the user convert different types of units, grouped by category.

The User Interface

First, the application's window stays quite small. Placing all the units on a single layout would result in a waste of valuable screen estate, not to mention that you can fit only so much in a window.

By grouping the various units as Figure 23.1 shows, the application becomes easier to use. People usually want to convert specific units from one system to another; they don't convert units at large, just for the sake of it. The user of the Conversions application will activate the appropriate tab and see on it the units he or she wants to convert.

Finally, once you have implemented the application, you can easily add tabs to accommodate other types of units. You just repeat the existing code and replace the prompts on the layout.

The Conversions application relies on the TabStrip control, which comes with Internet Explorer 3.0 and is one of topics discussed in this chapter. The TabStrip control is a collection of tabbed pages that contain related information. Each page in a TabStrip control contains identically structured information corresponding to a different group. If you wanted to display statistical data about various cities on a TabStrip control, you would use a different page per city. The structure of the data for each city is the same, just the data is different. In other words, all pages will contain the same controls, but different data. Of course, you can have variations on the basic structure of the data displayed on a TabStrip control. For instance, some cities may have unique features that must be displayed on separate controls, which will be visible on certain tabs and invisible on others.

The TabStrip Control

Now start by designing the application's user interface with the ActiveX Control Pad. Start with Control Pad, select New HTML Layout from the File menu, and when the new Layout appears on-screen, select the TabStrip tool and draw a relatively large TabStrip control on the Form. When you place a new TabStrip on an HTML Layout, it has two tabs, named Tab1 and Tab2. To change their names or add new tabs, right-click one of the tabs, and the shortcut menu seen in Figure 23.2 appears. The four commands on this shortcut menu enable you to

Figure 23.2 : To add, remove, or rearrange the tabs on a TabStrip control, right-click one of the tabs, and you see this

shortcut menu.

Insert a new tab at the location of the current tab.

Delete the current tab.

Rename the current tab.

Move the current tab to another location. If you choose Move, you'll be presented with a list of the tabs on the control. Select the tab you want to relocate and move it up and down the list.

Create an additional tab and name the three tabs Length, Weight, and Area. (Refer back to Figure 23.1.)

TabStrip Control's Properties

You can also adjust the appearance of the tabs on the TabStrip control using the Properties window. The Style property determines the look of the tabs and can have one of the following values (see Figure 23.3):

Figure 23.3 : There are three styles you can choose for your TabStrip control.

0 (default): Each page is identified with a tab.

1: Each page is identified with a button.

3: Pages have no marks on them.

Figure 23.3 illustrates the three possible values of the Style property. If the Style property is 0, you must select the page to appear on top of the others programmatically. If the control contains too many pages and their tabs, or buttons, can't be displayed in a single row, two buttons with arrows to the left and right are automatically attached next to the tabs; these arrows enable users to scroll and locate the one they need. If you prefer, you can set the MultiRow property to True, to make all tabs visible, even if they have to occupy multiple lines. This arrangement works in address book types of applications, as shown in Figure 23.4. The tabs on the TabStrip control of Figure 23.4 appear to the right side of the control by setting the TabOrientation to 3 (Right). The other values of the TabOrientation property are 0 (top), 1 (bottom), and 2 (left).

Figure 23.4 : The TabStrip control is ideal for address book types of applications.

Finally, you can set the width and height of each tab with the TabFixedWidth and TabFixedHeight properties respectively (both properties are expressed in pixels). By default, each tab can have its own dimensions, depending on the caption displayed. To set all tabs to the same width, set these two properties to a value large enough to accommodate all the tabs.

TabStrip Control's Methods

So far you have seen the properties for adjusting the appearance of the control at design time. To control the TabStrip programmatically, you must first understand the nature of this control, which is a bit unusual. The TabStrip control represents a collection of Tab objects, and each Tab object in the collection has its own index in the Tabs collection. Tabs is an array, whose elements are the individual tabs. To access the first tab and read or set its properties with VBScript commands, use the expression

TabStrip1.Tabs(0)

where TabStrip1 is the name of the control. The second tab has index 1, and so on.

The Tabs collection has a single property, Count, which returns the total number of tabs. To manipulate the control's tags at runtime, the Tabs collection provides four methods, which correspond to the commands of its shortcut menu. (See Figure 23.2.) The Tabs collection's methods are

Add adds a new tab to the Tabs collection.

Clear removes all objects from the Tabs collection.

Item returns a member of the Tabs collection.

Remove removes a Tab object from the collection.

To add a new tab at runtime, use a statement like

Set TabObject = TabStrip1.Tabs.Add([ Name [, Caption [, index]]])

where TabStrip1 is the name of the control and the bracket indicates that the arguments enclosed are optional. The simplest form of the Add method is

TabStrip1.Tabs.Add

which appends a new tab to the control and names it Tabx, where x is a number. If the control already has 2 tabs, Tab1 and Tab2, the previous call to the Add method will add a third one and name it Tab3. You can specify the name, caption, and order of the tabs added to the collection.

The Clear method removes all the tabs from the control, similar to the Clear method of the ListBox control, which removes all items in a List control. The Remove method removes a Tab object from the collection, and its syntax is

TabStrip1.Tabs.Remove(index)

where index is the order of the tab to be removed in the collection. The statement

TabStrip1.Tabs.Remove(0)

removes the first tab of the TabStrip1 control.

Finally, the Item method returns a member of the Tabs collection, and its syntax is

Set ThisTab = TabStrip1.Tabs.Item(index)

The Caption property controls the string that identifies each member of the Tabs collection. To set the caption of the first tab in the TabStrip1 control, you can use the statement

TabStrip1.Tabs(0).Caption = "Printers"

or extract the appropriate member of the collection and then set the property:

ThisTab=TabStrip1.Tabs(0).Item

ThisTab.Caption = "Printers"

Implementing the Conversions Utility

Place a TabStrip control on the layout and add a third tab with the Add command of the shortcut menu. Then change the captions of all three tabs to match the ones shown in Figure 23.1. To change the font of the captions, right-click the control and select properties from the shortcut menu that will appear. In the Properties window, set the Font property to

the appropriate value.

Now you're ready to place the various controls on the TabStrip control. The controls aren't really placed on the TabStrip control. Instead, they are placed on the layout and the TabStrip control enables them to appear. You can draw each one of the controls on the Layout outside the TabStrip control and then move them with the mouse to their places. You can also move the TabStrip control out of view while creating the rest of the user interface, and then place it on top of the controls and resize it. If the TabStrip hides the remaining controls, place it behind the other controls with the Send to Back command of the Format menu.

The box on which the conversion factors are placed is an ImageBox. The ImageBox control contains eight labels in two columns: the Label controls of the first column are named Units11, Units12, Units13, and Units14, and the labels of the second column are named Units21, Units22, Units23, and Units24. They hold the conversion factors for various pairs of units. The captions of these labels must change every time the user clicks a different tab, so they must be set from within the code. Don't bother to change them at this point. Just notice that the captions of the labels in the first column are left-aligned, and those of the second column are right-aligned.

Then, place the TextBox controls where the user will enter the amounts to be converted. Place the Command buttons and the TextBox controls where the results will be displayed. The TextBox controls on the first column are named From1, From2, From3, and From4, and the controls on the second column are named To1, To2, To3, and To4.

These text boxes hold the units to be converted and the equivalent amount in the new system. Place all the controls on the form, align them with the commands of the Format menu, and assign a common font name and size for them all.

Programming the Application

Now you can look at the code of the application. First, you must supply the subroutine that changes the captions of the Label controls. This subroutine must be invoked every time the user clicks a tab, an action signaled by the TabStrip control's Click event. The subroutine for this event provides an argument, which is the index of the tab that was clicked. Depending on the value of the Index argument, the captions are set to different values:

Sub TabStrip1_Click(Index)

 

If Index=0 Then

 

Unit11.Caption="1 inch

(in)"

Unit12.Caption="1 foot

(ft)"

Unit13.Caption="1 yard

(yd)"

Unit14.Caption="1 mile

(mi)"

Unit21.Caption="2.54 cm"

Unit22.Caption="0.3048

m"

Unit23.Caption="0.9144

m"

Unit24.Caption="1.6093

km"

ClearBoxes

 

End If

 

If Index=1 Then

Unit11.Caption="1 sq. inch"

Unit12.Caption="1 sq. foot"

Unit13.Caption="1 sq. yard"

Unit14.Caption="1 acre"

Unit21.Caption="6.4526 sq. cm"

Unit22.Caption="0.093 sq. m"

Unit23.Caption="0.8361 sq. m"

Unit24.Caption="4046.86 sq. m"

ClearBoxes

End If

If Index=2 Then

Unit11.Caption="1 ounce (oz)"

Unit12.Caption="1 pound (lb)"

Unit13.Caption="1 short ton"

Unit14.Caption="1 long ton"

Unit21.Caption="28.35 gr"

Unit22.Caption="0.4536 kg"

Unit23.Caption="0.9072 t"

Unit24.Caption="1.0161 t"

ClearBoxes

End If

End Sub

The ClearBoxes() subroutine clears the contents of the TextBox controls every time a new tab is displayed, because the amounts converted earlier wouldn't agree with the new units on the page. This subroutine takes care of all the elements that change as the user switches to a different page. When the layout is loaded for the first time, this subroutine must also be called, or else the labels will be blank until the user actually clicks on one of them. In the window_OnLoad event, enter the following lines:

Sub Window_onLoad()