【问题标题】:VB6 control iteration: one control gives me an error; which one?VB6控件迭代:一个控件给我一个错误;哪一个?
【发布时间】:2009-10-29 18:39:10
【问题描述】:

我正在尝试遍历表单中的所有控件: 对于 Me.Controls 中的每个 ctrl 为了根据某些条件启用/禁用控制。 但是当我尝试访问它时,表单上有一个控件会给出错误。什么样的控件可以做到这一点,我如何找到它?

【问题讨论】:

    标签: vb6


    【解决方案1】:

    当您收到错误并单击 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 属性真的是只读的,我很好奇会发生什么。

    【讨论】:

    • 当试图访问这个 ctrl 时(如循环所有控件以 debug.print 它们),当遇到这个特定控件时,一个弹出框说“Property is write only”。
    • 您描述的错误是当您尝试设置给您带来问题的控件的 Enabled 属性时?它是什么样的控制?当您在设计器中查看表单时,是否可以为控件设置 Enabled 属性?控件的 Enabled 属性可能是只读的 - 这就是您设置的错误消息的含义。请参阅我的编辑以了解另一个可能有效的想法。
    【解决方案2】:

    试试这个:

    Dim ctr 作为控制 Dim CtrStatus 布尔值 CtrStatus = 假 对于 Me.Controls 中的每个 ctr 如果 (SSTab.hwnd = GetParent(ctr.hwnd)) 那么 调用 CallByName(ctr, "Enabled", VbLet, CtrStatus) 别的 ctr.Enabled = CtrStatus 万一 下一个

    【讨论】:

      【解决方案3】:

      另一种方法如下,它也适用于运行时(而不是仅在 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
      

      【讨论】:

      • 它在 SSTab 上很糟糕。我正在检查控件的容器是否是某个帧,然后启用/禁用它...“如果 ctrl.Container = fraMovies Then...”。但是当程序循环并尝试检查 SSTab 的容器时,它会抛出异常。
      • 我猜 SSTab 没有 Enabled 属性。
      • @AngryHacker:起初我也认为 SSTab 一定没有 Enabled 属性:但tosa 的问题代码行是没有使用 Enabled 属性。请参阅我对这个问题的回答(= 不是)。您的回答很好地给出了原始问题,这强烈暗示问题发生在更改 Enabled 属性时,而不是尝试建立控件的 Container。
      【解决方案4】:

      在循环之前抑制错误报告,然后将其设置回标准错误处理:

      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
      

      【讨论】:

        【解决方案5】:

        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 
        

        【讨论】:

        • 你好,我回来看看这个问题。谢谢,“是”有效。现在问题出在 .container 检查部分。有些控件没有容器(例如commondialog),检查它们是否有容器会出错。我想要做的是遍历框架中的所有对象并禁用它们。原始帧中的帧中的对象和对象也应如此(迭代循环)。最好的方法是什么?
        • 您好,感谢您的回复。而不是在下一行继续处理(通过 On Error Resume Next,我如何改为转到 For Each 循环中的下一个对象?问题是即使某些控件没有容器,它们确实有一个 enabled 属性,因此它们在恢复部分被禁用/启用。更好的是,如何检查对象是否具有容器属性(不使用错误捕获器)?
        • 嗨,VB6 中没有Cycle 语句可以让您直接进入下一个对象。我的建议是使用 If 块来包装 Enabled 属性的使用。我将再次编辑我的答案以使其更清楚。除了使用错误陷阱之外,我认为没有任何更简单的方法可以检测对象是否具有容器属性。
        【解决方案6】:

        为避免此类问题,请在命名控件时遵循给定的规则

        • 在 Visual Basic 应用程序中命名元素时,该名称的第一个字符必须是字母字符或下划线。

        • **名称中的每个单独单词都以大写字母开头,如 FindLastRecord 和 RedrawMyForm。

        • 以动词开头的函数和方法名称,如 InitNameArray 或 CloseDialog。 以名词开头的类、结构、模块和属性名称,如 EmployeeName 或 CarAccessory。

        • 接口名称以前缀“I”开头,后接名词或名词短语,如 IComponent,或描述接口行为的形容词,如 IPersistable。不要使用下划线,并谨慎使用缩写,因为缩写会引起混淆。

        • 事件处理程序名称以描述事件类型的名词开头,后跟“EventHandler”后缀,如“MouseEventHandler”。

        • 在事件参数类的名称中,包含“EventArgs”后缀。 如果事件有“之前”或“之后”的概念,请使用现在或过去时的后缀,如“ControlAdd”或“ControlAdded”。

        • 对于较长或常用的术语,请使用缩写以保持名称长度合理,例如“HTML”,而不是“超文本标记语言”。通常,大于 32 个字符的变量名很难在设置为低分辨率的监视器上读取。此外,请确保您的缩写在整个应用程序中保持一致。在“HTML”和“超文本标记语言”之间随意切换项目可能会导致混淆。

        • 避免在内部范围中使用与外部范围中的名称相同的名称。如果访问错误的变量,可能会导致错误。如果变量与同名关键字发生冲突,则必须在关键字前面加上适当的类型库来标识该关键字。 例如,如果您有一个名为 Date 的变量,则只能通过调用 DateTime.Date 来使用内部 Date 函数。

        【讨论】:

          猜你喜欢
          • 2014-12-16
          • 1970-01-01
          • 2012-04-12
          • 2012-03-12
          • 2010-09-16
          • 2023-03-06
          • 2011-11-14
          • 1970-01-01
          • 2016-01-04
          相关资源
          最近更新 更多