在c#中创建不同的画笔模式

我正在尝试制作类似油漆的东西。 我想弄清楚如何制作不同的画笔样式。 就像在Paint 3D中一样,当使用钢笔工具和使用画笔工具时,你会得到一定的线条填充。

在此处输入图像描述

我不知道从哪里开始。 我花了很多时间查看文档,观看YouTubevideo。 我比起初时更迷茫。 我遇到的最接近的是线帽,但这绝对不是我想要的。

!!见下面的更新!!

Hans的链接应该指向正确的方向,即指向TextureBrushes 。

为了帮助您进一步观察以下几点:

  • TextureBrush是画笔,而不是笔。 因此,您无法沿着路径行进,例如沿着该曲线绘制的鼠标移动。 相反,您需要找到一个用刷子填充的区域。

  • 这也意味着 你需要决定如何以及何时触发绘图; 基本选项是按时间和/或按距离。 通常,用户可以为这些通常称为“流量”和“距离”的参数设置参数。

  • 您可以继续将形状添加到GraphicsPath并填充该路径,而不是填充简单的形状并绘制其中的许多形状。

  • 创建TextureBrush 你需要一个具有透明度的模式文件。 您可以制作一些或从网上下载它们,其中许多是免费的。

  • 大多数都是Photoshop画笔格式’abr’; 如果它们不是太近(<= CS5),您可以使用abrMate将它们转换为png文件。

  • 您可以将一组画笔加载到ImageList,设置足够大的尺寸(最大256×256)和32bpp以允许alpha。

  • 大多数图案都是黑色的alpha,所以如果你想要颜色,你需要创建当前画笔图像的彩色版本(可能使用ColorMatrix)。

  • 您可能还想更改其透明度(最好也使用ColorMatrix)。

  • 并且您需要将大小更改为当前画笔大小。


更新

在做了一些测试后,我不得不收回一个原始的假设,即TextureBrush是一个适合绘制纹理提示的工具。

填充区域是可以的,但是对于自由式绘图,它将无法正常工作。 有几个原因..:

  • 一个是TextureBrush将始终以某种方式平铺图案,翻转或不翻转,这总是看起来像是在显示一个大的底层图案而不是用几个笔划打桩。

  • 另一个是找到要填补的区域是相当有问题的。

  • 此外,提示可能是也可能不是正方形,但除非您填充矩形,否则会有间隙。

在此处查看您希望工作的示例。

解决方案非常简单,上述大部分仍然适用:

  • 你做的是非常规则的绘图,但最后,你用准备好的’brush’模式做一个DrawImage

定期绘图涉及:

  • 包含所有已完成鼠标路径的List> curves
  • 当前路径的List curentCurve

Paint事件中,您绘制所有曲线,如果有任何点,也绘制当前路径。

对于使用图案绘图,还必须知道何时绘制哪个图案版本。

如果我们确保不泄漏它们,我们可以缓存画笔模式..:

 Bitmap brushPattern = null; List>> curves = new List>>(); Tuple> curCurve = null; 

这是一种简单/简单的缓存方法。 为了提高效率,您可以使用Dictionary ,其命名方案可以根据模式索引,大小,颜色,alpha和旋转角度生成字符串; 这样每个模式只能存储一次。

这是一个工作的例子:

在此处输入图像描述

几点说明:

在MouseDown中,我们创建一个新的当前曲线:

 curCurve = new Tuple>(brushPattern, new List()); curCurve.Item2.Add(e.Location); 

在MouseUp中,我将当前曲线添加到曲线列表中:

  curves.Add(new Tuple>(curCurve.Item1, curCurve.Item2.ToList())); 

由于我们要清除当前曲线,我们需要复制其点列表; 这是通过ToList()调用实现的!

在MouseMove中,我们只需添加一个新点:

 if (e.Button == MouseButtons.Left) { curCurve.Item2.Add(e.Location); panel1.Invalidate(); } 

Paint遍历所有曲线,包括当前曲线:

 for (int c = 0; c < curves.Count; c++) { e.Graphics.TranslateTransform(-curves[c].Item1.Width / 2, -curves[c].Item1.Height / 2); foreach (var p in curves[c].Item2) e.Graphics.DrawImage(curves[c].Item1, p); e.Graphics.ResetTransform(); } if (curCurve != null && curCurve.Item2.Count > 0) { e.Graphics.TranslateTransform(-curCurve.Item1.Width / 2, -curCurve.Item1.Height / 2); foreach (var p in curCurve.Item2) e.Graphics.DrawImage(curCurve.Item1, p); e.Graphics.ResetTransform(); } 

它确保图案以中心绘制。

ListView设置为SmallIcons,其SmallImageList指向原始ImageList的较小副本。

让Panel Doublebffered是很重要的! 避免闪烁!

顺便说一句:上面的快速和脏的例子只有200(未注释)行。 添加画笔旋转,预览,步进距离,保存按钮和实现画笔缓存可将其转换为300行。