使用实体夹具-按空格键/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 ***** 在JigPrompOptions中,可以设置JigProppOptions。UserInputControls与UserInputContracts。InitialBlankTerminatesInput标志。 谢谢你,M.C .我希望事情能简单些。
我是否需要设置其他内容与之搭配?我实现了
prAngleOpts.UserInputControls = UserInputControls.InitialBlankTerminatesInput;
和 jigOpts.UserInputControls =
(UserInputControls.Accept3dCoordinates
| UserInputControls.NullResponseAccepted
| UserInputControls.NoNegativeResponseAccepted
| UserInputControls.InitialBlankTerminatesInput);
而且行为不会改变。
在尝试阅读UserInputControls的过程中,我在这篇文章中指出,也许可以使用消息过滤器。对于如此基本的东西来说,消息过滤器似乎是一个笨拙的解决方案。
在更元的层面上,我可以在哪里阅读这方面的资料?我将帮助文件安装到了VS2013中,但就我目前所知,它并没有太大的帮助。甚至autocad的objectbrowser也很少。搜索开发者指南很少会放弃任何有用的东西。我记得以前在COM帮助文件中找到过各种有用的用法示例。 您可能需要查看JigPromptOptions.Keywords.在您的情况下,您只能添加1个关键字,例如“取消”,并将其设置为默认值。然后测试PromptResult.Status不仅PromptStatus.Cancel和/或PromptStatus.Keyword. 我最终采用的解决方案是应用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);
您还需要设置或<strong>UserInputControls.AcceptOtherInputString
。否则,您不能输入空白,并且不会发生取消。
页:
[1]