Recipe 11.13 Collect and Display Information on the System and the Access Installation

11.13.1 Problem

Your application really needs to know some information about the computer on which it's running. In addition, you'd like to add some professional polish and an About... box that shows information about the computer, the resources, and the user. Access doesn't provide any way to find this information. How can you gather it?

11.13.2 Solution

You can use the Windows API to retrieve information about the system on which your program is running. By using these various functions as the control sources for unbound controls, you can present a selection of system information to your user.

Load 11-13.MDB and open frmSystemInfo in regular form view (see Figure 11-15). This form includes five "pages" of information about the current computer and its resources. If you like the look of this form, use it as-is in your own applications. (You'll need to import the form, frmSystemInfo, its subform, fsubInfo, and the module, basSystemInfo, into your application, as directed in Step 1.)

Figure 11-15. frmSystemInfo shows memory status information
figs/acb2_1115.gif

To create a similar form in your own application, follow these steps:

  1. Import the module basSystemInfo from 11-13.MDB into your own application. This module contains all the constants, API declarations, and wrapper functions that you'll need.

  2. Create a new form. Place an unbound text box (or checkbox, or option group; see fsubInfo for hints) on the form for each piece of information you wish to display. Set the control sources as shown in Table 11-13. The sample form, frmSystemInfo, uses an option group that lets you choose which page of the subform, fsubInfo, you'd like to see. This has nothing to do with the functionality of the sample beyond cosmetics; it just makes it easier to group the information.

Table 11-13. Control sources for text boxes on frmSystemInfo

Item

Control source

Screen resolution

=acbGetScreenX( ) & " x " & acbGetScreenY( )

Mouse installed

=acbMouseInstalled( )

Keyboard type

=acbKeyboardType( )

Memory load

=acbGetMemoryStatus(0)

Total physical memory

=acbGetMemoryStatus(1)

Available physical memory

=acbGetMemoryStatus(2)

Total page file

=acbGetMemoryStatus(3)

Available page file

=acbGetMemoryStatus(4)

Total virtual memory

=acbGetMemoryStatus(5)

Available virtual memory

=acbGetMemoryStatus(6)

Operating system version

=acbGetOSInfo(0) & "." & acbGetOSInfo(1)

Build number

=acbGetOSInfo(2)

Platform

=acbGetOSInfo(3)

Windows directory

=acbWindowsDirectory( )

System directory

=acbSystemDirectory( )

Temp path

=acbTempPath( )

Access directory

=acbAccessDirectory( )

OEM ID

=acbGetSystemStatus(0)

Page size

=acbGetSystemStatus(1)

Lowest memory address

=acbGetSystemStatus(2)

Highest memory address

=acbGetSystemStatus(3)

Active processor mask

=acbGetSystemStatus(4)

Number of processors

=acbGetSystemStatus(5)

Processor type

=acbGetSystemStatus(6)

11.13.3 Discussion

The functions used here employ a variety of techniques to return the requested information. In general, they query the low-level Windows API to retrieve hardware and Windows environment information. We've wrapped each low-level function in an Access function to handle data type conversions from the dynamic link libraries (DLLs) used by Windows into the format that Access can understand.

frmSystemInfo uses several functions to return information about the current computer:


Screen resolution

The acbGetScreenX and acbGetScreenY functions use the GetSystemMetrics API function to return the size of the screen in pixels. This API function can return many other details about your system, including the width of the window borders, the size of the icons, and whether a mouse is installed. To call it, just pass it one of the constants shown later, in Table 11-14; it will return the requested value to you. For example:

Public Function acbGetScreenX( )
   ' Retrieve the screen width in pixels.
   acbGetScreenX = GetSystemMetrics(SM_CXSCREEN)
End Function

Mouse installed

Again, the GetSystemMetrics function does the work:

Public Function acbMouseInstalled( ) As Boolean
   ' Is a mouse installed?
   acbMouseInstalled = CBool(GetSystemMetrics(SM_MOUSEPRESENT))
End Function

Keyboard type

The GetKeyboardType function provides the answers:

Public Function acbKeyboardType( )
   ' Retrieve information about the keyboard.
   ' Call GetKeyboardType with
   '   0   Keyboard Type
   '   1   Keyboard SubType (depends on the manufacturer)
   '   2   Number of function keys
   acbKeyboardType = GetKeyboardType(0)
End Function

Memory information

The GlobalMemoryStatusEx function fills in a user-defined data structure with information about the current memory load, available and total real and virtual memory, and paging space. We've wrapped all this information up in the acbGetMemoryStatus function:

Public Function acbGetMemoryStatus(intItem As Integer) As Variant

   ' Retrieve system memory information
   ' In:
   '    intItem: Which piece of information to retrieve
   '        0: Memory load (0 to 100)
   '        1: Total physical memory in bytes
   '        2: Available physical memory in bytes
   '        3: Total size in page file in bytes
   '        4: Available page file in bytes
   '        5: Total virtual memory in bytes
   '        6: Available virtual memory in bytes
   ' Out:
   '    Return Value: The requested information

   Dim MS As MEMORYSTATUSEX
   
   ' Set the length member before you call GlobalMemoryStatus.
   MS.dwLength = Len(MS)
   GlobalMemoryStatusEx MS
   Select Case intItem
      Case 0
         acbGetMemoryStatus = MS.dwMemoryLoad * 10000 / 1024
      Case 1
         acbGetMemoryStatus = MS.dwTotalPhys * 10000 / 1024
      Case 2
         acbGetMemoryStatus = MS.dwAvailPhys * 10000 / 1024
      Case 3
         acbGetMemoryStatus = MS.dwTotalPageFile * 10000 / 1024
      Case 4
         acbGetMemoryStatus = MS.dwAvailPageFile * 10000 / 1024
      Case 5
         acbGetMemoryStatus = MS.dwTotalVirtual * 10000 / 1024
      Case 6
         acbGetMemoryStatus = MS.dwAvailVirtual * 10000 / 1024
      Case Else
         acbGetMemoryStatus = 0
   End Select
End Function

Although it seems odd, the code in acbGetMemoryStatus is performing an important conversion. Because the values filled in by the GlobalMemoryStatusEx method are so large, you must use Currency values to contain the results. In order to store large values, VBA scales the contents of Currency variables by a factor of 10,000. Therefore, when you want to use the values here, you must multiply them by 10,000. In addition, to convert from bytes to KB, the code divides the totals by the number of bytes in a kilobyte, 1024.



Operating system information

The GetVersionEx API function does the work here. To simplify its use, we've provided the acbGetOSInfo function, as follows. Note that the Platform ID value simply indicates whether you're running a Windows 95-based operating system (such as Windows 98 or Windows ME) or a Windows NT-based operating system, such as Windows 2000, Windows XP, or Windows Server 2003. You can definitely retrieve more detailed results than this?see the documentation at http://msdn.microsoft.com for more information.

Public Function acbGetOSInfo(intItem As Integer) As Variant

   ' Retrieve operating system information
   ' In:
   '    intItem: Which piece of information to retrieve
   '        0: Major Version
   '        1: Minor version
   '        2: Build Number
   '        3: Platform ID
   '             0 = Win32s (not going to happen!)
   '             1 = Win95
   '             2 = WinNT
   ' Out:
   '    Return Value: The requested information
   
   Dim OSInfo As OSVERSIONINFO
   
   ' Set the length member before you call GetVersionEx.
   OSInfo.dwOSVersionInfoSize = Len(OSInfo)
   If GetVersionEx(OSInfo) Then
      Select Case intItem
         Case 0
            acbGetOSInfo = OSInfo.dwMajorVersion
         Case 1
            acbGetOSInfo = OSInfo.dwMinorVersion
         Case 2
            ' Get just the low word of the result.
            acbGetOSInfo = OSInfo.dwBuildNumber And &HFFFF&
         Case 3
            acbGetOSInfo = OSInfo.dwPlatformId
      End Select
   Else
      acbGetOSInfo = 0
   End If
End Function

Directories

To retrieve the Windows directory, call acbWindowsDirectory, shown in the following code. For the Windows System directory, call acbSystemDirectory; for the temporary storage path, call acbTempPath; and to find out which directory Access is running from, call acbAccessDirectory. (Note that acbAccessDirectory doesn't actually use the Windows API to find the location of Access; the SysCmd function in Access makes that information available.)

Public Function acbWindowsDirectory( )
   ' Retrieve the Windows directory.
   Dim strBuffer As String
   Dim intCount As Integer
   
   strBuffer = Space(MAX_PATH)
   intCount = GetWindowsDirectory(strBuffer, MAX_PATH)
   acbWindowsDirectory = CleanPath(Left(strBuffer, intCount))
End Function

System information

The GetSystemInfo API function provides all the information. To make this easier for you, we've provided the acbGetSystemStatus function, shown in the following code. Call this function with a number representing the piece of information you want.

Public Function acbGetSystemStatus(intItem As Integer) As Variant
   
   ' Retrieve system status information
   ' In:
   '    intItem: Which piece of information to retrieve
   '        0: Computer identifier, specific to OEM
   '        1: Returns page size and specifies the granularity of page
   '           protection and commitment
   '        2: Lowest memory address accessible to applications and 
   '           dynamic link libraries (DLLs)
   '        3: Highest memory address accessible to applications and DLLs
   '        4: Mask representing the set of processors configured into 
   '           the system
   '           Bit 0 is processor 0; bit 31 is processor 31
   '        5: Returns the number of processors in the system
   '        6: Type of the current processors in the system
   '        7: Allocation granularity in which memory will be allocated 
   '           on (usually 64K)
   ' Out:
   '    Return Value: The requested information
   
   Dim SI As SYSTEM_INFO
   
   GetSystemInfo SI
   Select Case intItem
      Case 0
         acbGetSystemStatus = SI.dwOemID
      Case 1
         acbGetSystemStatus = SI.dwPageSize
      Case 2
         acbGetSystemStatus = SI.lpMinimumApplicationAddress
      Case 3
         acbGetSystemStatus = SI.lpMaximumApplicationAddress
      Case 4
         acbGetSystemStatus = SI.dwActiveProcessorMask
      Case 5
         acbGetSystemStatus = SI.dwNumberOrfProcessors
      Case 6
         acbGetSystemStatus = SI.dwProcessorType
      Case 7
         acbGetSystemStatus = SI.dwAllocationGranularity
      Case Else
         acbGetSystemStatus = 0
   End Select
End Function

Table 11-14. Subset of the options for GetSystemMetrics

Constant name

Value

Meaning

 SM_CXSCREEN

0

Width of screen.

 SM_CYSCREEN

1

Height of screen.

 SM_CXVSCROLL

2

Width of arrow bitmap on a vertical scrollbar.

 SM_CYHSCROLL

3

Height of arrow bitmap on a horizontal scrollbar.

 SM_CYCAPTION

4

Height of window title. This is the title height plus the height of the window frame that cannot be sized (SM_CYBORDER).

 SM_CXBORDER

5

Width of window border.

 SM_CYBORDER

6

Height of window border or dimensions of a single border, in pixels.

 SM_CXFIXEDFRAME

7

Width of frame when window has the WS_DLGFRAME style.

 SM_CYFIXEDFRAME

8

Height of frame when window has the WS_DLGFRAME style.

 SM_CYVTHUMB

9

Height of scroll box on vertical scrollbar.

 SM_CXHTHUMB

10

Width of scroll box (thumb) on horizontal scrollbar.

 SM_CXICON

11

Width of icon.

 SM_CYICON

12

Height of icon.

 SM_CXCURSOR

13

Width of cursor.

 SM_CYCURSOR

14

Height of cursor.

 SM_CYMENU

15

Height of single-line menu bar.

 SM_CXFULLSCREEN

16

Width of window client area for a full-screen window.

 SM_CYFULLSCREEN

17

Height of window client area for a full-screen window (equivalent to the height of the screen minus the height of the window title).

 SM_CYKANJIWINDOW

18

Height of Kanji window.

 SM_MOUSEPRESENT

19

Nonzero if the mouse hardware is installed.

 SM_CYVSCROLL

20

Height of arrow bitmap on a vertical scrollbar.

 SM_CXHSCROLL

21

Width of arrow bitmap on a horizontal scrollbar.

 SM_DEBUG

22

Nonzero if the Windows version is a debugging version.

 SM_SWAPBUTTON

23

Nonzero if the left and right mouse buttons are swapped.

 SM_CXMIN

28

Minimum width of window.

 SM_CYMIN

29

Minimum height of window.

 SM_CXSIZE

30

Width of bitmaps contained in the titlebar.

 SM_CYSIZE

31

Height of bitmaps contained in the titlebar.

 SM_CXFRAME

32

Width of window frame for a window that can be resized. (Obsolete; use SM_CXFIXEDFRAME instead.)

 SM_CYFRAME

33

See SM_CXFRAME (height, instead). (Obsolete; use SM_CYFIXEDFRAME instead.)

 SM_CXMINTRACK

34

Minimum tracking width of window.

 SM_CYMINTRACK

35

Minimum tracking height of window.

 SM_CXDOUBLECLK

36

Width of the rectangle around the location of the first click in a double-click sequence. The second click must occur within this rectangle for the system to consider the two clicks a double-click.

 SM_CYDOUBLECLK

37

See SM_CXDOUBLECLK (height, instead).

 SM_CXICONSPACING

38

Width of rectangles the system uses to position tiled icons.

 SM_CYICONSPACING

39

Height of rectangles the system uses to position tiled icons.

 SM_MENUDROPALIGNMENT

40

Alignment of pop-up menus. If this value is zero, the left side of a pop-up menu is aligned with the left side of the corresponding menu-bar item. If this value is nonzero, the left side of a pop-up menu is aligned with the right side of the corresponding menu-bar item.

 SM_PENWINDOWS

41

Handle of the Pen Windows DLL if Pen Windows is installed.

 SM_DBCSENABLED

42

Nonzero if current version of Windows uses double-byte characters; zero otherwise.

 SM_CMOUSEBUTTONS

43

Number of buttons on the mouse, or zero if no mouse is present.

 SM_SECURE

44

Nonzero if security is present; zero otherwise.

 SM_CXMINSPACING

47

With SM_CYMINSPACING, dimensions of a grid cell for minimized windows, in pixels. Each minimized window fits into a rectangle this size when arranged. These values are always greater than or equal to SM_CXMINIMIZED and SM_CYMINIMIZED.

 SM_CYMINSPACING

48

See SM_CXMINSPACING.

 SM_CXSMICON

49

With SM_CYSMICON, recommended dimensions of a small icon, in pixels. Small icons typically appear in window captions and in small icon view.

 SM_CYSMICON

50

See SM_CXSMICON.

 SM_CXSMSIZE

52

With SM_CYSMSIZE, dimensions of small caption buttons, in pixels.

 SM_CYSMSIZE

53

See SM_CXSMSIZE.

 SM_CXMENUSIZE

54

Width of menu bar buttons (such as multiple document (MDI) child Close), in pixels.

 SM_CYMENUSIZE

55

Height of menu bar buttons (such as multiple document (MDI) child Close), in pixels.

 SM_ARRANGE

56

Flags specifying how the system arranges minimized windows.

 SM_CXMINIMIZED

57

Width of a normal minimized window, in pixels.

 SM_CYMINIMIZED

58

Height of a normal minimized window, in pixels.

 SM_CXMAXTRACK

59

Default maximum width of a window that has a caption and sizing borders. The user cannot drag the window frame to a size larger than these dimensions.

 SM_CYMAXTRACK

60

See SM_CXMAXTRACK (height, instead).

 SM_CXMAXIMIZED

61

Default width of a maximized top-level window, in pixels.

 SM_CYMAXIMIZED

62

Default height of a maximized top-level window, in pixels.

 SM_NETWORK

63

The least significant bit is set if a network is present; otherwise, it is cleared. The other bits are reserved for future use.

 SM_CLEANBOOT

67

Value that specifies how the system was started: 0 (Normal boot), 1 (Fail-safe boot), 2 (Fail-safe with network boot). Fail-safe boot (also called SafeBoot) bypasses the user's startup files.

 SM_SHOWSOUNDS

70

Nonzero if the user requires an application to present information visually in situations where it would otherwise present the information only in audible form; zero otherwise.

 SM_CXMENUCHECK

71

Width of the default menu checkmark bitmap, in pixels.

 SM_CYMENUCHECK

72

Height of the default menu checkmark bitmap, in pixels.

 SM_SLOWMACHINE

73

Nonzero if the computer has a low-end (slow) processor, zero otherwise.

 SM_CMETRICS

75

Number of system metrics and flags.

Some of the flags supported by GetSystemMetrics behave differently under different operating systems. Make sure you check the documentation (online at http://msdn.microsoft.com) for operating-system dependencies. You'll also find other options that you can add to this form; we didn't include every available option here.

In addition to the functions listed here, you may find the SystemParametersInfo API function useful. It allows you to set and retrieve many system parameters, but calling it is a bit more difficult than calling GetSystemMetrics. If you have access to a Windows API reference, you may want to dig into this useful function.