(Как нарисовать резиновую ленту или прямоугольник фокуса в Visual Basic .NET)
PSS ID Number: 317479
Последнее изменение статьи 2.11.2004
Информация в этой статье применима к:
Microsoft .NET Framework Class Libraries 1.0
Microsoft .NET Framework Class Libraries 1.1
Microsoft Visual Basic .NET (2002)
Microsoft Visual Basic .NET (2003)
Данная статья ранее опубликована как Q317479
Версию этой статьи для Microsft Visual Studio .NET C# смотрите под номером 314945.
ОБЩАЯ ИНФОРМАЦИЯ
Резиновая лента или прямоугольник фокуса - это прямоугольник, который следует за указателем мыши, пока вы держите нажатой левую кнопку мыши. Эта техника обычно используется для определения границ выделенной зоны при работе с указателем мыши. В интерфейсе графического устройства (GDI) этот прямоугольник обычно реализуется при помощи растровых операция (ROPs). Однако, методы System.Drawing основаны на GDI+ (преемник GDI), который не поддерживает ROPs.
Эта статья показывает другой подход для реализации прямоугольника фокуса в .NET Framework.
В GDI прямоугльник фокуса часто рисуется при помощи ROP кодов. В частности, часто используются ROP2 коды R2_XORPEN и R2_NOT. Когда вы используете один из этих ROP2 кодов, вы можете стирать предыдущую линию, рисуя еще раз в той же позиции. Эта методика известна также как эффект исключающего ИЛИ (XOR).
Пример кода
Поскольку ROPs не доступны в GDI+ и в System.Drawing, вы должны использовать другой способ рисования обратимых линий при помощи этих средств. Например, вы можете средства PInvoke для взаимодействия с GDI. Однако, решение использующее только управляемый код доступно при использовании статического метода ControlPaint::DrawReversibleFrame(). Следующий код, написанный в Visual Basic .NET и готовый для вставки в класс формы в приложение по умолчанию Visual Basic .NET, демонстрирует этот способ:
- Код: Выделить всё
Public Class Form1
Inherits System.Windows.Forms.Form
Dim bHaveMouse As Boolean
Dim ptOriginal As Point
Dim ptLast As Point
+[Windows Form Designer generated code]
' Конвертируем и нормализуем точки и рисуем обратимую рамку.
Private Sub MyDrawReversibleRectangle(ByVal p1 As Point,ByVal p2 As Point)
Dim rc As Rectangle
' Конвертируем точки в экранные координаты.
p1 = PointToScreen(p1)
p2 = PointToScreen(p2)
' Нормализуем прямоугольник.
If (p1.X < p2.X) Then
rc.X = p1.X
rc.Width = p2.X - p1.X
Else
rc.X = p2.X
rc.Width = p1.x - p2.X
End If
If (p1.Y < p2.Y) Then
rc.Y = p1.Y
rc.Height = p2.Y - p1.Y
Else
rc.Y = p2.Y
rc.Height = p1.Y - p2.Y
End If
' Рисуем обратимую рамку.
ControlPaint.DrawReversibleFrame(rc, Color.Red, FrameStyle.Dashed)
End Sub
' Вызывается при нажатии на левую кнопку мыши.
Public Sub MyMouseMove(ByVal sender As System.Object,ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
' Запоминаем, что мы обрабатываем движение мыши.
bHaveMouse = True
' Запоминаем "стартовую точку" прямоугольника резиновой ленты.
ptOriginal.X = e.X
prOriginal.Y = e.Y
' Специальное значение, указывающее на отсутстствие
' прямоугольника, который нужно стереть.
ptLast.X = -1
ptLast.Y = -1
End Sub
' Вызывается, когда левая кнопка мыши отпускается.
Public Sub MyMouseUp(ByVal sender As System.Object, ByVal e As System.Windows.MouseEventArgs) Handles MyBase.MouseUp
' Устанавливаем внутренний флаг, чтобы знать, что мы более не обрабатываем движение мыши.
bHaveMouse = False
' Если мы рисовали раньше, рисуем еще раз в этой же позиции
' для удаления линий.
if (ptLast.X <> -1) Then
Dim ptCurrent As Point
ptCurrent.X = e.X
ptCurrent.Y = e.Y
MyDrawReversibleRectangle(ptOriginal, ptLast)
End If
' Устанавливаем флаги, указывающие на отсутствие линий для обращения.
ptLast.X = -1
ptLast.Y = -1
ptOriginal.X = -1
ptOriginal.Y = -1
End Sub
' Вызывается при перемещении мыши.
Public Sub MyMouseMove(ByVal sender As System.Object, ByVal e As System.Windows.MouseEventArgs) Handles MyBase.MouseMove
Dim ptCurrent As Point
ptCurrent.X = e.X
ptCurrent.Y = e.Y
' Если мы обрабатываем движение мыши, то рисуем наши линии.
If (bHaveMouse) Then
' Если мы рисовали раньше, рисуем еще раз в этой же позиции
' для удаления линий.
If (ptLast.X <> -1) Then
MyDrawReversibleRectangle(ptOriginal, ptLast)
End If
' Обновляем послюднюю точку
ptLast = ptCurrent
' Рисуем новые линии.
MyDrawReversibleFrame(ptOriginal, ptCurrent)
End If
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
bHaveMouse = False
End Sub
End Class
Заметьте, что это решение доступно только для вывода на экран. Для рисования обратимых линий на графических объектах вы должны либо взаимодействовать с GDI, либо вызывать Bitmap::LockBits() и непосредственно манипулировать с битами изображения.
Примечания переводчика:
1. Подвигло меня на этот перевод участившиеся топики на тему "как сделать selection tool в VB.NET".
2. Несмотря на то, что указано, что это применимо к VB.NET 2002 и VB.NET 2003, все успешно применяется и в VB.NET 2005 поскольку ничего нового в NET Framework в этой части не появилось.
3. Помимо использования функции ControlPaint.DrawReversibleFrame() можно также использовать функции ControlPaint.DrawReversibleLine() для рисования обратимых отрезков и ControlPaint.FillReversibleRectangle(). А вот сделать что-либо подобное для других фигур (например для круга) невозможно
Примечания модератора:
1. Товарисч, ну не надо же такие хард-брейки текста оставлять...