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也存在这样的情况,那么如上设置就可以了...

      

    (完)

  • 相关阅读:
    Truck History(poj 1789)
    Highways poj 2485
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    115. Distinct Subsequences
    114. Flatten Binary Tree to Linked List
    113. Path Sum II
    109. Convert Sorted List to Binary Search Tree
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
  • 原文地址:https://www.cnblogs.com/JJBox/p/14187031.html
Copyright © 2011-2022 走看看