Atook 发表于 2015-5-7 03:35:08

使用实体夹具-按空格键/enter键取消

我刚刚开始使用BlockJig,它们工作正常,但用户需要按Esc退出while循环。我想在用户点击空格(enter)时取消该命令,这与大多数autocad命令类似。理想情况下,它会对空格/回车做出不同的反应:如果我在旋转夹具中,它会使块保持原始旋转,如果插入块,它会取消命令。一旦我捕获了空格/回车,我就可以计算出这个逻辑
基本上,我有一个do/while循环,在promptStatus正常时执行jig拖动。
我不确定是否需要更改调用jig的do/whole循环,或者它可能在SamplerStatus覆盖中的UserInputControls中?此外,如果我的执行愚蠢/效率低下,我会接受其他评论,我对这一点还是很陌生的
使用do/while循环调用jig:
public static void InsertRotatorBlockTest(ObjectId blockId, Scale3d scale, string layerName = "0", ResultBuffer optionalXData = null)
{
   Database db = Active.Database;
   Transaction tr = Active.Document.TransactionManager.StartTransaction();
   using (tr)
   {
      //Open block table to be sure it exists
      BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
      PromptResult pr;
      double rotation = 0;
      do
      {
         // now the jig
         // create the blockref
         Point3d pt = new Point3d(0, 0, 0);
         BlockReference br = new BlockReference(pt, blockId)
         {
            ScaleFactors = scale,
            Layer = layerName,
            Rotation = rotation
         };
         if (optionalXData != null)
         {
            br.XData = optionalXData;
         }
         InsertBlockJig insertJig = new InsertBlockJig(br);
         // insert the blockref into modelspace
         pr = Active.Editor.Drag(insertJig);
         if (pr.Status==PromptStatus.OK)
         {
            // rotate it
            RotatingBlockJig rotateJig = new RotatingBlockJig(br);
            pr = Active.Editor.Drag(rotateJig);
            
            BlockTableRecord curSpace = (BlockTableRecord)tr.GetObject(Active.Database.CurrentSpaceId,
               OpenMode.ForWrite);
            curSpace.AppendEntity(br);
            tr.AddNewlyCreatedDBObject(br, true);
            // Call a function to make the graphics display (otherwise it only shows after commit)
            Active.Document.TransactionManager.QueueForGraphicsFlush();
            rotation = br.Rotation;
         }
      } while (pr.Status != PromptStatus.Cancel &&
            pr.Status != PromptStatus.Error &&
            pr.Status != PromptStatus.Keyword);
      tr.Commit();
   }
}

两个EntityJig类:
class InsertBlockJig : EntityJig
{
   Point3d _mCenterPt, _mActualPoint;
   public InsertBlockJig(Entity ent)
      : base(ent)
   {
      _mCenterPt = ((BlockReference) ent).Position;
   }
   protected override SamplerStatus Sampler(JigPrompts prompts)
   {
      JigPromptPointOptions jigOpts =
      new JigPromptPointOptions();
      jigOpts.UserInputControls =
      (UserInputControls.Accept3dCoordinates
      | UserInputControls.NullResponseAccepted
      | UserInputControls.NoNegativeResponseAccepted);
      jigOpts.Message =
      "\nEnter insert point: ";
      PromptPointResult dres =
      prompts.AcquirePoint(jigOpts);
      if (_mActualPoint == dres.Value)
      {
         return SamplerStatus.NoChange;
      }
      else
      {
         _mActualPoint = dres.Value;
      }
      return SamplerStatus.OK;
   }
   protected override bool Update()
   {
      _mCenterPt = _mActualPoint;
      try
      {
         ((BlockReference)Entity).Position = _mCenterPt;
      }
      catch (Exception)
      {
         return false;
      }
      return true;
   }
}
class RotatingBlockJig : EntityJig
{
   // Fields
   private double _mRotation;
   private BlockReference _br;
   // Constructor
   public RotatingBlockJig(BlockReference br)
      : base(br)
   {
      _mRotation = br.Rotation;
      _br = br;
   }
   // Overrides
   protected override bool Update()
   {
      (Entity as BlockReference).Rotation = _mRotation;
      return true;
   }
   protected override SamplerStatus Sampler(JigPrompts prompts)
   {
      JigPromptAngleOptions prAngleOpts = new JigPromptAngleOptions("\n Rotation: ");
      prAngleOpts.BasePoint = _br.Position;
      prAngleOpts.UseBasePoint = true;
      prAngleOpts.Cursor=CursorType.RubberBand;
      PromptDoubleResult prRotResult = prompts.AcquireAngle(prAngleOpts);
      if (prRotResult.Status == PromptStatus.Cancel) return SamplerStatus.Cancel;
      // Return no change if no rotation, to prevent flashing
      if (prRotResult.Value.Equals(_mRotation))
      {
         return SamplerStatus.NoChange;
      }
      else
      {
         _mRotation = prRotResult.Value;
         return SamplerStatus.OK;
      }
      return SamplerStatus.OK;
   }
}

