VB使用大全 - 14

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)

221、如何判断目前文件资源管理器中,文件名称之扩展文件名是显示或隐藏?

由于我在集团性的资讯处工作,所负责的公司系统有的是属于外点,例如润泰建设有个单位是行销业务处,他们的工作是卖公司盖的房子,所以他们的业务人员平常都是待在各工地的接待中心,我替他们开发的销售系统在工地的部份是属于单机作业的,使用 Access 资料库,每一个星期资料回传总公司一次。

业务人员由于流动性大,不太了解系统,有时候,系统出了问题,业务人员又搞不清楚状况,于是我会要求他们将资料库 sale.mdb 回传公司,结果,常闹笑话,原来他们回传公司的,常常不是 sale.ldb 就是 sale.exe,为什么呢?

原因很简单,因为他们的文件资源管理器中,设定了将扩展文件名隐藏起来,结果只看到三个不同图示的 sale 文件 (分别是 Sale.mdb、Sale.ldb、Sale.exe),不太会操作的业务人员根本分不清楚那一个图示的 sale 文件才是资料库文件案!

我们在 VB 的程序中要如何判断,目前文件资源管理器中的设定是否显示扩展文件名呢?
Private Declare Function GetFileTitle Lib "comdlg32.dll" Alias "GetFileTitleA" (ByVal lpszFile As String, ByVal lpszTitle As String, ByVal cbBuf As Integer) As Integer
Private Function HasExtension(sFileName As String) As Long
Dim sTemp As String
Dim lTemp As Long
sTemp = String(1, 0)
lTemp = GetFileTitle(sFileName, sTemp, Len(sTemp))
If lTemp < 0 Then HasExtension = -1: Exit Function
sTemp = String(lTemp, 0)
Call GetFileTitle(sFileName, sTemp, Len(sTemp))

If (Left$(Right$(Left$(sTemp, lTemp - 1), 4), 1)) = "." Then
HasExtension = 1
Else
HasExtension = 0
End If
End Function
若有显示扩展文件名,返回值是 1,否则返回0。

222、如何判断某一个公立年是否为润年?

这是一个很简单的问题,只要知道公式,就可以了!

润年公式如下:

若公立年可以被 4 整除, 则很有可能为公立年, 除非..
这个公立年可以被 100 整除, 但是不可以被 400 整除, 就不是润年

测试程序及模组如下:

Public Function IsLeapYear(Yr As Integer) As Boolean
'设定预设返回值为 False
IsLeapYear = False
'若公立年可以被 4 整除, 则很有可能为公立年, 除非..
'这个公立年可以被 100 整除, 但是不可以被 400 整除, 就不是润年
If Yr Mod 4 = 0 Then
IsLeapYear = True
If Yr Mod 100 = 0 Then
If (Yr Mod 400) Then IsLeapYear = False
End If
End If
End Function

'在表单中放一个 CommandButton 及一个 TextBox

Private Sub Command1_Click()
If IsLeapYear(Text1.Text) Then
MsgBox "公立" & Text1.Text & "年 是 润年", 64, "是"
Else
MsgBox "公立" & Text1.Text & "年 不是 润年", 64, "不是"
End If

223、如何取得某个数值范围间的随机值?

要取得随机值会用到 Randomize 陈述式及 Rnd 函数,先说明如下: 《取材自 Msdn》

──────────────────────────────────
Randomize 陈述式:初始化随机产生器。语法如下:
Randomize [number]
选择性引数 number 可以是一型态为 Variant 的值或任何数值运算式。

Randomize 使用 number 的值当成新的随机种子来起始随机产生器,若要得到一随机值,则可呼叫 Rnd 函数。如果省略 number,则会以作业系统现在时间来当做新的随机种子。

如果没有呼叫 Randomize 来起始随机产生器,Rnd 函数 (没有引数) 则使用上次呼叫 Rnd 函数所得的随机值当做新的随机种子。
──────────────────────────────────
Rnd 函数:返回一型态为 Single 的值,其内容为一随机值。语法如下:
Rnd [(number)]
选择性引数 number 可以是一型态为 Single 的值,或任何数值运算式。

