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

时间:2018-03-15 03:09:17

标签: c# winforms picturebox

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

enter image description here

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

1 个答案:

答案 0 :(得分:6)

!!请参阅下面的更新!!

Hans' link应指向正确的方向,即指向TextureBrushes

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

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

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

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

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

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

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

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

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

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

<强>更新

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

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

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

  • 另一个问题是找到要填补的区域存在问题。

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

请参阅here,了解您 想要在工作中做什么的示例。

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

  • 你做的几乎是常规绘画,但最后,你用准备好的刷子做DrawImage&#39;图案。

定期绘图涉及:

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

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

对于使用图案绘图,还需要知道何时来绘制哪个图案版本。

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

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

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

以下是工作中的示例:

enter image description here

一些注意事项:

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

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

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

 curves.Add(new Tuple<Bitmap, List<Point>>(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 Doublebuffered!避免闪烁非常重要!

顺便说一句:以上快速而肮脏的例子只有200行(未注释)。添加画笔旋转,预览,步进距离,保存按钮和实现画笔缓存会使其达到300行。