WinForms中PictureBox鼠标绘点及矩形四角椭圆对齐问题
C# WinForms PictureBox 绘图问题解决方案
问题1:在鼠标点击位置绘制填充圆点
现有pictureBox2_MouseDown代码存在逻辑错误:手动将x和y设为0,导致后续坐标范围判断失效;且当前逻辑仅添加空尺寸的DrawingRectangle,未实现绘制圆点的需求。
修正后的MouseDown事件代码
private void pictureBox2_MouseDown(object sender, MouseEventArgs e) { if (e.Button != MouseButtons.Left) return; // 获取鼠标在PictureBox内的点击坐标 Point mousePos = e.Location; if (pictureBox2.Image != null && selectedPath != null) { // 校验点击位置是否在Image范围内 if (mousePos.X >= 0 && mousePos.X <= pictureBox2.Image.Size.Width && mousePos.Y >= 0 && mousePos.Y <= pictureBox2.Image.Size.Height) { int pointSize = 15; // 添加用于绘制圆点的DrawingRectangle,让圆点中心对齐鼠标位置 DrawingRects.Add(new DrawingRectangle() { Location = new Point(mousePos.X - pointSize/2, mousePos.Y - pointSize/2), Size = new Size(pointSize, pointSize), DrawingcColor = SelectedColor, Owner = (Control)sender }); // 触发重绘更新界面 pictureBox2.Invalidate(); } } }
Paint事件与绘制逻辑调整
修改pictureBox2_Paint事件,移除不必要的DrawingRects.Count > 0判断,确保有内容时就触发绘制:
private void pictureBox2_Paint(object sender, PaintEventArgs e) { if (pictureBox2.Image != null && selectedPath != null) { DrawShapes(e.Graphics); } }
更新DrawShapes方法,增加圆点绘制逻辑:
private void DrawShapes(Graphics g) { if (DrawingRects.Count == 0) return; g.SmoothingMode = SmoothingMode.AntiAlias; foreach (var dr in DrawingRects) { // 绘制圆点(尺寸为15x15的填充椭圆) if (dr.Size.Width == 15 && dr.Size.Height == 15) { using (SolidBrush brush = new SolidBrush(dr.DrawingcColor)) { g.FillEllipse(brush, dr.Rect); } } // 绘制矩形及四角控制点(逻辑见问题2) else if (dr.Rect.Width > 0 && dr.Rect.Height > 0) { using (Pen pen = new Pen(dr.DrawingcColor, DrawingRectangle.PenSize)) { g.DrawRectangle(pen, dr.Rect); int handleSize = 15; g.FillEllipse(Brushes.Red, dr.Rect.Left - handleSize/2, dr.Rect.Top - handleSize/2, handleSize, handleSize); g.FillEllipse(Brushes.Red, dr.Rect.Left - handleSize/2, dr.Rect.Bottom - handleSize/2, handleSize, handleSize); g.FillEllipse(Brushes.Red, dr.Rect.Right - handleSize/2, dr.Rect.Top - handleSize/2, handleSize, handleSize); g.FillEllipse(Brushes.Red, dr.Rect.Right - handleSize/2, dr.Rect.Bottom - handleSize/2, handleSize, handleSize); } } } }
可选:抽离AddPoint方法
如果需要复用添加点的逻辑,可封装为单独方法:
private void AddPoint(Point mousePos, Color color) { if (pictureBox2.Image == null || selectedPath == null) return; if (mousePos.X >= 0 && mousePos.X <= pictureBox2.Image.Size.Width && mousePos.Y >= 0 && mousePos.Y <= pictureBox2.Image.Size.Height) { int pointSize = 15; DrawingRects.Add(new DrawingRectangle() { Location = new Point(mousePos.X - pointSize/2, mousePos.Y - pointSize/2), Size = new Size(pointSize, pointSize), DrawingcColor = color, Owner = pictureBox2 }); pictureBox2.Invalidate(); } }
在MouseDown事件中调用:AddPoint(e.Location, SelectedColor);
问题2:修正矩形四角填充椭圆的位置
现有代码中,Rect.Bottom和Rect.Right是矩形的外边缘坐标,直接作为椭圆左上角坐标会导致椭圆超出矩形范围。需将椭圆位置向左、向上偏移椭圆尺寸的一半,让椭圆中心对齐矩形边角,确保椭圆完全在矩形内部或贴合边角。
修正后的DrawShapes方法(四角控制点部分)
private void DrawShapes(Graphics g) { if (DrawingRects.Count == 0) return; g.SmoothingMode = SmoothingMode.AntiAlias; foreach (var dr in DrawingRects) { if (dr.Rect.Width > 0 && dr.Rect.Height > 0) { using (Pen pen = new Pen(dr.DrawingcColor, DrawingRectangle.PenSize)) { g.DrawRectangle(pen, dr.Rect); int handleSize = 15; // 左上角:中心对齐矩形左上角 g.FillEllipse(Brushes.Red, dr.Rect.Left - handleSize/2, dr.Rect.Top - handleSize/2, handleSize, handleSize); // 左下角:中心对齐矩形左下角 g.FillEllipse(Brushes.Red, dr.Rect.Left - handleSize/2, dr.Rect.Bottom - handleSize/2, handleSize, handleSize); // 右上角:中心对齐矩形右上角 g.FillEllipse(Brushes.Red, dr.Rect.Right - handleSize/2, dr.Rect.Top - handleSize/2, handleSize, handleSize); // 右下角:中心对齐矩形右下角 g.FillEllipse(Brushes.Red, dr.Rect.Right - handleSize/2, dr.Rect.Bottom - handleSize/2, handleSize, handleSize); }; } } }
逻辑说明
- 椭圆尺寸为
15x15,偏移量取15/2=7(整数运算) - 通过偏移让椭圆中心与矩形边角重合,既保证控制点贴合边角,又不会超出矩形范围
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

