7. System Information Functions

Page 118
  7. System Information Functions  
   
  Let us put some of what we have learned to immediate practice. One of the areas of the Win32 API that we can use profitably even without knowing much about how Windows itself works is the area devoted to system information.  
   
  There are several API functions that can be used to gather information about the computer upon which the functions are running. The Win32 System Information functions are listed in Table 7-1.  
   
  Table 7-1. System Information Functions  
   
  GetComputerName  
   
  GetSystemMetrics  
   
  GetWindowsDirectory  
   
  GetKeyboardType  
   
  GetTempPath  
   
  SetComputerName  
   
  GetSysColor  
 
   
  GetUserNameSesSysColors  
   
  GetSystemDirectory  
   
  GetVersion  
   
  SystemParametersInfo  
   
  GetSystemInfo  
   
  GetVersionEx  
 


   
  Let us look at a few of these functions.  
 
  The Computer's Name  
   
  The GetComputerName function is used to get the current computer's name. The corresponding SetComputerName will set the computer's name. The VC++ declaration is:  
 
  BOOL GetComputerName(
   LPTSTR lpBuffer,    // address of name buffer
   LPDWORD nSize      // address of size of name buffer
);
 
Page 119
   
  Here the parameters are an LPSTR and a pointer to a DWORD, and the return type is BOOL. A corresponding VB declaration is:  
 
  Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" ( _
   ByVal lpBuffer As String, _
   nSize As Long _
) As Long
 
   
  According to the documentation, under Windows 9x the GetComputerName function will fail if the input size is less than the constant MAX_COMPUTERNAME_LENGTH + 1. This constant is defined in WINBASE.H as:  
 
  #define MAX_COMPUTERNAME_LENGTH 15  
   
  which in VB becomes:  
 
  Public Const MAX_COMPUTERNAME_LENGTH = 15  
   
  We can now write a small function to return the computer's name:  
 
  Public Function GetTheComputerName As String

Dim s As String
s = String(MAX_COMPUTERNAME_LENGTH + 1, 0)

lng = GetComputerName(s, MAX_COMPUTERNAME_LENGTH)

GetComputerName = Trim0(s)

End Function
 
   
  (Recall that Trim0 is a simple function to trim a string at the first null.) On my system, the return value is:  
 
  SRCOMPUTER  
 
  Special Windows Paths  
   
  The GetWindowsDirectory, GetSystemDirectory, and GetTempPath retrieve the path to the Windows, Windows System, and Windows temporary files directories. The functions are defined as follows:  
 
  UINT GetSystemDirectory(
   LPTSTR lpBuffer,     // address of buffer for system directory
   UINT uSize           // size of directory buffer
);

UINT GetWindowsDirectory( _
   LPTSTR lpBuffer,     // address of buffer for Windows directory
   UINT uSize           // size of directory buffer
);

DWORD GetTempPath(
   DWORD nBufferLength // size, in characters, of the buffer
 
 

Page 120
 
     LPTSTR lpBuffer     // pointer to buffer for temp path
);
 
   
  The VB declarations are:  
 
  Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" ( _
   ByVal lpBuffer As String, _
   ByVal nSize As Long _
) As Long

Declare Function GetWindowsDirectory Lib "kernel32" _
Alias "GetWindowsDirectoryA" ( _
   ByVal lpBuffer As String, _
   ByVal nSize As Long _
) As Long

Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" ( _
   ByVal nBufferLength As Long, _
   ByVal lpBuffer As String _
) As Long
 
   
  Each of these functions returns the number of characters placed in the string buffer. The size of the buffers should be set one larger than the symbolic constant:  
 
  Public Const MAX_PATH = 260  
   
  Here is some sample code:  
 
  Dim s As String, lng As Long

s = String(MAX_PATH + 1, 0)

lng = GetWindowsDirectory(s, MAX_PATH)
Debug.Print Left$(s, lng)

lng=GetSystemDirectory(s, MAX_PATH)
Debug.Print Left$(s, lng)

lng = GetTempPath(MAX_PATH, s)
Debug.Print Left$(s, lng)
 
   
  On my system, the output is:  
 
  C:\WINNT
C:\WINNT\System32
C:\TEMP\
 
   
  Note that, in each case, the documentation says that the return value is the number of characters copied to the buffer, not including the terminating null. This is why we can use the Left$ function to extract just the return string. On the other hand, the documentation for GetComputerName simply says that the return value in nonzero on success, so we used the Trim0 function instead.  
