您的位置:寻梦网首页编程乐园VB 编程乐园VB问题全功略

VB问题全功略(44)

上一页(44)下一页

216、如何读取 INI 文件的资料?
217、如何删除整个 Access 资料库内的资料?
218、如何在鼠标经过 Label 上方时改变 Label 的颜色?
219、如何对ListView中的列排序
220、如何自动出现动画、进度和确认的文件操作

216、如何读取 INI 文件的资料?

在本网站中很少提到有关 INI 文件的存取问题,因为我认为现在 Windows 已经将大部份的资料都写到注册文件中了,虽然 Windows 95/98 还有在使用 INI 文件,但是在 NT 中则已经不使用了!我猜将来 Windows 2000 应该也不会使用才对!不过,尽管如此,目前还是有人在使用,我们就分几次来说说!

读取 INI 文件的 API 有分二套,一套是专门用来读取 Win.ini 文件的,一套是用来读取所有 INI 文件的 ( 当然也包含 Win.ini 文件 ),而这二套的差别只在于读取所有 INI 文件的 API 在使用时必须多传入一个参数,用来指定 INI 文件的名称及路径。

想要存取 INI 文件,要先了解 INI 文件的结构,如下:

[Section1] 'Section Name
Key1=Content1 '=前面是 Key,=后面是 Key 的内容
Key2=Content2
Key3=Content3
:
[Section2]
Key1=Content1
Key2=Content2
Key3=Content3
::

'以下是用来读取所有 INI 文件的 API ( 适用于所有的ini 文件,包含 Win.ini 文件 )

'读取 INI 中的数值资料
Declare Function GetPrivateProfileInt Lib "kernel32" Alias "GetPrivateProfileIntA" _
(ByVal lpApplicationName As String, _ 'Section Name
ByVal lpKeyName As String, _ 'Key
ByVal nDefault As Long, _ 'Key 的内容,若无法读取则返回 Default 值
ByVal lpFileName As String) As Long 'INI 文件的名称及路径

'读取 INI 中的字串资料
Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" _
(ByVal lpApplicationName As String, _ '若是传入 vbNullString,则返回所有的 Section 名称
ByVal lpKeyName As Any, _ '若是传入 vbNullString,则返回所有的 Key 名称
ByVal lpDefault As String, _ 'Key 的内容Default 值
ByVal lpReturnedString As String, _ '若无法读取则返回第三个参数 Default 值
ByVal nSize As Long, _ '返回值的长度
ByVal lpFileName As String) As Long

'读取某一个 Section 之所有资料
Declare Function GetPrivateProfileSection Lib "kernel32" Alias "GetPrivateProfileSectionA" _
(ByVal lpAppName As String, _
ByVal lpReturnedString As String, _ '返回值中各行资料以 chr(0) 分开
ByVal nSize As Long, _ '返回值的长度
ByVal lpFileName As String) As Long

'以下是专门用来读取 Win.ini 文件的 API ( 只适用于 Win.ini 文件 )

'读取 Win.ini 中的数值资料
Declare Function GetProfileInt Lib "kernel32" Alias "GetProfileIntA" _
(ByVal lpAppName As String, _ 'Section Name
ByVal lpKeyName As String, _ 'Key
ByVal nDefault As Long) As Long 'Key 的内容

'读取 Win.ini 中的字串资料
Declare Function GetProfileString Lib "kernel32" Alias "GetProfileStringA" (ByVal lpAppName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long) As Long

'读取 Win.ini 某一个 Section 之所有资料
Declare Function GetProfileSection Lib "kernel32" Alias "GetProfileSectionA" (ByVal lpAppName As String, ByVal lpReturnedString As String, ByVal nSize As Long) As Long

由于读取所有 INI 文件的 API 也适用于 Win.ini 文件,所以我们将以读取所有 INI 文件的 API 来实作范例,在这个例子中,我们提供的功能有:

1、可以选择不同的目录
2、开启某一个目录后,可以选择开启任何一个 INI 文件
3、开启任一个 INI 文件后,可以选择想要浏览的 Section
4、读入某一个 Section 后,可以查阅每一个 Key 的详细内容

而在这个练习中,除了读取 INI 文件的 API 之外,我们也用到了以前提到的一些技巧,如下:

