【问题标题】:AddHandler for custom controls error visual studio自定义控件错误 Visual Studio 的 AddHandler
【发布时间】:2012-06-02 09:30:59
【问题描述】:

我有一个 MouseEnter 事件,它当前处理我表单上的一些自定义控件。该程序是一个纸牌游戏。我有一个集合(handCards),当用户画一张卡片时会填充它,然后它将最新的卡片添加到表单中。这个集合包含各种自定义类型的卡片,所有这些卡片都继承自 picturebox。从牌组中抽出卡片并将它们添加到表格中可以正常工作。我遇到的麻烦是,在运行时,在卡片被绘制并添加到表单后,我创建了一个 addhandler 代码行来让这些卡片响应我的 MouseEnter 事件,但是我的 addhandler 代码行告诉我MouseEnter 不是对象的事件。如何解决这个问题,以便在卡片被绘制并添加到表单后,当鼠标进入新的自定义控件时,我的 MouseEnter 事件会触发?这是我尝试过的众多方法之一,我认为应该是最简单的方法。

deck.DrawCard()
AddHandler handCards(handCards.Count).MouseEnter, AddressOf Cards_MouseEnter

附: MouseEnter 事件适用于运行前窗体上的自定义控件,它所做的只是获取控件的图像并通过将图像放置在窗体上更大的卡片上来放大它。