Page 121
 
  The Operating System Version  
   
  The GetVersionEx function returns version information about the Windows operating system and can be used to determine whether the system is running Windows 95, Windows 98, or Windows NT. The declaration is:  
 
  BOOL GetVersionEx(
   LPOSVERSIONINFO lpVersionInformation   // pointer to version info structure
);
 
   
  where lpVersionInformation is a pointer to an OSVERSIONINFO structure, which is defined as follows:  
 
  typedef struct_OSVERSIONINFO{
   DWORD dwOSVersionInfoSize;
   DWORD dwMajorVersion;
   DWORD dwMinorVersion;
   DWORD dwBuildNumber;
   DWORD dwPlatformId;
   TCHAR szCSDVersion[ 128 ];
} OSVERSIONINFO;
 
   
  The documentation for this structure is as follows:  
 
  dwOSVersionInfoSize
Specifies the size, in bytes, of the OSVERSIONINFO structure. This is a common requirement in structures. Since a DWORD is a 4-byte unsigned long and since VB will translate the 128-character string into a 128-byte ANSI character array, the total size is 4*5+128=148.This is also the value returned by the Len function, but not the LenB function, which doesn't take into account the Unicode-to-ANSI translation
 
 
  dwMajorVersion
Indicates the major version number of the operating system. For example, for Windows NT Version 3.51, the major version number is 3. For Windows NT 4. 0 and Windows 9x, the major version number is 4.
 
 
  dwMinorVersion
Indicates the minor version number of the operating system. For example, for Windows NT Version 3.51, the minor version number is 51. For Windows NT 4.0, the minor version number is 0. For Windows 95, the minor version number is 0. For Windows 98, the minor version number is 10.
 
 
  dwBuildNumber
Indicates the build number of the operating system under Windows NT. For Windows 9x, the low-order word contains the build number of the operating system, and the high-order word contains the major and minor version numbers.
 
Page 122
 
  dwPlatformId
Identifies the operating system platform, and can be one of the following values:
 
 
  VER_PLATFORM_WIN32s (= 0)
Win32s running on Windows 3.1
 
 
  VER_PLATFORM_WIN32_WINDOWS (= 1)
Win32 running on Windows 95 or Windows 98
 
 
  VER_PLATFORM_WIN32_NT (= 2)
Win32 running on Windows NT
 
 
  szCSDVersion
For Windows NT, contains a null-terminated string, such as ''Service Pack 3," that indicates the latest Service Pack installed on the system. If no Service Pack has been installed, the string is empty. For Windows 95, this string contains a null-terminated string that provides arbitrary additional information about the operating system.
 
   
  Translating the GetVersionEx declaration into VB gives:  
 
  Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" ( _
   lpVersionInformation As OSVERSIONINFO _
) As Long
 
   
  The intention here is to pass the address of an OSVERSIONINFO structure by reference.  
   
  To translate the structure definition, we replace the DWORDs with Longs, and the TCHAR array, being fixed length, with either a fixed-length string or a byte array. In the former case, VB will do the usual Unicode-to-ANSI translation, but that's fine:  
 
  Type OSVERSIONINFO
   dwOSVersionInfoSize As Long
   dwMajorVersion As Long
   dwMinorVersion As Long
   dwBuildNumber As Long
   dwPlatformId As Long
   szCSDVersion As String 
* 128 ' 128 characters
End Type
 
   
  Let's give this a try:  
 
  Public Sub PrintVersionInfo

Dim lret As Long
Dim osverinfo As OSVERSIONINFO
osverinfo.dwOSVersionInfoSize = Len(osverinfo)
lret = GetVersionEx(osverinfo)
If lret = 0 Then
   RaiseApiError lret
 
 

Page 123
 
  Else
   Debug.Print "Version: " & osverinfo.dwMajorVersion & "." _
      & osverinfo.dwMinorVersion
   Debug.Print "Build: " & osverinfo.dwBuildNumber
   Debug.Print "Platform ID: " & osverinfo.dwPlatformId
   Debug.Print "String: " & osverinfo.szCSDVersion
End If

End Sub
 
   
  (You will find the RaiseAPIError function defined at the end of Chapter 3, API Declarations.) The output on my system is:  
 
  Version: 4.0
Build: 1381
Platform ID: 2
String: Service Pack 3
 
   
  Here is a short function that returns the name of the operating system:  
 
  Public Function GetOSVersion() As String

' Return name of operating system
Dim lret As Long
Dim osverinfo As OSVERSIONINFO

osverinfo.dwOSVersionInfoSize = Len(osverinfo)

lret = GetVersionEx(osverinfo)

If lret = 0 Then
   GetOSVersion = "unknown"
Else
   Select Case osverinfo.dwPlatformId & "/" & osverinfo.dwMajorVersion
 & "/" & osverinfo.dwMinorVersion
      Case "1/4/0"
         GetOSVersion = "Win95"
      Case "1/4/10"
         GetOSVersion = "Win98"
      Case "2/3/51"
         GetOSVersion = "WinNT351"
      Case "2/4/0"
         GetOSVersion = "WinNT4"
   End Select