问题: 如何用 VB 呼叫出在【寻找:所有文件】中的【浏览资料夹】问话框?
问题: 如何找出 Windows / System / Temp 目录的正确路径? (二)
问题: 如何一次读取整个文件的内容?
问题: 按下 CommandButton 之前后,如何让光标停留在同一个物件中?
问题: 您用过【符号字型】吗?

注:网友 琏琏 提到,上面这些处理 INI 文件的 API,只能处理文件前 64 k 的资料!

注:不过我个人认为,如果资料量真的很大时,倒可以考虑一下改用资料库来处理!

217、如何删除整个 Access 资料库内的资料?

当一个资料库用了一阵子之后,您可能必须清除资料库中所有的资料,例如:我在开发一个新系统时,使用一个 Access 资料库, 面可能有二、三十个 Table,中间经过系统的测试,系统完成后,准备系统上线时,必须将所有的测试资料删除!

当然,要完成这件事情有很多种作法,例如:

1、在 Access 中逐一开启所有资料库的每一个 Table → 选取所有资料 → 删除。
2、在 Access 开启一个新资料库 → Import 原资料库的所有 Table (只有 Structure)。
3、写一段 VB 小程序去删除所有资料!

前二种作法是人工的作法,当 Table 越多时就越烦琐,不在我们讨论之列,至于第三种作法,我已经写了一个小小的模组,您只要传入资料库的名称、路径就可以自动帮您完成了! 程序码如下:

Function DeleteAllRecords(ByVal dbpath As String)
Dim db As Database
Dim X As Integer
Dim TDF As TableDef

Set db = opendatabase(dbpath)
For X = 0 To db.TableDefs.Count - 1
Set TDF = db.TableDefs(X)
If (TDF.Attributes And dbSystemObject) = 0 Then '避开系统的 Table
db.Execute "Delete * From [" & db.TableDefs(X).Name & "]"
End If
Next X
End Function
在 Access 资料库中,除了您自己建立的 Table 之外,还隐藏了一些系统的 Table,判断 dbSystemObject 就是为了要避开这些系统的 Table。

程序中实际使用时,方法如下:

Private Sub Command1_Click()
DeleteAllRecords "c:\Test.mdb" 'c:\Test.mdb 要转换成您自己的资料库
End Sub
注:Access 资料库有个缺点,当您写资料进去时,文件会变大,但是删除资料库中的资料后,资料库文件并不会变小,所以,如果您使用以上的程序来清空 Access 资料库内的资料后,原来已经 10MB 的资料库,处理完之后文件大小仍然还是 10MB!

注:建议在清空资料库中之资料后,再使用 CompactDataBase 来处理,它会将您的资料库再还原成只有几十k 或几百k 的大小。CompactDataBase 之语法如下:

DBEngine.CompactDataBase "原资料库文件名", "新资料库文件名", , , ";pwd=密码"
实例例如:
DBEngine.CompactDatabase "C:\Db1.mdb", "C:\Db2.mdb", , , ";pwd=1"

218、如何在鼠标经过 Label 上方时改变 Label 的颜色?

在我的网站中,当您的鼠标经过每一个连结时,连结的颜色 (ForeColor) 及底色 (BackColor) 都会改变,这是使用 CSS (Cascading Style Sheets) 的语法所营造出来的效果!我感觉很棒,很醒目,不知道各位感觉如何?

您是否想过在您使用 VB 开发的系统中,也可以使用这个技巧?

一般我们都是使用 Menu 选单来让使用者执行程序,当然很好。不过有的系统不是很大,没有几支程序,若是使用 Menu 选单的话,主程序会略显单薄,这时候我都是使用 Label 来当作程序选单,可以将字型稍微放大,例如 28 或 36,但若只是使用标准的 Label 功能的话,使用者 Click 之后会不知道是否已按下 Label 选单,但若是当鼠标经过每一个 Label 选单时,我们将颜色改变,鼠标离开 Label 选单后,我们再将颜色还原回来,效果就很好了!

以下的范例中,我们在表单中放进二个 Label 当作程序选单,您也可以多放几个效果更好!

将以下的程序码全部复制到表单中:

Dim MyFocusColor, MyNormalColor '声明鼠标经过每一个 Label 选单及离开 Label 选单之颜色变数
Dim Lbl As Label