Rnd 函数返回的随机值介于 0 和 1 之间,可等于 0,但不等于 1。若想产生在某个范围内(非 0 到 1)的随机值,可使用下列公式:

Int((upperbound - lowerbound + 1) * Rnd + lowerbound)

上述公式中,upperbound 是随机范围的上限,而 lowerbound 则是随机的下限。
──────────────────────────────────

好了,理论说完了,希望您还清醒,来说今天的主题吧!下面的 Random_Number 是完成的模组:

Function Random_Number(ByVal UpperBound As Long, ByVal LowerBound As Long) As Long
Randomize
Random_Number = Int((UpperBound - LowerBound + 1) * Rnd + LowerBound)
End Function

'在程序中实际使用的方式如下:

Private Sub Command1_Click()
Dim MyNum As Long
'取得 1-100 的随机值
MyNum = Random_Number(100, 1)
Msgbox MyNum
End Sub
注意:或许看上面的理论说明,有一点您还是不很清楚,不过我要再强调一次:

若是您省略掉 Randomize 这个陈述式,而直接使用 Rnd 函数,则当您重复执行程序取随机的功能时,例如一些掷色子的游戏,您每次都会到相同的随机,例如上面的例子,省略掉 Randomize 这个陈述式之后,测试三次结果如下: 《完全相同》

第一次:71,54,58,29,31,78,2,77,82,71,5.....
第二次:71,54,58,29,31,78,2,77,82,71,5.....
第三次:71,54,58,29,31,78,2,77,82,71,5.....


224、如何建立磁盘 / 目录的共享 (Share)?

在【文件资源管理器】或【我的电脑】中,我们都可以直接在磁盘或目录上按滑鼠右键,选【属性】,在【共享】页中设定磁盘或目录的共享,如图:


我在集团的资讯部门工作,要处理一二十家以上的公司系统,在正常的状况下,为了方便,我们在机器交给使用者使用时,会替他们将某个磁盘或某个目录设定可以共享,但是并不是每个使用者都喜欢开放自己的电脑让别人存取,于是他们便会将共享的功能取消,造成资讯人员些许不方便。

这时候,也不必和使用者争得脸红脖子粗的,反正山不转路转,我们就不知不觉地,让使用者自己在莫名其妙的情形下,按照您的意思,在某个磁盘或某个目录设定您想要设定的共享,然后又神不知鬼不觉地取消共享!

要怎么做呢?其实很简单,就是将设定/取消共享的功能写在 VB 程序中,像人事差勤系统是每个使用者都要使用的系统,我们就在这些系统的 VB 程序中,去设定/取消共享!而且使用者完全没有感觉!

下面这个模组文件中 (.bas文件) 已经有完整的声明及完成的二个模组,只要呼叫这二个模组,就可以建立/取消磁盘或目录的资料分享:
这二个模组说明如下:
Public Function CreateShare _ ' 建立共享模组
(ByVal sSharePath As String, _ ' 完整路径
ByVal sShareName As String, _ ' 共享名称
ByVal sRemark As String, _ ' 说明
ByVal sROPass As String, _ ' 只读密码
ByVal sRWPass As String) As Long ' 完整存取密码

Public Function DeleteShare _ ' 取消共享模组
(ByVal sShareName As String) As Long ' 共享名称

呼叫范例如下:

Private Sub Command1_Click()
' 建立共享 CDISK
CreateShare "C:\", "CDISK", "小纪的 C 磁盘", "JWHR", "JWHRW"
End Sub

Private Sub Command2_Click()
' 取消共享 CDISK
DeleteShare "CDISK"
End Sub
注:就像一般教人家做坏事的书或电视节目一样,我也要声明一下:
注:以上方式请用于正途 (系统需要),请勿使用以上方法来不当窃取不该看的文件!

225、如何快速建立目录

声明:
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
函数:
'Call CreateNewDirectory("c:\test\directory\vb\tips\")
Public 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
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

226、如何知道您的机器中预设打印机的机型、驱动程序及连接端口?(二)

