hide random home http://www.zdnet.com/pcmag/issues/1507/pcmg0092.htm (PC Press Internet CD, 03/1996)

PC Magazine -- April 9, 1996

A Bitmap Photo Album

Michael J. Mefford

PicAlbum finds and organizes all the bitmaps on your hard disk.

How many bitmap files are scattered around your hard disk? You'd probably be surprised at the number. This issue's utility, PicAlbum, finds all the bitmaps, displays them, and lets you organize them into picture albums. The bitmaps are not actually moved; the albums use references to the bitmaps on your disk. Knowing what your bitmap files look like and where they are located makes it easier to incorporate them into documents you create. The bitmap file types that PicAlbum supports are .BMP, .DIB, .PCX, .GIF, TIFF, and Targa.

You can obtain PicAlbum by downloading it from PC Magazine Online or through the mail. (Refer to the sidebar "Guide to Our Utilities" for details.) The source code for PicAlbum, which was written in Borland's visual programming tool, Delphi, is also provided for those interested in seeing how it works.

Using PicAlbum

PicAlbum consists of two program files (PICALBUM.EXE and PICALBUM.HLP), an .INI file that is automatically created when you run PicAlbum, and four support files (BIVBX11 .DLL, IKDSP16.VBX, IKEND16.DLL, and IKCOL16.DLL). The support files that start with IK are from a third-party VBX component called ImageKnife, from Media Architects. ImageKnife gives PicAlbum the ability to display all the different bitmap file formats mentioned above. The component has other capabilities as well, but these were not needed for PicAlbum.

We chose to use ImageKnife in PicAlbum because developing the capability from scratch would have been pointlessly time consuming. Since the capability was readily and inexpensively available from a third party, there was no point in reinventing it.

The easiest way to install PicAlbum is to copy the program files and support files to a directory on your hard disk. This method will always work, but you may want to put the ImageKnife support files in the Windows SYSTEM directory, where other programs can share them. If you choose to do this, be aware that you may already have some or all of these files on your system, and the versions you have may be newer. Check the files' dates before copying over them, and don't overwrite newer versions with older versions. If you have any doubt and want to be safe, simply place the ImageKnife files in the same directory as PICALBUM.EXE.

When you've copied all the files to your hard disk, place PicAlbum's icon in the folder of your choice and double-click on the icon to launch the program. The PicAlbum interface is divided into four quadrants (Figure 1). The list of albums you create is displayed in the upper-left quadrant. The bitmaps in the highlighted album are displayed in the upper-right quadrant. The lower quadrants show you the bitmaps that exist on your hard disk. The directories you select to search are displayed in the lower-left quadrant; the bitmaps contained in those directories are displayed in the lower-right quadrant.

To create an album, click on the leftmost button above the Albums list or select File | New Album. (Note that if you place the mouse cursor over a button, flyover help will appear with a description of the button.) A dialog box will prompt you for the name of your album. Type in a descriptive name, such as "PCX bitmaps" or "Bitmaps of telephones." You do not have to use a DOS-style filename since album information is stored in PicAlbum's .INI file, not in a separate album file.

Next, select which directories to search for bitmaps by clicking on the leftmost button above the Directories list box or by selecting File | Select Directories. This will bring up the Bitmap Directories dialog box (see Figure 2).

The Bitmap Directories dialog box lets you build a list of directories to scan for bitmaps. To find all the bitmaps on a particular disk drive, select the disk drive in the Drives combo box, highlight the root directory in the Directory To Add list box, make sure Include Subdirectories is checked, and click the Add button. All the directories on the drive will be added to the Directories to Scan list box.

You can add directories from another drive to the list by selecting the drive, highlighting the directory, and pressing Add. If the Include Subdirectories box is checked, all directories below the selected directory will be added as well.

To selectively remove a directory from the list, highlight the directory, then click Remove or press the Delete key. To clear the list and start over, press the Clear button. The check boxes at the bottom of the Bitmap Directories dialog box let you select the types of bitmaps to scan for.

When you have finished building your Directories to Scan list and have checked the bitmap types you want to include, click the OK button to return to the main window. The directories you selected will appear in the Directories list box in the lower-left quadrant. To begin scanning, click the right-arrow button above the Directories list box or select File | Find Bitmaps from the menu. When scanning is complete, all the bitmaps in the selected directories of the types you specified will appear in the Directory Bitmaps list box in the lower-right quadrant.

