VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)
首页 - 经验之谈 - VB编程之提高篇(1)文件系统
发表评论(0)作者:影子, 平台:VB6.0+Win98, 阅读:14347, 日期:2001-01-01
VB编程之提高篇(1)文件系统
自我介绍:影子 VB爱好者乐园的站长 http://www.d1vb.com
前言:VB是现在比较流行的一种语法,相关的书籍也非常多,因此在这里也就没有必要介绍基础的呢(如果非要,那你就去买本VB入门的书吧),编程要如何提高呢,当然要多看,多做,多问,下面是我在实际应用中(或在网上收集的)的相关技巧(大部分是 API 技巧),经过仔细的整理后,希望对大家学习提高VB编程有帮助。
文件系统的相关操作总览
(1)如何读取 Windows 的所在目录?1
(2)如何读取Winddows\System 的所在目录?1
(3)如何将文件丢到"回收站"?1
(4)如何快速改变文件的所在目录?1
(5)如何复制整个目录(包含子目录及其所有文件)?1
(6)如何读取磁盘的空间及可用空间?1
(7)如何读取文件的创建时间、访问时间?
(8)如何建立快捷方式 ?
(9)如何解读快捷方式(.lnk)中的消息 ?1
(10)快速建立目录
(11)打开文件的属性窗口
(12)激活文件目录对话窗口
怎么样,是不是感觉特别好,不用多长时间,你就能完全理解这些操作了。

(1)如何读取 Windows 的所在目录?
API函数:GetWindowsDirectory
Private Declare Function GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
Const MAX_PATH = 260  注释:定义足够长的字符串
Sub GetWinDir() 注释:定义函数
Dim S As String, Length As Long    
S = String(MAX_PATH, 0) 注释:赋值
Length = GetWindowsDirectory(S, MAX_PATH)   注释:S为取得目录,MAX_PATH 为长度
S = Left(S, InStr(S, Chr(0)) - 1) 注释:去掉多余的空格
  MsgBox "Windows 路径=" & S, , "Win 目录"
End Sub
补充:S 和 MAX_PATH 的值是可以随便赋的,
如:Dim S as String *20
        Length = GetWindowsDirectory(S,20)
不过,这两个的值,一定要够大(一定要大于系统的 Windows 的目录的字符数),不然就不能正常运行。

(2)如何读取Winddows\System 的所在目录?
API 函数:GetSystemDirectory
Private Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
大家注意这个 API 函数和一个的用法完全一样,只是把相应的位置做一个修改就行了,因此这里就不在多讲了。

(3)如何将文件丢到"回收站"?
VB 本身的文件操作语句 Kill,是把文件直接删除,而不是移到回收站中,那么这要如何做呢?
由于这个操作及参数比较多,因此就讲得比较仔细,希望大家仔细理解。
API 函数:SHFileOperation
Private Declare Function SHFileOperation Lib "shell32.dll" Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long
注释: 参数 ipFileOp:传入---- SHFILEOPSTRUCT 数据结构的变量,其结构如下 :
Type SHFILEOPSTRUCT
    hWnd As Long 注释:调用都的窗口代码,不填也无所谓
    wFunc As Long 注释:指定成"复制、删除、移动、更名"等功能
    pFrom As Strin0g 注释:来源目录文件
    pTo As String 注释:目的目录或文件
    fFlags As Integer  注释:操作文件的旗标
    fAborted As Boolean 注释:是否允许使用都中断
    hNameMaps As Long 注释:不必填写
    sProgress As String 注释:进呀字符串,通常不填写
End Type
在 SHFILEOPSTRUCT 数据结构中,大部分的栏是可以必堵塞填写的,下面我就针对需要填写的栏说明一下:
wFunc:指定成"复制、删除、移动、更名"等功能的设置值,如下:







pFrom:来源目录或文件,设置时,一事实上要在文件名称后面补上Chr(0)。
pTo:目的目录或文件。
fFlags:操作文件的旗标,可以是以下设置值的组合。

















fAborted:允许使用都中途中断,也就是在进度对话框中,会显示"取消"按钮。
例子:
1、把 "c:\1.txt" 丢到回收站。
Dim SHFileOp As SHFILEOPSTRUCT

