Back to 9/96 How To: Applications
Up to Table of Contents
Ahead to 9/96 How To: Power Windows

9/96 How To: Power Windows

Keep an Eye On Your Windows

Here's a utility that will let you track your programs.

By Karen Kenworthy

DEEP INSIDE YOUR PC, stealth programs and other unseen visitors are carrying out secret missions. Wouldn't you sleep-and work-better if you could keep an eye on these strangers?

It doesn't take a private eye to keep tabs on your Windows programs. Windows maintains a so-called Master List with information about all open windows, visible and invisible. By sneaking a peek at this list, you can learn what's happening inside your PC. And with a little help, you'll gain more control over your applications.

Master the Master List

Bill Gates had a reason for naming his favorite operating system family Windows. Every program running under Windows 95, 3.1x or NT must open at least one window, even if you never see it on screen. Likewise, every program triggers at least one entry in the Master List.

Using the list, you can create an audit file showing all the programs you've run, and the start and stop time for each. Or you could build a program that prevents you from launching more than one copy of a particular application. The catch is finding a way to view the Master List.

That's why I wrote the WinMag Task List utility. This little program displays the Master List, with each window's information on a separate line in a scrollable list box (see Master the Master List).

The beginning of each line shows the window's "handle"-a unique number Windows assigns to distinguish one window from another. After the handle number, the utility displays the information from each window's title bar. "Microsoft Word - Document1," for instance, provides clues to the window's purpose. If the WinMag Task List encounters a window with a blank title (which happens often, especially for dialog boxes) it displays the string <no title>.


A short Visual Basic function named GetMasterList is the heart of the WinMag Task List utility (see Find the Hidden Windows). This function scans or "walks" the Master List, obtaining each window's handle and title bar text, and stores what it finds in the utility's list box. It also counts the number of windows in the Master List so it can display them later.

To accomplish this, GetMasterList uses a function called GetWindow. This workhorse, part of the Windows application programming interface (API), reports each window's handle number and allows you to walk the Master List. Find the Hidden Windows shows the Visual Basic Declare statement that allows you to call GetWindow, along with the declarations of two other Windows API functions you'll use (GetWindowTextLength and GetWindowText).

GetWindow appears in the function's fifth line. This line passes two parameters to GetWindow: the handle of the program's main window (frmTasks.hwnd), and a constant named GW_HWNDFIRST for the definition of this and other constants. As its name implies, this constant tells GetWindow that you want the handle of the first "top-level" window in the Master List. (Top-level windows are linked directly to applications, as opposed to child windows, which are controlled by windows called parents.) Once GetWindow does your bidding, you store the window handle it returns in a variable named WndHnd (window handle).

Next, GetMasterList enters a While/Wend loop that executes repeatedly as long as WndHnd doesn't equal zero. GetWindow returns zero, an illegal window handle number, whenever it's unable to provide any requested information.

At the bottom of the loop, GetWindow is called again (line 16) and WndHnd then stores the value it returns. This time you pass GetWindow a constant named GW_HWNDNEXT, which indicates you'd like the handle of the next window in the Master List. If you've reached the end of the list, GetWindow returns a value of zero, ending your loop.

Round and round it goes

Windows executes a loop for each entry in the Master List. Each time through the loop, the variable WndHnd contains the handle of a different window. The loop is where the GetMasterList function performs its heavy lifting. It's carried out in lines 7 through 15.

Line 7 passes WndHnd to the Windows API function GetWindowTextLength to determine the number of characters in the window's title bar. This value is then stored in the variable named TextLen.

The If statement in line 8 tests the value of TextLen. If TextLen is zero, indicating a blank window title, the program skips directly to line 13. This AddItem statement adds a line to the list box lbTasks, which contains only the window's handle, and the special string <no title>.

If TextLen is greater than zero, however, lines 9 through 11 are executed. First, the variable named WndTitle (window title) is initialized, ensuring the variable is large enough to hold the window's title text. As a precaution, allow for one more character than GetWindowText Length reports.

Line 10 is where you call the Windows API function GetWindowText and obtain the actual title text. This function requires three parameters: the handle of the window whose text is being retrieved, the variable where the text should be stored and a figure indicating the maximum number of characters that can be stored in parameter two. Next, in line 11, the AddItem statement adds a line containing the window's handle and title text to the list box lbTasks.

Finally, in line 15, you add one to your window counter. Because the counter has the same name as the function (GetMasterList), this value will be returned to statements elsewhere in our program that call GetMasterList.

To complete the WinMag Task List, just create the main window shown in Master the Master List. Add lines that call GetMasterList to the main form's Form_Load procedure, and the Refresh button's Click procedure.

The sample statements in both examples are written in the 32-bit version of Visual Basic 4.0, which requires Windows 95 or NT. If you're still using Windows 3.1x, don't worry. I've also written a version of the WinMag Task List in 16-bit Visual Basic 3.0. You can download complete source code for both versions, and ready-to-run 16- and 32-bit EXEs and a .txt file from WINDOWS Magazine online sources. Look for the file named PWTL.ZIP and .TXT.

The road ahead

Where do you go from here? As I hinted earlier, you can use GetMasterList to create several helpful programs. Create an audit file showing all programs run, and the start and stop time for each. Or use GetMasterList to build a program that prevents you from launching more than one copy of a particular application. If this program detects the launch of a second copy of an application, it activates the original copy instead.

I may return to GetMasterList and examine some of these possibilities in detail in a later column. Until then, don't hold back! Drop me a note if you find a use for GetMasterList you'd like to share.

Contributing Editor Karen Kenworthy is the author of Visual Basic for Applications, Revealed! (Prima Publishing, 1994) and the manager of WINDOWS Magazine forums on America Online and CompuServe. Contact Karen in the "Power Windows" topic of these areas. Karen Kenworthy's e-mail ID is:

Back to 9/96 How To: Applications
Up to Table of Contents
Ahead to 9/96 How To: Power Windows