LearnDgnTool-07_DgnElementSetTool的使用_移动元素


上一个例子中我们没有使用DgnElementSetTool中的动态绘制元素的功能,现在我们模仿一下Mstn中元素移动工具来看一下如何使用DgnElementSetTool为我们提供的动态绘制的功能。以下链接是是实现了元素移动工具的代码:

communities.bentley.com/.../LearnDgnTool_5F00_Ver6.7z

编译后,执行key-in命令:LearnDgnTool Move,启动我们的工具。通过光标选择需要移动的元素后,我们可以看到随着鼠标在视图中移动,我们选中的元素也会跟着光标不停地移动。在视图中再次单击鼠标左键,选中的元素就完成了移动。我们在MoveTool中声明了一个Transform成员变量m_tranform,在_SetupForModify函数中根据函数参数ev设置m_tranform的值,在_OnElementModify函数中对传递进来的元素进行变换。我们再来测试一下DgnElementSetTool::_OnResetButton中为我们封装的元素重定位的功能。我们在通过鼠标点选获取元素时,有时候会遇到多个元素重叠或者距离比较近的情况,我们很难一次直接选中我们的元素,这个时候我们只要单击鼠标右键就可以在最近一次鼠标左键点击的位置继续往后定位其他元素。启动我们的移动元素工具,找到一处有多个元素重叠在一起的地方,单击鼠标左键拾取其中一个元素后,单击鼠标右键会选中左键点击处的其他元素。

当前我们的工具在鼠标点选时,一次只能移动一个元素,我们改善一下我们的工具使其能够选中多个元素。在MoveTool.h中加入如下所示的内容:

virtual bool    _WantAdditionalLocate(DgnButtonEventCP ev)override;

在MoveTool.cpp中加入如下所示的内容:

bool    MoveTool::_WantAdditionalLocate(DgnButtonEventCP ev)
{
	if (NULL == ev)
		return true;
	if (ev->IsControlKey())
		return true;
	return false;
}

再次启动我们的工具,按下Ctrl键选择元素。选中多个元素后释放Ctrl键,此时选中的元素都会随着光标在视图中动态移动,再次单击鼠标左键会看到选中的元素全部移动到选中的位置。我们在MoveTool的声明中加入如下内容,此时我们的工具就支持框选以及划选(框选时按“Alt”键切换至划选模式)。

virtual UsesDragSelect  _AllowDragSelect()override { return USES_DRAGSELECT_Box; }

框选时,如果选中的元素中有我们不想处理的元素该如何过滤掉呢?前面我们讲过,可以重写_FilterAgendaEntries函数来实现。在MoveTool.h中加入如下所示的内容:

virtual bool    _FilterAgendaEntries()override;

在MoveTool.cpp中加入如下所示的内容:

bool    MoveTool::_FilterAgendaEntries()
{
	bool isInvalid = false;
	for (ElementAgenda::iterator iter = GetElementAgenda().begin(); iter != GetElementAgenda().end(); iter++)
	{
		if (ELLIPSE_ELM == (*iter).GetElementType())
		{
			(*iter).Invalidate();
			isInvalid = true;
		}
	}
	return isInvalid;
}

重新编译后启动我们的工具,此时会看到无论是点选还是框选的结果中圆都会被排除掉。但是你会发现点选的时候我们仍然能选择圆,只不过是在构造ElementAgenda的时候将其移除了。我们能否限制用户不能选中圆呢?此时就要重写我们前面介绍的_OnPostLocate函数了。在MoveTool.h中加入如下所示的内容:

virtual bool    _OnPostLocate(HitPathCP path, WStringR cantAcceptReason)override;

在MoveTool.cpp中加入如下所示的内容:

bool    MoveTool::_OnPostLocate(HitPathCP path, WStringR cantAcceptReason)
{
	if (ELLIPSE_ELM == path->GetHeadElem()->GetElementType())
	{
		cantAcceptReason = WString(L"Circ isn't valid");
		return false;
	}
	return __super::_OnPostLocate(path, cantAcceptReason);
}

重新编译后启动我们的工具,此时你会发现当光标移动到圆上时,会出现如下图所示的图标并伴有提示表明当前元素不能被选择。

以下链接包含元素移动工具的完整代码:

communities.bentley.com/.../LearnDgnTool_5F00_Ver7.7z