You can review the bitmaps by scrolling down through the list. A reduced, thumbnail view of the highlighted bitmap file will appear to the right of the list box. If you want a better look, there are many ways to do it: Double-click on the thumbnail, click the magnifying glass button above the Directory Bitmaps list box, select File | View Directory Bitmap, or press Enter or double-click on a bitmap filename.

While viewing a full-size bitmap, you can press the PgUp or PgDn keys to see the next bitmap in the list without having to return to the main window to select a new bitmap. Pressing the cursor arrow keys (left, right, up, and down) will scroll any bitmap that is too large to fit on the screen. Any other keystroke or mouse click will take you back to PicAlbum.

When you see a bitmap that you want to place in an album, first make sure the album you want to place it in is highlighted in the Albums list in the upper-left quadrant. You can then add the highlighted bitmap to the album in several ways: Click the up arrow located above the Directory Bitmaps list box, select File | Add Bitmap to Album from the menu, or use drag-and-drop. You can drag the selected bitmap(s) from the Directory Bitmaps list box or drag the thumbnail of the selected bitmap. And you can drop your dragged bitmap(s) into the Album Bitmaps list box or onto the desired album name in the Albums list box. Note that PicAlbum doesn't actually move the bitmap files but rather stores the path to the bitmap files, so you don't have to worry about dislocating bitmaps used by other programs.

Once you have added bitmaps to albums, there are two images on the main screen at once. Only one of them can have control of the palette--the set of colors Windows uses to display the bitmap. If both are 256-color images and their palettes are very different, the one that's not active can look pretty bad. Just click on it or on the associated list box to activate it.

To remove bitmaps from an album, first highlight the bitmap(s). Then press Delete, click the button with the scissors over the Album Bitmaps list box, or choose File | Remove Album Bitmap from the menu. Similarly, to delete albums, first highlight the album(s). Then press Delete, click the button with the scissors over the Albums list box, or choose File | Delete Album from the menu. Deleting a bitmap from an album doesn't delete the actual bitmap; it merely removes the pointer to that bitmap from PicAlbum's .INI file.

You can rename albums in any of three ways: double-click on the album name, highlight the album and select the rightmost button over the Albums list box, or select File | Rename Album from the menu.

To save your album changes, click the second button from the left above the Albums list box or select File | Save Albums. If you attempt to exit PicAlbum without saving your changes, PicAlbum will ask you if you want to save before exiting.

PicAlbum Innards

PicAlbum is essentially a database program that uses its .INI file to house its data--the names of your albums and the bitmaps they contain. When PicAlbum is launched, the album names are read from the .INI file into a list box.

Delphi list boxes can associate an object with each item in the list. PicAlbum takes advantage of this feature to associate a list of bitmaps with each album. You can see how this is done in PicAlbum's NewAlbumNameClick procedure (Figure 3). When a user creates a new album, the first thing PicAlbum does is to create a TStringList object called Alist for future storage of bitmap filenames. The new album name and its associated object, the string list, are added to the Albums list box's Items property. PicAlbum then sets the list box's ItemIndex property to the index of the last item (the newly added album name) so that it will be highlighted. The last index is one less than the number of items because indexes start at zero.

Next, PicAlbum calls its UpdateAlbums procedure to update the Album Bitmaps list box (Figure 4). The UpdateAlbums procedure has two main tasks. First, it stores the filenames from the previously highlighted album (the names previously displayed in the Album Bitmaps list box) in the TStringList object associated with that album in the Albums list box. Second, it loads the Album Bitmaps list box with the filenames stored in the TStringList object associated with the newly highlighted item in the Albums list box. Both these tasks are accomplished using the Assign method.

The Assign method of a TStringList object copies strings from a source list to a destination list. The syntax is Destination.Assign (Source), which means it's the Destination object's Assign method that is responsible for the copying. The two statements look like simple inverses of one another, but they differ in the index used to access the Albums list box object. AlbumsIndex is an index maintained by PicAlbum that stores the index of the last album highlighted. ItemIndex is maintained by the list box, and it stores the index of the currently highlighted album.

Thus, the first Assign statement in the UpdateAlbums procedure stores the old AlbumBitmaps filenames. The Albums list box object must be typecast to a TStringList type, because the Objects array property of a TStringList simply stores pointers, without any information about the data type they point to. The second Assign statement copies the filenames associated with the newly highlighted album to the Album Bitmaps list box.

