如何在VB.NET画图类应用中实现绘制前光标处画笔预览效果?
实现画笔预览的方案
核心逻辑是拆分实际画布存储和临时预览层,预览内容仅在控件绘制时临时渲染,不会写入到实际画布的存储对象中,具体实现步骤如下:
1. 定义全局状态变量
首先添加必要的全局变量存储画布、画笔属性和鼠标状态:
' 存储实际画布内容,所有最终绘制的内容都会存在这里 Private canvasBmp As Bitmap ' 标记是否正在绘制(鼠标按住状态) Private bStart As Boolean = False ' 画笔当前属性 Private brushSize As Integer = 10 Private brushColor As Color = Color.Red ' 记录当前鼠标位置 Private currentMousePos As Point = Point.Empty
2. 初始化画布
窗体加载时初始化和PictureBox尺寸一致的实际画布,同时开启控件双缓冲避免预览闪烁:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' 初始化画布,底色设为白色 canvasBmp = New Bitmap(pbPhoto.Width, pbPhoto.Height) Using g As Graphics = Graphics.FromImage(canvasBmp) g.Clear(Color.White) End Using pbPhoto.Image = canvasBmp ' 开启双缓冲减少闪烁 pbPhoto.GetType().GetProperty("DoubleBuffered", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic).SetValue(pbPhoto, True, Nothing) End Sub
3. 修改鼠标事件逻辑
鼠标移动时不再直接向PictureBox绘制内容,仅更新鼠标位置,按住时才将笔触写入实际画布:
Private Sub pbPhoto_MouseDown(sender As Object, e As MouseEventArgs) Handles pbPhoto.MouseDown If e.Button = MouseButtons.Left Then bStart = True ' 按下时直接绘制第一笔到实际画布 Using g As Graphics = Graphics.FromImage(canvasBmp) g.FillEllipse(New SolidBrush(brushColor), e.X - brushSize \ 2, e.Y - brushSize \ 2, brushSize, brushSize) End Using pbPhoto.Invalidate() End If End Sub Private Sub pbPhoto_MouseMove(sender As Object, e As MouseEventArgs) Handles pbPhoto.MouseMove currentMousePos = e.Location ' 仅按住鼠标时才将笔触写入实际画布 If bStart AndAlso e.Button = MouseButtons.Left Then Using g As Graphics = Graphics.FromImage(canvasBmp) g.FillEllipse(New SolidBrush(brushColor), e.X - brushSize \ 2, e.Y - brushSize \ 2, brushSize, brushSize) End Using End If ' 强制刷新控件触发绘制事件 pbPhoto.Invalidate() End Sub Private Sub pbPhoto_MouseUp(sender As Object, e As MouseEventArgs) Handles pbPhoto.MouseUp bStart = False pbPhoto.Invalidate() End Sub
4. 实现Paint事件绘制预览层
在PictureBox的Paint事件中先渲染实际画布,再在最上层临时绘制画笔预览,这部分内容不会写入canvasBmp,不会污染实际画布:
Private Sub pbPhoto_Paint(sender As Object, e As PaintEventArgs) Handles pbPhoto.Paint ' 先绘制实际画布内容 e.Graphics.DrawImage(canvasBmp, Point.Empty) ' 未按住鼠标时绘制半透明预览笔触 If Not bStart AndAlso currentMousePos <> Point.Empty Then Using previewBrush As New SolidBrush(Color.FromArgb(180, brushColor)) e.Graphics.FillEllipse(previewBrush, currentMousePos.X - brushSize \ 2, currentMousePos.Y - brushSize \ 2, brushSize, brushSize) End Using End If End Sub
补充说明
- 调整画笔大小或颜色时,只需修改
brushSize和brushColor变量的值,预览效果会自动更新 - 坐标计算时减去画笔尺寸的一半,可保证笔触中心和光标位置完全对齐,和MS Paint的交互逻辑一致
- 如果需要更高性能的预览,也可以将画笔形状生成自定义光标替换系统光标,这种方案无需频繁刷新控件,适合固定形状的画笔场景
内容的提问来源于stack exchange,提问作者Fame th
相关产品推荐
相关产品推荐

