Icons with an Attitude

Before I get to icons in WinWatch, I want to digress to note the big changes that have happened to icons in Windows 95 and in Windows NT version 4. Iconically speaking, the enhanced Windows interface is a whole new metaphor. You’ll see icons everywhere—big ones and little ones, in list views, tree views, title bars, and the taskbar. The Picture property has always made standard icons easy to use with Visual Basic, so you might expect that small icons would be a simple extension of an existing feature. Not so. Before we start digging icons out of other people’s programs, let’s examine icons in our own programs and see how the Picture object handles (or fails to handle) them.

The icons we’re most familiar with are 32 by 32 pixels in as many as 16 colors. They consist of a color bitmap of the icon image and a monochrome mask with the outline of the image. They work very much like the CPictureGlass class described in Chapter 7 except that they have a fixed size and built-in API calls to handle them (DrawIcon, CreateIcon, LoadIcon, and so on). Although icons were generally 32 by 32 pixels in previous versions of Windows, the detailed specification allowed any size—a possibility that was rarely tapped. Windows 95 supports four specific icon sizes: small (16 by 16 pixels), large (32 by 32 pixels, with most video adapters), huge (48 by 48 pixels), and shell size (determined by the user on the Appearance tab of the Display Properties dialog box). In addition, you can define icons of arbitrary sizes, although Windows leaves you on your own to manage them.

The ICO file format supports multiple images. You can and should put small icons and large icons in the same file. Unfortunately, the icon tool of choice, IconWorks, doesn’t know a small icon from smallpox. You have to use the ImagEdit tool provided in the \Tools directory on the Visual Basic CD to create icons with multiple images. (Or better yet, purchase one of the excellent shareware icon editors.) Technically, you could put images of any size in ICO files, but ImagEdit supports only 32 by 32 pixels, 16 by 16 pixels, and—for that one last CGA monitor left on earth—32 by 16 pixels. The icons supplied with Visual Basic version 5 contain large and small images, although most parts of Visual Basic can’t do much with the small image, at least not without a little help.

Visual Basic has always supported the concept of a Picture object that can contain an icon, a metafile, or a bitmap. The Picture object (like the Font object) is one of the features COM Automation took from Visual Basic. See “Picture Objects” in Chapter 7 for a more detailed discussion of the Picture object. Unfortunately, when Windows changed the way it uses icons, COM Automation didn’t change the Picture object to match. A Picture can still contain only one icon image. So—if you call LoadPicture on an icon file that contains multiple images, which image is loaded? The same question applies to LoadResPicture and the Load Picture dialog box. You could handle this problem in several ways, but all of them require redesigning the Picture architecture, a redesign that didn’t take place for this version of Visual Basic.

Let’s compare the new Windows way of icons to the Basic way of icons and try to figure out some hacks to bring Visual Basic around to the Windows point of view.

The problem of single icons in the Picture object was well known in the Visual Basic version 4 time frame. Since the Picture object isn’t owned by Visual Basic, there’s nothing Visual Basic could do to fix it, but the owners of the Picture object could have fixed it. Unfortunately, ownership changed sometime after Visual Basic version 4 shipped and promises to redesign the Picture object were “forgotten.” As a result, the Picture object remains a feature designed for 16-bit Windows and completely ignores innovations added by 32-bit Windows. Fortunately, Visual Basic controls such as Image and PictureBox have fixed some of their bugs related to how they display icons.