After the two transfers, PicAlbum updates the AlbumsIndex by assigning it to the new ItemIndex, then calls UpdateAlbumBitmaps. This last procedure loads the thumbnail with the highlighted bitmap.

UpdateAlbums is called not only when the user creates a new album, but also whenever the user selects a different album. Detecting when a different album was selected involves a small trick. Several components have an OnChange event that is triggered when the component's selection changes, but list boxes have only OnClick. OnClick is triggered by a mouse click or keyboard equivalent whether or not the selection actually changes. PicAlbum gets the equivalent of an OnChange event by storing the previous value of ItemIndex in AlbumsIndex and taking action in the OnClick event handler only when ItemIndex has changed:

    procedure
    TMainForm.AlbumsClick(Sender:
    TObject);
    begin
      if AlbumsIndex <> Albums.ItemIndex
    then
      begin
        UpdateAlbums;
        with AlbumBitmaps do
        if Items.Count > 0 then
          Selected[0]:= true;
      end;
    end;

Calling UpdateAlbums every time the OnClick event occurred would cause the thumbnail to be rewritten (and thus to flash) each time the user clicked on the Albums list box, even if a new album was not selected.

The PicAlbum .Ini File

Instead of creating a new database file format, PicAlbum uses an .INI file to store its data. I chose this method because the Windows API makes maintaining an .INI file a breeze. A limitation of .INI files is that they cannot exceed 64K, but PicAlbum's storage needs are so minimal that this is not a problem.

PicAlbum's .INI file uses three types of section headers--options, album names, and album contents. These may appear in any order in the .INI file. The two option headers are associated with the Bitmap Directories dialog box. The first, [Options], heads the section where the Include Subdirectories preference is stored. The second, [Bitmap Types], heads the section where the bitmap type selections are stored.

The [Albums] section stores the album names as keys whose values are blank. That is, the lines in the section have the form "name=", with nothing after the equal sign. The Delphi TIniFile object's ReadSection method will read all key names in a section directly into a TStringList object. Thus, storing the names as keys rather than values makes loading them into the program very simple.

For each album name in the Albums section, there is a section header of the same name. Under each album-name section header is a list of the bitmap filenames associated with the album.

As noted above, PicAlbum uses the ReadSection of a TIniFile object to fill the Albums list box. The Album Bitmaps list box is also filled by a single call to this method. Similarly, a call to the EraseSection method of the TIniFile object removes the section for a deleted album from the .INI file.

EraseSection is also used when an album is renamed. When PicAlbum renames an album, it deletes the old album, then writes the album information again under the new name. This is because neither the TIniFile object nor the Windows API functions for .INI file management support renaming headers or keys.

The process is slightly complicated by the fact that the changes to albums and their contents aren't made to the .INI file right away; changes aren't written unless the user presses the Save button or agrees to save changes when prompted on Exit. This means that PicAlbum must store all the renaming information until that time. New album names are stored in the Albums list box. PicAlbum uses a TStringList called RenamedList to store old album names. When the changes are actually saved, PicAlbum erases the sections stored in RenamedList and writes out the new ones.

PicAlbum's Directories dialog box has a Bitmap Types group box with check boxes for each file type. When the user closes the dialog box by clicking OK, the selected types are saved in the .INI file so that PicAlbum can remember the selections the next time it is run.

The state of the six check boxes could be saved with six lines of code, but an easier way is to store the check box states as elements in an array and save them by iterating over the array in a loop. Delphi makes this easy to do. The bitmap-type check boxes are stored in the Controls property of the group box that encloses them. Since the caption of each check box uniquely identifies it, saving each checked state can neatly be done with one statement:

    with Dirs.BitmapsTypesGroupBox do
            for i:= 0 to ControlCount - 1 do
        if Controls[i] is TCheckBox then
    WriteBool('BitmapsTypes',
    TCheckBox(Controls[i]).Caption,
    TCheckBox(Controls[i]).Checked);

This loop writes the state of each of the check box controls owned by the BitmapsTypes group box. Note that each element of the Controls array property must be typecast to TCheckBox in order to access its Caption and Checked properties.

ImageKnife