在 问题: 如何知道您的机器中预设打印机的机型、驱动程序及连接端口 中我们曾经提过使用 GetProfileString API 到 Win.ini 文件中抓取这些资料,其实如果不使用 API,我们还是可以使用 Printer 物件很轻易的就得到我们要的资料!

Printer 物件有很多个属性,其中三个是:

DeviceName:返回驱动程序支持的周边设备名称。
DriverName:返回 Printer 物件的驱动程序名称。
Port:返回连接端口。

使用实例如下:

Private Sub Command1_Click()
Debug.Print Printer.DeviceName
Debug.Print Printer.DriverName
Debug.Print Printer.Port
End Sub
Printer 物件还有很多好用的属性及方法,例如设定打印机的打印方向 (Orientation)、纸张大小 (PaperSize)、打印份数 (Copies)、打印品质 (PrintQuality)、放大缩小 (Zoom)...等,大家可以自行到线上手册或 Msdn 上查询!

227、如何在程序中更改预设的打印机?

在上一个单元中,我们使用 Printer 物件来取得机器中预设打印机的机型、驱动程序及连接端口,那是否可以更改预设打印机呢?可以的,不过除了 Printer 物件之外,这次我们要多用一个 Printers 集合物件!

先来看一段程序码:

Private Sub Form_Load()
'利用 Printers 集合物件取得所有打印机
For i = 0 To Printers.Count - 1
'在 Combo1 中依序加入打印机名称
Combo1.AddItem Printers(i).DeviceName
Next
'将目前的预设打印机放在 Combo1.Text 中
Combo1.Text = Printer.DeviceName
End Sub

Private Sub Command1_Click()
'未选择
If Combo1.ListIndex = -1 Then
MsgBox "打印机未更改,请先选择打印机!"
Exit Sub
End If
'使用者选定之打印机设定为预设打印机
Set Printer = Printers(Combo1.listindex)
End Sub
在这一段程序中,我们在 Form_Load 中先利用 Printers 集合物件找出所有的打印机名称,放在 Combo1 中,记得 Combo1 不可将 Sorted 设成 True,这样子的话,Combo1 的索引值 (Index) 便会和 Printers 集合物件的索引值 (Index) 相同!

使用者在 Combo1 中选定打印机后,在 Command1_Click 中,我们便可以将 Combo1 的索引值带入Printers 集合物件的索引值,重新设定新的预设打印机。

这样子的设定只有在程序中有效,程序结束后,预设打印机会恢复成原来的预设打印机!

228、如何读取及设定 NumLock / CapsLock / ScrollLock 的值?

若只是要取得这三个按键 (NumLock / CapsLock / ScrollLock) 的状态,只要呼叫 GetKeyState API 就可以了!
若是要设定这三个按键的状态,则要呼叫 GetKeyboardState 及 SetKeyboardState 二个 API!

在表单的声明区中,加入以下的声明及模组:

Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Private Declare Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long
Private Declare Function SetKeyboardState Lib "user32" (lppbKeyState As Byte) As Long

Private Sub SetKeyState(intKey As Integer, fTurnOn As Boolean)
'取得键盘目前的状态,设定您想设定的任意键,再将其他键还成之前的状态,只改变一个键值
Dim abytBuffer(0 To 255) As Byte
GetKeyboardState abytBuffer(0)
abytBuffer(intKey) = CByte(Abs(fTurnOn))
SetKeyboardState abytBuffer(0)
End Sub

Function GetCapslock() As Boolean
'返回 Capslock 的状态
GetCapslock = CBool(GetKeyState(vbKeyCapital) And 1)
End Function

Function GetNumlock() As Boolean
'返回 Numlock 的状态
GetNumlock = CBool(GetKeyState(vbKeyNumlock) And 1)
End Function

Function GetScrollLock() As Boolean
'返回 ScrollLock 的状态
GetScrollLock = CBool(GetKeyState(vbKeyScrollLock) And 1)
End Function

Sub SetCapslock(Value As Boolean)
'设定 Capslock 的状态
Call SetKeyState(vbKeyCapital, Value)
End Sub

