在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行。