PicAlbum could have used the Delphi Image component to display the bitmaps. The Image component, however, has the smarts to display only the image types supported by Windows itself: .BMP, .ICO, and .WMF. To be useful, PicAlbum had to broaden its bitmap-type display capability. I wasn't about to write a custom component to perform this task; bitmap formats are complicated. Besides, Media Architects has a Visual Basic custom control (VBX) package called ImageKnife with the capabilities I needed.

Media Architects has granted a license to PC Magazine to use ImageKnife in this utility, but if you want to make changes to PicAlbum's code and recompile it, you will have to obtain the license file by purchasing ImageKnife. The Pro edition (used in this utility) costs $349. For more information, call Media Architects at 503-639-2505 (fax, 503-620-5451) or visit the company's Web site at http://www.mediarch.com.

ImageKnife includes support for two formats that use .LZW compression technology: .GIF and TIFF. Since Unisys Corp. holds a patent on .LZW compression, you must obtain an additional license from Unisys before Media Architects will release the code that enables use of these formats. You can contact Unisys through its Web site at http://www.unisys .com.

Although native Delphi components are not VBXs, you can use VBXs in Delphi programs. Delphi automatically generates code to create a "wrapper" component for a VBX; Delphi programs access the VBX through this component. You install a VBX on the component palette by selecting Options | Install Components. The Install Components dialog box has a special VBX button for file selection. Other than that, VBX installation is as seamless as it is for any Delphi component. Once you select the component and click OK, the new component is added to the Component Palette, ready for use.

To load a bitmap into a Delphi Image component, you call its Picture property's LoadFromFile method with the bitmap filename as the argument. ImageKnife's VBX component, called PicBuf, works a little differently but is just as easy. First you assign the bitmap filename to the PicBuf FileName property, then you call ikLoad with the PicBuf control as the argument:

    AlbumPicBuf.FileName :=
    AlbumBitmaps.Items[ItemIndex];
    ikLoad(AlbumPicBuf.Ctl);

If the image loaded successfully, a call to ikSetScreenPal activates its palette.

PicAlbum uses the PicBuf component in two ways: to display thumbnails of bitmaps and to display actual-size bitmaps. To display a thumbnail, I first set the PicBuf AutoScale property to False so the image is initially at actual size. To prevent distortion should the image later need to be scaled, I set the ScaleImage and ScaleScreen properties to 1, for 1-to-1 scaling. Then I load the image into the thumbnail frame and check to see if it fits within the frame's borders. The image's size is found in the PicBuf's XResolution and YResolution properties. If it fits, then the image is displayed in the thumbnail frame as is (actual size). Otherwise, the AutoScale property is set to true and PicBuf shrinks the image to fit, using a 1-to-1 ratio. The reason I don't start off by setting AutoScale to true is to prevent small bitmaps from being stretched to fill the thumbnail frame.

AutoScale is set to false when displaying a bitmap for actual-size viewing, but the AutoSize property, which controls the size of the PicBuf image, is set to true. Thumbnails are displayed in a frame of a fixed size, but actual-size bitmaps can be any dimension. When AutoSize is set to true, the borders of the PicBuf expand or contract to fit the bitmap snugly in its actual size. You don't actually see the PicBuf border in PicAlbum, since I set the BorderStyle to 0. I didn't want a frame around the images.

Actual-size bitmaps are centered on the screen by setting the left side of the PicBuf to the result of the screen's width in pixels minus the bitmap's width, divided by 2. The top of the PicBuf is similarly set using heights instead of widths.

Some bitmaps viewed at actual size are larger than the screen. PicAlbum lets the user scroll these large bitmaps 30 pixels at a time. The scroll rate of 30 was plucked out of the air; it seemed to be a comfortable value. The scrolling procedure is called from the View form's OnFormKeyUp event. When the user presses the Up Arrow key (VK_UP), PicAlbum first checks to see if PicBuf's Top is less than zero. If true, it means PicBuf is off the top of the screen and needs to be moved down. If Top plus the ScrollRate is greater than 0--placing the PicBuf below the top of the screen--then the PicBuf Top is simply set to 0 (the top of the screen). Otherwise, the value of Top is decreased by the value of the ScrollRate. The three other arrow keys are similarly handled.

New Album Name

Whenever the user is allowed to enter a value instead of picking it from a list, the application needs to look over the input carefully for errors. PicAlbum does such an inspection when the user enters a new album name. PicAlbum is concerned about four aspects of a name: that it isn't blank, that it is a unique name, that it doesn't have any leading or trailing space characters, and that it doesn't contain an equal sign.

