如何避免 graphics.drawrectangle() 上的不透明矩形重叠?

How to avoid overlapping of opaque rectangles on graphics.drawrectangle()?

在 Google 搜索失败后,我终于想到请专家来帮助我解决这个问题,因为这个网站总是帮助我。

我想要什么?

I want to create a Highlighter for my some kind of drawing application. I want this to be similar to the highlighter you can see on the Windows Snipping Tool.

我的问题是什么?

The problem is that although I can draw the semitransparent or opaque rectangles using the code, gfx.FillRectangle(New SolidBrush(Color.FromArgb(100, Colors.GreenYellow)), x, y, width, height), but if I draw another rectangle overlapping any previous rectangles the colors gets darker and reduces the transparency of the rectangles where they overlapped.

代码:

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

应用程序的屏幕截图(显示问题

我试过了,效果很好:没有边框,你甚至无法区分不同的盒子: 我更改了以下内容:

New SolidBrush(Color.FromArgb(100, Color.GreenYellow)), New Point(200, 200))

进入这个:

New SolidBrush(Color.GreenYellow), New Point(200, 200))

两次:对于声明和 Panel1_MouseDown 这是因为默认情况下这会将 Alpha 设置为 1,因此也无法更改,因此重叠不会更改任何颜色、图层或可见性。

您应该只在要控制颜色的 alpha 时使用 FromArgb,但在这种情况下,您是让计算机为您做这件事

嗯。我从来没有真正使用过图形,但我唯一能想到的就是创建一个要绘制的高光列表,然后每次 mouse_up 事件触发时,创建一个新的位图,绘制每个矩形像素按像素,将半透明像素绘制到位图,然后使用刷新面板时触发的面板的绘制事件处理程序将生成的位图绘制到面板。这似乎是 .net 自动执行的内置 alpha 混合。

将此添加到表单的变量声明中

Dim highlightsList As New List(Of Rectangle)
Dim bmp1 As Bitmap

将您的 form_shown 活动更改为

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

这似乎可行,但如果您将面板用于显示高亮显示的任何其他内容,它可能无法按预期工作。