What can you do with a process ID? Two things. You can pass it to OpenProcess to get a process handle, or you can use it for the same thing Windows uses it for—a unique identifier of the process. A process handle can’t serve this purpose because there might be multiple handles to the same process. WinWatch stores process IDs in the ItemData array of the Processes list box. It stores top window handles in the ItemData array of the Top Windows list box. Since it’s possible to get a process ID from a top window handle and vice versa, WinWatch can use the ItemData information to keep all the list boxes in sync.
Whenever a user clicks on any of the list boxes or takes any other action that could change their contents, the UpdateDisplay procedure is called. This procedure is the heart of WinWatch logic where all exceptions and special cases are worked out. I’m not particularly proud of this procedure, but I can say it’s more structured than the baling wire code that held previous versions of WinWatch together.
I’ll let you study UpdateDisplay on your own, but I would like to make one
minor point about the event procedures that call it. They use a module-level fInClick flag to protect agains circular references. For example, the lstTopWin_Click procedure calls UpdateDisplay, which might set the ListIndex property of lstTopwin, which would call lstTopWin_Click, which would call UpdateDisplay, which might set the ListIndex property of lstTopWin, and so on. You have the potential for an infinite call cycle, or, depending on the program logic, perhaps just one extra call. Instead the lstTopWin_Click procedure checks the module-level fInClick flag and exits immediately if it is True. If it’s False, the procedure sets fInClick to True and then calls UpdateDisplay. You might want to use a similar strategy in your programs to guard against recursive Click events.