VB Net单击控件的事件

时间:2016-07-21 03:22:39

标签: .net vb.net winforms events controls

我有这样的用户控件:

user control 1

在该控件中有一个Panel(包括一个Title标签)和另一个Panel(包括Gridview,一个标签)。

我的问题:如何为此控件设置点击事件(意味着我可以点击此控件中的任何位置来执行事件)

该控件用于以下用户控件:user control 2

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

您必须向每个单独的控件添加一个单击事件才能使其正常工作,但幸运的是,您也可以通过循环遍历所有控件来自动执行此操作。

只需将以下代码添加到您的用户控件中,它就会自动向所有子控件添加/删除任何点击事件:

public new event EventHandler Click {
    add {
        base.Click += value;
        foreach (Control control in Controls) {
            control.Click += value;
        }
    }
    remove {
        base.Click -= value;
        foreach (Control control in Controls) {
            control.Click -= value;
        }
    }
}

的引用:

答案 1 :(得分:2)

您可以通过在每个控件触发单击事件时引发Click事件来执行此操作,但这是漫长的,并且如果添加新控件,则必须记住添加处理程序。

更好的方法是使用递归方法为用户控件中的每个控件添加click事件处理程序:

Public Class UserControl1
    'declare the event (must shadow as the usercontrol already has it's own click event)
    Public Shadows Event Click(sender As Object, e As EventArgs)

    Private Sub ClickEventHandlerForAllControls(sender As Object, e As EventArgs)
        RaiseEvent Click(sender, e)
    End Sub

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        AddClickHandlersForControl(Me)
    End Sub


    Private Sub AddClickHandlersForControl(ctl As Control)
        'add the click event handler for this control
        AddHandler ctl.Click, AddressOf ClickEventHandlerForAllControls
        'if the control has children (e.g. panel, form) then iterate through those and add the click event for each one
        If ctl.HasChildren Then
            For Each childCtl As Control In ctl.Controls
                AddClickHandlersForControl(childCtl)
            Next
        End If
    End Sub
End Class

编辑:正如你所说,你希望能够点击任何地方,包括标题行等。这样做的方法是使用全局鼠标挂钩(非托管代码,所以不太需要)。

以下是一个有效的例子:

Public Class UserControl1

    Private Structure MSLLHOOKSTRUCT
        Public pt As Point
        Public mouseData As Int32
        Public flags As Int32
        Public time As Int32
        Public extra As IntPtr
    End Structure

    Private _mouseHook As IntPtr
    Private Const WH_MOUSE_LL As Int32 = 14
    Private Const LEFT_MOUSE_DOWN = 513
    Private Const LEFT_MOUSE_UP = 514

    Private Delegate Function MouseHookDelegate(ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32
    <Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.FunctionPtr)> Private _mouseProc As MouseHookDelegate
    Private Declare Function SetWindowsHookExW Lib "user32.dll" (ByVal idHook As Int32, ByVal HookProc As MouseHookDelegate, ByVal hInstance As IntPtr, ByVal wParam As Int32) As IntPtr
    Private Declare Function UnhookWindowsHookEx Lib "user32.dll" (ByVal hook As IntPtr) As Boolean
    Private Declare Function CallNextHookEx Lib "user32.dll" (ByVal idHook As Int32, ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32
    Private Declare Function GetModuleHandleW Lib "kernel32.dll" (ByVal fakezero As IntPtr) As IntPtr

    'declare the event (must shadow as the usercontrol already has it's own click event)
    Public Shadows Event Click(sender As Object, e As EventArgs)

    Private Sub UserControl1_HandleCreated(sender As Object, e As EventArgs) Handles Me.HandleCreated
        HookMouse()
    End Sub

    Private Sub UserControl1_HandleDestroyed(sender As Object, e As EventArgs) Handles Me.HandleDestroyed
        UnHookMouse()
    End Sub

    Public Function HookMouse() As Boolean
        If _mouseHook = IntPtr.Zero Then
            _mouseProc = New MouseHookDelegate(AddressOf MouseHookProc)
            _mouseHook = SetWindowsHookExW(WH_MOUSE_LL, _mouseProc, GetModuleHandleW(IntPtr.Zero), 0)
        End If
        Return _mouseHook <> IntPtr.Zero
    End Function

    Public Sub UnHookMouse()
        If _mouseHook = IntPtr.Zero Then Return
        UnhookWindowsHookEx(_mouseHook)
        _mouseHook = IntPtr.Zero
    End Sub

    Private Function MouseHookProc(ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32
        Static downLocation As Point = New Point(-1, -1)

        Select Case wParam.ToInt32
            Case LEFT_MOUSE_DOWN
                downLocation = lParam.pt

            Case LEFT_MOUSE_UP
                'don't raise click event if we have dragged
                If lParam.pt = downLocation Then
                    'check the mouse location is inside the bounding rectangle of the usercontrol
                    Dim usercontrolLocation = New Point(Me.Parent.Location.X + Me.Location.X, Me.Parent.Location.Y + Me.Location.Y)
                    Dim usercontrolRect = New Rectangle(usercontrolLocation, Me.Size)
                    If usercontrolRect.Contains(lParam.pt) Then RaiseEvent Click(Me, New EventArgs())
                End If

        End Select
        Return CallNextHookEx(WH_MOUSE_LL, nCode, wParam, lParam)
    End Function

End Class

您的点击事件将由用户控制您的表单引发:

Public Class Form1

    Private Sub UserControl11_Click(sender As Object, e As EventArgs) Handles UserControl11.Click
        MessageBox.Show("Usercontrol was clicked")
    End Sub

End Class