SHFileOp.wFunc = FO_DELETE 注释:删除
SHFileOp.pFrom = "c:\1.txt" + Chr(0) 注释:来源目录或文件
SHFileOp.fFlags = FOF_ALLOWUNDO + FOF_NOCONFIRMATION 注释:丢到回收站+不预选征询使用者是否删除文件。
SHFileOperation SHFileOp 注释:执行
2、把"c:\*.txt"丢到回收站。
SHFileOperation 也可以一次删除多个文件,方法有两种,一种是使用通配符(*或?),例如将 pFrom 栏设置 "c:\*.txt",另一种方法则是将想要删除的文件以 Chr(0) 为分隔字符,然后串在一起指定给 pFrom 栏,例如:
Dim Files As String
Files="c:\1.txt"+Chr(0)+"c:\2.txt"+Chr(0)+"c:\3.txt"+Chr(0)
注意:其他的操作与例子1是一样的。
补充:你也可以删除整个目录,只要 SHFileOp.pFrom = "d:\temp" 就行了。
(4)如何快速改变文件的所在目录。
当我们想改变某一个文件的所在目录,若使用 VB 所提供的功能,通常是先执行 FileCopy 将文件复制到另一个目录,然后才将原文件删除,例如:
FileCopy Path1 & FileName,Path2 & FileName
Kill Path1 & FileName
这一方法对于比较大的文件(假设是200MB),十分浪费时间,若使用 SHFileOperation API 函数,则可以不必复制文件,而直接将文件移至另一个目录,方法如下(假设将 c:\game.dbf 移至 c:\tools 目录):
Dim SHFileOp As SHFILEOPSTRUCT

SHFileOp.wFunc = FO_MOVE 注释:移动
SHFileOp.pFrom = "c:\game.dbf"+Chr(0)
SHFileOp.pTO="c:\tools" 注释:必须是一个已存在的目录
SHFileOp.fFlags = FOF_ALLOWUNDO +FOF_NOCONFIRMMKDIR 注释:在复制文件时若需要建立目录,不预先征询使用者即直接建立
SHFileOperation SHFileOp 注释:执行
补充:文件可以移到另一个驱动器,但它的作者相当于复制文件之后再把原文件删除,唯有在同一磁盘中移动才具有快速移动的效果;如果想一次移动多个文件,则是将想要移动的文件以 Chr(0)为分隔字符,然后串在一起指定给 pFrom 栏。

(5)复制整个目录(包含子目录及其所有文件)
假设我们想把 "c:\vb" 目录下的所有文件(包含其子目录)复制到 "d:\vb" 目录底下
程序代码如下:
Dim SHFileOp As SHFILEOPSTRUCT

SHFileOp.wFunc = FO_COPY 注释:拷贝
SHFileOp.pFrom = "c:\vb*.* 注释:也可以指定成 "c:\vb"
SHFileOp.pTO="d:\vb" 注释:目标目录
SHFileOp.fFlags = FOF_ALLOWUNDO +FOF_NOCONFIRMMKDIR 注释:在复制文件时若需要建立目录,不预先征询使用者即直接建立
SHFileOperation SHFileOp 注释:执行

(6)如何读取磁盘的空间及可用空间?
API 函数:GetDiskFreeSpace
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
参数说明:
lpRootPathName:驱动器根目录,以 C 盘为例,必须写成"C:\",不可以写成"C:"或"C"。
lpSectorsPerCluste:每一簇的扇区数。
lpBytesPerSector:每一扇区的字节数。
lpNumberOfFreeClusters :可用的簇数。
lpTtoalNumberOfClusters:总簇数。
示例:
Dim Sectors As Long, Bytes As Long, Free As Long, Total As Long, FreeMB As Long, TotalMB As Long, WisMB As Long


GetDiskFreeSpace "c:\", Sectors, Bytes, Free, Total
FreeMB = Bytes * Sectors * Free \ 1024 \ 1024 注释:可用空间,以 MB 为单位
TotalMB = Bytes * Sectors * Total \ 1024 \ 1024 注释:总空间,以 MB 为单位
WisMB = TotalMB - FreeMB 注释:已用空间,以 MB 为单位