Sub SetNumlock(Value As Boolean)
'设定 Numlock 的状态
Call SetKeyState(vbKeyNumlock, Value)
End Sub

Sub SetScrollLock(Value As Boolean)
'设定 ScrollLock 的状态
Call SetKeyState(vbKeyScrollLock, Value)
End Sub
实际运用的方式如下:

Private Sub Command1_Click()
SetScrollLock True ' 设定 ScrollLock 为 On
End Sub

Private Sub Command2_Click()
MsgBox "ScrollLock:" & GetScrollLock ' 取得 ScrollLock 状态
End Sub

229、如何在 Windows95/98 中如何自动结束由 Shell 启动之 DOS 视窗?

以前,在 Windows 3.1、Windows for Workgroups 3.11 及 Windows NT 3.51 中,当您从 VB 程序中使用 Shell 去启动一个 Batch 文件或 MS-DOS 程序,当 Batch 文件或 MS-DOS 程序结束后,会自动关闭 DOS 视窗。

但是,到了 Windows 95/98 之后,自动关闭的功能不见了,所以当您使用 Shell 去启动一个 Batch 文件或 MS-DOS 程序之后,总是会留下一个 DOS 视窗在工作列中,还要使用者自己去将这个 DOS 视窗关闭。

要避免这种情形发生,其实很简单,只要在您原来执行的 Shell 指令中加上 "/C" 就可以了!语法如下:

h = Shell("COMMAND.COM /C <pathname>")

加上 "/C" 之后,在 Windows 95/98 中 DOS 视窗便会自动关闭,而在 在 Windows 3.1、Windows for Workgroups 3.11 及 Windows NT 3.51 中也不会有问题产生!

看个实例吧:

Private Sub Command1_Click()
h = Shell("COMMAND.COM /C c:\windows\command\edit.com")
End Sub
当您结束 Edit.com 时,DOS 视窗便会自动关闭!

230、如何开启文件属性窗口

声明:
Type SHELLEXECUTEINFO
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

代码:
' 使用: ShowProps("c:\command.com",Me.hWnd)
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

231、如何知道您的机器中预设打印机的机型、驱动程序及连接端口?(二)

在 问题: 如何知道您的机器中预设打印机的机型、驱动程序及连接端口 中我们曾经提过使用 GetProfileString API 到 Win.ini 文件中抓取这些资料,其实如果不使用 API,我们还是可以使用 Printer 物件很轻易的就得到我们要的资料!

Printer 物件有很多个属性,其中三个是:

DeviceName:返回驱动程序支持的周边设备名称。
DriverName:返回 Printer 物件的驱动程序名称。
Port:返回连接端口。

使用实例如下:

Private Sub Command1_Click()
Debug.Print Printer.DeviceName
Debug.Print Printer.DriverName
Debug.Print Printer.Port
End Sub
Printer 物件还有很多好用的属性及方法,例如设定打印机的打印方向 (Orientation)、纸张大小 (PaperSize)、打印份数 (Copies)、打印品质 (PrintQuality)、放大缩小 (Zoom)...等,大家可以自行到线上手册或 Msdn 上查询!

232、如何在程序中更改预设的打印机?

在上一个单元中,我们使用 Printer 物件来取得机器中预设打印机的机型、驱动程序及连接端口,那是否可以更改预设打印机呢?可以的,不过除了 Printer 物件之外,这次我们要多用一个 Printers 集合物件!

先来看一段程序码:

Private Sub Form_Load()
'利用 Printers 集合物件取得所有打印机
For i = 0 To Printers.Count - 1
'在 Combo1 中依序加入打印机名称
Combo1.AddItem Printers(i).DeviceName
Next
'将目前的预设打印机放在 Combo1.Text 中
Combo1.Text = Printer.DeviceName
End Sub

