#vb.net
Вопрос:
В следующем примере кода рисуются три прямоугольника и изменяется тип курсора на ручной/по умолчанию, если мышь находится внутри/снаружи прямоугольных областей соответственно. Программа выполняется по назначению, за одним исключением: при нахождении внутри области мышь мигает при перемещении.
Проведя расследование, кажется, что проблема может быть связана с противоречием между моим кодом и базовым элементом управления в отношении того, какой тип мыши следует отображать, что приводит к мерцанию. Правильно это или нет, к сожалению, я не смог решить эту проблему. Пожалуйста, вы можете помочь?
Imports System.Drawing.Drawing2D
Public Class Form1
Private myRectangles() As Rectangle
Private myRegions(2) As Region
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Write an array of rectangles.
myRectangles = {New Rectangle(100, 100, 50, 50), New Rectangle(200, 200, 50, 50), New Rectangle(300, 300, 50, 50)}
' Write an array of rectangle regions.
For i As Integer = 0 To myRegions.length - 1
Dim myPath As New GraphicsPath
myPath.AddRectangle(myRectangles(i))
Dim myRegion As New Region(myPath)
myRegions(i) = myRegion
Next
End Sub
Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
' Iterate myRegions to check if the mouse is over a region.
For i As Integer = 0 To myRegions.Count - 1
Dim IsHit As Boolean = myRegions(i).IsVisible(e.Location)
If IsHit Then
Cursor.Current = Cursors.Hand
Exit For
Else
Cursor.Current = Cursors.Default
End If
Next
End Sub
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
' Paint myRectangles.
For i As Integer = 0 To myRegions.Length - 1
e.Graphics.DrawRectangle(New Pen(Color.Black, 1), myRectangles(i))
Next
End Sub
End Class
EDIT1: Вышеприведенный подраздел MouseMove можно упростить до следующего:
Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
' Check if the mouse is located within any region.
Dim isHit As Boolean = myRegions.Any(Function(p) p.IsVisible(e.Location))
If isHit Then
Cursor.Current = Cursors.Hand
Else
Cursor.Current = Cursors.Default
End If
End Sub
ПРАВКА2: Пересмотренный полный код:
Imports System.Drawing.Drawing2D
Public Class Form1
Private myRectangles() As Rectangle
Private myGraphicsPaths As New List(Of GraphicsPath)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Write a graphics path list of rectangles.
myRectangles = {New Rectangle(100, 100, 50, 50), New Rectangle(200, 200, 50, 50), New Rectangle(300, 300, 50, 50)}
For i As Integer = 0 To myRectangles.Length - 1
Dim myPath As New GraphicsPath
myPath.AddRectangle(myRectangles(i))
myGraphicsPaths.Add(myPath)
Next
End Sub
Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
' Check if the mouse is located within any graphicspath.
Dim isHit As Boolean = myGraphicsPaths.Any(Function(p) p.IsVisible(e.Location))
If isHit And Cursor.Current IsNot Cursors.Hand Then
Cursor.Current = Cursors.Hand
Else
Cursor.Current = Cursors.Default
End If
End Sub
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
' Paint myRectangles.
For i As Integer = 0 To myRectangles.Length - 1
e.Graphics.DrawRectangle(New Pen(Color.Black, 1), myRectangles(i))
Next
End Sub
End Class
Комментарии:
1. Какая польза от этих регионов? Из того, что вы показываете здесь, похоже, что вы используете массив областей только для того, чтобы проверить, находится ли указатель мыши внутри одной из них. Вместо этого вы могли бы обработать a
List(Of GraphicsPath)
и использоватьAddRectangle()
для добавления ваших фигур в прямоугольнике. С помощью этого списка вы просто проверяете, есть лиdim isVisible = [YourListOfGraphicsPaths].Any(Function(p) p.IsVisble([Point]))
. Если значение true, установите тип курсора — только если он еще не установлен — в противном случае измените его на другой.2. Привет, Джими. Приведенный выше код является выдержкой из программы, которая будет анализировать ферменные мосты. Пользователь введет в datagridview координаты узлов фермы, т. е. местоположение, в котором пересекаются элементы фермы. Узлы фермы будут окрашены в виде кругов; со временем элементы фермы будут окрашены в виде прямоугольников. Я хочу, чтобы тип курсора мыши менялся на «рука», когда пользователь наводит курсор на узел/элемент, и чтобы был выбран соответствующий номер узла/элемента в представлении datagrid, а также для визуальной подсказки о возможности «выбрать» узел/элемент.
3. В любом случае, похоже, что ваше предложение, хотя и упрощает мой код, не решает проблему… если только Список(Из…) не делает чего-то, о чем я не знаю. См. выше упрощенный код для модуля MouseMove.
4. Ты упустил главное. У вас есть несколько фигур (прямоугольников), и это то, что вы используете для рисования. Это уже неправильно, так как вам нужно обрабатывать эти фигуры, а не просто рисовать их. Таким образом, как представляется, для управления этими фигурами вы вводите новую коллекцию областей, полученных из объекта GraphicsPath (от которого вы никогда не избавляетесь), просто чтобы использовать этот
Isvisible()
метод. Я предлагаю отказаться от коллекции областей и прямоугольников и просто использовать aList(Of GraphicsPath)
для всех, чтобы упростить процедуру. — Тогда я также предложил установить курсор только в том случае, если он отличается от текущего, ни в коем случае.5. Вы рисуете на поверхности Формы. Даже если предположить, что Форма имеет двойной буфер, я предлагаю не использовать ее поверхность для рисования. Используйте элемент управления с двойной буферизацией в качестве графического поля или плоской метки, оба из которых имеют двойную буферизацию самостоятельно. — В любом случае, не используйте области для определения того, содержится ли точка в фигуре. GraphicsPath предоставляет тот же метод, плюс
IsOutlineVisible
метод, аналогичный, но связанный только с границей пути. — Я сомневаюсь, что вам нужно всего 3 прямоугольника, явно больше, поэтому вычисления должны быть как можно быстрее.