如何在实际绘画之前在光标处显示画笔?
How to display brush at cursor before actually paint?
我想制作像 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,会在光标的中心看到一个画笔。它总是显示,但在按下鼠标之前不会绘制到图片框。如果您更改画笔大小或颜色,您可以在光标处看到预览。
如何在没有绘画的情况下显示笔触?
您可以创建一个图像来反映画笔工具的颜色和大小,并使用它为绘图创建自定义光标 canvas。每当您 select 画笔工具或在 select 编辑画笔工具时更改 color/size 时,都应调用此例程。自定义游标的句柄在不再使用时应销毁。例如,当您 select 另一个绘图工具或关闭表单时。
图像
有些接近。 penWidth
和 maxWidth
参数来计算画笔的大小。图片中的红色圆圈。例如,TrackBar
控件的 Value 和 Maximum 属性。
' +
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, 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.Width - 1) \ 2, 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
实施
画笔工具select时调用CreateBrushCursor
方法创建和设置自定义光标,设置画笔color/size。在此示例中,picSelectedColor
、tbPenWidth
是用于创建光标图像的输入控件。 picCanvas
是绘图 canvas.
Private Sub CreateBrushCursor()
DestroyBrushCursor()
customBrushCursor = CreateBrushCursor(
CreateBrushBitmap(
picSelectedColor.BackColor, tbPenWidth.Value, tbPenWidth.Maximum), 16, 16)
picCanvas.Cursor = customBrushCursor
End Sub
最后调用DestroyBrushCursor
方法进行清理。当你select另一个工具时,关闭绘图窗体...等等
Private Sub DestroyBrushCursor()
If customBrushCursor IsNot Nothing Then
customBrushCursor.Dispose()
customBrushCursor = Nothing
End If
End Sub
注:绘图例程无关故不列出。
我想制作像 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,会在光标的中心看到一个画笔。它总是显示,但在按下鼠标之前不会绘制到图片框。如果您更改画笔大小或颜色,您可以在光标处看到预览。
如何在没有绘画的情况下显示笔触?
您可以创建一个图像来反映画笔工具的颜色和大小,并使用它为绘图创建自定义光标 canvas。每当您 select 画笔工具或在 select 编辑画笔工具时更改 color/size 时,都应调用此例程。自定义游标的句柄在不再使用时应销毁。例如,当您 select 另一个绘图工具或关闭表单时。
图像
有些接近。 penWidth
和 maxWidth
参数来计算画笔的大小。图片中的红色圆圈。例如,TrackBar
控件的 Value 和 Maximum 属性。
' +
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, 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.Width - 1) \ 2, 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
实施
画笔工具select时调用CreateBrushCursor
方法创建和设置自定义光标,设置画笔color/size。在此示例中,picSelectedColor
、tbPenWidth
是用于创建光标图像的输入控件。 picCanvas
是绘图 canvas.
Private Sub CreateBrushCursor()
DestroyBrushCursor()
customBrushCursor = CreateBrushCursor(
CreateBrushBitmap(
picSelectedColor.BackColor, tbPenWidth.Value, tbPenWidth.Maximum), 16, 16)
picCanvas.Cursor = customBrushCursor
End Sub
最后调用DestroyBrushCursor
方法进行清理。当你select另一个工具时,关闭绘图窗体...等等
Private Sub DestroyBrushCursor()
If customBrushCursor IsNot Nothing Then
customBrushCursor.Dispose()
customBrushCursor = Nothing
End If
End Sub
注:绘图例程无关故不列出。