Several API functions used in this chapter require you to send them a user-defined type, and they supply values to fill the elements of the structure. Depending on the circumstances, the wrapper class may call the function in either of two ways, in terms of information retrieval:
All the API functions in this chapter that pass information in this manner provide information that’s read-only. Therefore, there are no issues involved in saving information back to the API.
For example, the GetVersionEx API call requires you to supply it a data structure of type OSVERSIONINFO. Listing 9.4 shows the necessary declarations, and the class Initialize event procedure, from the SystemInfo class (SYSTEMINFO.CLS). The event procedure first fills in the dwOSVersionInfoSize element of the structure with the length of the structure itself (many API calls require this step), and then it passes the structure to the GetVersionEx function. This function fills in the various members of the OSVI variable, and other properties of the class use these members in order to supply their information. For example, the OSMajorVersion property, also shown in Listing 9.4, uses the dwMajorVersion member of the OSVERSIONINFO structure to do its work.
Listing 9.4: Use the GetVersionEx API Function (Code Gathered from the SystemInfo Class Module)
Private Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128
End Type
Private Declare Function GetVersionEx Lib "kernel32" _
Alias "GetVersionExA" (OSVI As OSVERSIONINFO) _
As Long
Private OSVI As OSVERSIONINFO
Private Sub Class_Initialize()
' Fill in the OSVersionInfo structure
OSVI.dwOSVersionInfoSize = Len(OSVI)
Call GetVersionEx(OSVI)
' Fill in the SystemInformation structure.
Call GetSystemInfo(si)
End Sub
Property Get OSMajorVersion() As Long
' Retrieve the major version number of the
' operating system. For example, for Windows
' NT version 3.51, the major version number
' is 3; and for Windows NT version 4.0, the
' major version number is 4.
OSMajorVersion = OSVI.dwMajorVersion
End Property
Because the information retrieved by the GetVersionEx API function isn’t likely to change as your application runs, there’s no reason to call the function more than once during the lifetime of your class. The properties of the MemoryStatus class, however, return data that changes constantly. Therefore, it makes sense to call the GlobalMemoryStatus API function each time you access any property of the MemoryStatus class. This ensures that the property values are always up to date. The code in Listing 9.5 has been excerpted from the MemoryStatus class (MEMORYSTATUS.CLS). This listing shows the type and API declarations, as well as the Initialize event procedure of the class and one of the property procedures. The Initialize event procedure of the class fills in the lngLength member of the structure, and this information never changes. The TotalPhysical property then calls the GlobalMemoryStatus API function, passing in the structure, and returns the lngTotalPhys member of the structure as its return value.
Listing 9.5: Excerpts from the MemoryStatus Class Module
Private Type typMemoryStatus
lngLength As Long
lngMemoryLoad As Long
lngTotalPhys As Long
lngAvailPhys As Long
lngTotalPageFile As Long
lngAvailPageFile As Long
lngTotalVirtual As Long
lngAvailVirtual As Long
End Type
Private Declare Sub GlobalMemoryStatus Lib "kernel32" _
(lpBuffer As typMemoryStatus)
Dim ms As typMemoryStatus
Private Sub Class_Initialize()
' ms is declared at the module level.
ms.lngLength = Len(ms)
End Sub
Property Get TotalPhysical() As Long
' Indicates the total number of bytes of physical memory.
Call GlobalMemoryStatus(ms)
TotalPhysical = ms.lngTotalPhys
End Property
The remainder of the chapter provides details on each of the nine system information classes we’ve created. (Although there are, in reality, ten class modules associated with this chapter, FONT.CLS is used only within other classes, so there’s no section devoted to this small class.) In each case, you’ll find a table listing all the properties and methods of the class. If creating the class provided an unusual challenge (aside from the issues already discussed in the chapter), the sections will also include a description of the coding techniques used by the specific class.
To make it easier for you to experiment with the various classes presented in this chapter, we’ve created a simple starting point, Sub Main in SYSINFOTEST.BAS. This procedure declares variables for each of the various classes and then hits a Stop statement. All you need to do is run Main from the Immediate window, and then, once it’s stopped, enter test lines of code in the Immediate window.