Leading and trailing spaces are invisible, but they can cause confusion in a program by making a duplicate entry look like a unique one. Leading and trailing spaces are therefore stripped before checking if an album of the same name exists. The equal sign is an illegal character because it's used by .INI files to separate a key name from its value. If an album name is blank, is a duplicate, or contains an equal sign, the name is disallowed and an explanatory warning box is displayed to the user.

Drag-and-drop

PicAlbum lets the user add a bitmap to an album by dragging a filename from the Directory Bitmaps list box to an album name in the Albums list box. During a drag event, when the cursor is over the Albums list box, its OnDragOver event handler is called. The list box will accept a drop only if it's coming from the Directory Bitmaps list box and the cursor is exactly over a name in the Albums list box.

The OnDragOver event handler's arguments include Sender (the component over which the item is dragged), Source (the component that's being dragged) and X,Y (the mouse cursor coordinates). The Accept parameter determines whether a drop would be accepted; it's true by default. If the Source is not the Directory Bitmaps list box, or if the mouse is not over an existing item in the Albums list box, then the event handler sets Accept to false. When the mouse is released, an OnDragDrop event occurs only if the most recent OnDragOver event set Accept to true.

Delphi components have drag-drop functionality built in; an internal method serves to distinguish a simple mouse click from the beginning of a drag operation. Unfortunately, this drag-testing method is subverted when the OnClick handler for such a component pops up a message box. The drag-testing method doesn't get to finish until after the message box has been closed, and it erroneously detects dragging. The mouse cursor changes to indicate that a drag operation is pending, and nothing works right until you click the mouse. Ordinarily, Delphi programmers just avoid popping up message boxes in such a situation, but the error message displayed by the PicBuf control to report a file-loading problem can't be avoided. All PicAlbum can do is watch for this situation and correct it as quickly as possible. It's important that the correction occurs after the internal drag-testing method has finished but before anything else happens.

To accomplish this, PicAlbum uses a Timer component that's initially disabled by having its Interval set to 0. When a file-loading problem occurs in the OnClick handler for the AllBitmaps list box, it sets the Timer's Interval to 1, which triggers an OnTimer event as soon as the drag-testing method has finished. The OnTimer event handler sets the Interval back to zero, then stops the dragging process by calling the EndDrag method.

Get Organized

PicAlbum lets users organize the bitmaps on their hard disks by simply dragging them onto albums. PicAlbum takes care of the behind-the-scenes data management, while ImageKnife takes care of the complicated bitmap display. Using third-party components in an application can dramatically improve your application and, at the same time, reduce development time. Don't hesitate to scan development tools catalogs when you want some pizzazz in your product without the extra work.

To tell you the truth, I was quite surprised by the wealth of bitmaps on my system that I found with PicAlbum. I've got them all organized now, ready to add flair to my documents.

Michael J. Mefford is a contributing editor of PC Magazine.

PicAlbum finds all the bitmaps on your hard disk, displays them, and lets you organize them in picture albums without changing their locations on your disk. PicAlbum supports .BMP, .DIB, .GIF, TIFF, and Targa file types

FIGURE 3: When the user creates a new album, PicAlbum creates a TStringList for bitmap filename storage and adds this to the Albums list box along with the new album name.

    procedure TMainForm.NewAlbumNameClick(Sender:
    TObject);
    var
      AList : TStringList;
    begin
      if NewAlbum.ShowModal = mrOK then
      begin
      with Albums do
        begin
          AList:= TStringList.Create;
          Items.AddObject(NewAlbum.EditName.Text, AList);
          ItemIndex:= Items.Count - 1;
          UpdateAlbums;
          Modified:= true;
        end;
      end;
    end;

FIGURE 4: PicAlbum saves the previously highlighted album's bitmap filenames before loading the Album Bitmaps list box with the newly highlighted album's bitmaps.

    procedure TMainForm.UpdateAlbums;
    begin
      with Albums do
      begin
        if Items.Count > 0 then
        begin

    TStringList(Albums.Items.Objects[AlbumsIndex]).Assign(
            AlbumBitmaps.Items);
          AlbumBitmaps.Items.Assign(
            TStringList(Albums.Items.Objects[ItemIndex]));
        end;
        AlbumsIndex:= ItemIndex;
        UpdateAlbumBitmaps;
      end;
    end;

