<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://wiki.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C_-_SimpleComposer%E7%95%8C%E9%9D%A2%E5%BC%80%E5%8F%91_-_CAD%E5%B7%A5%E5%85%B7</id>
	<title>开发手册 - SimpleComposer界面开发 - CAD工具 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C_-_SimpleComposer%E7%95%8C%E9%9D%A2%E5%BC%80%E5%8F%91_-_CAD%E5%B7%A5%E5%85%B7"/>
	<link rel="alternate" type="text/html" href="https://wiki.lessokaji.com/index.php?title=%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C_-_SimpleComposer%E7%95%8C%E9%9D%A2%E5%BC%80%E5%8F%91_-_CAD%E5%B7%A5%E5%85%B7&amp;action=history"/>
	<updated>2026-04-15T16:08:20Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki.lessokaji.com/index.php?title=%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C_-_SimpleComposer%E7%95%8C%E9%9D%A2%E5%BC%80%E5%8F%91_-_CAD%E5%B7%A5%E5%85%B7&amp;diff=551&amp;oldid=prev</id>
		<title>2024年4月18日 (四) 06:10 Artheru</title>
		<link rel="alternate" type="text/html" href="https://wiki.lessokaji.com/index.php?title=%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C_-_SimpleComposer%E7%95%8C%E9%9D%A2%E5%BC%80%E5%8F%91_-_CAD%E5%B7%A5%E5%85%B7&amp;diff=551&amp;oldid=prev"/>
		<updated>2024-04-18T06:10:46Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;zh-Hans-CN&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;←上一版本&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;2024年4月18日 (四) 14:10的版本&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l72&quot;&gt;第72行：&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;第72行：&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 更复杂的鼠标事件 ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 更复杂的鼠标事件 ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;如果获取位置/路段等方法不够用，也可以使用全功能的鼠标注册事件（较为繁琐）：registerDownevent：&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;如果获取位置/路段等方法不够用，也可以使用全功能的鼠标注册事件（较为繁琐）：registerDownevent：&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[MethodMember(name = &quot;精确移动&quot;, desc = &quot;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;选择一个方向，以&lt;/del&gt;&quot;)]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[MethodMember(name = &quot;精确移动&quot;, desc = &quot;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;选择一个方向，然后输入移动距离&lt;/ins&gt;&quot;)]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;public async void PreciseMove()&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;public async void PreciseMove()&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key mdcs_wiki:diff::1.12:old-550:rev-551 --&gt;
&lt;/table&gt;</summary>
		<author><name>Artheru</name></author>
	</entry>
	<entry>
		<id>https://wiki.lessokaji.com/index.php?title=%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C_-_SimpleComposer%E7%95%8C%E9%9D%A2%E5%BC%80%E5%8F%91_-_CAD%E5%B7%A5%E5%85%B7&amp;diff=550&amp;oldid=prev</id>
		<title>Artheru：​创建页面，内容为“SimpleComposer支持自定义CAD工具。开发者可以设计CAD工具来自动写入标签、调整站点姿态等，从而方便现场人员使用系统。开发者只需要在插件里声明一个公共类，继承CADTool，并增加CADToolDescriptor即可在界面中添加该工具。添加的CAD工具位置如下图所示： CADTool放置位置 相关的接口如下：&lt;syntaxhighlight lang=&quot;c#&quot; line=&quot;1&quot;&gt;     pub…”</title>
		<link rel="alternate" type="text/html" href="https://wiki.lessokaji.com/index.php?title=%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C_-_SimpleComposer%E7%95%8C%E9%9D%A2%E5%BC%80%E5%8F%91_-_CAD%E5%B7%A5%E5%85%B7&amp;diff=550&amp;oldid=prev"/>
		<updated>2024-04-18T06:08:58Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“SimpleComposer支持自定义CAD工具。开发者可以设计CAD工具来自动写入标签、调整站点姿态等，从而方便现场人员使用系统。开发者只需要在插件里声明一个公共类，继承CADTool，并增加CADToolDescriptor即可在界面中添加该工具。添加的CAD工具位置如下图所示： &lt;a href=&quot;/index.php?title=%E6%96%87%E4%BB%B6:Cad_tool_place.png&quot; title=&quot;文件:Cad tool place.png&quot;&gt;无|缩略图|CADTool放置位置&lt;/a&gt; 相关的接口如下：&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;     pub…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;SimpleComposer支持自定义CAD工具。开发者可以设计CAD工具来自动写入标签、调整站点姿态等，从而方便现场人员使用系统。开发者只需要在插件里声明一个公共类，继承CADTool，并增加CADToolDescriptor即可在界面中添加该工具。添加的CAD工具位置如下图所示：&lt;br /&gt;
