等待cad界面完成
需要等待cad界面完成有很多作用,
因为调用Acad的IExtensionApplication接口时:
a:执行新建图纸会致命错误
b:在获取Autodesk.Windows.ComponentManager.Ribbon==null
事件触发
using Acap = Autodesk.AutoCAD.ApplicationServices.Application;
public class AutoDocs2 : IExtensionApplication { bool flag = true; public void Initialize() {
//直接启动Acad2008这个是无效的 //会频繁空闲,所以会频繁发生事件 System.Windows.Forms.Application.Idle += Application_Idle; //高版可以用这个 //Acap.Idle += Application_Idle; } private void Application_Idle(object sender, System.EventArgs e) { if (flag) { flag = false; //但是要注意成功的次数.... Document doc = Acap.DocumentManager.Add("acad.dwt"); } } public void Terminate() { } }
上面这个方法是单线程的,
但是这和新建一个线程之后循环等待Acad是一样的,只是新建线程方式需要线程安全来处理...
命令栏就绪
而若海利用了 Utils.IsEditorReady(命令栏准备就绪)来控制,但是这个方法同样Acad2008也不能用...
那Acad2008就只能用多线程了...同时此方法也是万能的...
多线程的解决方案
上篇的文章 描述了一个问题WPF的UI线程是新建的,新建的线程又无法和Acad2008进行线程安全的操作..
但是好巧不巧的是WinForm却能使用这个线程安全来操作cad...
所以只能用一个看不见的窗口来调用内部的委托了,
我已经试图利用上下文切换,但是依然无法成功在wpf调度cad的上下文,
其中调度上下文时候,vs在调试期间可以调度,但是直接运行cad08时,调度语句会直接卡死...若你成功,麻烦告知 :)
WinForm:
AcadIntermediary.cs
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Threading; using System.Windows.Forms; using Autodesk.AutoCAD.ApplicationServices; using Acap = Autodesk.AutoCAD.ApplicationServices.Application; namespace JoinBox { public partial class AcadIntermediary : Form { /// <summary> /// Acad2008无法WPF多线程直接交互,为此建立桥梁. /// bug是Acad2008调试WPF时候执行良好,但是直接运行却无法实现多线程的委托获取. /// 实例化时必须在Acad主线程中 /// </summary> public AcadIntermediary() { InitializeComponent(); this.ShowInTaskbar = false; this.WindowState = FormWindowState.Minimized; Load += Start_Load; } private void Start_Load(object sender, EventArgs e) { this.Hide();//一定要这句,不然左下角有一条小小的标题栏 } //新建线程之后以委托方式可以切换图纸. //但是同样的代码,WPF却会被 推帧Dispatcher.Run() 报错 //所以只能以winform作为中介了. public void Action(Action ac) { while (true) { //句柄创建后才可以用委托 && cad启动界面完成Acap.IsQuiescent(重建图纸的时候会为false,所以不使用它) if (this.IsHandleCreated) { //当前如果有活动命令,会致命错误,所以发送esc直到取消完命令 if (CadSystem.Getvar("cmdnames") == "") { Invoke((Action)delegate ()//调度CAD程序的线程安全 { ac?.Invoke(); }); break; } else { Document doc = Acap.DocumentManager.MdiActiveDocument; doc.SendStringToExecute(SendEsc.Esc(), false, true, true); //不需要切换文档 } } Thread.Sleep(100); } } //================================================================================================== /// <summary> /// 让程序不显示在alt+Tab视图窗体中 /// </summary> /// https://www.cnblogs.com/xielong/p/6626105.html protected override CreateParams CreateParams { get { const int WS_EX_APPWINDOW = 0x40000; const int WS_EX_TOOLWINDOW = 0x80; CreateParams cp = base.CreateParams; cp.ExStyle &= ~WS_EX_APPWINDOW; // 不显示在TaskBar cp.ExStyle |= WS_EX_TOOLWINDOW; // 不显示在Alt+Tab return cp; } } } }
AcadIntermediary.Designer.cs
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
namespace JoinBox { partial class AcadIntermediary { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.SuspendLayout(); // // Start // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSize = true; this.ClientSize = new System.Drawing.Size(10, 10); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.Name = "Start"; this.Text = "Start"; this.ResumeLayout(false); } #endregion } }
调用方式:Gitee有完整的代码,见上篇
WPF整个都处于新线程中,所以Acad交互就可以通过这种方式来进行...
(完)