在 C# 中创建不同的画笔图案

2024-01-05

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

我不知道从哪里开始。我一天中的大部分时间都在浏览文档并观看 YouTube 视频。我比刚开始时更加失落。我遇到的最接近的东西是线帽,但这绝对不是我要找的。


!!请参阅下面的更新!

Hans' link https://msdn.microsoft.com/en-us/library/system.drawing.texturebrush(v=vs.110).aspx should point you in the right direction, namely toward TextureBrushes https://msdn.microsoft.com/en-us/library/system.drawing.texturebrush(v=vs.110).aspx.

为了进一步帮助您,请注意以下几点:

  • TextureBrush is a brush, not a pen. So you can't follow a path, like the mouse movements to draw along that curve. Instead, you need to find an area to fill with the brush.

  • This also implies that you need to decide how and when to trigger the drawing; basic options are by time and/or by distance. Usually, the user can set parameters for these often called 'flow' and 'distance'..

  • Instead of filling a simple shape and drawing many of those, you can keep adding the shapes to a GraphicsPath https://msdn.microsoft.com/en-us/library/system.drawing.drawing2d.graphicspath(v=vs.110).aspx and fill that path.

  • To create a TextureBrush you need a pattern file that has transparency. You can either make some or download them from the web where loads of them are around, many for free.

  • 大多数都是 Photoshop 画笔格式“abr”;如果它们不是太新(abrMate将它们转换为 png 文件。

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

  • 大多数图案都是带有 Alpha 的黑色,因此如果您想要颜色,则需要创建当前画笔图像的彩色版本(可能使用 ColorMatrix)。

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

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


Update

在做了一些测试之后,我不得不撤回最初的假设,即“TextureBrush”是使用纹理笔尖进行绘图的合适工具。

对于填充区域来说是可以的,但是对于徒手绘制它就无法正常工作。有几个原因..:

  • 一是TextureBrush总是tile以某种方式翻转图案,无论是否翻转,这总是看起来像是在揭示一个大的底层图案,而不是用几笔画堆积油漆。

  • 另一个是找到要填充的区域是相当困难的。

  • 另外,提示可能是也可能不是方形的,但除非你用矩形填充,否则就会有间隙。

See here https://stackoverflow.com/questions/40105910/fill-texture-brush-using-image-not-tile/40112000?s=4%7C28.3185#40112000举个你的例子don't想要在工作中。

解决方案非常简单,上面的大部分内容仍然适用:

  • 你所做的几乎是常规绘图,但最后,你做了一个DrawImage与准备好的“画笔”图案。

常规绘图涉及:

  • A List<List<Point>> curves保存所有已完成的鼠标路径
  • A List<Point> curentCurve对于当前路径

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

对于用图案进行绘画,还需要了解when画画which图案版本。

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

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 以及可能的旋转角度生成字符串;这样每个模式将只存储一次。

这是一个工作中的例子:

一些注意事项:

在 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() call!

在 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 的较小副本。

重要的是让面板双缓冲! https://stackoverflow.com/questions/44185298/update-datagridview-very-frequently/44188565#44188565以避免闪烁!


Update:代替Panel,这是一个Container控制而不是真正意味着绘制你可以使用Picturebox or a Label (with Autosize=false);两者都有DoubleBuffered属性开箱即用,并且支持绘图比Panels do.

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C# 中创建不同的画笔图案 的相关文章

  • 将 new 与 decltype 一起使用

    T t T is an implementation detail t new T want to avoid naming T to allow for flexibility t new decltype t error cannot
  • 在 Java 中创建 T 的新实例

    在C 中 我们可以定义一个泛型class A
  • 在 OnModelCreating 期间设置列名称

    Issue 我目前正在尝试通过设置的属性为我的表及其列添加前缀 我正在使用实体框架核心 我已经正确地为表名添加了前缀 但我似乎无法弄清楚列的前缀 我有一种感觉 我需要使用反射 我已经留下了我的 可能很糟糕的 反思尝试 有人有办法在实体中设置
  • 检测wlan是否关闭

    任何人都可以给我一个提示 如何在 Windows Phone 上以编程方式检测 C 8 1 应用程序 不是 8 0 是否启用 禁用 WLAN 我不想更改这些设置 只是需要知道 该解决方案是一个 Windows 8 1 通用应用程序 Wind
  • 将完整模板参数值映射到原始类型

    我想将数字映射到类型 在这个例子中 我将创建一个函数 将 sizeof 结果映射到有符号的原始类型 我想知道是否有更好的方法来完成我在现代 C 中所做的事情 即采用模板化值并将其转换为类型 现在 这可以将大小转换为已知类型 但我似乎无法在标
  • std::call_once 可重入且线程安全吗?

    std call once http en cppreference com w cpp thread call once是线程安全的 但它也是可重入的吗 我使用 VS2012 调试和发布 进行的测试表明 调用std call once从单
  • 运行需要 MySql.Data 的内置 .NET 应用程序

    我在运行我编写的内置 NET 应用程序时遇到问题 我的应用程序使用最新的 MySql 连接器 该连接器安装在我的系统上 当我尝试将其添加为引用时 该连接器显示为 NET 4 Framwork 组件 当我在环境中以调试模式运行应用程序时 一切
  • 一元 +/- 运算符如何可能导致“-a”或“+a”中的整数提升,“a”是算术数据类型常量/变量?

    这句看似微不足道的台词摘自我的迈克 巴纳汉和布雷迪的 C 书 第 2 8 8 2 节 http publications gbdirect co uk c book chapter2 expressions and arithmetic h
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • 增强精神、递归和堆栈溢出

    为什么下面的代码在运行时崩溃 它会给出堆栈溢出错误 include
  • C# 编译器不会优化不必要的强制转换

    前几天 在写答案的时候这个问题 https stackoverflow com questions 2208315 why is any slower than contains在这里 关于溢出 我对 C 编译器感到有点惊讶 它没有按照我的
  • 如何在三个 IEnumerable 上使用 Zip [重复]

    这个问题在这里已经有答案了 可能的重复 使用 Linq 从 3 个集合创建项目 https stackoverflow com questions 5284315 create items from 3 collections using
  • 析构函数中的异步操作

    尝试在类析构函数中运行异步操作失败 这是代码 public class Executor public static void Main var c1 new Class1 c1 DoSomething public class Class
  • 如何使用 NPOI 按地址(A1、A2)获取 Excel 单元格值

    我有一个 Excel 单元格地址 例如 A1 A2 如何使用 C 中的 NPOI 框架以编程方式访问此单元格 我找到的一些 Java POI 示例代码 CellReference cr new CellReference A1 row my
  • 从BackgroundWorker线程更新图像UI属性

    在我正在编写的 WPF 应用程序中 我有一个 TransformedBitmap 属性 该属性绑定到 UI 上的 Image 对象 每当我更改此属性时 图像就会更新 因此显示在屏幕上的图像也会更新 为了防止在检索下一张图像时 UI 冻结或变
  • Project Euler #8,我不明白我哪里出了问题[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我正在做项目欧拉第八题 https projecteuler net problem 8 其中我得到了这个大得离谱的数字 7316
  • 在 C#.NET 中安全删除文件

    在我正在做的一个项目中 我想为用户提供 安全 删除文件的选项 例如 用随机位或 0 覆盖它 在 C NET 中是否有一种简单的方法可以做到这一点 效果如何 你可以调用系统内部删除 http technet microsoft com en
  • C++ 中 void(*)() 和 void(&)() 之间的区别[重复]

    这个问题在这里已经有答案了 在此示例代码中 func1是类型void int double and funky是类型void int double include
  • DataContractSerializer 事件/委托字段问题

    在我的 WPF 应用程序中 我正在使用DataContractSerializer序列化对象 我发现它无法序列化具有事件或委托声明的类型 考虑以下失败的代码 Serializable public abstract class BaseCl
  • 如何将 SQL“LIKE”与 LINQ to Entities 结合使用?

    我有一个文本框 允许用户指定搜索字符串 包括通配符 例如 Joh Johnson mit ack on 在使用 LINQ to Entities 之前 我有一个存储过程 该存储过程将该字符串作为参数并执行以下操作 SELECT FROM T

随机推荐

  • 使用 ETW 跟踪 Windows 用户模式进程系统调用

    有些人告诉我 ETW 提供了一种捕获用户模式进程发出的系统调用的机制 我已经列举了可用的提供者 并且只提出了两个可能提供此信息的可能的提供者 第一个是 Microsoft Windows Kernel Audit API Calls 该提供
  • 如何使用 pycharm 调试 docker-compose 内运行的进程

    我正在尝试将本地 Pycharm Django 切换到基于 docker 的开发环境 我在 mac 上运行并使用 Docker Compose 很少的 docker 我的 django 应用程序 一些 db 和 nginx 一切运行良好 代
  • scikit-learn 中 SVC 和 SVM 有什么区别?

    来自文档 http scikit learn org stable modules svm htmlscikit learn 实现了 SVC NuSVC 和 LinearSVC 这些类能够在数据集上执行多类分类 另一方面 我还了解到 sci
  • 是否总是可以使用 HTML5

    我一直注意到您可以使用 HTML5 标签播放音频文件 考虑到您只需要使用 1 个元素来播放视频和音频 这看起来真的很方便 一个例子是这个 JSFiddle http jsfiddle net oacLrnvv
  • 如何在 Windows/Linux 上设置 Java Swing 应用程序的 DPI?

    如果您的显示器的 DPI 超过 150 例如 Macbook Pro 您也可能会发现问题 Java Swing 应用程序上的字体对于高 DPI 显示器来说太小 而且我根本无法更改字体大小 它直接忽略Windows DPI 只显示最初的 DP
  • 如何在 Android 中向操作栏显示溢出菜单项

    我正在编写一个Android应用程序 我试图在其中将溢出菜单项显示到 ActionBar 使用这个很棒的教程链接 http wptrafficanalyzer in blog adding action items and overflow
  • 未找到 Codeception Yii

    我尝试使用 codecept 在 Yii2 项目中运行单元测试 并收到下一个错误 PHP Fatal error Class Yii not found in var www html mysite vendor codeception c
  • 运行应用程序时出现 iOS Phonegap Infinite Dialog 错误?

    我在为 iOS 开发 PhoneGap 应用程序时遇到问题 我刚刚将所有 html css javascript 标记复制到phonegap 应用程序中 我在 10 6 8 的 Mac 上使用 xcode3 当我运行该应用程序时 加载并安装
  • 将 nvarchar 值转换为数据类型 int 时转换失败

    我的代码隐藏中出现转换失败的错误 我的代码如下 using SqlCommand cmd new SqlCommand tempUsertype 0 Select from tbl students Select from tbl stud
  • 闪屏安卓

    我正在尝试创建一种效果 看起来就像您在拍摄设备屏幕截图时看到的闪光一样 我的问题是 有什么办法可以做到这一点吗 如果可以的话我可以改变那个小闪光灯的颜色吗 您将需要使用 FrameLayout 或relativelayout 作为根视图 然
  • 从 ResultSet 获取 Integer 对象 [重复]

    这个问题在这里已经有答案了 A ResultSet提供方法getInt 返回原始值int 是否可以获得Integer对象 它允许null 我正在检索的数据库字段可以为空并且getInt 返回我0每当该字段null Thanks 只需检查该字
  • [azure 服务总线 - 如何在 Azure 服务总线中使用 JMS 设置消息 ID

    使用 Spring JMS 向 Azure 服务总线发送消息时 消息 ID 被覆盖 因此 重复检测无法按预期工作 我读过 JMS 文档 其中说 JMSMessageId 不能由生产者设置 它由 JMS 保留供内部使用 现在的问题是如何设置
  • SQL表-根据条件组合行[重复]

    这个问题在这里已经有答案了 我有一张像这样的桌子 DateCol TaskID EventName 2017 09 25 10 A 2017 07 26 10 B 2017 07 27 10 A 2017 09 14 10 A 2017 0
  • 如何在 ASP.NET WebAPI 中返回文件 (FileContentResult)

    在常规 MVC 控制器中 我们可以使用以下命令输出 pdfFileContentResult public FileContentResult Test TestViewModel vm var stream new MemoryStrea
  • Node.js、protobuf、buffer.length..如何通过 tcp 发送结构化缓冲区/消息?

    我写了一个 node ssjs 程序 它可以 使用 TLS 模块与数据服务器 Apache MIMA 进行 TCP 连接 好的 通过 protobuffer 模块对消息进行编码 解码 序列化 反序列化 OK 将序列化消息发送到服务器并获取响
  • 默认插入向量不是默认初始化吗?

    中的一个std vector构造函数规定为 强调我的 explicit vector size type n const Allocator Allocator Effects 构造一个vector with n 默认插入使用指定分配器的元
  • 如何在组框中获取选中的单选按钮? [复制]

    这个问题在这里已经有答案了 我的组框中有很多单选按钮 通常我会使用单独检查每个单选按钮If radiobutton1 Checked True Then 但我认为也许有一种聪明的方法来检查组框中正在检查哪个单选按钮 任何想法 try thi
  • 从 sqlite 数据库中获取最后一行

    我正在尝试从 SQLite 数据库中获取最后一行 到目前为止 我已经尝试过 max sql sequence 但似乎没有任何效果 我必须获取行值并将其分配给类变量 由于我是 SQLite 和 Android 的新手 因此非常感谢任何帮助 谢
  • 使用自定义引导加载程序创建可引导 ISO 映像

    我正在尝试将我用汇编语言编写的引导加载程序转换为ISO图像文件 以下是代码来自MikeOS http mikeos sourceforge net write your own os html引导加载程序 这是我的引导加载程序代码 BITS
  • 在 C# 中创建不同的画笔图案

    我正在尝试做一些类似于绘画的东西 我想弄清楚如何制作不同的画笔样式 就像在 Paint 3D 中一样 使用钢笔工具与使用画笔工具时 您会得到一定的线条填充 我不知道从哪里开始 我一天中的大部分时间都在浏览文档并观看 YouTube 视频 我