После нескольких неудачных поисков в Google, наконец, я подумал о том, чтобы попросить экспертов помочь мне в этой проблеме, поскольку этот сайт всегда мне помогал.
Чего я хочу?
Я хочу создать маркер для своего приложения для рисования. Я хочу, чтобы это было похоже на маркер, который вы видите в Windows Snipping Tool.
В чем моя проблема?
Проблема заключается в том, что хотя я и могу рисовать полупрозрачные или непрозрачные прямоугольники с помощью кода gfx.FillRectangle(New SolidBrush(Color.FromArgb(100, Colors.GreenYellow)), x, y, width, height), но если я рисую другой прямоугольник, перекрывающий любые предыдущие прямоугольники, цвета становятся темнее и уменьшают прозрачность прямоугольников в местах их перекрытия.
Код:
Public Class Form1
Dim drag As Boolean
Dim mouseX, mouseY As Integer
Dim prev As Point
Dim initi As Point
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Dim grx As Graphics = Panel1.CreateGraphics
grx.DrawString("+", New Font("Arial", 144, FontStyle.Regular), New SolidBrush(Color.FromArgb(100, Color.GreenYellow)), New Point(200, 200))
End Sub
Private Sub Panel1_MouseDown(sender As Object, e As MouseEventArgs) Handles Panel1.MouseDown
drag = True
mouseX = MousePosition.X - Me.Left - 8
mouseY = MousePosition.Y - Me.Top - 34
initi = New Point(mouseX, mouseY)
End Sub
Private Sub Panel1_MouseMove(sender As Object, e As MouseEventArgs) Handles Panel1.MouseMove
If drag Then
mouseX = MousePosition.X - Me.Left - 8
mouseY = MousePosition.Y - Me.Top - 34
End If
End Sub
Private Sub Panel1_MouseUp(sender As Object, e As MouseEventArgs) Handles Panel1.MouseUp
drag = False
prev = New Point(0, 0)
Dim grx As Graphics = Panel1.CreateGraphics
grx.FillRectangle(New SolidBrush(Color.FromArgb(100, Color.GreenYellow)), initi.X, initi.Y, (mouseX - initi.X), (mouseY - initi.Y))
End Sub
End Class
Скриншот приложения (показывает проблему)
- Левый "+" тот, который я хочу нарисовать.
- Правильный "+" - это тот, который я получаю, когда рисую.

Ответ 1 · David Wilson
Что ж. Я никогда не использовал графику, но единственное, что я мог придумать, это создать список бликов, которые нужно нарисовать, а затем каждый раз, когда срабатывает событие mouse_up, создавать новое растровое изображение, рисовать каждый прямоугольник попиксельно, с полупрозрачные пиксели в растровое изображение, а затем нарисуйте полученное растровое изображение на панели с помощью обработчика события рисования панели, который срабатывает при обновлении панели. Это похоже на встроенное альфа-смешивание, которое .net делает автоматически.
Добавьте это в объявления переменных вашей формы
Dim highlightsList As New List(Of Rectangle)
Dim bmp1 As Bitmap
измените ваше событие form_show на
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
bmp1 = New Bitmap(Panel1.Width, Panel1.Height)
End Sub
добавьте этот подраздел, который обрабатывает добавление прямоугольников в список и создание растрового изображения
Private Sub addRectangle(gr As Graphics, x As Integer, y As Integer, v1 As Integer, v2 As Integer)
Dim newRectangle As New Rectangle(x, y, v1, v2)
highlightsList.Add(newRectangle)
Using G As Graphics = Graphics.FromImage(bmp1)
G.Clear(Color.White)
End Using
bmp1.MakeTransparent(Color.White)
For Each rect As Rectangle In highlightsList
For i As Integer = rect.X To rect.X + rect.Width - 1
For j As Integer = rect.Y To rect.Y + rect.Height - 1
bmp1.SetPixel(i, j, Color.FromArgb(100, Color.GreenYellow))
Next
Next
Next
Panel1.Refresh()
End Sub
добавить обработчик события рисования панели, чтобы при обновлении панели растровое изображение рисовалось на ней
Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint
e.Graphics.DrawImage(bmp1, 0, 0)
End Sub
и измените событие mouse_up, чтобы использовать приведенный выше подраздел для рисования
Private Sub Panel1_MouseUp(sender As Object, e As MouseEventArgs) Handles Panel1.MouseUp
drag = False
prev = New Point(0, 0)
Dim grx As Graphics = Panel1.CreateGraphics
'grx.Clear(Panel1.BackColor)
addRectangle(grx, initi.X, initi.Y, (mouseX - initi.X), (mouseY - initi.Y))
End Sub
Кажется, это работает, но если вы используете панель для чего-то другого, что показывает основные моменты, это может работать не так, как ожидалось.
Ответ 2 · рейтинг 1 · TGamer
Я попробовал это, и это работает: границ нет, вы даже не можете различить разные поля: я изменил следующее:
New SolidBrush(Color.FromArgb(100, Color.GreenYellow)), New Point(200, 200))
В это:
New SolidBrush(Color.GreenYellow), New Point(200, 200))
В ОБОИХ случаях: для объявлений и для Panel1_MouseDown Это потому, что это устанавливает альфа-канал равным 1, по умолчанию также делая неизменяемым, поэтому перекрытие не изменит ни цвета, ни слои, ни видимость.
Вы должны использовать FromArgb только тогда, когда собираетесь управлять альфой цвета, но в этом случае вы позволяете компьютеру сделать это за вас.