VBA provides almost no native support for operations involving system information; because Windows itself provides easy-to-call API functions for determining and controlling the environment, VBA doesn’t have to duplicate that functionality. Of course, some of the API functions are tricky to call, and information you need is scattered throughout the Windows API. In addition, the Windows API provides so many functions for working with system information, and their functional-ities overlap so much, that it’s difficult to know which one to use in any given circumstance.
To make it simpler to call the selected API functions, we’ve created a series of class modules that wrap up their functionality. Why class modules? That is, what do you gain by having this functionality wrapped up in a class as opposed to a standard module? Unlike other situations in which you use class modules, in this case you don’t care about the multiple instancing. (You’ll never create more than one instance of the Keyboard class in your application, for example.) What you do gain is the ability to treat disparate function calls as simple properties. For example, to retrieve information about a particular setting, you’ll often use the GetSystemMetrics API function. To change the same information, you need to use the SystemParametersInfo function. Rather than provide two separate functions for you, one to get and one to change the value, we’ve provided a single property, with its Let and Get Property procedures. This way, from your application, you can write simple code like this to retrieve a value, change it, and then set it back at a later time:
Dim lngBorderColor As Long
Dim sc As New SystemColors
' Store away the original color.
lngBorderColor = sc.ActiveBorder
sc.ActiveBorder = 255
' Do work in here...
' Now reset the color and release the object.
sc.ActiveBorder = lngBorderColor
Set sc = Nothing
In addition, class modules provide another benefit: because class modules trigger their Initialize event when you create a new instance of the class, the class can call an API function that initializes a data structure. Several of the system information functions require you to pass a single data structure, with many elements. For these functions, the corresponding class can call the function in its Initialize event, retrieve all the information at once, and return the various pieces of information to you as properties of the class. For more information, see the section “Creating the Memory Status Class” later in this chapter.
Each of the classes provided in this chapter is self-contained. If you’re interested only in controlling the keyboard, you’ll need to import only the single KEYBOARD.CLS module. If you need more information, import the classes you need. The bulk of this chapter, organized to match the class modules themselves, describes in detail each of the properties and methods of the classes. In each case, you can either dig into or skip over the details of how the class works. If you just need the functionality and don’t care about the details, skip over the description of the API calls and their usage. If, on the other hand, you want to understand exactly how these classes work or want to expand their functionality, all the information you need is here.
If you find yourself importing multiple classes, you may want to “factor out” the repeated API and constant declarations. Although there aren’t a great many of repeated declarations from module to module, there’s no point adding extra heft to your applications. Once you’ve imported all the classes you’ll need, you can copy the shared declarations to a standard module, remove the “Private” keyword, and use the new shared declarations for your API calls. Don’t forget that you’ll also need to move the necessary data structures and constants to a shared location.