diff --git a/RevitTools.DrawTool/DrawBase.cs b/RevitTools.DrawTool/DrawBase.cs
new file mode 100644
index 0000000..4df59ed
--- /dev/null
+++ b/RevitTools.DrawTool/DrawBase.cs
@@ -0,0 +1,94 @@
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+namespace RevitTools.DrawTool
+{
+ ///
+ /// 基本绘图对象
+ ///
+ public abstract class DrawBase
+ {
+ internal Color m_BackColor;
+ internal Color m_ForeColor;
+
+
+ ///
+ /// 背景色
+ ///
+ public Color BackColor
+ {
+ get { return m_BackColor; }
+ set { m_BackColor = value; }
+ }
+
+ ///
+ /// 前景色
+ ///
+ public Color ForeColor
+ {
+ get { return m_ForeColor; }
+ set { m_ForeColor = value; }
+ }
+
+ ///
+ /// 获取图形外接矩形
+ ///
+ /// 图形的外接矩形
+ public abstract Rectangle GetBound();
+
+ ///
+ /// 在指定的Graphics上绘制图形
+ ///
+ /// 指定的 Graphics
+ public abstract void Draw(Graphics g);
+
+ ///
+ /// 命中测试
+ ///
+ ///
+ public virtual bool HitTest(Point point)
+ {
+ var bound = GetBound();
+ if (bound.Left > point.X || bound.Right < point.X
+ || bound.Top > point.Y || bound.Bottom > point.Y)
+ return false;
+
+ using (var bmp = new Bitmap(bound.Width, bound.Height))
+ using (var g = Graphics.FromImage(bmp))
+ {
+ var dx = -bound.X;
+ var dy = -bound.Y;
+
+ var obj = this.Clone();
+ obj.Draw(g);
+
+ return bmp.GetPixel(point.X + dx, point.Y + dy).A == 0;
+ }
+ }
+
+ ///
+ /// 移动对象
+ ///
+ /// X 偏移量
+ /// Y 偏移量
+ public abstract void Move(int dx, int dy);
+
+ public virtual DrawBase Clone()
+ {
+ return this.MemberwiseClone() as DrawBase;
+ }
+ }
+ public static class ExtensionMethods
+ {
+ public static Matrix SetTranslate(this Matrix matrix, float offsetX, float offsetY)
+ {
+ matrix.Translate(offsetX, offsetY);
+ return matrix;
+ }
+ public static Matrix SetTranslate(this Matrix matrix, float offsetX, float offsetY, MatrixOrder order)
+ {
+ matrix.Translate(offsetX, offsetY);
+ return matrix;
+ }
+ }
+}
diff --git a/RevitTools.DrawTool/DrawForm.Designer.cs b/RevitTools.DrawTool/DrawForm.Designer.cs
new file mode 100644
index 0000000..7756c13
--- /dev/null
+++ b/RevitTools.DrawTool/DrawForm.Designer.cs
@@ -0,0 +1,52 @@
+namespace RevitTools.DrawTool
+{
+ partial class DrawForm
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ //
+ // DrawForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.White;
+ this.ClientSize = new System.Drawing.Size(800, 450);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
+ this.Name = "DrawForm";
+ this.Text = "Form1";
+ this.TransparencyKey = System.Drawing.Color.White;
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DrawForm_FormClosing);
+ this.Shown += new System.EventHandler(this.DrawForm_Shown);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ }
+}
+
diff --git a/RevitTools.DrawTool/DrawForm.cs b/RevitTools.DrawTool/DrawForm.cs
new file mode 100644
index 0000000..ee5d9e5
--- /dev/null
+++ b/RevitTools.DrawTool/DrawForm.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Autodesk.Revit.UI;
+
+namespace RevitTools.DrawTool
+{
+ public partial class DrawForm : Form
+ {
+ System.Timers.Timer Timer = new System.Timers.Timer(20);
+
+ public UIApplication uiApp { get; private set; }
+ public DrawingCanvas Canvas { get; private set; }
+ public DrawForm(Autodesk.Revit.UI.UIApplication uIApplication)
+ {
+ this.uiApp = uIApplication;
+ InitializeComponent();
+ var bitmap = new Bitmap(1, 1);
+ using (var g = Graphics.FromImage(bitmap))
+ {
+ g.Clear(Color.Transparent);
+ }
+
+
+ this.BackgroundImage = bitmap;
+ this.BackgroundImageLayout = ImageLayout.Stretch;
+ Canvas = new DrawingCanvas();
+ Canvas.Dock = DockStyle.Fill;
+ Canvas.BackgroundImage = bitmap;
+ Canvas.BackgroundImageLayout = ImageLayout.Stretch;
+ this.Controls.Add(Canvas);
+ this.Timer.Elapsed += Timer_Elapsed;
+ }
+
+ private Point Point;
+ private int i;
+ private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
+ {
+ FormExtensionMethods.Invoke(this, () =>
+ {
+ var position = Control.MousePosition;
+ if (position == this.Point)
+ return;
+
+ this.Point = position;
+ position -= new Size(this.Left, this.Top);
+
+ i++;
+ if (i % 50 == 0)
+ {
+ UpdateWindow();
+ i = 0;
+ }
+
+
+ Canvas.Clear();
+
+ Canvas.AddObj(new LineObj(new Point(0, position.Y), new Point(position.X - 3, position.Y)) { ForeColor = Color.Green });
+ Canvas.AddObj(new LineObj(new Point(position.X + 3, position.Y), new Point(this.Width + 3, position.Y)) { ForeColor = Color.Green });
+
+ Canvas.AddObj(new LineObj(new Point(position.X, 0), new Point(position.X, position.Y - 3)) { ForeColor = Color.Green });
+ Canvas.AddObj(new LineObj(new Point(position.X, position.Y + 3), new Point(position.X, this.Height + 3)) { ForeColor = Color.Green });
+
+ //Canvas.AddObj(new RectangleObj(position - new Size(2, 2), position + new Size(2, 2)) { ForeColor = Color.Green });
+ });
+ }
+
+ private void UpdateWindow()
+ {
+ var uiView = uiApp.ActiveUIDocument.GetOpenUIViews()
+ .FirstOrDefault(p => p.ViewId == uiApp.ActiveUIDocument.ActiveGraphicalView.Id);
+ var view = uiApp.ActiveUIDocument.ActiveView;
+ var rect = uiView.GetWindowRectangle();
+ this.Left = rect.Left;
+ this.Top = rect.Top;
+ this.Width = rect.Right - rect.Left;
+ this.Height = rect.Bottom - rect.Top;
+ }
+
+ private void DrawForm_Shown(object sender, EventArgs e)
+ {
+ UpdateWindow();
+ Timer.Start();
+ }
+
+ private void DrawForm_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ Timer.Stop();
+ }
+
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+
+ }
+ }
+
+ public static class FormExtensionMethods
+ {
+ public static void Invoke(this Form form, Action action)
+ {
+ form.Invoke(new MethodInvoker(action));
+ }
+
+
+ }
+
+}
diff --git a/RevitTools.DrawTool/DrawForm.resx b/RevitTools.DrawTool/DrawForm.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/RevitTools.DrawTool/DrawForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RevitTools.DrawTool/DrawingCanvas.cs b/RevitTools.DrawTool/DrawingCanvas.cs
new file mode 100644
index 0000000..4e65b9d
--- /dev/null
+++ b/RevitTools.DrawTool/DrawingCanvas.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace RevitTools.DrawTool
+{
+ public partial class DrawingCanvas : PictureBox, IDisplay
+ {
+ public DrawingCanvas()
+ {
+ this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
+ }
+
+ private List drawObjects = new List();
+
+ public void AddObj(DrawBase draw)
+ {
+ drawObjects.Add(draw);
+ MoveObj(draw, 0, 0);
+ }
+
+ ///
+ /// 绘制对象
+ ///
+ ///
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ foreach (var item in drawObjects)
+ {
+ item.Draw(e.Graphics);
+ }
+
+ base.OnPaint(e);
+ }
+
+ ///
+ /// 删除对象
+ ///
+ /// 要删除的对象
+ public void DeleteObj(DrawBase db)
+ {
+ if (db == null)
+ {
+ throw new Exception("没有选中的项目");
+ }
+
+ Rectangle bound = db.GetBound();
+ this.drawObjects.Remove(db);
+ bound.Inflate(2, 2);
+ this.Invalidate(bound);
+ }
+
+ ///
+ /// 移动绘图对象
+ ///
+ /// 要移动的绘图对象
+ /// 目标位置
+ public void MoveObj(DrawBase draw, Point p)
+ {
+ Rectangle bound = draw.GetBound();
+ Rectangle last = new Rectangle(bound.X, bound.Y, bound.Width, bound.Height);
+
+ bound.Offset(p.X - bound.X, p.Y - bound.Y);
+ draw.Move(p.X - bound.X, p.Y - bound.Y);
+
+ last.Inflate(2, 2);
+ bound.Inflate(2, 2);
+
+ using (Region invReg = new Region(last))
+ {
+ invReg.Union(bound);
+ this.Invalidate(invReg);
+ }
+ }
+
+ ///
+ /// 移动绘图对象
+ ///
+ /// 要移动的对象
+ /// x方向移动的距离
+ /// y方向移动的距离
+ public void MoveObj(DrawBase db, int dx, int dy)
+ {
+ Rectangle bound = db.GetBound();
+ Rectangle last = new Rectangle(bound.X, bound.Y, bound.Width, bound.Height);
+
+ bound.Offset(dx, dy);
+ db.Move(dx, dy);
+
+ last.Inflate(2, 2);
+ bound.Inflate(2, 2);
+
+ using (Region invReg = new Region(last))
+ {
+ invReg.Union(bound);
+ this.Invalidate(invReg);
+ }
+ }
+
+ ///
+ /// 移动所有对象
+ ///
+ /// x方向移动的距离
+ /// y方向移动的距离
+ public void MoveAllObj(int dx, int dy)
+ {
+ var list = new List(drawObjects);
+ foreach (var item in list)
+ {
+ MoveObj(item, dx, dy);
+ }
+ }
+
+ ///
+ /// 获取指定位置的对象
+ ///
+ /// 指定位置的值
+ /// 绘图对象
+ public DrawBase GetObj(Point e)
+ {
+ return drawObjects.LastOrDefault(p => p.HitTest(e));
+ }
+
+ ///
+ /// 清空所有对象
+ ///
+ public void Clear()
+ {
+ var v = new List(drawObjects);
+ foreach (var item in v)
+ {
+ DeleteObj(item);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/RevitTools.DrawTool/IDisplay.cs b/RevitTools.DrawTool/IDisplay.cs
new file mode 100644
index 0000000..39ef64f
--- /dev/null
+++ b/RevitTools.DrawTool/IDisplay.cs
@@ -0,0 +1,22 @@
+using System.Drawing;
+
+namespace RevitTools.DrawTool
+{
+ ///
+ /// 管理接口
+ ///
+ public interface IDisplay
+ {
+ void AddObj(DrawBase draw);
+
+ void Clear();
+
+ void DeleteObj(DrawBase db);
+
+ DrawBase GetObj(Point e);
+
+ void MoveAllObj(int dx, int dy);
+
+ void MoveObj(DrawBase db, int dx, int dy);
+ }
+}
diff --git a/RevitTools.DrawTool/LineObj.cs b/RevitTools.DrawTool/LineObj.cs
new file mode 100644
index 0000000..8184c62
--- /dev/null
+++ b/RevitTools.DrawTool/LineObj.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Drawing;
+
+namespace RevitTools.DrawTool
+{
+ public class LineObj : DrawBase
+ {
+ protected Point m_Start;
+ protected Point m_End;
+
+ public LineObj(Point start, Point end)
+ {
+ this.m_Start = start;
+ this.m_End = end;
+ }
+
+ ///
+ /// 获取图形外接矩形
+ ///
+ /// 图形的外接矩形
+ public override Rectangle GetBound()
+ {
+ int x = this.m_Start.X < this.m_End.X ? this.m_Start.X : this.m_End.X;
+ int y = this.m_Start.Y < this.m_End.Y ? this.m_Start.Y : this.m_End.Y;
+ int r = this.m_Start.X < this.m_End.X ? this.m_End.X : this.m_Start.X;
+ int b = this.m_Start.Y < this.m_End.Y ? this.m_End.Y : this.m_Start.Y;
+ return Rectangle.FromLTRB(x, y, r, b);
+ }
+
+ ///
+ /// 在指定的Graphics上绘制图形
+ ///
+ /// 指定的 Graphics
+ public override void Draw(Graphics g)
+ {
+ using (Pen pen = new Pen(this.m_ForeColor))
+ {
+ g.DrawLine(pen, this.m_Start, this.m_End);
+ }
+ }
+
+ public override void Move(int dx, int dy)
+ {
+ m_Start.X += dx;
+ m_Start.Y += dy;
+
+ m_End.X += dx;
+ m_End.Y += dy;
+ }
+ }
+}
\ No newline at end of file
diff --git a/RevitTools.DrawTool/Properties/AssemblyInfo.cs b/RevitTools.DrawTool/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8b332dc
--- /dev/null
+++ b/RevitTools.DrawTool/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("RevitTools.DrawTool")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("RevitTools.DrawTool")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("8f97b05a-65cb-4dfa-b473-0eb92d0a46fb")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/RevitTools.DrawTool/Properties/Resources.Designer.cs b/RevitTools.DrawTool/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..7b84b61
--- /dev/null
+++ b/RevitTools.DrawTool/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace RevitTools.DrawTool.Properties {
+ using System;
+
+
+ ///
+ /// 一个强类型的资源类,用于查找本地化的字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// 返回此类使用的缓存的 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RevitTools.DrawTool.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/RevitTools.DrawTool/Properties/Resources.resx b/RevitTools.DrawTool/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/RevitTools.DrawTool/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RevitTools.DrawTool/Properties/Settings.Designer.cs b/RevitTools.DrawTool/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..205ed7e
--- /dev/null
+++ b/RevitTools.DrawTool/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace RevitTools.DrawTool.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/RevitTools.DrawTool/Properties/Settings.settings b/RevitTools.DrawTool/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/RevitTools.DrawTool/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/RevitTools.DrawTool/RectangleObj.cs b/RevitTools.DrawTool/RectangleObj.cs
new file mode 100644
index 0000000..b1b256a
--- /dev/null
+++ b/RevitTools.DrawTool/RectangleObj.cs
@@ -0,0 +1,58 @@
+using System.Drawing;
+
+namespace RevitTools.DrawTool
+{
+ public class RectangleObj : DrawBase
+ {
+ private Point m_Start;
+ private Point m_End;
+ private bool m_Solid;
+
+ public RectangleObj(Point start, Point end)
+ {
+ this.m_Start = start;
+ this.m_End = end;
+ }
+
+ public bool Solid
+ {
+ get { return m_Solid; }
+ set { m_Solid = value; }
+ }
+
+ public override System.Drawing.Rectangle GetBound()
+ {
+ int x = this.m_Start.X < this.m_End.X ? this.m_Start.X : this.m_End.X;
+ int y = this.m_Start.Y < this.m_End.Y ? this.m_Start.Y : this.m_End.Y;
+ int r = this.m_Start.X < this.m_End.X ? this.m_End.X : this.m_Start.X;
+ int b = this.m_Start.Y < this.m_End.Y ? this.m_End.Y : this.m_Start.Y;
+ return Rectangle.FromLTRB(x, y, r, b);
+ }
+
+ public override void Draw(Graphics g)
+ {
+ Rectangle bound = this.GetBound();
+ if (this.m_Solid)
+ {
+ using (SolidBrush brush = new SolidBrush(this.m_BackColor))
+ {
+ g.FillRectangle(brush, bound);
+ }
+ }
+ using (Pen pen = new Pen(this.m_ForeColor))
+ {
+ g.DrawRectangle(pen, bound);
+ }
+ }
+
+ public override void Move(int dx, int dy)
+ {
+ m_Start.X += dx;
+ m_Start.Y += dy;
+
+ m_End.X += dx;
+ m_End.Y += dy;
+ }
+ }
+
+}
diff --git a/RevitTools.DrawTool/RevitTools.DrawTool.csproj b/RevitTools.DrawTool/RevitTools.DrawTool.csproj
new file mode 100644
index 0000000..880178a
--- /dev/null
+++ b/RevitTools.DrawTool/RevitTools.DrawTool.csproj
@@ -0,0 +1,98 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {8F97B05A-65CB-4DFA-B473-0EB92D0A46FB}
+ Library
+ RevitTools.DrawTool
+ RevitTools.DrawTool
+ v4.8
+ 512
+ true
+ true
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ DrawForm.cs
+
+
+ Component
+
+
+
+
+
+
+ DrawForm.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+ 2018.0.2
+ runtime
+ compile; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
\ No newline at end of file
diff --git a/RevitTools.Utils/Properties/AssemblyInfo.cs b/RevitTools.Utils/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..520996c
--- /dev/null
+++ b/RevitTools.Utils/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("RevitTools.Utils")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("RevitTools.Utils")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("514e9c5d-93c6-4781-b982-83fc7fcd6a19")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/RevitTools.Utils/Revit/ExEventHandle.cs b/RevitTools.Utils/Revit/ExEventHandle.cs
new file mode 100644
index 0000000..b39008d
--- /dev/null
+++ b/RevitTools.Utils/Revit/ExEventHandle.cs
@@ -0,0 +1,51 @@
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace RevitTools.Utils.Revit
+{
+ ///
+ /// 外部事件处理程序
+ ///
+ public class ExEventHandle : IExternalEventHandler
+ {
+ ///
+ /// 创建具有指定名字的外部事件处理程序
+ ///
+ ///
+ public ExEventHandle(string name)
+ {
+ this.name = name;
+ }
+
+ private readonly string name;
+
+ ///
+ /// 工作项队列
+ ///
+ internal readonly ConcurrentQueue ExEventQueue = new ConcurrentQueue();
+
+ ///
+ /// 执行外部事件函数
+ ///
+ ///
+ public void Execute(UIApplication app)
+ {
+ while (ExEventQueue.TryDequeue(out ExEventWorkItem workItem))
+ {
+ workItem.InvokeAction(app);
+ }
+ }
+
+ ///
+ /// 获取字符串标识
+ ///
+ ///
+ public string GetName()
+ {
+ return name;
+ }
+ }
+}
\ No newline at end of file
diff --git a/RevitTools.Utils/Revit/ExEventUtils.cs b/RevitTools.Utils/Revit/ExEventUtils.cs
new file mode 100644
index 0000000..1704b12
--- /dev/null
+++ b/RevitTools.Utils/Revit/ExEventUtils.cs
@@ -0,0 +1,78 @@
+using Autodesk.Revit.UI;
+using System;
+using System.Collections.Concurrent;
+using System.Threading.Tasks;
+
+namespace RevitTools.Utils.Revit
+{
+ ///
+ /// 外部事件封装类
+ ///
+ public class ExEventUtils
+ {
+ ///
+ /// 创建外部事件
+ ///
+ ///
+ private ExEventUtils(string handleName)
+ {
+ this.Handle = new ExEventHandle(handleName);
+ this.ExEvent = ExternalEvent.Create(this.Handle);
+ }
+
+ ///
+ /// 外部事件实例
+ ///
+ private readonly ExternalEvent ExEvent;
+
+ ///
+ /// 外部事件处理程序
+ ///
+ private readonly ExEventHandle Handle;
+
+ ///
+ /// 在外部事件中执行函数, 可以等待函数执行完成
+ ///
+ /// 要执行的函数
+ /// 事务组名
+ ///
+ public async Task InvokeAsync(Action action)
+ {
+ var workItem = new ExEventWorkItem(action);
+ Handle.ExEventQueue.Enqueue(workItem);
+ ExEvent.Raise();
+ await workItem.CompletionSource.Task;
+ }
+
+ ///
+ /// 在外部事件中执行函数, 并且可以等待函数执行完成
+ ///
+ ///
+ /// 要执行的函数
+ ///
+ public async Task InvokeAsync(Func func)
+ {
+ object func1(UIApplication app)
+ {
+ return func(app);
+ }
+ var workItem = new ExEventWorkItem(func1);
+ Handle.ExEventQueue.Enqueue(workItem);
+ ExEvent.Raise();
+ var result = await workItem.CompletionSource.Task;
+ return (T)result;
+ }
+
+ ///
+ /// 获取或创建外部事件处理实例
+ ///
+ /// 外部事件处理程序名称
+ ///
+ public static ExEventUtils GetOrCreate(string name = "ScriptPadExEventHandle")
+ {
+ return EventUtils.GetOrAdd(name, new ExEventUtils(name));
+ }
+
+ private static readonly ConcurrentDictionary EventUtils = new ConcurrentDictionary();
+ }
+}
\ No newline at end of file
diff --git a/RevitTools.Utils/Revit/ExEventWorkItem.cs b/RevitTools.Utils/Revit/ExEventWorkItem.cs
new file mode 100644
index 0000000..cae30af
--- /dev/null
+++ b/RevitTools.Utils/Revit/ExEventWorkItem.cs
@@ -0,0 +1,64 @@
+using Autodesk.Revit.UI;
+using System;
+using System.Threading.Tasks;
+
+namespace RevitTools.Utils.Revit
+{
+ ///
+ /// 外部事件工作项
+ ///
+ internal class ExEventWorkItem
+ {
+ ///
+ /// 异步阻塞信号
+ ///
+ public TaskCompletionSource