简体   繁体   English

在VB.net中使用自定义控件处理焦点

[英]Handling Focus with Custom Controls in VB.net

I have a custom control I'm creating. 我有一个正在创建的自定义控件。 When I click on it, it draws a dotted border and puts some nubs on it for resizing. 当我单击它时,它会绘制一个虚线边框,并在其上放一些小块以调整大小。 This all works perfectly. 所有这一切都完美。 Now I want it so when I click off of it, it deselects. 现在我想要它,所以当我单击它时,它会取消选择。 I already have a variable to set up if it's selected or not and subs to draw/clear it. 我已经有了一个变量来设置是否被选中,以及用来绘制/清除它的子控件。 I just have to be able to detect when something else is selected or it gets clicked off of. 我只需要能够检测何时选择了其他选项或将其单击。

What I've Tried 我尝试过的

My first and best solution to this was to use the LostFocus event, but, by custom control apparently won't let it fire. 我对此的第一个也是最好的解决方案是使用LostFocus事件,但是,通过自定义控件显然不会触发它。 After some research, as far as I know, custom controls don't have Focus events because they are custom and could be changed (basically, you have to implement the focus events yourself). 据我所知,经过一些研究,自定义控件没有Focus事件,因为它们是自定义的并且可以更改(基本上,您必须自己实现focus事件)。

My Question 我的问题

Does anybody have a solution to either implement the focus events or a way to handle off clicking for custom controls? 是否有人解决焦点事件解决自定义控件单击问题的方法?

Sources 资料来源

Here is my controls current source: 这是我的控件的当前来源:

Imports System.Drawing.Drawing2D

