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.)
To create a similar form in your own application, follow these steps:
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. 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|
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.
|