【发布时间】:2009-10-29 18:39:10
【问题描述】:
我正在尝试遍历表单中的所有控件: 对于 Me.Controls 中的每个 ctrl 为了根据某些条件启用/禁用控制。 但是当我尝试访问它时,表单上有一个控件会给出错误。什么样的控件可以做到这一点,我如何找到它?
【问题讨论】:
标签: vb6
我正在尝试遍历表单中的所有控件: 对于 Me.Controls 中的每个 ctrl 为了根据某些条件启用/禁用控制。 但是当我尝试访问它时,表单上有一个控件会给出错误。什么样的控件可以做到这一点,我如何找到它?
【问题讨论】:
标签: vb6
当您收到错误并单击 Debug 时,错误是否在设置控件的 Enabled 属性的行上?
如果是这样,添加一个 Debug.Print 语句,写出控件的名称。在设置 Enabled 属性之前执行此操作。
这就是我的意思:
Dim ctrl As Control
For Each ctrl In Me.Controls
Debug.Print ctrl.Name
ctrl.Enabled = True
Next
Debug.Print 语句将在即时窗口中写出最后在循环中处理的控件的名称,可能是导致错误的那个。
编辑
这可能有效。将此控件放在 Panel 控件中,并将 Panel 的 Enabled 属性设置为 False。如果我没记错的话,在 VB6 中将容器控件的 Enabled 属性设置为 False 也会将容器的子控件 Enabled 设置为 False。如果你的控件的 Enabled 属性真的是只读的,我很好奇会发生什么。
【讨论】:
试试这个:
Dim ctr 作为控制 Dim CtrStatus 布尔值 CtrStatus = 假 对于 Me.Controls 中的每个 ctr 如果 (SSTab.hwnd = GetParent(ctr.hwnd)) 那么 调用 CallByName(ctr, "Enabled", VbLet, CtrStatus) 别的 ctr.Enabled = CtrStatus 万一 下一个【讨论】:
另一种方法如下,它也适用于运行时(而不是仅在 IDE 中):
private sub SetEnabled()
on error goto errHandle
Dim ctrl As Control
For Each ctrl In Me.Controls
ctrl.Enabled = True
Next
exitPoint:
exit sub
errHandle:
MsgBox "Error " & err.Description & " with Control " & ctrl.Name
resume exitPoint
end sub
【讨论】:
tosa 的问题代码行是没有使用 Enabled 属性。请参阅我对这个问题的回答(= 不是)。您的回答很好地给出了原始问题,这强烈暗示问题发生在更改 Enabled 属性时,而不是尝试建立控件的 Container。
在循环之前抑制错误报告,然后将其设置回标准错误处理:
On Error Resume Next
For Each ctrl In Me.Controls
ctrl.Enabled = lIsEnabled
Next
On Error GoTo 0
或使用标准前缀/后缀命名您的控件,您可以按名称检查并跳过循环。
For Each ctrl In Me.Controls
If Left(ctrl.Name, 3) = "sst" Then
ctrl.Enabled = lIsEnabled
End If
Next
【讨论】:
Tosa:从您对AngryHacker's answer 的评论来看,我认为您正在错误地检查容器。
你的代码是这样的
' BAD CODE '
If ctrl.Container = fraMovies Then
对我来说,这给出了错误 450 Wrong number of arguments or invalid property assignment。你得到同样的错误吗?
代码应该使用Is而不是=,像这样
' GOOD CODE '
If ctrl.Container Is fraMovies Then
解释。您想检查两个变量是否“指向”同一个控件。控件是对象:you must use Is not = 检查两个对象变量是否“指向”同一个对象。这是 VB6 中的一个经典陷阱。
最后一句话。 下一次,您能否尝试发布 10 行或更少的实际代码,重现错误,并给出确切的错误编号和消息以及发生错误的确切行?它确实让我们更容易解决您的问题 - 我知道缩短代码对您有用,但这样您会得到更好的答案。
编辑欢迎回来! :) 你说有些控件没有 Container 属性。您可以尝试将测试包装在 On Error Resume Next 中,类似这样。
' GOOD CODE '
Dim bMatch As Boolean
Dim ctrl As Control
For Each ctrl In Me.Controls
bMatch = False
On Error Resume Next
bMatch = (ctrl.Container Is fraMovies)
On Error Goto 0
If bMatch Then
ctrl.Enabled = True
End If
Next
【讨论】:
Cycle 语句可以让您直接进入下一个对象。我的建议是使用 If 块来包装 Enabled 属性的使用。我将再次编辑我的答案以使其更清楚。除了使用错误陷阱之外,我认为没有任何更简单的方法可以检测对象是否具有容器属性。
为避免此类问题,请在命名控件时遵循给定的规则
在 Visual Basic 应用程序中命名元素时,该名称的第一个字符必须是字母字符或下划线。
**名称中的每个单独单词都以大写字母开头,如 FindLastRecord 和 RedrawMyForm。
以动词开头的函数和方法名称,如 InitNameArray 或 CloseDialog。 以名词开头的类、结构、模块和属性名称,如 EmployeeName 或 CarAccessory。
接口名称以前缀“I”开头,后接名词或名词短语,如 IComponent,或描述接口行为的形容词,如 IPersistable。不要使用下划线,并谨慎使用缩写,因为缩写会引起混淆。
事件处理程序名称以描述事件类型的名词开头,后跟“EventHandler”后缀,如“MouseEventHandler”。
在事件参数类的名称中,包含“EventArgs”后缀。 如果事件有“之前”或“之后”的概念,请使用现在或过去时的后缀,如“ControlAdd”或“ControlAdded”。
对于较长或常用的术语,请使用缩写以保持名称长度合理,例如“HTML”,而不是“超文本标记语言”。通常,大于 32 个字符的变量名很难在设置为低分辨率的监视器上读取。此外,请确保您的缩写在整个应用程序中保持一致。在“HTML”和“超文本标记语言”之间随意切换项目可能会导致混淆。
避免在内部范围中使用与外部范围中的名称相同的名称。如果访问错误的变量,可能会导致错误。如果变量与同名关键字发生冲突,则必须在关键字前面加上适当的类型库来标识该关键字。 例如,如果您有一个名为 Date 的变量,则只能通过调用 DateTime.Date 来使用内部 Date 函数。
【讨论】: