VB5应用程序对系统配置参数的确定
对于程序员而言,了解系统配置的情况对应用程序的开发具有重要的意义。在开发诸如多媒体应用、图形软件等与系统配置密切相关的软件时,由于用户机器配置不尽相同,所以,由软件在执行时动态获取这些配置参数以确定执行流程,则是软件能否顺利运行的至关重要的因素。这里指的系统配置是Windows 95操作系统的系统配置。程序员对系统物理配置的信息经常需要了解的是中央处理器类型、物理内存、虚拟内存、外部存储器、Windows路径、显示器和打印机信息等。
Visual Basic是一套优秀的软件开发工具,现已成为覆盖微软大部分桌面产品的程序设计语言。Visual Basic 5.0的专业版和企业版引入了本机代码、ActiveX文档、多线程环境、分布式COM和远程自动化工具等功能,将Visual Basic应用程序推到了一个更高的境界。但是VB5并没有直接给出获取系统配置参数的语句或函数,而是需要程序员利用Windows的应用程序接口(API)来获取这些参数。Windows API是为C或C++程序员而设计的,对于一般VB程序员而言,要深入应用Windows API是很困难的,本文将给出通过调用Win32 API来确定系统配置的基本方法。
一.Win32 API基本概念和调用
Windows的32位应用程序接口(Win32 API)包含1000多个复杂的函数和几百种Windows常量、消息和结构,使得程序员可以用不同类型的程序设计语言开发出运行在Windows 95和Windows NT操作系统上的应用程序。C和C++语言可以访问全部Windows的消息和用法,而VB就无法能全部访问到,但是通过使用Win32 API可以扩展VB来超越基本的属性、方法和事件,使得程序对系统拥有更大的控制权和灵活性。
Win32 API包括以下四种常用的函数类型。
1.Windows Management(User)
提供基本的窗口构造块和建立管理程序输入显示、检索用户输入的函数,通过Win32 API的Windows Management层为应用程序创建和管理用户界面。Windows Management支持动态数据交换DDE(Dynamic Data Exchange)一类的系统功能和剪贴板函数。
2.Graphics Device Interface(GDI)
提供支持系统中已有的物理设备和逻辑设备的功能,如监视器、打印机、内存设备描述表等。通过GDI可以定义不同的绘图对象,提供了画线、圆和其他形状的功能,对位图操作提供有力的支持。
3.System Server(Kernel)
提供了访问系统资源和工具的途径,包括内存、文件系统、运行处理等等。VB透过访问和使用动态链接库(DLL:Dynamic Link Libraries),如API或自定义DLL,从这里可以获取操作系统控制下的设备参数和改变其工作状态。
4.Multimedia
提供了对音频(WAV)、MIDI音乐、AVI视频、游戏操纵杆和高精度定时器的支持。在VB5中对Win32 API的调用是很方便的。Microsoft专门整理了Win32 API函数中所用到的函数、类型结构声明和全局常量的值,形成的文件WIN32API.TXT在VB专业版或企业版中放在所在路径下的WINAPI子目录中。在VB5中可以通过两种途径引用这些整理好的参数:(1)直接启动VB5文件夹中的API文本查看器;(2)通过VB5编辑环境中的“外接程序管理器”调入API文本查看器。Microsoft有时对WIN32API.TXT作出修订,公布在其网点上,供用户下载使用。
二.Windows系统路径的获取
应用程序在对操作系统的基本参数进行配置和调用时,必须获取Windows的安装路径,其中包括system的路径。Win32 API给出了获取Windows和system路径的函数调用。
1.获取Windows的路径
Declare Function GetWindowsDirectory Lib "kernel32" Alias _
"GetWindowsDirectoryA" (ByVal lpBuffer As String, _
ByVal nSize As Long) As Long
GetWindowsDirectory()属于System Server的函数成员,用于获取Windows目录的路径名称;GetWindowsDirectoryA是其函数的别名(Alias)。在多数情况下,当一个API函数被声明时,会使用一个别名来替代真正的函数名,别名提供了用另一个名称调用API函数的方法。如果API函数名与VB中的保留字相冲突,就必须使用别名,如GetObject。
2.获取system的路径
Declare Function GetSystemDirectory Lib "kernel32" Alias _
"GetSystemDirectoryA" (ByVal lpBuffer As String, _
ByVal nSize As Long) As Long
GetSystemDirectory()属于System Server的函数成员,用于获取windows\system目录的路径名称。
首先在VB5中新建一个项目,再添加一个模块,在Module1的“声明”部分加入以下代码。
Declare Function GetWindowsDirectory Lib "kernel32" Alias _
"GetWindowsDirectoryA" (ByVal lpBuffer As String, _
ByVal nSize As Long) As Long
Declare Function GetSystemDirectory Lib "kernel32" Alias _
"GetSystemDirectoryA" (ByVal lpBuffer As String, _
ByVal nSize As Long) As Long
'定义Windows和Windows\system所在路径的全局变量
Public WindowsDir As String, WindowsSysDir As String
为了防止在API函数调用返回的字符串中出现空格,有必要对其进行处理,去掉所有空格。VB5没有提供消除字符间空格的函数,所以我们在Module1中编制自定义函数来完成这个功能。
'AllTrim() 删除字符串中的空白字符函数
Function AllTrim$(Incoming$)
Temp$ = Incoming$
n% = InStr(Temp$, Chr$(0))
If n% Then Temp$ = Left$(Temp$, n% - 1)
Temp$ = LTrim$(RTrim$(Temp$))
AllTrim$ = Temp$
End Function
在Module1中设立获取windows和system路径的过程:
' WinSysDir --- 获取Windows和Windows\system路径的过程
Sub WinSysDir()
WindowsDir = Space(144)
WindowsSysDir = Space(144)
If GetWindowsDirectory(WindowsDir,144) = 0 Or _
GetSystemDirectory(WindowsSysDir, 144) = 0 Then
MsgBox "无法定位 Windows 的路径 !", 16, "出现错误"
Else
WindowsDir = AllTrim$(WindowsDir)
WindowsSysDir = AllTrim$(WindowsSysDir)
End If
End Sub
在Form1的Form_Load()事件中调用WinSysDir()就可以获得windows和system路径的名称,演示代码如下:
WinSysDir
Debug.Print WindowsDir
Debug.Print WindowsSysDir
在VB5环境下运行,就会在调试所用的“立即”窗口中给出这两个路径。
三.驱动器参数的确定
Win32 API中的GetDriveType()函数用来识别驱动器类型。该函数只有一个字符型参数,用以指定希望识别的驱动器号。GetDriveType()函数返回值是一个长整型数值,不同的数值表示不同的驱动器类型,具体对应关系如下:
2---软盘驱动器
3---硬盘驱动器
4---网络驱动器
5---光盘驱动器
6---内存驱动器
Win32 API的GetDiskFreeSpace()函数可以获得系统中驱动器的容量参数。
建立一个新项目,在Form1的“通用”部分中声明API函数:
Private Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" _
(ByVal nDrive As String) As Long
Private Declare Function GetDiskFreeSpace Lib "kernel32" Alias _
"GetDiskFreeSpaceA" (ByVal lpRootPathName As String, _
lpSectorsPerCluster As Long, lpBytesPerSector As Long, _
lpNumberOfFreeClusters As Long, lpTtoalNumberOfClusters As Long) _
As Long
Private Const DRIVE_REMOVABLE = 2 ' 可移动驱动器
Private Const DRIVE_FIXED = 3 ' 固定驱动器
Private Const DRIVE_REMOTE = 4 ' 网络驱动器
Private Const DRIVE_CDROM = 5 ' 光盘驱动器
Private Const DRIVE_RAMDISK = 6 ' 内存模拟驱动器
在窗体Form1中添加三个Label控件和一个ComboBox控件。在Form_Load()和Combo1_Click()事件中分别编写如下代码。
Private Sub Form_Load()
Dim Num As Long
Dim buff As String
Label1.Caption = ""
Label2.Caption = ""
Label3.Caption = ""
For i = 0 To 25
buff = Chr$(65 + i) + ":\"
Num = GetDriveType(buff)
If Num > 1 Then
Combo1.AddItem Chr$(65 + i)
End If
Next i
Combo1.Text = "C"
End Sub
Private Sub Combo1_Click()
Dim DriveType As Long
Dim DriveSize As Long
Dim TotalC As Long
Dim NumC As Long
Dim SectorsC As Long
Dim BytesS As Long
Dim buff As String
buff = Combo1.Text + ":\"
DriveType& = GetDriveType(buff)
Select Case DriveType&
Case DRIVE_REMOVABLE
Label1.Caption = "这是可移动驱动器"
Case DRIVE_FIXED
Label1.Caption = "这是固定驱动器"
Case DRIVE_REMOTE
Label1.Caption = "这是网络驱动器"
Case DRIVE_CDROM
Label1.Caption = "这是CD - ROM驱动器"
Case DRIVE_RAMDISK
Label1.Caption = "这是内存模拟驱动器"
Case Else
Label1.Caption = "这是无效的该驱动器"
End Select
DriveSize = GetDiskFreeSpace(buff, SectorsC, BytesS, TotalC, NumC)
If DriveSize Then
TotalC = TotalC * SectorsC * BytesS
NumC = NumC * SectorsC * BytesS
Label2.Caption = "该驱动器全部空间 " + _
Str(Val(Format$(NumC, "##########0")) / 1024) + " KBytes"
Label3.Caption = "该驱动器剩余空间 " + _
Str(Val(Format$(TotalC, "##########0")) / 1024) + " KBytes"
Else
Label2.Caption = ""
Label3.Caption = ""
End If
End Sub
运行这段程序,通过下拉框来选择系统中存在的驱动器,从而获得其相关参数。
四.获取中央处理器的类型
Win32 API的GetSystemInfo()函数提供了对CPU类型的判别。首先在窗体Form1的“通用”部分中声明对这一函数的调用:
Private Declare Sub GetSystemInfo Lib "kernel32" (lpSystemInfo As SYSTEM-INFO)
由于SYSTEM-INFO是一个类型,所以还要对其进行定义:
Private Type SYSTEM_INFO
dwOemID As Long
dwPageSize As Long
lpMinimumApplicationAddress As Long
lpMaximumApplicationAddress As Long
dwActiveProcessorMask As Long
dwNumberOrfProcessors As Long
dwProcessorType As Long
dwAllocationGranularity As Long
dwReserved As Long
End Type
Dim SysInfo As SYSTEM—INFO
在窗体中添加一个Label控件。将如下代码加到Form_Load()事件中:
Call GetSystemInfo(SysInfo)
Select Case SysInfo.dwProcessorType
Case 386
Label1.Caption = "该机器中央处理器类型为: 386"
Case 486
Label1.Caption = "该机器中央处理器类型为: 486"
Case 586
Label1.Caption = "该机器中央处理器类型为: 奔腾"
Case Else
Label1.Caption = "无法判断该机器的中央处理器类型"
End Select
五.获取内存信息
利用Win32 API的GlobalMemoryStatus()可以方便地获取系统中物理内存总量、虚拟内存总量、已用的虚拟内存数量和剩余的虚拟内存数量。
在窗体Form1的“通用”部分中声明对GlobalMemoryStatus()函数的调用:
Private Declare Sub GlobalMemoryStatus Lib "kernel32" (lpBuffer As MEMORYSTATUS)
定义MEMORYSTATUS类型:
Private Type MEMORYSTATUS
dwLength As Long
dwMemoryLoad As Long
dwTotalPhys As Long
dwAvailPhys As Long
dwTotalPageFile As Long
dwAvailPageFile As Long
dwTotalVirtual As Long
dwAvailVirtual As Long
End Type
Dim MemInfo As MEMORYSTATUS
在窗体Form1中添加三个Label控件,分别为Label1、Label2和Label3,在Form_Load()事件中编写下列代码:
Call GlobalMemoryStatus(MemInfo)
Label1.Caption = "物理内存总量:" + Str$(MemInfo.dwTotalPhys) + " Bytes"
Label2.Caption = "虚拟内存总量:" + Str$(MemInfo.dwTotalVirtual) + " Bytes"
Label3.Caption = "已用虚拟内存:" + Str$(MemInfo.dwAvailPhys) + " Bytes"
Label4.Caption = "剩余虚拟内存:" + Str$(MemInfo.dwAvailVirtual) + " Bytes"
六.获取当前显示器的分辨率
Win32 API中的GetSystemMetrics()函数提供了这方面的度量参数。在窗体的“通用”部分中声明调用:
Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Const SM_CXSCREEN = 0
Const SM_CYSCREEN = 1
在窗体中添加一个Label控件,在Form_Load()事件中调用GetSystemMetrics()函数来判断当前显示器的分辨率。
Dim x As String
Dim y As String
n = Str(GetSystemMetrics(SM_CXSCREEN))
y = Str(GetSystemMetrics(SM_CYSCREEN))
Label1.Caption = "当前显示器分辨率: " + n + "x" + y
七.调用MSINFO32.EXE程序
在MS Office套件中,Microsoft提供了MSINFO32.EXE实用程序,它较为全面地为用户提供了系统、打印、DLL、字体、校对、图形过滤器、文本转换器、显示、音频、视频、CD-ROM、OLE注册表、活动模块、输入法等信息。该程序一般放置在Windows所在驱动器的\ Program Files\ Microsoft Shared\ MSInfo路径下。在VB应用程序中,一般在“关于”窗口中对这个实用程序加以调用,虽然其中的信息无法直接应用,但它增加了程序的专业性。
要想成功地调用MSINFO32.EXE,关键在于获取它所在的路径。这一路径无法直接由Win32 API函数获得,也不存在于Windows的配置文件中,而仅存在于Windows 的注册表中。Office套件在安装时对MSINFO32.EXE进行了注册,可供Office各部件共同调用,其路径信息保存在注册表的HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\MSINFO中,因此,获取路径的问题转化成了对注册表的查询。
Win32 API提供了一系列操纵注册表的函数,这里用到了RegOpenKeyEx()、RegQueryValueEx()和RegCloseKey()函数,分别用于打开注册表关键字、检索注册表关键字的值和关闭注册表关键字。如果RegOpenKeyEx()和RegQueryValueEx()返回为0,说明成功地打开了注册表关键字,并且检索到了预定的MSIFO32.EXE关键字值,最后调用Shell()函数来启动MSINFO32.EXE。
VB5的窗体向导提供了标准的调用过程。首先建立一个新项目,然后在“项目”菜单中选择“删除Form1”,再添加一个窗体,在弹出的对话框中选择“关于对话框”,这样就产生了一个定制好的标准的“关于”窗体,其中就有对MSINFO32.EXE的调用,并对运行错误设置了相应的处理。Microsoft对代码做了详尽的注释,这里就不再赘述了。
Visual Basic的企业版提供了Microsoft Developer Network(MSDN)启动工具箱,安装之后,就可以访问Win32 Software Development Kit(SDK),它为Win32 API提供了文件说明,可以帮助程序员理解每一个函数、结构和常量的工作原理。对VB程序员来讲,理解和使用Windows API有一定的难度,它要求程序员对Windows的工作原理有较为深入的了解,如果掌握好Windows API的使用方法,则能够极大地扩展Visual Basic语言的功能,使应用程序对系统的控制更加深入、灵活。