Private Sub Command1_Click()
'未选择
If Combo1.ListIndex = -1 Then
MsgBox "打印机未更改,请先选择打印机!"
Exit Sub
End If
'使用者选定之打印机设定为预设打印机
Set Printer = Printers(Combo1.listindex)
End Sub
在这一段程序中,我们在 Form_Load 中先利用 Printers 集合物件找出所有的打印机名称,放在 Combo1 中,记得 Combo1 不可将 Sorted 设成 True,这样子的话,Combo1 的索引值 (Index) 便会和 Printers 集合物件的索引值 (Index) 相同!
使用者在 Combo1 中选定打印机后,在 Command1_Click 中,我们便可以将 Combo1 的索引值带入Printers 集合物件的索引值,重新设定新的预设打印机。
这样子的设定只有在程序中有效,程序结束后,预设打印机会恢复成原来的预设打印机!
233、如何读取及设定 NumLock / CapsLock / ScrollLock 的值?
若只是要取得这三个按键 (NumLock / CapsLock / ScrollLock) 的状态,只要呼叫 GetKeyState API 就可以了!
若是要设定这三个按键的状态,则要呼叫 GetKeyboardState 及 SetKeyboardState 二个 API!
在表单的声明区中,加入以下的声明及模组:
Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Private Declare Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long
Private Declare Function SetKeyboardState Lib "user32" (lppbKeyState As Byte) As Long
Private Sub SetKeyState(intKey As Integer, fTurnOn As Boolean)
'取得键盘目前的状态,设定您想设定的任意键,再将其他键还成之前的状态,只改变一个键值
Dim abytBuffer(0 To 255) As Byte
GetKeyboardState abytBuffer(0)
abytBuffer(intKey) = CByte(Abs(fTurnOn))
SetKeyboardState abytBuffer(0)
End Sub

Function GetCapslock() As Boolean
'返回 Capslock 的状态
GetCapslock = CBool(GetKeyState(vbKeyCapital) And 1)
End Function

Function GetNumlock() As Boolean
'返回 Numlock 的状态
GetNumlock = CBool(GetKeyState(vbKeyNumlock) And 1)
End Function

Function GetScrollLock() As Boolean
'返回 ScrollLock 的状态
GetScrollLock = CBool(GetKeyState(vbKeyScrollLock) And 1)
End Function

Sub SetCapslock(Value As Boolean)
'设定 Capslock 的状态
Call SetKeyState(vbKeyCapital, Value)
End Sub

Sub SetNumlock(Value As Boolean)
'设定 Numlock 的状态
Call SetKeyState(vbKeyNumlock, Value)
End Sub

Sub SetScrollLock(Value As Boolean)
'设定 ScrollLock 的状态
Call SetKeyState(vbKeyScrollLock, Value)
End Sub
实际运用的方式如下:
Private Sub Command1_Click()
SetScrollLock True ' 设定 ScrollLock 为 On
End Sub
Private Sub Command2_Click()
MsgBox "ScrollLock:" & GetScrollLock ' 取得 ScrollLock 状态
End Sub
234、如何在 Windows95/98 中如何自动结束由 Shell 启动之 DOS 视窗?
以前,在 Windows 3.1、Windows for Workgroups 3.11 及 Windows NT 3.51 中,当您从 VB 程序中使用 Shell 去启动一个 Batch 文件或 MS-DOS 程序,当 Batch 文件或 MS-DOS 程序结束后,会自动关闭 DOS 视窗。
但是,到了 Windows 95/98 之后,自动关闭的功能不见了,所以当您使用 Shell 去启动一个 Batch 文件或 MS-DOS 程序之后,总是会留下一个 DOS 视窗在工作列中,还要使用者自己去将这个 DOS 视窗关闭。
要避免这种情形发生,其实很简单,只要在您原来执行的 Shell 指令中加上 "/C" 就可以了!语法如下:
h = Shell("COMMAND.COM /C <pathname>")
加上 "/C" 之后,在 Windows 95/98 中 DOS 视窗便会自动关闭,而在 在 Windows 3.1、Windows for Workgroups 3.11 及 Windows NT 3.51 中也不会有问题产生!
看个实例吧:
Private Sub Command1_Click()
h = Shell("COMMAND.COM /C c:\windows\command\edit.com")
End Sub
当您结束 Edit.com 时,DOS 视窗便会自动关闭!

235、如何使用 Windows 的选择目录对话框

