C# TEKLA STRUCTURES 2022 二次开发 开发环境搭建
初步接触二次TEKLA,以下仅为个人观点
使用的exe方式开发的
引用的nuget包
程序入口点稍作处理,开启了TEKLA 软件才能启动本程序,TEKLA软件关闭,本程序退出
internal static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { try { if (TeklaStructures.Connect()) { TeklaStructures.Closed += (s, e) => { Interaction.MsgBox("Tekla Structures程序已经退出!", MsgBoxStyle.OkOnly | MsgBoxStyle.Critical); Application.Exit(); }; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } else { Interaction.MsgBox("请先保证Tekla软件已经被启动!", MsgBoxStyle.OkOnly | MsgBoxStyle.Critical); Application.Exit(); } } catch (Exception ex) { Interaction.MsgBox(ex.StackTrace, MsgBoxStyle.OkOnly | MsgBoxStyle.Critical); } } }
主窗口采用反射搭建一个 固定的界面
效果如下
反射的特性标签自己定义的如下
public class MyTeklaCmdAtt : Attribute { public string ImageName { get; set; } public string ButtonName { get; set; } public string CategoryName { get; set; } public string HelpString { get; set; } public MyTeklaCmdAtt(string _category, string _cmdName, string helpStr = "", string _img = "") { this.ImageName = _img; this.ButtonName = _cmdName; this.CategoryName = _category; this.HelpString = helpStr; } }
主界面代码如下
public partial class MainForm : ApplicationFormBase { public static Model MyModel { get; set; } public static ModelInfo ModelInfo => MyModel?.GetInfo(); public MainForm() { this.InitializeComponent(); if (MyModel == null) MyModel = new Model(); base.AutoSize = true; base.InitializeForm(); base.Size = this.Size; base.Text = Application.ProductName + $"({ModelInfo.ModelName})"; Dialogs.SetSettings(string.Empty); TeklaStructures.MainWindow.AttachChildForm(this); //AllocConsole(); } private void Form1_Load(object sender, EventArgs e) { var cls = System.Reflection.Assembly.GetExecutingAssembly().GetTypes().Where(c => c.IsClass && c.IsPublic); var Cmdmis = new List<MethodInfo>(); foreach (var item in cls) { var mis = item.GetMethods().Where(m => m.IsPublic && m.IsStatic && m.GetCustomAttribute(typeof(MyTeklaCmdAtt)) != null); if (!mis.Any()) continue; Cmdmis.AddRange(mis.ToArray()); } Dictionary<string, List<MethodInfo>> dicts = Cmdmis.GroupBy(m => m.DeclaringType.Name).ToDictionary(c => c.Key, c => c.ToList()); foreach (var item in dicts) { var tabPage = new TabPage() { //Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right, Text = item.Key, Name = $"tbPage_{item.Key}", BorderStyle = BorderStyle.Fixed3D, BackColor = Color.AliceBlue, //AutoSizeMode = AutoSizeMode.GrowOnly, //AutoSize = true }; var clsFlowLayoutPanel = new FlowLayoutPanel { Name = $"flwPan_{item.Key}", FlowDirection = FlowDirection.TopDown, Padding = new Padding(3), BorderStyle = BorderStyle.FixedSingle, AutoSize = true, Parent = tabPage, Dock = DockStyle.Fill, AutoScroll = true, WrapContents = true }; tabPage.Controls.Add(clsFlowLayoutPanel); foreach (var mi in item.Value) { var att = mi.GetCustomAttribute<MyTeklaCmdAtt>(); var btn = new Button() { Name = $"btn_{att.ButtonName}", Text = att.ButtonName, FlatStyle = FlatStyle.Popup, AutoSize = true }; var tt1 = new System.Windows.Forms.ToolTip { IsBalloon = true, BackColor = Color.LightYellow, UseAnimation = true, }; tt1.SetToolTip(btn, att.HelpString); btn.Click += (s1, e1) => { try { var frm = mi.GetParameters().FirstOrDefault(); mi.Invoke(null, (frm==null?null:new object[] { this })); } catch (Exception ex) { Interaction.MsgBox(ex.StackTrace, MsgBoxStyle.OkOnly | MsgBoxStyle.Exclamation); } }; clsFlowLayoutPanel.Controls.Add(btn); } this.tabControl1.TabPages.Add(tabPage); } } }
开始码代码,今天分享一个在图纸界面画出折断线的代码
public class 图纸工具 { [MyTeklaCmdAtt(nameof(图纸工具), nameof(折断线), nameof(图纸工具) + "." + nameof(折断线))] public static void 折断线() { DrawingHandler dwgHd = new DrawingHandler(); var doc = dwgHd.GetActiveDrawing(); if (doc == null) { return; } var p = dwgHd.GetPicker(); p.PickTwoPoints("", "", out Point p1, out Point p2, out ViewBase viewb); if (p1 == null || p2 == null || viewb == null) return; if (p1 == p2) return; var pts = new PointList(); var v = (p2 - p1).GetAsVector().GetNormal(); var dis = p1.DistanceTo(p2); var p11 = p1.PolarPoint2d(0.05 * dis,v.DegtoXAixs()+180); pts.Add(p11); Point p3 = p1.Add(v.MultipleBy(0.4 * dis)); Point p4 = p3.PolarPoint2d(0.08 * dis,v.DegtoXAixs()+50); Point p6 = p1.Add(v.MultipleBy(0.6 * dis)); Point p5 = p6.PolarPoint2d(0.08 * dis, v.DegtoXAixs()+230); pts.Add(p3); pts.Add(p4); pts.Add(p5); pts.Add(p6); var p22 = p2.PolarPoint2d(0.05 * dis, v.DegtoXAixs()); pts.Add(p22); var pline = new Polyline(viewb, pts); pline.Insert(); doc.CommitChanges(); } } public static class PointEx { public static Point GetMidPoint(this Point sp, Point ep) { return new Point(0.5 * (ep.X + sp.X), 0.5 * (ep.Y + sp.Y), 0.5 * (ep.Z + sp.Z)); } public static Point Add(this Point sp, Vector v) { return new Point(sp.X + v.X, sp.Y + v.Y + sp.Z + v.Z); } public static double DistanceTo(this Point sp, Point ep) { return sp.GetVectorTo(ep).GetLength(); } //public static double Length(this Vector v) //{ // return v.GetLength(); //} public static Vector GetAsVector(this Point p) { return new Vector(p); } public static double DegtoXAixs(this Vector v) { if (v.X == 0.0) { return v.Y > 0 ? 90 : 270; } else if (v.Y == 0.0) { return v.X > 0 ? 0 : 180; } return Math.Atan(v.Y / v.X) * 180 / Math.PI; } public static Vector MultipleBy(this Vector v, double d) { return new Vector(v.X * d, v.Y * d, v.Z * d); } public static Vector DivideBy(this Vector v, double d) { return new Vector(v.X / d, v.Y / d, v.Z / d); } public static Vector GetVectorTo(this Point sp, Point ep) { return new Vector(ep - sp); } public static Point PolarPoint2d(this Point p, double dis, double deg) { return new Point(p.X + dis * Math.Cos(deg * Math.PI / 180), p.Y + dis * Math.Sin(deg * Math.PI / 180)); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具