Public Class wDOMElement
    Inherits Control

    Public selected As Boolean = False

    Private mdown As Boolean = False
    Private moffset As Point = Nothing

    Private nubs As New List(Of PictureBox)

    Private Sub wDOMElement_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.GotFocus
        MsgBox("test <-- DOES NOT SHOW!")
    End Sub

    Private Sub wDesignEditor_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
        If mdown Then Return
        mdown = True
        moffset = MousePosition - Location
        selectME()
    End Sub

    Private Sub selectME()
        selected = True
        updateDraw()
        updateBorder()
        For Each v As PictureBox In nubs
            v.Show()
        Next
    End Sub

    Private Sub unselectME()
        selected = False
        updateBorder()
        updateDraw()
        For Each v As PictureBox In nubs
            v.Hide()
        Next
    End Sub

    Private Sub updateBorder()
        Using gfx As Graphics = Graphics.FromHwnd(Me.Handle)
            gfx.Clear(BackColor)
            If selected Then
                Dim blackPen As New Pen(Brushes.Black)
                blackPen.DashStyle = DashStyle.Dot
                gfx.DrawRectangle(blackPen, 4, 4, Width - 9, Height - 9)
            End If
        End Using
    End Sub

    Private Sub updateDraw()
        'Needs to be overriden
    End Sub

    Private Sub configureFirstSelection()
        Using gfx As Graphics = Graphics.FromHwnd(Me.Handle)
            Dim blackPen As New Pen(Brushes.Black)
            blackPen.DashStyle = DashStyle.Dot
            gfx.DrawRectangle(blackPen, 4, 4, Width - 9, Height - 9)
            'Top Handle
            placeHandle(My.Resources.Handle, CInt(Width / 2 - 3), CInt(0), New Point(0, 1), New Point(0, -1), Cursors.SizeNS, AnchorStyles.Top)
            'Bottom Handle
            placeHandle(My.Resources.Handle, CInt(Width / 2 - 3), CInt(Height - 7), New Point(0, 0), New Point(0, 1), Cursors.SizeNS, AnchorStyles.Bottom)
            'Left Handle
            placeHandle(My.Resources.Handle, CInt(0), CInt(Height / 2 - 3), New Point(1, 0), New Point(-1, 0), Cursors.SizeWE, AnchorStyles.Left)
            'Right Handle
            placeHandle(My.Resources.Handle, CInt(Width - 7), CInt(Height / 2 - 3), New Point(0, 0), New Point(1, 0), Cursors.SizeWE, AnchorStyles.Right)
            'Top Left Handle
            placeHandle(My.Resources.Handle, CInt(0), CInt(0), New Point(1, 1), New Point(-1, -1), Cursors.SizeNWSE, AnchorStyles.Top + AnchorStyles.Left)
            'Top Right Handle
            placeHandle(My.Resources.Handle, CInt(Width - 7), CInt(0), New Point(0, 1), New Point(1, -1), Cursors.SizeNESW, AnchorStyles.Top + AnchorStyles.Right)
            'Bottom Left Handle
            placeHandle(My.Resources.Handle, CInt(0), CInt(Height - 7), New Point(1, 0), New Point(-1, 1), Cursors.SizeNESW, AnchorStyles.Bottom + AnchorStyles.Left)
            'Bottom Right Handle
            placeHandle(My.Resources.Handle, CInt(Width - 7), CInt(Height - 7), New Point(0, 0), New Point(1, 1), Cursors.SizeNWSE, AnchorStyles.Bottom + AnchorStyles.Right)
        End Using
    End Sub

    Private Sub placeHandle(ByVal pic As Image, ByVal x As Integer, ByVal y As Integer, ByVal mov As Point, ByVal siz As Point, ByVal cur As Cursor, ByVal ancr As AnchorStyles)
        Dim nPB As New PictureBox
        nPB.SizeMode = PictureBoxSizeMode.AutoSize
        nPB.Image = pic
        nPB.Location = New Point(x, y)
        nPB.Cursor = cur
        nPB.Visible = False
        nPB.Anchor = ancr
        nPB.Parent = Me
        Dim md As Boolean = False
        Dim lpos As Point = Nothing
        Dim moveClock As New Timer
        moveClock.Interval = 1
        moveClock.Enabled = False
        AddHandler nPB.MouseDown, Sub()
                                      md = True
                                      lpos = MousePosition
                                      moveClock.Start()
                                  End Sub

        AddHandler moveClock.Tick, Sub()
                                       If md Then
                                           Dim nX As Integer = (MousePosition.X - lpos.X) * mov.X
                                           Dim nY As Integer = (MousePosition.Y - lpos.Y) * mov.Y
                                           Dim nWidth As Integer = (MousePosition.X - lpos.X) * siz.X
                                           Dim nHeight As Integer = (MousePosition.Y - lpos.Y) * siz.Y
                                           Left += nX
                                           Top += nY
                                           Width += nWidth
                                           Height += nHeight
                                           lpos = MousePosition
                                           updateDraw()
                                           updateBorder()
                                       End If
                                   End Sub
        AddHandler nPB.MouseUp, Sub()
                                    md = False
                                    moveClock.Stop()
                                End Sub
        nubs.Add(nPB)
    End Sub

    Private Sub wDesignEditor_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
        If mdown Then
            Location = MousePosition - moffset
        End If
    End Sub

    Private Sub wDesignEditor_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
        mdown = False
    End Sub

End Class

Try using the Enter and Leave events for your custom control. 尝试对您的自定义控件使用Enter和Leave事件。

GotFocus and LostFocus have sort of been deprecated in favor of Enter and Leave. GotFocus和LostFocus已经过时,转而支持Enter和Leave。

Update: 更新:

Since you are inheriting from Control, you should probably be overriding your events, not handling them. 由于您是从Control继承的,因此您可能应该覆盖事件,而不是处理它们。 MouseDown won't necessarily grab the focus either, so you should probably check that, too: MouseDown也不一定会吸引焦点,因此您也应该检查一下:

Example: 例:

Public Class ControlEx
  Inherits Control

  Protected Overrides Sub OnEnter(e As EventArgs)
    MyBase.OnEnter(e)
    MessageBox.Show("Hello")
  End Sub

  Protected Overrides Sub OnLeave(e As EventArgs)
    MyBase.OnLeave(e)
    MessageBox.Show("Good-bye")
  End Sub

  Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
    If Me.Enabled AndAlso Not Me.Focused Then
      Me.Focus()
    End If

    MyBase.OnMouseDown(e)
  End Sub

End Class

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM