cad.net WPF嵌入技术3_等待cad界面完成+Acad多线程的解决方案

等待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

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;
            }
        }

    }
}
View Code

AcadIntermediary.Designer.cs

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
    }
}
View Code

调用方式:Gitee有完整的代码,见上篇

WPF整个都处于新线程中,所以Acad交互就可以通过这种方式来进行...

(完)

原文地址:https://www.cnblogs.com/JJBox/p/14179921.html