声明:
Private Type BrowseInfo
hWndOwner As Long
pIDLRoot As Long
pszDisplayName As Long
lpszTitle As Long
ulFlags As Long
lpfnCallback As Long
lParam As Long
iImage As Long
End Type
Private Const BIF_RETURNONLYFSDIRS = 1
Private Const MAX_PATH = 260
Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal hMem As Long)
Private Declare Function lstrcat Lib "kernel32" Alias "lstrcatA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long
Private Declare Function SHBrowseForFolder Lib "shell32" (lpbi As BrowseInfo) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32" (ByVal pidList As Long, ByVal lpBuffer As String) As Long
函数:
Public Function BrowseForFolder(hWndOwner As Long, sPrompt As String) As String
Dim iNull As Integer
Dim lpIDList As Long
Dim lResult As Long
Dim sPath As String
Dim udtBI As BrowseInfo
With udtBI
.hWndOwner = hWndOwner
.lpszTitle = lstrcat(sPrompt, "")
.ulFlags = BIF_RETURNONLYFSDIRS
End With
lpIDList = SHBrowseForFolder(udtBI)
If lpIDList Then
sPath = String$(MAX_PATH, 0)
lResult = SHGetPathFromIDList(lpIDList, sPath)
Call CoTaskMemFree(lpIDList)
iNull = InStr(sPath, vbNullChar)
If iNull Then
sPath = Left$(sPath, iNull - 1)
End If
End If
BrowseForFolder = sPath
End Function

236、ZOrder 的迷思?
ZOrder 拆开以后就是 Z 及 Order,其意义说明如下:
Z:这里是指三度空间中的 Z 座标轴 (注一),而不是指英文字母的第 26 个字母。
Order:排列顺序。
所以 ZOrder 就是指在 Z 座标轴上的排列顺序!
ZOrder 语法如下:
object.ZOrder position
--------------------------------------------------------------------------------
object 选择性引数。物件运算式,用来指定「适用于」清单中的物件。
如果省略 object,则假设具有驻点的 Form 物件为 object。
Position 选择性引数。整数,用以指示 object 相对于同一 object 其它执行个体的位置。
如果 position 为 0 或省略,则 object 放置在 z- 顺序前面 (上方)。
如果 position 为 1,则 object 放置在 z- 顺序后面 (下方)。

--------------------------------------------------------------------------------

在设计阶段选取快显功能表中的「移至顶层」或「移至底层」功能表指令,可以设定物件的 z- 顺序。

ZOrder 用在不同的地方,有二种不同的意义:
1、用于 MDIForm 中的 Child Form 时,指的是每一个 Child Form 的上下位置关系。
2、用于每一个 Form 中的所有控制项时,指的是每一个控制项间的上下位置关系。 (注二)
注一:一般我们的二度平面座标轴是指 X 座标轴 (东西向)及 Y 座标轴 (南北向),
   二个轴构成一个平面,再加上垂直的 Z 座标轴,就构成了三度立体空间了!
   所以 ZOrder 指的就是物件在垂直的 Z 座标轴上的上下位置关系。
注二:虽然 ZOrder 指的是物件在垂直的 Z 座标轴上的上下位置关系。
   但是很多人搞不清楚,为什么他已经设定了 ZOrder 了,为什么在某些控制项中是无效的?
   原因是对单一 Form 或 单一 Container 而言,在垂直的 Z 座标轴上又分成三个层次:
   最下一层:显示图形方法结果的绘图空间。
   中间一层:用来显示图形物件(例如 Image) 和 Label 控制项。
   上面一层:显示所有非图形控制项,例如 CommandButton、CheckBox 或 ListBox。
   而 ZOrder 只对单一层次内的控制项有效而已!
   例如:您如果设定 Label 及 Image 的 ZOrder 是有效的,因为它们都在中间一层!
      您如果设定 Label 及 CommandButton 的 ZOrder 是无效的,因为它们在不同层!
   最重要的是:不管 ZOrder 如何设定,
         在上面一层的物件永远会在中间一层的物件的上方!
         在中间一层的物件永远会在最下一层的物件的上方!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值