如何在实际绘画之前在光标处显示画笔?

问题描述

我想让照片编辑器像 MS-Paint 一样。 笔刷模式,当用户点击鼠标并移动鼠标时,会绘制描边。

Private Sub pbPhoto_MouseDown(sender As Object,e As MouseEventArgs) Handles pbPhoto.MouseDown
    bStart = true
End Sub
Private Sub pbPhoto_MouseMove(sender As Object,e As MouseEventArgs) Handles pbPhoto.MouseMove
    If bStart Then
         Dim b As SolidBrush(Color.Red)
        pbPhoto.CreateGraphics.FillEllipse(b,e.X,e.Y,10,10)
    End If
End Sub
Private Sub pbPhoto_MouseUp(sender As Object,e As MouseEventArgs) Handles pbPhoto.MouseUp
     bStart = false
End Sub

画的很好。但是,如果您查看 MS-Paint,则会在光标中心看到一个画笔。它总是显示,但在鼠标按下之前它不会绘制到图片框。如果您更改画笔大小或颜色,您可以在光标处看到预览。

enter image description here

如何在没有油漆的情况下显示笔触?

解决方法

您可以创建一个图像来反映画笔工具的颜色和大小,并使用它为绘图画布创建自定义光标。每当您选择画笔工具或在选择画笔工具时更改颜色/大小时,都应调用此例程。自定义光标的句柄在不再使用时应销毁。例如,当您选择其他绘图工具或关闭表单时。

图片


接近的东西。 penWidthmaxWidth 参数用于计算画笔的大小。图片中的红色圆圈。例如,TrackBar 控件的 ValueMaximum 属性。

' +
Imports System.Drawing.Drawing2D

' ...

Private Function CreateBrushBitmap(color As Color,penWidth As Integer,maxWidth As Integer) As Bitmap
    Dim bmp As New Bitmap(32,32)
    Dim rec As New Rectangle(0,32,32)

    Using g = Graphics.FromImage(bmp),br = New SolidBrush(color),pn = New Pen(Color.Gray) With {.DashStyle = DashStyle.Dot}

        g.SetClip(Rectangle.Inflate(rec,-8,-8),CombineMode.Exclude)
        g.DrawLine(pn,(rec.Width - 1) \ 2,rec.Y,rec.Height)
        g.DrawLine(pn,rec.X,(rec.Height - 1) \ 2,rec.Width,(rec.Height - 1) \ 2)
        g.ResetClip()

        Dim ellipseRec = Rectangle.Inflate(rec,-10,-10)
        Dim sz = CSng(Math.Round(ellipseRec.Width * penWidth / maxWidth))
        Dim r = New RectangleF(
            ellipseRec.X + (ellipseRec.Width - sz) / 2 - 1,ellipseRec.Y + (ellipseRec.Height - sz) / 2 - 1,sz,sz)

        g.SmoothingMode = SmoothingMode.AntiAlias
        g.FillEllipse(br,r)
    End Using

    Return bmp
End Function

自定义光标


CreateBrushCursor 函数调用下面显示的本机函数来创建自定义光标。 Credit

' +
Imports System.Runtime.InteropServices

' ...

Private Function CreateBrushCursor(bmp As Bitmap,xHotspot As Integer,yHotspot As Integer) As Cursor
    Dim inf As New ICONINFO With {
        .xHotspot = xHotspot,.yHotspot = yHotspot,.fIcon = False,.hbmMask = bmp.GetHbitmap(),.hbmColor = bmp.GetHbitmap()
    }

    Dim pnt As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(inf))

    Marshal.StructureToPtr(inf,pnt,True)

    Dim curPtr As IntPtr = CreateIconIndirect(pnt)

    DestroyIcon(pnt)
    DeleteObject(inf.hbmMask)
    DeleteObject(inf.hbmColor)

    Return New Cursor(curPtr)
End Function

Private Structure ICONINFO
    Public fIcon As Boolean
    Public xHotspot As Integer
    Public yHotspot As Integer
    Public hbmMask As IntPtr
    Public hbmColor As IntPtr
End Structure

<DllImport("user32.dll",EntryPoint:="CreateIconIndirect")>
Private Shared Function CreateIconIndirect(ByVal iconInfo As IntPtr) As IntPtr
End Function

<DllImport("user32.dll",SetLastError:=True)>
Private Shared Function DestroyIcon(ByVal hIcon As IntPtr) As Boolean
End Function

<DllImport("gdi32.dll")>
Private Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean
End Function

实施


在选择画笔工具时调用 CreateBrushCursor 方法创建和设置自定义光标,设置画笔的颜色/大小。在本例中,picSelectedColortbPenWidth 是用于创建光标图像的输入控件。 picCanvas 是绘图画布。

Private Sub CreateBrushCursor()
    DestroyBrushCursor()
    customBrushCursor = CreateBrushCursor(
        CreateBrushBitmap(
        picSelectedColor.BackColor,tbPenWidth.Value,tbPenWidth.Maximum),16,16)
    picCanvas.Cursor = customBrushCursor
End Sub

最后,调用 DestroyBrushCursor 方法进行清理。当您选择其他工具时,关闭绘图表单...等

Private Sub DestroyBrushCursor()
    If customBrushCursor IsNot Nothing Then
        customBrushCursor.Dispose()
        customBrushCursor = Nothing
    End If
End Sub

SOQ68208917

注意:绘图程序无关,因此未列出。