cad.net 以激活形式在前台打开cad文档

说明

委托的学习一文中,提供了一个函数用于输入路径获取数据库,而本文提供的是以激活形式打开cad文档,也就是和用户拖动dwg到cad打开一样.

需要对锁文档的有所理解.
容易发生的坑是:不能使用doc.Dispose();
因为我十分喜欢手动释放图元和记录,因为曾经发生过不释放就出错的问题.....
尤其是遍历全图的时候,必须手动释放,不然某些实体没有释放就会引起错误..(可能由于我使用的是Acad2008)

尼克劳斯的这篇博文里也有说过,不手动释放面域,也会引起错误...

代码

#if !HC2020
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;
using Acap = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.Runtime;
#else
using GrxCAD.DatabaseServices;
using GrxCAD.ApplicationServices;
using Acap = GrxCAD.ApplicationServices.Application;
using GrxCAD.Runtime;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System;

using JoinBox;

namespace JoinBox;
public class OpreateCad {
    [CommandMethod("test_qiantai", CommandFlags.Session)]
    public void test_qiantai() {
        var paths = new List<string>();
        string dwgPath = AutoGo.DwgCurrentPath();
        var ofd = new OpenFileDialog {
            AutoUpgradeEnabled = false,//OpenFileDialog会卡顿,用这个就好了
            Filter = "AutoCAD 图形(*.dwg)|*.dwg",
            Multiselect = true,//允许同时选择多个文件
            InitialDirectory = dwgPath,
        };
        if (ofd.ShowDialog() == DialogResult.OK)
            paths.AddRange(ofd.FileNames);

        ActiveDwg(paths, (doc, layout) => {
            var ed = doc.Editor;
            ed.WriteMessage(Environment.NewLine + "打印的数据库:" + doc.Database.Filename);
            ed.WriteMessage("打印的布局:" + layout.LayoutName);
            //插入打印的代码
        });
    }

/// <summary>
/// 前台打开dwg,并且激活
/// </summary>
/// <param name="dwgPaths"></param>
void ActiveDwg(List<string> dwgPaths, Action<Document, Layout> action) {
    foreach(var item in dwgPaths)
        Opendwg(tiem);

    //遍历激活
    foreach (Document doc in Acap.DocumentManager) {
        //IsActive在初始化时会异常,CommandFlags.Session则不会是IsActive的
        if (!doc.IsDisposed && !doc.IsActive) {
        //切换文档,如果切换过来之后后续代码没有执行了,是因为没有CommandFlags.Session
         Acap.DocumentManager.MdiActiveDocument = doc;

        var db = doc.Database;
        doc.Action(() => {//锁定文档,为了切换布局
            db.Action(tr => {
                    var bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                     foreach (ObjectId btrId in bt) {
                            var btr = tr.GetObject(btrId, OpenMode.ForRead) as BlockTableRecord;
                            if (!btr.IsLayout) continue;

                            var layout = (Layout)tr.GetObject(btr.LayoutId, OpenMode.ForRead);
                            if (LayoutManager.Current.CurrentLayout != layout.LayoutName)
                             LayoutManager.Current.CurrentLayout = layout.LayoutName;//非模态这里会失败,所以要锁文档

                             action(doc, layout);//然后打印......其他操作.......
                             layout.Dispose();
                             btr.Dispose();
                          }
                          bt.Dispose();
                        });
                    });
#if 重要解释
                    //如果doc.Dispose()切换会导致内存报错问题,没有CommandFlags.Session的话,释放了之后 doc.IsActive == false
#endif
                }
            }
    }

    /// <summary>
    /// 在cad的前台打开dwg
    /// </summary>
    /// <param name="dwgPath"></param>
    bool Opendwg(string dwgPath) {
        var dm = Acap.DocumentManager;
        var doc = dm.MdiActiveDocument;
        var ed = doc.Editor;

       if (!File.Exists(dwgPath)) {
          ed.WriteMessage("此文件不存在: " + dwgPath);
         return false;
       }
       try {
#if NET35
         dm.Open(dwgPath, false);
#elif NET40
          DocumentCollectionExtension.Open(dm, dwgPath, false);
#else
           dm.AppContextOpenDocument(strFileName);
#endif
     } catch (System.Exception e) {
         ed.WriteMessage("\n****此文件打开错误: " + dwgPath + "\n错误信息:" + e.Message);
         return false;
    }
    return true;
    }
}

(完)

posted @ 2020-06-24 00:10  惊惊  阅读(1200)  评论(0编辑  收藏  举报