Sub ChangeColor(Lbl As Label) '模组:鼠标经过每一个 Label 选单时变更颜色
If Lbl.ForeColor <> MyFocusColor Then
Lbl.ForeColor = MyFocusColor
End If
End Sub

Private Sub Form_Load()
MyNormalColor = QBColor(0) '黑色:每一个 Label 平时的颜色 / 离开 Label 选单之颜色
MyFocusColor = QBColor(15) '白色:声明鼠标经过每一个 Label 选单之颜色
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim i As Integer
For Each i In Me.Controls
If TypeOf i Is Label Then '鼠标离开 Label 选单后将颜色还原
If i.ForeColor <> MyNormalColor Then
i.ForeColor = MyNormalColor
End If
End If
Next i
End Sub

Private Sub Label1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Call ChangeColor(Label1)
End Sub

Private Sub Label2_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Call ChangeColor(Label2)
End Sub

 : '若您使用二个以上的 Label 时,类推。
 :
感觉如何?还不错吧

219、如何对ListView中的列排序

设置 ListView 控件到 report 视图。下面的代码允许你使用
任何的列进行排序,主要在列头上点击。
如果已经排序,顺序将反一下。

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As ColumnHeader)
With ListView1
If (ColumnHeader.Index - 1) = .SortKey Then
.SortOrder = (.SortOrder + 1) Mod 2
Else
.Sorted = False
.SortOrder = 0
.SortKey = ColumnHeader.Index - 1
.Sorted = True
End If
End With
End Sub

220、如何自动出现动画、进度和确认的文件操作

使用以下的 API , 得到与资源管理器相同的感觉!
Private Type SHFILEOPSTRUCT
hwnd As Long
wFunc As Long
pFrom As String
pTo As String
fFlags As Integer
fAnyOperationsAborted As Long
hNameMappings As Long
lpszProgressTitle As String '只有在 FOF_SIMPLEPROGRESS 时用
End Type

Private Declare Function SHFileOperation Lib "shell32.dll" Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long

'wFunc 常数
'FO_COPY 把 pFrom 文件拷贝到 pTo。
Const FO_COPY = &H2
'FO_DELETE 删除 pFrom 中的文件(pTo 忽略)。
Const FO_DELETE = &H3
'FO_MOVE 把 pFrom 文件移动到 pTo。
Const FO_MOVE = &H1

'fFlag 常数
'FOF_ALLOWUNDO 允许 Undo 。
Const FOF_ALLOWUNDO = &H40
'FOF_NOCONFIRMATION 不显示系统确认对话框。
Const FOF_NOCONFIRMATION = &H10
'FOF_NOCONFIRMMKDIR 不提示是否新建目录。
Const FOF_NOCONFIRMMKDIR = &H200
'FOF_SILENT 不显示进度对话框
Const FOF_SILENT = &H4

例子:
Dim SHFileOp As SHFILEOPSTRUCT
' 删除
SHFileOp.wFunc = FO_DELETE
SHFileOp.pFrom = "c:\config.old" + Chr(0)
SHFileOp.fFlags = FOF_ALLOWUNDO + FOF_NOCONFIRMATION
Call SHFileOperation(SHFileOp)
' 删除多个文件
SHFileOp.wFunc = FO_DELETE
SHFileOp.pFrom = "c:\config.old" +Chr(0) + "c:\autoexec.old"+Chr(0)
SHFileOp.fFlags = FOF_ALLOWUNDO
Call SHFileOperation(SHFileOp)
' 拷贝
SHFileOp.wFunc = FO_COPY
SHFileOp.pFrom = "c:\t\*.*"
SHFileOp.pTo = "d:\t\*.*"
SHFileOp.fFlags = FOF_ALLOWUNDO + FOF_NOCONFIRMMKDIR
Call SHFileOperation(SHFileOp)
' 移动
SHFileOp.wFunc = FO_MOVE
SHFileOp.pFrom = "c:\config.old" + Chr(0)
SHFileOp.pTo = "d:\t"
SHFileOp.fFlags = FOF_ALLOWUNDO + FOF_NOCONFIRMATION
Call SHFileOperation(SHFileOp)

上一页(44)下一页