End If

End Function
 
 
  System Metrics  
   
  The GetSystemMetrics function retrieves metric (measurement) information about the system. The VC++ declaration is simply as follows.  
Page 124
 
  int GetSystemMetrics(
   int nIndex    // system metric or configuration setting to retrieve
);
 
   
  This translates into VB as:  
 
  Declare Function GetSystemMetrics Lib "user32" ( _
   ByVal nIndex As Long _
) As Long
 
   
  The nIndex parameter is set to one of 49 different possible constants. The requested measurement (generally in pixels or nondimensional units) is returned by the function.  
   
  To give you an idea of the type of information returned, here is a sampling of the constants for this function. All height and width measurements are in pixels:  
  Const SM_CMOUSEBUTTONS = 43        ' Number of mouse buttons     Const SM_MOUSEWHEELPRESENT = 75    ' True if mouse wheel present                                     ' (Win NT 4 or Win 98 only)       Const SM_SWAPBUTTON = 23           ' True if mouse buttons swapped     Const SM_CXBORDER = 5              ' Width and height of a window border     Const SM_CYBORDER = 6     Const SM_CXSCREEN = 0              ' Width and height of screen     Const SM_CYSCREEN = 1           Const SM_CXFULLSCREEN = 16         ' Width and height of client area for a  Const SM_CYFULLSCREEN = 17         ' full-screen window            Const SM_CXHTUMB = 10              ' Width of the thumb box in a horizontal                                     ' scroll bar.            Const SM_CXICONSPACING = 38        ' Dimensions of a grid cell for items in  Const SM_CYICONSPACING = 39        ' large icon view.     Const SM_CYCAPTION = 4             ' Height of a normal caption area.       
 
  System Parameters  
   
  The SystemParametersInfo function is a powerful function for getting or setting system-wide parameters. The function can also update the user profile while setting a parameter. The declaration is:  
 
  BOOL SystemParametersInfo(
   UINT uiAction, // system parameter to query or set
   UINT uiParam,  // depends on action to be taken
   PVOID pvParam, // depends on action to be taken
   UINT fWinIni   // user profile update flag
);
 
Page 125
   
  which can be translated into VB as:  
 
  Declare Function SystemParametersInfo Lib "user32" _
Alias "SystemParametersInfoA" ( _
   ByVal uiAction As Long, _
   ByVal uiParam As Long, _
   pvParam As Any, _
   ByVal fWinIni As Long _
) As Long
 
   
  Note that, for type safety, we can alter the data type of the pvParam depending upon the action to be taken.  
   
  This powerful function can take at least 90 different uiAction values. We will content ourselves with a single example. Note that the function returns a nonzero value on success and 0 on failure. It will set GetLastError, so we can use VB's Err.LastDLLError value.  
   
  System Icon Metrics  
   
  We can get or set the characteristics of system icons (such as those that appear on the desktop) using the constants  
 
  Public Const SPI_GETICONMETRICS = 45
Public Const SPI_SETICONMETRICS = 46
 
   
  For SPI_GETICONMETRICS, the documentation says that the parameter pvParam must point to an ICONMETRICS structure that receives the information. For SPI_SETICONMETRICS, the parameter pvParam must point to an ICONMETRICS structure that contains the new parameters.  
   
  In both cases, we must also set the cbSize member of the ICONMETRICS structure (see the following) and the uiParam parameter of SystemParametersInfo to the size, in bytes, of the structure.  
   
  The ICONMETRICS structure has declaration:  
  typedef struct tagICONMETRICS {       UINT cbSize;       int iHorzSpacing;       int iVertSpacing;       int iTitleWrap;       LOGFONT lfFont;     } ICONMETRICS, FAR **LPICONMETRICS;            
   
  and the LOGFONT structure is:  
 
  typedef struct tagLOGFONT { // lf
   LONG lfHeight;
   LONG lfWidth;
   LONG lfEscapement;
   LONG lfOrientation;
 
 

Page 126
 
     LONG lfWeight;
   BYTE lfItalic;
   BYTE lfUnderline;
   BYTE lfStrikeOut;
   BYTE lfCharSet;
   BYTE lfOutPrecision;
   BYTE lfClipPrecision;
   BYTE lfQuality;
   BYTE lfPitchAndFamily;
   TCHAR lfFaceName[LF_FACESIZE];
} LOGFONT;
 
   
  where:  
 
  Public Const LF_FACESIZE = 32  
   
  There is an important point to note here. Very often one structure will contain pointers to other structures. In this case, however, the lfFont variable is not a pointer it is the actual structure. Thus, we must combine the two structures when creating a VB version:  
 
  Public Type ICONMETRICS
   cbSize As Long
   iHorzSpacing As Long
   iVertSpacing As Long
   iTitleWrap As Long
   lfHeight As Long
   lfWidth As Long
   lfEscapement As Long
   lfOrientation As Long
   lfWeight As Long
   lfItalic As Byte
   lfUnderline As Byte
   lfStrikeOut As Byte
   lfCharSet As Byte
   lfOutPrecision As Byte
   lfClipPrecision As Byte
   lfQuality As Byte
   lfPitchAndFamily As Byte
   lfFaceName As String 