[[文件:Cad tool place.png|无|缩略图|CADTool放置位置]]&lt;br /&gt;
相关的接口如下：&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    public abstract class CADEventHandler&lt;br /&gt;
    {&lt;br /&gt;
        public virtual void OnSelect() //当选中某个元素的时候触发&lt;br /&gt;
&lt;br /&gt;
        public virtual void OnDelete(Prop props) //当某个元素删除时触发&lt;br /&gt;
&lt;br /&gt;
        public virtual void OnAdd(Prop prop) //当某个元素新建的时候触发&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public abstract class CADTool&lt;br /&gt;
    {&lt;br /&gt;
        public abstract void Invoke();&lt;br /&gt;
    }&lt;br /&gt;
    public class CADToolDescriptor : Attribute&lt;br /&gt;
    {&lt;br /&gt;
        public enum Place&lt;br /&gt;
        {&lt;br /&gt;
            SceneTool, //场景工具，显示在场景面板-工具下拉菜单中&lt;br /&gt;
            CarTool, //车辆工具，显示在车辆面板-工具下拉菜单中&lt;br /&gt;
            ProjectTool //工程工具，显示在“插件”按钮中&lt;br /&gt;
        }&lt;br /&gt;
        public string name;&lt;br /&gt;
        public string shortcut;&lt;br /&gt;
        public Place place = Place.SceneTool;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;以下是一个例子&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
[CADToolDescriptor(name = &amp;quot;批量增删改字段&amp;quot;, shortcut = &amp;quot;Ctrl+Alt+M&amp;quot;)]&lt;br /&gt;
public class BatchFields:CADTool&lt;br /&gt;
{&lt;br /&gt;
    public override void Invoke()&lt;br /&gt;
    {&lt;br /&gt;
        if (InputBox.ShowDialog(&amp;quot;输入要增加或修改的字段名称和值，格式为\r\n[字段]:[值]，若要删除只需要写字段名&amp;quot;, &amp;quot;参数增删改&amp;quot;, &amp;quot;name:val&amp;quot;) ==&lt;br /&gt;
            DialogResult.OK)&lt;br /&gt;
        {&lt;br /&gt;
            foreach (var sel in SimpleMonitor.selected)&lt;br /&gt;
            {&lt;br /&gt;
                var obj = sel;&lt;br /&gt;
                var dict = (Dictionary&amp;lt;string, string&amp;gt;)obj.GetType().GetField(&amp;quot;fields&amp;quot;).GetValue(obj);&lt;br /&gt;
                var idx = InputBox.ResultValue.IndexOf(':');&lt;br /&gt;
                if (idx == -1)&lt;br /&gt;
                {&lt;br /&gt;
                    // remove.&lt;br /&gt;
                    dict.Remove(InputBox.ResultValue);&lt;br /&gt;
                    continue;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var key = InputBox.ResultValue.Substring(0, idx);&lt;br /&gt;
                var val = InputBox.ResultValue.Substring(idx + 1);&lt;br /&gt;
                var fi = obj.GetType().GetField(key);&lt;br /&gt;
                if (fi != null)&lt;br /&gt;
                {&lt;br /&gt;
                    fi.SetValue(obj, TypeDescriptor.GetConverter(fi.FieldType).ConvertFromString(val));&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                    dict[key] = val;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;注：以上例子第9行处使用了SimpleMonitor.selected来访问选择的元素。SimpleMonitor.selected也可以用来写入应该选择哪些元素。&lt;br /&gt;
&lt;br /&gt;
CADTool中可以使用所有SimpleMonitor支持的UI操作类型。比如：&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
var target = await Program.UI.getPoint(); //用于获取一个位置。&lt;br /&gt;
var site = await Program.UI.getPoint(new getPointOptions() { site = true }); //获取一个位置，这个位置必须是站点&lt;br /&gt;
var shelfLane = await Program.UI.GetTrack(true); //获取一个路段。参数true表示要将这个路段放入选择&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 更复杂的鼠标事件 ===&lt;br /&gt;
如果获取位置/路段等方法不够用，也可以使用全功能的鼠标注册事件（较为繁琐）：registerDownevent：&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
[MethodMember(name = &amp;quot;精确移动&amp;quot;, desc = &amp;quot;选择一个方向，以&amp;quot;)]&lt;br /&gt;
public async void PreciseMove()&lt;br /&gt;
{&lt;br /&gt;
    var pp = getPainter(&amp;quot;cad&amp;quot;);&lt;br /&gt;
    SimpleMonitor.registerDownevent((_,_) =&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        if (InputBox.ShowDialog(&amp;quot;输入位移距离，单位mm&amp;quot;, &amp;quot;位移&amp;quot;, &amp;quot;0&amp;quot;) != DialogResult.OK) return;&lt;br /&gt;
        var str = InputBox.ResultValue;&lt;br /&gt;
        if (str == null || !float.TryParse(str, out var d)) return;&lt;br /&gt;
        var dx = mouseX - x;&lt;br /&gt;
        var dy = mouseY - y;&lt;br /&gt;
        var dd = Math.Sqrt(dx * dx + dy * dy);&lt;br /&gt;
        dx /= (float)dd;&lt;br /&gt;
        dy /= (float)dd;&lt;br /&gt;
        x += dx * d;&lt;br /&gt;
        y += dy * d;&lt;br /&gt;
        clearDownevent();&lt;br /&gt;
        Task.Delay(1000).ContinueWith(p =&amp;gt; pp.clear());&lt;br /&gt;
    }, cancelEvent: () =&amp;gt; { pp.clear(); }, preselect: (sender, args) =&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        pp.clear();&lt;br /&gt;
        pp.drawLine(Pens.Red, x, y, mouseX, mouseY);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;registerDownevent的说明如下：&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
public static void registerDownevent(&lt;br /&gt;
UIMouseEvent start=null, //鼠标点击时触发。&lt;br /&gt;
Action cancelEvent = null, //动作取消时触发（点击右键为取消），一般还要调用clearDownevent()来清除鼠标事件。&lt;br /&gt;
UIMouseEvent drag = null, //拖动时触发&lt;br /&gt;
UIMouseEvent release = null, //动作结束时触发&lt;br /&gt;
UIMouseEvent preselect = null //刚开始拖动时触发&lt;br /&gt;
)&lt;br /&gt;
//可以使用SimpleMonitor.mouseX/mouseY来获取鼠标在地图上的坐标，&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Artheru</name></author>
	</entry>
</feed>