(7)如何读取文件的创建时间、访问时间?
如果我们利用 VB 所提供的 FileDateTime 来读取文件时间,则所得到的是文件最后一次被修改的时间,但是当我们利用资源管理器来检查某一个文件时,除了文件"修改时间"之外,却还可看到文件的"创建时间"与"访问时间"。
想要进一步读取文件的相关信息,必须先调用 API 函数的 OpenFile 取得文件的 Handle ,然后再利用 Handle 调用 GetFileInformationByHandle 读取文件的相关信息,而所读取文件相关消息中便含有文件建立、修改及访问时间。
程序代码如下:
Module1.bas(这些都是一些常量的声明,大家可查看 WinAPI 32
Option Explicit
Public Const OFS_MAXPATHNAME = 128
Public Const OF_READ = &H0

Declare Function OpenFile Lib "kernel32" (ByVal lpFileName As String, lpReOpenBuff As OFSTRUCT, ByVal wStyle As Long) As Long 注释:建立、打开或删除文件
Declare Function GetFileInformationByHandle Lib "kernel32" (ByVal hFile As Long, lpFileInformation As BY_HANDLE_FILE_INFORMATION) As Long 注释:返回文件信息
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long 注释:关闭打开的对象句柄
Declare Function GetTimeZoneInformation Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long 注释:返回当前时区信息
Declare Function FileTimeToSystemTime Lib "kernel32" (lpFileTime As FileTime, lpSystemTime As SYSTEMTIME) As Long 注释:将64位时间转换为系统时间

Type FileTime
    dwLowDateTime As Long
    dwHighDateTime As Long
End Type

Type OFSTRUCT
    cBytes As Byte
    fFixedDisk As Byte
    nErrCode As Integer
    Reserved1 As Integer
    Reserved2 As Integer
    szPathName(OFS_MAXPATHNAME) As Byte
End Type

Type BY_HANDLE_FILE_INFORMATION
    dwFileAttributes As Long
    ftCreationTime As FileTime
    ftLastAccessTime As FileTime
    ftLastWriteTime As FileTime
    dwVolumeSerialNumber As Long
    nFileSizeHigh As Long
    nFileSizeLow As Long
    nNumberOfLinks As Long
    nFileIndexHigh As Long
    nFileIndexLow As Long
End Type

Type SYSTEMTIME
    wYear As Integer
    wMonth As Integer
    wDayOfWeek As Integer
    wDay As Integer
    wHour As Integer
    wMinute As Integer
    wSecond As Integer
    wMilliseconds As Integer
End Type

Type TIME_ZONE_INFORMATION
    bias As Long
    StandardName(32) As Integer
    StandardDate As SYSTEMTIME
    StandardBias As Long
    DaylightName(32) As Integer
    DaylightDate As SYSTEMTIME
    DaylightBias As Long
End Type
注释:取得文件的创建时间、访问时间的子程序
Sub apiFileDateTime(ByVal PathName As String, dtCreate As Date, dtAccess As Date, dtWrite As Date)

Dim FileHandle As Long
Dim FileInfo As BY_HANDLE_FILE_INFORMATION
Dim lpReOpenBuff As OFSTRUCT, ft As SYSTEMTIME
Dim tZone As TIME_ZONE_INFORMATION
Dim bias As Long

FileHandle = OpenFile(PathName, lpReOpenBuff, OF_READ)

GetFileInformationByHandle FileHandle, FileInfo
CloseHandle FileHandle

GetTimeZoneInformation tZone
bias = tZone.bias

FileTimeToSystemTime FileInfo.ftCreationTime, ft
dtCreate = DateSerial(ft.wYear, ft.wMonth, ft.wDay) + _
           TimeSerial(ft.wHour, ft.wMinute - bias, ft.wSecond)

FileTimeToSystemTime FileInfo.ftLastAccessTime, ft
dtAccess = DateSerial(ft.wYear, ft.wMonth, ft.wDay) + _
           TimeSerial(ft.wHour, ft.wMinute - bias, ft.wSecond)

FileTimeToSystemTime FileInfo.ftLastWriteTime, ft
dtWrite = DateSerial(ft.wYear, ft.wMonth, ft.wDay) + _
          TimeSerial(ft.wHour, ft.wMinute - bias, ft.wSecond)
End Sub

例子:
Dim dtCreate As Date 注释:建立时间
Dim dtAccess As Date 注释:存取日期
Dim dtWrite As Date 注释:修改时间

apiFileDateTime "c:\autoexec.bat", dtCreate, dtAccess, dtWrite
Debug.Print dtCreate
Debug.Print dtAccess
Debug.Print dtWrite

补充:由于这个技巧涉及多个 API 函数,每个 API 函数除这个例子说的外,还有许多其他的功能,希望大家能够自己理解。

(8)如何建立快捷方式 ?
(9)如何解读快捷方式(.lnk)中的消息 ?
这两个问题,都可以在 VB 的光盘中找到解答,使用"查找"功能,可以在光盘之中找到 Shelllnk 目录(注:VB5 与 VB6 的光盘中都含有这个目录,但路径略有不同),找到这个目录之后,打开其中的 Shelllnk.vbp 工程,然后将它编译成 Shelllnk.dll,接着我们便可以利用 Shelllnk.dll 所提供的对象来解读快捷方式中的消息 ,也可以建立快捷方式。(注:Shelllnk.dll 是一个 ActiveX DLL 文件)
引用 Shelllnk 之中的对象
编译好 Shelllnk.dll 之后,你可以关闭 Shelllnk.vbp 工程,接下来打开另一个程序来引用 Shelllnk.dll 之中的对象,引用的方法是选取菜单的"工程/引用",然后在"引用"对话框中,选取"pShelllnk"即可以引用。
引用 "pShelllnk" 之后,接下来要利用以下语句建立一个 cShelllnk 对象:
Dim lnkObj As New cShelllnk
在 cShelllnk 对象中,我们可使用的方法如下:
CreateShellLink:用来建立快捷方式。
GetShellLinkInfo:用来读取快捷方式中的消息。
GetSystemFolderPath:用来读取特殊文件夹的所在目录。
使用 GetShellLinkInfo 方法
GetShellLinkInfo 含有以下几个参数:
LnkFile:传入 .lnk 快捷方式。
ExeFile:返回快捷方式之中所定义的执行文件。
WorkDir:返回快捷方式之中所定义的工作目录。
ExeArgs:返回快捷方式之中所定义的执行文件参数。
IconFile:返回快捷方式之中所定义的图标来源文件。
IconIdx:返回快捷方式之中所定义的图标来源文件之索引。
ShowCmd:返回快捷方式之中所定义的窗口显示方式。
示例如下:
Dim lnkObj As New cShellLink
Dim ExeFile As String, WorkDir As String, ExeArgs As String
Dim IconFile As String, IconIdx As Long, ShowCmd As Long

lnkObj.GetShellLinkInfo "d:\NetCaptor 6.0.lnk", ExeFile,WorkDir, ExeArgs, IconFile, IconIdx, ShowCmd  
注释:读取"d:\NetCaptor 6.0.lnk"的信息,假设以存在
    Print "Exefile = ", ExeFile   注释:目标位置
    Print "WorkDir = ", WorkDir 注释:起始位置
    Print "ExeArgs = ", ExeArgs
    Print "IconFile = ", IconFile  注释:图标文件
    Print "IconIdx = ", IconIdx  注释:图标索引
    Print "ShowCmd = ", ShowCmd 注释:运行方式
使用 CreateShellLink 方法
CreateShellLink 的参数跟 GetShellLinkInfo 完全相同,利用 CreateShellLink 方法来建立快捷方式的例子如下:
Dim lnkObj As New cShellLink
Dim ExeFile As String, WorkDir As String, ExeArgs As String
Dim IconFile As String, IconIdx As Long, ShowCmd As Long

注释:先设置 ExeFile、WorkDir 等参数值
lnkObj.CreateShellLink 欲建立快捷方式的完整路径名,ExeFile,WorkDir, ExeArgs, IconFile, IconIdx, ShowCmd  

(10)快速建立目录
如果你想建立"c:\vb\code\"这样的目录,你会怎么办呢?
VB 本身的函数 MkDir 只提建立单个目录的功能,如果你用 MkDir "c:\vb\code\" 将会得到"路径未找到"的提高错误,这时你只有借助 API 函数来完成"快速建立目录"的操作。
API 函数:CreateDirectory
声明函数及相关变是量:
Private Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type
Private Declare Function CreateDirectory Lib "kernel32" Alias "CreateDirectoryA" (ByVal lpPathName As String, lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long
定义子程序(以后只要用这个子程序就能随便建立多级子目录了)
Sub CreateNewDirectory(NewDirectory As String)
Dim sDirTest As String
Dim SecAttrib As SECURITY_ATTRIBUTES
Dim bSuccess As Boolean
Dim sPath As String
Dim iCounter As Integer
Dim sTempDir As String
Dim iFlag As Integer
iFlag = 0
sPath = NewDirectory 注释:等于子程序取得的目录
If Right(sPath, Len(sPath)) <> "\" Then 注释:判断,如果最右边的字符不为"\",则加上
sPath = sPath & "\"
End If
iCounter = 1
Do Until InStr(iCounter, sPath, "\") = 0 注释:循环,如果再没有找到"\"则退出循环
iCounter = InStr(iCounter, sPath, "\") 注释:取得"\"出现的位置
sTempDir = Left(sPath, iCounter) 注释:取得"\"前面的字符
sDirTest = Dir(sTempDir) 注释:检查目录是否存在
iCounter = iCounter + 1
注释:create directory
SecAttrib.lpSecurityDescriptor = &O0
SecAttrib.bInheritHandle = False
SecAttrib.nLength = Len(SecAttrib)
bSuccess = CreateDirectory(sTempDir, SecAttrib) 注释:建立目录
Loop
End Sub
快速建立目录
CreateNewDirectory ("c:\vb\code\")

(11)打开文件的属性窗口
在 VB 中没有提供"打开文件属性窗口"的函数,不过可以通过调用 API 函数"ShellExecuteEX "来完成。
Module1.bas
注释:声明 API 函数
Type SHELLEXECUTEINFO 注释:这可以VB自代的API帮助中找到
cbSize As Long
fMask As Long
hwnd As Long
lpVerb As String
lpFile As String
lpParameters As String
lpDirectory As String
nShow As Long
hInstApp As Long
lpIDList As Long
lpClass As String
hkeyClass As Long
dwHotKey As Long
hIcon As Long
hProcess As Long
End Type

Public Const SEE_MASK_INVOKEIDLIST = &HC
Public Const SEE_MASK_NOCLOSEPROCESS = &H40
Public Const SEE_MASK_FLAG_NO_UI = &H400

Declare Function ShellExecuteEX Lib "shell32.dll" Alias _
"ShellExecuteEx" (SEI As SHELLEXECUTEINFO) As Long

注释:定义子程序
Public Sub ShowProps(FileName As String, OwnerhWnd As Long)
Dim SEI As SHELLEXECUTEINFO
Dim r As Long
With SEI
.cbSize = Len(SEI)
.fMask = SEE_MASK_NOCLOSEPROCESS Or _
SEE_MASK_INVOKEIDLIST Or SEE_MASK_FLAG_NO_UI
.hwnd = OwnerhWnd
.lpVerb = "properties"
.lpFile = FileName
.lpParameters = vbNullChar
.lpDirectory = vbNullChar
.nShow = 0
.hInstApp = 0
.lpIDList = 0
End With
r = ShellExecuteEX(SEI)
End Sub
注释:调用窗口
ShowProps "c:\command.com", Me.hwnd
(12)激活文件目录对话窗口
文件目录对话框如图所示,这个对话框在 VB 编中经常用到,可是 VB 却没有调用它的函数,只有通过下面 API 函数来完成相关操作。

声明 API 函数
Declare Function SHBrowseForFolder Lib "shell32.dll" Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long 注释:ITEMIDLIST
Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long

Public Type BROWSEINFO
    hOwner As Long
    pidlRoot As Long
    pszDisplayName As String
    lpszTitle As String
    ulFlags As Long
    lpfn As Long
    lParam As Long
    iImage As Long
End Type
注释:定义子程序
Sub BrowDir()
Dim bi As BROWSEINFO
Dim pidl&, rtn&, path$, pos%
pidl& = SHBrowseForFolder(bi)
    path$ = Space$(512)
    rtn& = SHGetPathFromIDList(ByVal pidl&, ByVal path$)
    If rtn& Then
      pos% = InStr(path$, Chr$(0))
      MyPath = Left(path$, pos - 1)
    End If
End Sub

好的到现在为此上面所列出的技巧已全部讲完了,希望对大家有帮助呀!!