* LF_FACESIZE
End Type
 
   
  Note that this structure behaves well with respect to member alignment. (I'll bet you forgot to check that!) We could have used a byte array for lfFaceName as well as a fixed-length string. A fixed-length string is easier to use when outputting the return value, however.  
   
  Here is some code that uses this function:  
 
  Public Sub PrintIconMetrics

Dim im As ICONMETRICS
im.cbSize = Len(im)
lret = SystemParametersInfo(SPI_GETICONMETRICS, Len(im), im, 0&
 
 

Page 127
 
  If lret = 0 Then
   RaiseApiError Err.LastDllError
Else
   Debug.Print "Hor Spacing:" & im.iHorzSpacing
   Debug.Print "Vert Spacing:" & im.iVertSpacing
   Debug.Print im.lfFaceName & "/"
End If

End Sub
 
   
  The output on my system is:  
 
  Hor Spacing:101
Vert Spacing:109
MS Sans Serif
 
 
  System Colors  
   
  The functions GetSysColor and SetSysColors are used to get and set colors for various system elements, such as buttons, title bars, and so on. These items can also be set by the user through the Display applet in the Control Panel.  
   
  The declaration of GetSysColor is simple:  
 
  DWORD GetSysColor(
   int nIndex    // display element
);
 
   
  where nIndex can be set to one of many symbolic constants, for example:  
 
  #define COLOR_ACTIVECAPTION 2  
   
  In VB this becomes:  
 
  Declare Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long

Public Const COLOR_ACTIVECAPTION = 2
 
   
  The return value is the RGB color. In particular, each color gets a byte in the returned unsigned long: red is the least significant byte, green is next, followed by blue. The high-order byte is 0. (These color bytes appear in reverse order in the long because when it is stored in memory, the bytes are reversed.)  
   
  The SetSysColors function is:  
   BOOL WINAPI SetSysColors(        int cElements,                  // number of elements to change        CONST INT *lpaElements,         // address of array of elements        CONST COLORREF *lpaRgbValues    // address of array of RGB values      );        
   
  Here, cElements specifies the number of system elements whose color we want to change, lpaElements is a pointer to a VC++ integer array that contains the indices of elements to change, and lpaRgbValues points to a VC++ integer array of new RGB color values.  
Page 128
   
  The VB version is:  
 
  Declare Function SetSysColors Lib "user32" ( _
   ByVal nChanges As Long, _
   lpSysColor As Long, _
   lpColorValues As Long _
) As Long
 
   
  where we must call the function by specifying the first array element for each array parameter.  
   
  Note finally that both functions return 0 on success and set GetLastError.  
   
  The following example will flash the active title bar between its default color and red every 0.5 seconds, finally leaving the title bar in its original state:  
 
  Public Function FlashTitleBarColor()

Dim i As Integer
Dim lret As Long
Dim SaveColor As Long
Dim lIndices(0 To 0) As Long
Dim lNewColors(0 To 0) As Long

' Get and save current color
SaveColor = GetSysColor(COLOR_ACTIVECAPTION)
Debug.Print "Current color:" & Hex(SaveColor)

For i = 1 To 5

   ' Change to red
   lIndices(0) = COLOR_ACTIVECAPTION
   lNewColors(0) = &HFF
   lret = SetSysColors(1&, lIndices(0), lNewColors(0))
   If lret = 0 Then
      RaiseApiError Err.LastDllError
   End If

   Delay 0.5

   ' Restore original color
   lIndices(0) = COLOR_ACTIVECAPTION
   lNewColors(0) = SaveColor
   lret = SetSysColors(1&, lIndices(0), lNewColors(0))
   If lret = 0 Then
      RaiseApiError Err.LastDllError
   End If

   Delay 0.5

Next

End Function
 
Page 129
   
  The Delay utility is just:  
 
  Sub Delay(rTime As Single)

'Delay rTime seconds (min=.01, max=300)

Dim OldTime As Variant

'Safty net
If rTime < 0.01 Or rTime > 300 Then rTime = 1

OldTime = Timer
Do
    DoEvents
Loop Until Timer - OldTime >=rTime

End Sub


WIN32 API Programming with Visual Basic
Win32 API Programming with Visual Basic
ISBN: 1565926315
EAN: 2147483647
Year: 1999
Pages: 31
Authors: Steven Roman

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net