zoukankan      html  css  js  c++  java
  • cad.net WPF嵌入技术4_重置cad之后创建文档出错,拦截cad致命错误

    如果重置过一次cad08,然后直接创建文档,那么你会得到一个致命错误.

    然后你会重启cad,再创建文件,这个时候就不会产生致命错误.

    这个不起眼的bug似乎没有人去理它.. 

    直到我制作了文档栏,在文档栏上面创建文档,然后弹出了一个致命错误... 

    为了修复这个致命错误,我尝试了以下几个步骤:

    方案一,自写模板:

    var lastTemplate = CadSystem.Getvar("LastTemplate");//最后使用的模板
    if (!File.Exists(lastTemplate))
    {
        var templatePath = CadSystem.Getvar("TemplatePath");//模板路径
        lastTemplate = templatePath + "\acad.dwt";//设置默认选中
    }
    
    var sa = new Autodesk.AutoCAD.Windows.OpenFileDialog("选择模板", lastTemplate, "dwt", "",
        OpenFileDialogFlags.AllowAnyExtension | OpenFileDialogFlags.ForceDefaultFolder);
    if (sa.ShowDialog() == System.Windows.Forms.DialogResult.OK)
    {
        //System.Runtime.InteropServices.COMException:“内部应用程序出错。”
        Acap.DocumentManager.Add(sa.Filename);
    }

    方案二,发送命令:

    然后我分析了一下,用 Acap.DocumentManager.Add() 创建文档是愚蠢的(后来证明并不....),

    正常也应该直接调用cad自带的方式,毕竟官方的方法可以避免错误...

    于是乎,我改用了

    Acap.DocumentManager.MdiActiveDocument.SendStringToExecute("_new
    ", false, true, true);
    //第二个参数true时,命令必须有CommandFlags.Session,否则容易致命错误

    方案三:Win32API发送消息:

    但是遇到一个尴尬的事情,没有文档的时候不存在 MdiActiveDocument 此时发送新建命令是错误的...

    然后e大协助了我,利用了win32API的方式来处理:

    //下面两个值都行的
    WinApi.SendMessage(Acap.MainWindow.Handle, (int)MsgType.WM_COMMAND, (IntPtr)18, IntPtr.Zero);//qnew
    WinApi.SendMessage(Acap.MainWindow.Handle, (int)MsgType.WM_COMMAND, (IntPtr)57600, IntPtr.Zero);//new

    子类化拦截

    这个时候,由于文档栏之前实现过<子类化窗口>截获了cad的消息,

    所以重置cad之后创建cad文档(ctrl+n),就可以截获了这个错误,会得到一个 Autodesk.AutoCAD.Runtime.Exception:“eFilerError”

      

    但是截获了又该如何处理呢?

    从"重置"二字中得知,cad将当前配置放在注册表中,

    而重置之后不关闭cad直接去获取注册表,是一份残缺的注册表.

    而重置之后重启cad,cad会自动补充完成这份注册表,是一份完整的注册表.

    对比两份注册表就可以得知需要添加一些什么注册表到内部..

    子类化cad窗体--拦截cad创建文档命令,如果不回调,就相当ban掉了命令,同时等价于拦截了致命错误,贼好玩:

    using System;
    
    public class Anchor
    {
        //子类化cad
        private CallProc_Acad _AcadCallWProc;
        public Anchor()
        {
            //Acad主窗口的句柄
            var _Handle_AC = Acap.MainWindow.Handle;
            _AcadCallWProc = new CallProc_Acad(this);
            _AcadCallWProc.AssignHandle(_Handle_AC);
        }
        //窗口控件子类化,消息拦截
        public class CallProc_Acad : System.Windows.Forms.NativeWindow
        {
            private readonly Anchor _Anchor;
    
            /// <summary>
            /// 拦截消息:CAD主窗口
            /// </summary>
            /// <param name="Anchor"></param>
            public CallProc_Acad(Anchor Anchor)
            {
                _Anchor = Anchor;
            }
    
            //57600_new || 18_qnew 对应cad命令
            IntPtr _new = (IntPtr)57600;
            IntPtr _qnew = (IntPtr)18;
            IntPtr _chongZhi = (IntPtr)0x0001e100;//重置之后ctrl+n取得的
    
            //<子类化-处理cad的新建图纸错误>
            protected override void WndProc(ref Message m)
            {
                try
                {
                    if (m.Msg == (int)MsgType.WM_MOVE) // WM_SIZE
                    {
                        _Anchor.RefreshPos();
                    }
    
                    if (Acap.MainWindow.Handle == m.HWnd && m.Msg == (int)MsgType.WM_COMMAND)
                    {
                        if (m.WParam == _new || m.WParam == _qnew || m.WParam == _chongZhi)
                        {
                            // 这里补充注册表完整,然后给回调函数就可以了.
                            AcadRegistry.CreateDocumentsComplementation();
                        }
                    }
                    base.WndProc(ref m);//回调函数
                }
                catch //cad崩溃的时候会触发
                { }
            }
        }
    }
    View Code

    补充不完整的注册表,防止致命错误..

        public static class AcadRegistry
        {
            /// <summary>
            /// *这个函数功能就是在重置之后,不重启cad而创建文档不会致命错误*
            /// Acad08重置之后,新建文档会致命错误.
            /// 重置cad会清理注册表,这个时候新建图纸就会致命错误(即使是自带的ctrl+n操作)
            /// 所以这个时候导出-用户配置注册表-是缺失的.
            /// 重启cad之后,会自动补充这部分注册表,这个时候是完整的(另存为图纸也可以实现,就是完全关闭掉所有文档则没法另存).
            /// 两份注册表就可以用来对比.
            /// </summary>
            public static void CreateDocumentsComplementation()
            {
                bool writable = true;
                //通过注册表获取上次另存为的路径
                var cprofile = CadSystem.Getvar("cprofile"); //当前用户配置的名称
    
    #if AC2006 || AC2007 || AC2008 || AC2009 || AC20081 || AC2011 || AC2012
                string key = HostApplicationServices.Current.RegistryProductRootKey; //这里浩辰读出来是""
    #elif !HC2020
                string key = HostApplicationServices.Current.UserRegistryProductRootKey;
    #endif
                var currentUser = Registry.CurrentUser.OpenSubKey(key, writable);
    
                //注册表_当前配置
                var regedit_Cprofile = currentUser.CreateSubKey($"Profiles\{cprofile}");
    
                //注册表_
                var regedit_Dialogs = regedit_Cprofile.CreateSubKey("Dialogs");
                {
                    var acDim_DimstyleFormat = regedit_Dialogs.CreateSubKey("AcDim:DimstyleFormat");
                    {
                        ChangReg(acDim_DimstyleFormat, "ActiveTab", 0, RegistryValueKind.DWord);
                    }
    
    
                    var allAnavDialogs = regedit_Dialogs.CreateSubKey("AllAnavDialogs");
                    {
                        ChangReg(allAnavDialogs, "PlacesOrder0", "History");
                        ChangReg(allAnavDialogs, "PlacesOrder0Display", "历史记录");
                        ChangReg(allAnavDialogs, "PlacesOrder0Ext", string.Empty);
    
                        ChangReg(allAnavDialogs, "PlacesOrder1", "Personal");
                        ChangReg(allAnavDialogs, "PlacesOrder1Display", "文档");
                        ChangReg(allAnavDialogs, "PlacesOrder1Ext", string.Empty);
    
                        ChangReg(allAnavDialogs, "PlacesOrder2", "Favorites");
                        ChangReg(allAnavDialogs, "PlacesOrder2Display", "收藏夹");
                        ChangReg(allAnavDialogs, "PlacesOrder2Ext", string.Empty);
    
                        ChangReg(allAnavDialogs, "PlacesOrder3", "FTPSites");
                        ChangReg(allAnavDialogs, "PlacesOrder3Display", "FTP");
                        ChangReg(allAnavDialogs, "PlacesOrder3Ext", string.Empty);
    
                        ChangReg(allAnavDialogs, "PlacesOrder4", "Desktop");
                        ChangReg(allAnavDialogs, "PlacesOrder4Display", "桌面");
                        ChangReg(allAnavDialogs, "PlacesOrder4Ext", string.Empty);
    
                        ChangReg(allAnavDialogs, "PlacesOrder5", "ACPROJECT");
                        ChangReg(allAnavDialogs, "PlacesOrder5Display", "Buzzsaw");
                        ChangReg(allAnavDialogs, "PlacesOrder5Ext", string.Empty);
    
                        ChangReg(allAnavDialogs, "PlacesOrder6", string.Empty);
                    }
    
                    string[] cus = { "CustomizeDialog", "DrawingSettingsDialog", "OptionsDialog" };
                    foreach (var item in cus)
                    {
                        var cu = regedit_Dialogs.CreateSubKey(item + "\TabExtensions");
                        ChangReg(cu, "acmgd.dll", "acmgd.dll");
                    }
    
                    var xzyb = regedit_Dialogs.CreateSubKey("选择样板");
                    {
                        var templatePath = CadSystem.Getvar("TemplatePath");//模板路径
    
                        ChangReg(xzyb, "InitialFilterIndex", 0x00000000, RegistryValueKind.DWord);
                        ChangReg(xzyb, "ViewMode", 0x00000004, RegistryValueKind.DWord);
    
                        ChangReg(xzyb, "InitialDirectory", templatePath + "\", RegistryValueKind.String);
    
                        ChangReg(xzyb, "PreviewVisible", 0x00000001, RegistryValueKind.DWord);
                        ChangReg(xzyb, "X", 0x00000226, RegistryValueKind.DWord);
                        ChangReg(xzyb, "Y", 0x00000158, RegistryValueKind.DWord);
    
                        ChangReg(xzyb, "Width", 0x00000283, RegistryValueKind.DWord);
                        ChangReg(xzyb, "Height", 0x000001a1, RegistryValueKind.DWord);
                    }
                }
    
    
                //注册表_Dialogs_Window
                var regedit_Drawing_Window = regedit_Cprofile.CreateSubKey("Drawing Window");
                {
                    ChangReg(regedit_Drawing_Window, "SDIMode", 0, RegistryValueKind.DWord);
                }
    
                //注册表_Editor_Configuration
                var regedit_Editor_Configuration = regedit_Cprofile.CreateSubKey("Editor Configuration");
                {
                    //"CustomDictionary" = "C:\Users\LQH\AppData\Roaming\Autodesk\AutoCAD 2008\R17.1\chs\support\sample.cus"
                    //这里没有设置好
                    ChangReg(regedit_Editor_Configuration, "CustomDictionary", "", RegistryValueKind.String);
                    ChangReg(regedit_Editor_Configuration, "MainDictionary", "enu", RegistryValueKind.String);
                    ChangReg(regedit_Editor_Configuration, "MTextEditor", "内部", RegistryValueKind.String);
    
                    var temp = Path.GetTempPath();
                    ChangReg(regedit_Editor_Configuration, "SaveFilePath", temp, RegistryValueKind.String);
                    ChangReg(regedit_Editor_Configuration, "XrefLoadPath", temp, RegistryValueKind.String);
                }
    
                //注册表_General
                var regedit_General = regedit_Cprofile.CreateSubKey("General");
                {
                    ChangReg(regedit_General, "ACET-ACETMAIN-MENULOADED", "1", RegistryValueKind.String);
                    ChangReg(regedit_General, "Anyport", 0, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "Attdia", 0, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "Attreq", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "Blipmode", 0, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "Coords", 1, RegistryValueKind.DWord);
    
                    //try
                    //{
                    //     ChangReg(regedit_General, "Delobj", 0xffffffff, RegistryValueKind.DWord);//这句会报错,不设置也没事
                    //}
                    //catch (Exception e)
                    //{ 
                    //    throw e;
                    //}
    
                    ChangReg(regedit_General, "Dragmode", 2, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "HideSystemPrinters", 0, RegistryValueKind.DWord);
    
                    ChangReg(regedit_General, "LayerPMode", "1", RegistryValueKind.String);
                    ChangReg(regedit_General, "MRUConfig", "Adobe PDF", RegistryValueKind.String);
    
                    ChangReg(regedit_General, "OLEQUALITY", 3, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "Osmode", 0x00001025, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "PAPERUPDATE", 0, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "Pickstyle", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "PLOTLEGACY", 0, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "PLSPOOLALERT", 0, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "PSTYLEPOLICY", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "RASTERTHRESHOLD", 0x14, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "RASTERPERCENT", 0x14, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "UseMRUConfig", 0, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "Validation Policy", 0x3, RegistryValueKind.DWord);
                    ChangReg(regedit_General, "Validation Strategy", 0x1, RegistryValueKind.DWord);
                }
                //注册表_
                var regedit_MLeader = regedit_Cprofile.CreateSubKey("MLeader");
                {
                    ChangReg(regedit_MLeader, "", "", RegistryValueKind.String);//这种是默认吗???
                    ChangReg(regedit_MLeader, "CreatedMode", 1, RegistryValueKind.DWord);
                }
                //注册表_
                var regedit_Previous_plot_settings = regedit_Cprofile.CreateSubKey("Previous plot settings");
                {
                    regedit_Previous_plot_settings.CreateSubKey("Layout");
                    regedit_Previous_plot_settings.CreateSubKey("Model");
                }
                //注册表_
                var regedit_StatusBar = regedit_Cprofile.CreateSubKey("StatusBar");
                {
                    var regedit_Application = regedit_StatusBar.CreateSubKey("Application");
                    ChangReg(regedit_Application, "AnnotationScales", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "AnnotationVisibility", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "AutoScale", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "CleanScreenPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "CursorCoordinatesPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "DynamicUCSPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "DynInputPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "FloatPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "GridPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "LayoutIconPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "LayoutMoreIconPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "LineweightPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "ModelIconPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "OrthoPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "OSnapPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "OTrackPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "Paper/ModelPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "PolarPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "SnapPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "SpacerPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "TabletPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "ViewportLockState", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "ViewportScales", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "VpMaxPrevPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "VpMaxPane", 1, RegistryValueKind.DWord);
                    ChangReg(regedit_Application, "VpMaxNextPane", 1, RegistryValueKind.DWord);
                }
            }
    
            /// <summary>
            /// 如果注册表没有这个值才加入,否则就不加入
            /// </summary>
            /// <param name="regedit"></param>
            /// <param name="name"></param>
            /// <param name="value"></param>
            /// <param name="kind"></param>
            private static void ChangReg(RegistryKey regedit, string name, object value, RegistryValueKind kind = RegistryValueKind.String)
            {
                bool flag = true;
                foreach (var item in regedit.GetValueNames())
                {
                    if (item == name)
                    {
                        flag = false;
                        break;
                    }
                }
                if (flag)
                {
                    regedit.SetValue(name, value, kind);
                }
            } 
        }
    View Code

    原因

    再后来分析了一下,

    由于cad08的自带的创建文档(也是发送win32API消息)容易引发致命错误,之前并没有考虑这个问题,

    所以我全盘修改了,

    我的实现是通过键盘钩子拦截了ctrl+n,再通过命令事件拦截所有创建文档命令,

    最后通过调用我最上面的<自写模板>来实现...过程比较复杂,大家可以去看[WPF嵌入技术1]中的源码

    这样创建cad文档就没有了致命错误了...开心~

    若其他cad也存在这样的情况,那么如上设置就可以了...

      

    (完)

  • 相关阅读:
    子组 正则表达式
    正则表达式
    马云北大演讲完整版:真心话,什么才是阿里的核心竞争力?-2014-03-20
    形象化的spring 依赖注入原理
    程序员的六层境界
    apache配置运行zendframework 2
    php编写简单的页面跳转功能
    php随机验证码
    没啥说的
    PHP流程控制语句下
  • 原文地址:https://www.cnblogs.com/JJBox/p/14187031.html
Copyright © 2011-2022 走看看