使用WPF创建画图箭头
原文:使用WPF创建画图箭头
今天要给leader line画个箭头,所以就google一下,找到下面的文章,写的不错,可以实现我的需求,所以就摘录下来。
我把源代码中的arraw.cs加入到我的工程,修改了namespace,然后写了个方法进行调用:
private void DrawLeaderLineArrow(Point startPt, Point endPt)
{
Arrow arrow = new Arrow();
arrow.X1 = startPt.X;
arrow.Y1 = startPt.Y;
arrow.X2 = endPt.X;
arrow.Y2 = endPt.Y;
arrow.HeadWidth = 15;
arrow.HeadHeight = 5;
arrow.Stroke = Brushes.Black;
arrow.StrokeThickness = 1;
_canvas.Children.Add(arrow);
}
WPF Arrow and Custom Shapes
Introduction
WPF is the best UI Framework ever. It provides us with a large arsenal of vector graphic types such as Line
, Ellipse
, Path
and others. Sometimes we need shapes which are not provided in the WPF arsenal (such an Arrow
), and with all due respect to the Path
shape, which can be used to create any type of 2D shape, we do not want to recalculate each point every time. This is a good reason and opportunity to create a custom shape.
Background
WPF provides two kinds of vector types: Shapes and Geometries.
Shape
is any type that derives from the Shape
base class. It provides Fill
, Stroke
and other properties for coloring, and is actually a FrameworkElement
. Thus we can place shapes inside Panel
s, we can register shapes routed events and do anything related to FrameworkElement
. (MSDN)
Geometry
is any type that derives from the Geometry
base type. It provides properties for describing any type of 2D geometry. A geometry is actually a Freezable
type, thus can be frozen. A frozen object provides better performance by not notifying changes, and can be safely accessed by other threads. Geometry
is not Visual
, hence should be painted by other types such as Path
. (MSDN)
Using the Code
Now that we have a little background, and we know what the differences between a Geometry
and Shape
are, we can create our shape based on one of these two types. Correct?
Well, surprisingly we can't base our custom shape on the Geometry
type, since its one and only default constructor is marked as internal. Shame on you Microsoft.
Don't worry! We still have an option to base our custom shape on the Shape
base class.
Now, let’s say that we want to create an Arrow
shape. An arrow is actually a kind of line, so let’s derive our custom type from the WPF Line
type which has X1
, Y1
, X2
and Y2
properties.
Ooopps... Line
is sealed! (Shame on you twice).
Never mind, let's derive directly from the Shape
base class, and add X1
, Y1
, X2
, Y2
and two additional properties for defining the arrow's head width
and height
.
Our code should end up with something like this:
public sealed class Arrow : Shape
{
public static readonly DependencyProperty X1Property = ...;
public static readonly DependencyProperty Y1Property = ...;
public static readonly DependencyProperty HeadHeightProperty = ...;
... [TypeConverter(typeof(LengthConverter))]
public double X1
{
get { return (double)base.GetValue(X1Property); }
set { base.SetValue(X1Property, value); }
} [TypeConverter(typeof(LengthConverter))]
public double Y1
{
get { return (double)base.GetValue(Y1Property); }
set { base.SetValue(Y1Property, value); }
} [TypeConverter(typeof(LengthConverter))]
public double HeadHeight
{
get { return (double)base.GetValue(HeadHeightProperty); }
set { base.SetValue(HeadHeightProperty, value); }
}
... protected override Geometry DefiningGeometry
{
get
{
// Create a StreamGeometry for describing the shape
StreamGeometry geometry = new StreamGeometry();
geometry.FillRule = FillRule.EvenOdd; using (StreamGeometryContext context = geometry.Open())
{
InternalDrawArrowGeometry(context);
} // Freeze the geometry for performance benefits
geometry.Freeze(); return geometry;
}
} /// <summary>
/// Draws an Arrow
/// </summary>
private void InternalDrawArrowGeometry(StreamGeometryContext context)
{
double theta = Math.Atan2(Y1 - Y2, X1 - X2);
double sint = Math.Sin(theta);
double cost = Math.Cos(theta); Point pt1 = new Point(X1, this.Y1);
Point pt2 = new Point(X2, this.Y2); Point pt3 = new Point(
X2 + (HeadWidth * cost - HeadHeight * sint),
Y2 + (HeadWidth * sint + HeadHeight * cost)); Point pt4 = new Point(
X2 + (HeadWidth * cost + HeadHeight * sint),
Y2 - (HeadHeight * cost - HeadWidth * sint)); context.BeginFigure(pt1, true, false);
context.LineTo(pt2, true, true);
context.LineTo(pt3, true, true);
context.LineTo(pt2, true, true);
context.LineTo(pt4, true, true);
}
}
As you can see, it is very easy to implement a custom shape, thanks to the great work in the Shape
base class. All we have to do is derive our custom shape type from Shape
, and override the DefiningGeometry
property. This property should return a Geometry
of any type.
使用WPF创建画图箭头的更多相关文章
- 利用WPF创建含多种交互特性的无边框窗体
咳咳,标题一口气读下来确实有点累,让我先解释一下.另外文章底部有演示程序的下载. 本文介绍利用WPF创建一个含有以下特性的窗口: 有窗口阴影,比如QQ窗口外围只有几像素的阴影: 支持透明且无边框,为了 ...
- WPF 创建无边框的圆角窗口
原文:WPF 创建无边框的圆角窗口 如题所述,在WPF中要创建一个没有边框且为圆角的窗体,有如下几步工作要进行: 第一步:去掉窗体默认样式的边框 首先将窗体的背景设为透明,将允许透明的属性设置为Tru ...
- WPF 创建自定义窗体
在前面的一篇博客"WPF 自定义Metro Style窗体",展示了如何创建一个类似于Metro Style的Window,并在程序中使用.但是这个窗体不能够自由的改变大小.今天的 ...
- wpf 创建动画三种方式
动画类型 : 故事版,CompositionTarget,DispachTime 那么到此,三种动态创建动画的方法都已经详细介绍过了,大家可能会有种感觉,比较钟情于第一种WPF/Silverlight ...
- 使用WPF创建无边框窗体
一.无边框窗口添加窗口阴影 实际上在WPF中添加无边框窗口的窗口阴影十分简单. 首先,设置WindowStyle="None"以及AllowsTransparency=" ...
- 使用 WPF 创建单实例应用程序
一个简单的例子就是大家在使用很多应用程序,例如在使用Microsoft Word 时会遇到一种情况,不管你打开多少个文档,系统一次只能加载一个winword.exe 实例.当打开新文档时,文档在新窗口 ...
- WPF InkCanvas 画图 基础使用教程
大家好,由于很多原因,我有很长一段时间没有在 CSDN 上分享我的学习成果了,如今终于可以回归分享之路了. 之前在做一个项目的时候,想在一个区域里绘制自己的图形,于是上网搜索资料,无意中找到了 Ink ...
- AutoCAD 凸度(bulge)的概念及使用WPF函数画图
前言 凸度(bulge)是AutoCAD 中一个非常重要的概念,凸度控制着两点之间弧度大小,弧度的方向.各种复杂的图像有可能就是成百上千的弧线组成的.从AutoCAD中导出的数据也有该值,一般的形式 ...
- WPF 创建用户控件并引用
项目源码地址:https://github.com/lizhiqiang0204/WpfControlLibrary.git 首先创建新项目->WPF用户控件库项目 在UserControl1. ...
随机推荐
- Ubuntu12.04.4 Vmware 虚拟机安装总结
Ubuntu12.04.4 Vmware 虚拟机安装总结 背景:近期准备入手一块树莓派(RaspberryPI),准备一下开发环境,可惜机器硬盘小,又舍不得格调Win7,所以仅仅好装虚拟机了.考虑到对 ...
- JAVA后端实现统一扫码支付:微信篇
最近做完了一个项目,正好没事做,产品经理就给我安排了一个任务. 做一个像收钱吧这样可以统一扫码收钱的功能. 一开始并不知道是怎么实现的,咨询了好几个朋友,才知道大概的业务流程:先是开一个网页用 ...
- DIKW模型与数据工程(了解)
DIKW 体系 DIKW体系是关于数据.信息.知识及智慧的体系,可以追溯至托马斯·斯特尔那斯·艾略特所写的诗--<岩石>.在首段,他写道:"我们在哪里丢失了知识中的智慧?又在哪里 ...
- 阿里云服务器安全设置 分类: B3_LINUX 2014-07-24 11:10 5197人阅读 评论(1) 收藏
1.开启云盾所有服务 2.通过防火墙策略限制对外扫描行为 请您根据您的服务器操作系统,下载对应的脚本运行,运行后您的防火墙策略会封禁对外发包的行为,确保您的主机不会再出现恶意发包的情况,为您进行后续数 ...
- Windows Phone 8.1 应用间共享
(1)LaunchUriAsync 将简单数据包含在 Uri 中,然后发送到目标应用: await Launcher.LaunchUriAsync(new Uri("target:messa ...
- 【27.77%】【BZOJ 4066】简单题
Time Limit: 50 Sec Memory Limit: 20 MB Submit: 1919 Solved: 533 [Submit][Status][Discuss] Descript ...
- 【40.17%】【codeforces 569B】Inventory
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- Spring ContextLoaderListener与DispatcherServlet所加载的applicationContext的区别
http://www.lai18.com/content/9755931.html Spring 容器(Spring 的上下文) https://my.oschina.net/jast90/blog/ ...
- 【u011】乘法难题
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 乘法难题是一种用一行的卡片来玩的单人游戏,每张卡片上有一个正整数.在游戏者从中拿出一卡片,并且得到一个 ...
- MVC4中AJAX Html页面打开调用后台方法实现动态载入数据库中的数据
之前一直用window.onload方法来调用js方法来实现,今天纠结能不能换个方法实现. 非常明显是能够的. 在html前台页面引用js代码例如以下 @Scripts.Render("~/ ...