当前位置: 北大青鸟学士后主页 > 在线教程 > .net > -> 文章内容

使用事件处理函数来控制AutoCAD的行为

发布: 2011-02-23 11:50 | 来源: 未知 | 编辑:北大青鸟学士后 | 查看: 次 |

  本章的目的是解释AutoCAD事件怎样才能被用于控制AutoCAD图形中的行为。现在,让我们使用前一章(第六章)的内容在AutoCAD图形中创建几个EMPLOYEE块索引。我们不想让用户能改变EMPLOYEE块索引的位置,而对于其它的非EMPLOYEE块索引的位置则没有这个限制。我们将混合使用数据库与文档事件来做到这一点。

  首先,我们想要监视将要被执行的AutoCAD命令(使用CommandWillStart事件)。特别地,我们要监视MOVE命令。另外,当一个对象要被修改时,我们应该被通知(使用ObjectOpenedForModify事件),这样我们可以确定它是否为一个EMPLOYEE块索引。如果这时就修改对象可能是无效的,因为我们的修改可能会再次触发事件,从而引起不稳定的行为。所以,我们要等待Move命令的执行结束(使用CommandEnded事件),这时就可以安全地修改对象了。当然,任何对块索引的修改将会触发ObjectOpenedForModify事件。我们还需要设置一些全局变量来表明一个MOVE命令在运行和被修改的对象是一个EMPLOYEE块索引。

  注意:因为本章需要比较多的代码来获得想要的结果,所以我们不会解释任何与事件处理无关的代码,而只是将它们粘贴到事件处理函数中。这里的重点是成功创建和注册事件处理函数。

  第一步:创建新工程

  我们以第六章的工程开始。请新加入一个类AsdkClass2。我们还要加入四个全局变量。前两个是Boolean型的:一个用来表示我们监视的命令是否是活动的,另外一个用来表示ObjectOpenedForModify事件处理函数是否该被忽略。

  //全局变量

  bool bEditCommand;

  bool bDoRepositioning;

  接下来,我们要声明一个全局变量来表示一个ObjectIdCollection,它用来存储我们所选择的要修改的对象的ObjectID。

  ObjectIdCollection changedObjects = new ObjectIdCollection();

  最后,我们要声明一个全局变量来表示一个Point3dCollection,它用来包含我们所选对象的位置(三维点)。

  Point3dCollection employeePositions = new Point3dCollection();

  第2步:创建第一个文档事件处理函数(回调函数)

  现在我们要创建一个事件处理函数。当AutoCAD命令开始执行的时候它会通知我们。我们要检查GlobalCommandName的值是否为MOVE。

  if ( e.GlobalCommandName == "MOVE" )

  {

  }

  如果MOVE命令开始执行的话,我们要相应地设置Boolean变量bEditCommand的值,这样我们可以知道我们所监视的命令是活动的。同样地,我们应该把另外一个Boolean变量bDoRepositioning设置为false来忽略ObjectOpenedForModify事件处理函数。两个变量设置好以后,在命令活动期间,我们必须要获得所选块索引的信息。

  我们还应该把两个集合对象的内容清空。我们只关心当前选择的对象。

  第3步: 创建数据库事件处理函数(回调函数)

  无论什么时候一个对象被打开并要被修改时,数据库事件处理函数会被调用。当然,如果这时我们监视的命令不是活动的,我们就应该跳过任何被这个回调函数调用的内容。

  if ( bEditCommand == false )

  {

  return;

  }

  同样地,如果我们监视的命令已经结束,而ObjectOpenedForModify事件被另一个回调函数再次触发的话,而这时有对象被修改时,我们要阻止所有由这个回调函数执行的动作。

  if ( bDoRepositioning == true )

  {

  return;

  }

  这个回调函数剩余部分的代码用来验证我们是否正在处理EMPLOYEE块索引。如果是的话,我们就获取它的ObjectID和位置(三维点)。下面的代码可以被粘贴到这个事件处理函数函数。

  public void objOpenedForMod(object o, ObjectEventArgs e)

  {

  if ( bEditCommand == false )

  { return; }

  if ( bDoRepositioning == true )

  { return; }

  ObjectId objId;

  objId = e.DBObject.ObjectId;

  Transaction trans;

  Database db;

  db = HostApplicationServices.WorkingDatabase;

  trans = db.TransactionManager.StartTransaction();

  using(Entity ent = (Entity)trans.GetObject(objId, OpenMode.ForRead, false))

  {

  if ( ent.GetType().FullName.Equals( "Autodesk.AutoCAD.DatabaseServices.BlockReference" ) )

  { //We use .NET//s RTTI to establish type.

  BlockReference br = (BlockReference)ent;

  //Test whether it is an employee block

  //open its extension dictionary

  if ( br.ExtensionDictionary.IsValid )

  {

  using(DBDictionary brExtDict = (DBDictionary)trans.GetObject(br.ExtensionDictionary, OpenMode.ForRead))

  {

  if ( brExtDict.GetAt("EmployeeData").IsValid )

  { //successfully got "EmployeeData" so br is employee block ref

  //Store the objectID and the position

  changedObjects.Add(objId);

  employeePositions.Add(br.Position);

  //Get the attribute references,if any

  AttributeCollection atts;

  atts = br.AttributeCollection;

  if ( atts.Count > 0 )

  {

  foreach(ObjectId attId in atts )

  {

  AttributeReference att;

  using(att = (AttributeReference)trans.GetObject(attId, OpenMode.ForRead, false))

  {

  changedObjects.Add(attId);

  employeePositions.Add(att.Position);

  }

  }

  }

  }

  }

  }

  }

  }

  trans.Commit();

  }

  第4步: 创建第二个文档事件处理函数(回调函数)

  当一个命令结束时,第三个事件处理函数被调用。同样地,我们要检查全局变量来验证这个将要结束的命令是我们监视的命令。如果是我们监视的,那么我们要重置这个变量:

  if ( bEditCommand == false )

  { return; }

  bEditCommand = false;

  这个回调函数执行的动作将会再次触发ObjectOpenedForModify事件。我们必须确定在这个回调函数中跳过了所有与此事件有关的动作。

  //设置标志来跳过OpenedForModify处理函数

  bDoRepositioning = true;

  这个回调函数的剩余代码用来把EMPLOYEE块索引和它的关联属性引用的当前(修改过的)位置与它们的初始位置作比较。如果位置改变了,我们在这个回调函数中把它们重置这初始的位置。下面的代码可以被粘贴到这个事件处理函数中。

  public void cmdEnded(object o , CommandEventArgs e)

  {

  //Was our monitored command active?

  if ( bEditCommand == false )

  {

  return;

  }

  bEditCommand = false;

  //Set flag to bypass OpenedForModify handler

  bDoRepositioning = true;

  Database db = HostApplicationServices.WorkingDatabase;

  Transaction trans ;

  BlockTable bt;

  Point3d oldpos;

  Point3d newpos;

  int i ;

  for ( i = 0; i< changedObjects.Count; i++)

  {

  trans = db.TransactionManager.StartTransaction();

  using( bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead) )

  {

  using(Entity ent = (Entity)trans.GetObject(changedObjects[i], OpenMode.ForWrite))

  {

  if ( ent.GetType().FullName.Equals("Autodesk.AutoCAD.DatabaseServices.BlockReference") )

  { //We use .NET//s RTTI to establish type.

  BlockReference br = (BlockReference)ent;

  newpos = br.Position;

  oldpos = employeePositions[i];

  //Reset blockref position

  if ( !oldpos.Equals(newpos) )

  {

  using( trans.GetObject(br.ObjectId, OpenMode.ForWrite) )

  {

  br.Position = oldpos;

  }

  }

  }

  else if ( ent.GetType().FullName.Equals("Autodesk.AutoCAD.DatabaseServices.AttributeReference") )

  {

  AttributeReference att = (AttributeReference)ent;

  newpos = att.Position;

  oldpos = employeePositions[i];

  //Reset attref position

  if ( !oldpos.Equals(newpos) )

  {

  using( trans.GetObject(att.ObjectId, OpenMode.ForWrite))

  {

  att.Position = oldpos;

  }

  }

  }

  }

  }

  trans.Commit();

  }

  }

  第5步  创建命令来注册/断开事件处理函数

  创建一个ADDEVENTS命令,使用+=语句来把上面的3个事件处理函数连接到各自的事件。在这个命令中,我们还应该设置全局Boolean变量:

  bEditCommand = false;

  bDoRepositioning = false;

  创建另外一个命令REMOVEEVENTS,使用-=语句把事件处理函数与事件断开。

  第6步: 测试工程

  要测试这个工程,请使用CREATE命令创建一个或多个EMPLOYEE块索引。如果你要作比较的话,你也可以插入一些非EMPLOYEE的块索引。

  在命令行中键入ADDEVENTS命令来执行它。

  在命令行中输入MOVE命令,然后选择你想要的块索引。注意,当MOVE命令结束时,EMPLOYEE块索引(包括属性)还留在原处。

  执行REMOVEEVENTS命令,然后在试一下MOVE命令。注意,EMPLOYEE块索引现在可以被移动了。

  附加的问题:添加一个附加的回调函数,当用户改变EMPLOYEE块索引的”Name”属性时,这个回调函数被触发。

温馨提示:如果您对北大青鸟的学费、专业设置、就业推荐有任何疑问,可以咨询"400-9679-776"与老师沟通!
相关阅读:

发表评论】 【收藏此页】 【推荐本文

】 【我要挑错】 【打印此页

  北大青鸟开班信息

11月05日 S1脱产 热招
11月10日 S1脱产 热招
11月12日 S1脱产 热招
11月17日 S1脱产 热招
11月22日 S1业余 热招
订座,报名

  北大青鸟在线报名
   姓 名:  *
 联系电话:  *
 qq:  *
 验证码:
E-mail:
 
  北大青鸟免费讲座
讲座日期: 本周六 点击抢座
讲座时间: 下午1点30分
讲座地点: 北大青鸟华腾校区
主讲老师: 王老师 金牌讲师
讲座主题: 网络安全
讲座内容: 检测、防御、黑客信息,如何过滤不安全的网站,如何防御黑客的进攻。
订座电话: 010-82462067/2167