在委托的学习一文中,提供了一个函数用于输入路径获取数据库,
而本文提供的是以激活形式打开cad文档,也就是和用户拖动dwg到cad打开一样.
需要对锁文档的有所理解.
容易发生的坑是:不能使用doc.Dispose();
因为我十分喜欢手动释放图元和记录,因为曾经发生过不释放就出错的问题.....
尤其是遍历全图的时候,必须手动释放,不然某些实体没有释放就会引起错误..(可能由于我使用的是Acad2008)
在尼克劳斯的这篇博文里也有说过,不手动释放面域,也会引起错误...
#if !HC2020
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.PlottingServices;
using Autodesk.AutoCAD.Geometry;
using PlotType = Autodesk.AutoCAD.DatabaseServices.PlotType;
using Acap = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
#else
using GrxCAD.DatabaseServices;
using GrxCAD.EditorInput;
using GrxCAD.Geometry;
using GrxCAD.ApplicationServices;
using GrxCAD.Runtime;
using GrxCAD.Colors;
using GrxCAD.GraphicsInterface;
using Acap = GrxCAD.ApplicationServices.Application;
using PlotType = GrxCAD.DatabaseServices.PlotType;
using GrxCAD.PlottingServices;
#endif
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using System.Collections.Specialized;
using JoinBox;
using System;
using System.IO;
namespace JoinBox.JoinBox_Code.Winform.批量打印
{
public class OpreateCad
{
[CommandMethod("tete", CommandFlags.Session)]
public void tete()
{
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="m_ps"></param>
public static void ActiveDwg(IEnumerable<string> m_ps, Action<Document, Layout> action)
{
var m_printfiles = m_ps.ToList();
for (int i = 0; i < m_printfiles.Count(); i++)
{
Opendwg(m_printfiles[i]);
}
//遍历激活
foreach (Document doc in Acap.DocumentManager)
{
if (!doc.IsActive && !doc.IsDisposed)//CommandFlags.Session则不会是IsActive的
{
Acap.DocumentManager.MdiActiveDocument = doc;//切换文档,如果切换过来之后后续代码没有执行了,是因为没有CommandFlags.Session
var db = doc.Database;
using (doc.LockDocument()) //锁定文档,为了切换布局
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
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 = tr.GetObject(btr.LayoutId, OpenMode.ForRead) as Layout;
if (LayoutManager.Current.CurrentLayout != layout.LayoutName)
{
LayoutManager.Current.CurrentLayout = layout.LayoutName;//非模态这里会失败,所以要锁文档
}
action(doc, layout);//然后打印......其他操作.......
layout.Dispose();
btr.Dispose();
}
//不是必须的
//if (m_printfiles.Contains(doc.Name)) //这里还要判断是不是已经保存了的
//{
// //这里一定要保存一次,不然就会切换文档卡死.cad08版本的时候
// doc.SendStringToExecute("_qsave\n", false, true, true); //不需要切换文档
//}
bt.Dispose();
tr.Commit();
}
}
//if (!doc.IsActive)
//{
// doc.CloseAndDiscard();
//}
#if 重要解释
//不可以释放doc,因为切换会导致内存报错问题......
//没有CommandFlags.Session的话,释放了之后 doc.IsActive == false了.
//doc.Dispose();
#endif
}
}
}
/// <summary>
/// 在cad的前台打开dwg
/// </summary>
/// <param name="strFileName"></param>
public static bool Opendwg(string strFileName)
{
var dm = Acap.DocumentManager;
if (File.Exists(strFileName))
{
try
{
#if NET35 || NET40
dm.Open(strFileName, false);
#else
dm.AppContextOpenDocument(strFileName);
#endif
}
catch (System.Exception e)
{
dm.MdiActiveDocument.Editor.WriteMessage("此文件打开错误: " + strFileName + "\n\r错误信息:" + e.Message);
return false;
}
}
else
{
dm.MdiActiveDocument.Editor.WriteMessage("此文件不存在: " + strFileName);
return false;
}
return true;
}
}
}
(完)