【问题讨论】:

    标签: vb.net controls mouseenter addhandler


    【解决方案1】:

    我假设你的 handCards 集合是一个对象集合。尝试使用CType 将其转换为正确的类型,如下所示:

    AddHandler CType(handCards(handCards.Count), PictureBox).MouseEnter, AddressOf Cards_MouseEnter
    

    正如@Jason 提到的,使用handCards.Count 作为索引将不起作用,因为它是项目的总数,因为您的索引从零开始,并且将比计数少一。 所以handCards(handCard.Count) 应该是handCards(handCards.Count -1)

    【讨论】:

    • 铸造它可能有效,但我想通了并发布了解决方案。感谢您的帮助。
    • @clanier9 很高兴你知道了。因为你的卡片是基于 PictureBox 的,所以铸造本来可以工作的。
    【解决方案2】:

    所以这就是我修复它的方法,以防万一有人看到这篇文章。制作了一个单独的 Sub 来执行 AddHandler。程序抽出一张卡片后,它会调用此方法,然后添加我需要的 MouseEnter 处理程序。 ByVal 是关键。我原本以为我应该使用 ByRef,但没有。 MouseEnter 是一个控制事件,但显然不是 Object,所以现在它可以工作了。

    Public Sub addHandlers(ByVal inputObject As Control)
        AddHandler inputObject.MouseEnter, AddressOf Cards_MouseEnter
    End Sub
    

    【讨论】:

    • 如果你的handCards 数组仍然是Object 类型,那么这不是一个好主意,因为你传递给addHandlers 的对象将被隐式转换为Control 类型。您可以将任何对象添加到引用类型为Object 的数组中,因为每个对象都源自Object 类型。但是,如果您将不从 Control 下降的东西添加到 handCards 数组,然后将其传递给 addHandlers 方法,那么当隐式转换失败时,您将获得运行时异常。你可能会说这永远不会发生,但隐式类型转换通常被认为是一个坏主意。
    • 您的编译器设置可能会忽略隐式转换,但我个人认为更改设置以至少警告隐式转换是个好主意。
    • 嗯,不知道该怎么做或找到那个设置。我只是边走边学。认为我应该在那里尝试一下?我真的不认为牌组中的任何一张牌(都继承自 PB)不能与 addhandler 消息一起使用,但我想最好是安全的。
    • 要更改编译器设置,请转到您的项目属性,编译选项卡,然后更改“隐式转换”条件的“通知”。最好为意外情况保留异常处理,并尽可能避免异常。例如,在我的回答中,我添加了代码来检查 Nothing 的最后一个元素或零计数数组。同样,最好让您的类型正确,而不是依赖异常处理。您可以通过将数组的类型更改为PictureBox(如我的回答)或合适的接口类型(如果您的对象不共享共同祖先)来简单地做到这一点。
    【解决方案3】:

    您可以使用泛型集合来避免类型转换。

    Private handCards As System.Collections.Generic.List(Of PictureBox) _
        = New System.Collections.Generic.List(Of PictureBox)(52)
    

    或者你可以只使用PictureBox对象的数组

    Private handCards(5) As PictureBox
    

    请记住,您必须通过将 PictureBox 对象分配给数组的每个元素来初始化集合或数组。

    现在您可以将处理程序添加到数组的PictureBox 元素,因为PictureBox 派生自实现MouseEnter 事件的Control

    deck.DrawCard()
    If handCards.Count > 0 andAlso handCards.Last() IsNot Nothing then
        AddHandler handCards.Last().MouseEnter, AddressOf Cards_MouseEnter
    End If
    

    您的处理程序将如下所示

    Private Function Cards_MouseEnter(sender As Object, e As System.EventArgs) As Object
        ' Handle mouse events here
    End Function
    

    【讨论】:

    • handcards 是一个从索引 1 开始的集合。我实际上确实尝试通过该集合循环并以这种方式添加处理程序,但它也不起作用(同样的错误)。不过,我确实让它工作了,并在下面发布了解决方案。感谢您的帮助。
    • @clanier9 数组索引点是偶然的。更重要的是,在您的问题中,您正在为索引 handCards.Count 处的项目添加处理程序,这可能不是您想要的。真正的重点是关于类型和继承。在您的问题中,您试图从 Object 引用访问 MouseEnter 事件。由于MouseEnter 是在Control 类上定义的,因此您需要Control 或其子类之一的引用,例如我建议的PictureBox,因为您说所有对象都来自该类。
    • @clanier9 在问题中你说“这个集合包含各种自定义类型的卡片,所有这些卡片都继承自图片框”。听起来您可能会遇到多重继承问题,在这种情况下(并且作为一般规则),您可能需要考虑使用Interfaces 而不是子类。或者用GoF 的话来说就是“编程到接口,而不是实现”。
    • @Jason S - 我确实希望处理程序在 index handcards.Count 处添加项目,因为这是最后一张牌,因为每张牌都被添加到 handcards 集合中。多重继承会产生什么样的问题?我只需要一种创建图片框的方法,它可以存储不同的自定义变量,同时保留图片框的所有属性,这是我知道的唯一方法。接口看起来很混乱,难道我还需要在每个接口内部进行继承吗?
    • @clanier9 抱歉,我对索引的猜测是错误的。接口将允许您使用多种类型,这些类型甚至可能不会从彼此继承作为您方法的参数类型。您可能会发现Java Tutorial 在这些概念上比 MS 文档更清晰(我愿意)。该页面底部有一些关于多重继承的内容。另见Using an interface as a type。无法在此评论中解释所有这些。
    【解决方案4】:

    幸运的是,我正在努力解决这个问题。

    首先添加事件处理程序方法,无论你想什么,为了测试,我已经在 Button_Click 处添加了这个函数

    addHandlers(Label1) 'Label one is the control on which I have to attach Mouse Events (Enter,LEave)
    

    现在“addHandlers”函数实现

     Public Sub addHandlers(ByVal obj1 As Control)
        AddHandler obj1.MouseEnter, AddressOf MouseEventArgs
        AddHandler obj1.MouseLeave, AddressOf _MouseLeave
     End Sub
    

    现在鼠标事件:

    Private Function _MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) As Object
        Try
            Me.Cursor = Cursors.Default
        Catch ex As Exception
    
        End Try
    
    End Function
    
    Private Function MouseEventArgs(ByVal sender As Object, ByVal e As System.EventArgs) As Object
        Try
            Me.Cursor = Cursors.Hand
        Catch ex As Exception
    
        End Try
    End Function
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-30
      • 1970-01-01
      • 1970-01-01
      • 2017-07-30
      • 1970-01-01
      • 2012-07-06
      相关资源
      最近更新 更多