Although native Delphi components are not VBXs, you can use VBXs in Delphi programs.


The Top 10 Utilities

1 WORDJUNCTION Creates word puzzles

2 STRING Batch file enhancer

3 1MBF Protects low memory

4 WMATCH Compares directory contents

5 WINBAR Taskbar for Windows 3.1

6 INCTR2 Monitors program installation

7 FDDLLS Finds dead DLLs

8 SUPERPAD Improved Windows notepad

9 COA Program location notifier

10 FINDIR Analyzes IRQ lines


Guide to Our Utilities

About PicAlbum . . .

PURPOSE: PicAlbum finds all the bitmaps on your hard disk, displays them, and lets you organize them in picture albums. The bitmaps are not actually moved; the albums use references to the bitmaps on your disk. The bitmap file types PicAlbum supports are .BMP, .DIB, .PCX, .GIF, TIFF, and Targa. PicAlbum is a 16-bit Windows application that runs compatibly under Windows 95.

USAGE: To install PicAlbum, copy all its program files to a directory on your hard disk, then create an icon for PicAlbum in the folder of your choice.

To create an album, click on the leftmost button above the Albums list. A dialog box will prompt you for the name. Next, select which directories to search for bitmaps by clicking on the leftmost button above the Directories list box. This will bring up the Bitmap Directories dialog box.

When you have finished building your Directories to Scan list and have checked the bitmap types you want to include, click the OK button to return to the main window. The directories you selected will appear in the Directories list box in the lower-left quadrant. To begin scanning, click the right-arrow button above the Directories list box. When scanning is complete, all the bitmaps in the selected directories of the types you specified will appear in the Directory Bitmaps list box in the lower-right quadrant.

You can review the bitmaps by scrolling down the list. A thumbnail of the highlighted bitmap file will appear to the right of the list box. To get a better look, double-click on the thumbnail. When you see a bitmap that you want to place in an album, highlight the album, then highlight the bitmap(s) and click the up arrow above the Directory Bitmaps list box. You can also use drag-and-drop.

FILES FOR DOWNLOAD:

PICALBUM.EXE--Just the program file.

PICALBUM.HLP--The help file.

PICALBUM.TXT--The documentation file.

PICALBUM.ZIP--All the source, program, and documentation files compressed into a .ZIP file.

SUPPORT: Help for PC Magazine's free utilities can be obtained electronically in the Utilities section of ZD Net's Tips forum (GO ZNT:TIPS). The authors of current utilities generally visit this forum daily. You may find an answer to your question simply by reading the messages posted in the forum. If the author is not available and the forum sysops can't answer your question, the Utilities column editor, who also checks this forum each day, will contact the author for you.

..And Getting PC Magazine Utilities

Here's how you can access PC Magazine Online, where you'll find all our utilities and other PC Tech files:

ZD Net

To join CompuServe/ZD Net (formerly Ziff-Net), call 800-895-4596 (voice) and request the PMZ offer. CompuServe members can join ZD Net by typing GO ZIFFMEM at any CompuServe ! prompt. If you're already a member of ZD Net, you can get the current utility free of connect charges by typing GO FREEUTIL at any CompuServe ! prompt. Other PC Tech Files are available individually in the Utilities/Tips and Programming forums or bundled as the volume archive file.

Internet

You can obtain the utility and the volume archive through anonymous FTP from our Internet site. The address is ftp.zdnet.com. Use the word anonymous as your log-in name and any of your e-mail addresses as the password. Look in the subdirectory /pcmag/1996/0409/. The volume archive filename is v15n0 7.zip. The utility and archive are compressed with PKZIP, Version 2.04.

You can also visit our home page on the World Wide Web at http://www.pcmag.com and choose Download from the navigation bar at the bottom of the page.

By Fax or Mail

If you don't have a modem or Internet access, you can fax 508-368-0141 or write to PC Magazine Utilities, c/o Image Software Services, 55 Green St., Clinton, MA 01510-3099.

The programs presented in PC Magazinecan be copied but are copyrighted. You may make copies for others if no charge is involved, but making copies or using any portion for any commercial purpose is strictly prohibited.

Imagemap: Load Images for selection
Home ZDNet
Advertising Index

Copyright (c) 1996 Ziff-Davis Publishing Company