**** Hidden Message *****

MexicanCustard 发表于 2015-5-7 07:48:52

在JigPrompOptions中,可以设置JigProppOptions。UserInputControls与UserInputContracts。InitialBlankTerminatesInput标志。

Atook 发表于 2015-5-7 14:03:12

谢谢你,M.C .我希望事情能简单些。
我是否需要设置其他内容与之搭配?我实现了

prAngleOpts.UserInputControls = UserInputControls.InitialBlankTerminatesInput;
和 jigOpts.UserInputControls =
               (UserInputControls.Accept3dCoordinates
                 | UserInputControls.NullResponseAccepted
               | UserInputControls.NoNegativeResponseAccepted
               | UserInputControls.InitialBlankTerminatesInput);
而且行为不会改变。
在尝试阅读UserInputControls的过程中,我在这篇文章中指出,也许可以使用消息过滤器。对于如此基本的东西来说,消息过滤器似乎是一个笨拙的解决方案。
在更元的层面上,我可以在哪里阅读这方面的资料?我将帮助文件安装到了VS2013中,但就我目前所知,它并没有太大的帮助。甚至autocad的objectbrowser也很少。搜索开发者指南很少会放弃任何有用的东西。我记得以前在COM帮助文件中找到过各种有用的用法示例。

n.yuan 发表于 2015-5-7 17:00:25

您可能需要查看JigPromptOptions.Keywords.在您的情况下,您只能添加1个关键字,例如“取消”,并将其设置为默认值。然后测试PromptResult.Status不仅PromptStatus.Cancel和/或PromptStatus.Keyword.

Atook 发表于 2015-5-19 00:35:34

我最终采用的解决方案是应用IMessageFilter,如下所示:

Filter:

      public class SpaceRightClickFilter : WinForms.IMessageFilter
      {
            public bool canceled = false;
            public bool PreFilterMessage(ref WinForms.Message m)
            {
                int WM_RIGHTCLICK = 0x0205;
                int WM_KEYDOWN = 0x0100;
                Keys kc = (Keys) (int) m.WParam & Keys.KeyCode;
                // check for space press or right click
                if ((m.Msg == WM_KEYDOWN && (kc==Keys.Space)) || m.Msg==WM_RIGHTCLICK)
                {
                  canceled = true;
                }
                // never falter
                return false;
            }
      }

用法:
                  InsertBlockJig insertJig = new InsertBlockJig(br);
                  // insert the blockref into modelspace
                  insertPrompt = Active.Editor.Drag(insertJig);
                  // Add a message filter to the window
                  SpaceRightClickFilter cancelInsertFilter = new SpaceRightClickFilter();
                  System.Windows.Forms.Application.AddMessageFilter(cancelInsertFilter);
                  if (insertPrompt.Status == PromptStatus.OK && !cancelInsertFilter.canceled)
                  {
                        // get rid of insert filter
                        System.Windows.Forms.Application.RemoveMessageFilter(cancelInsertFilter);
                        // Do some cool stuff where space/rightclick doesn't cancel
                        // ...
                  else
                  {
                        canceled = true;
                  }
                  // Clean up; remove the filter
                  System.Windows.Forms.Application.RemoveMessageFilter(cancelInsertFilter);

cincir 发表于 2015-5-22 11:47:22

您还需要设置或<strong>UserInputControls.AcceptOtherInputString
。否则,您不能输入空白,并且不会发生取消。
页: [1]
查看完整版本: 使用实体夹具-按空格键/enter键取消