LearnDgnTool-08_ToolSetting窗口


目前为止我们DgnTool的例子中还没有用到任何UI界面,但实际工作中,我们的交互式工具大部分情况下需要用户输入一些额外的参数。例如如果你开发一个单元放置的工具,你的工具需要提供一个对话框让用户选择一个单元库,然后需要将单元库中的单元罗列出来供用户选择。如果你是用的NativeCode的开发方式,那么就需要用Bentley提供的通过“.r”文件来订制UI用户界面的方式来设计用户界面,用这种方式你可以使用多种Bentley内置的原生态控件,例如颜色表等。但是这种方式不像微软的WinForm(WinForm已经是微软比较早的技术了,目前比较流行的是WPF技术,有兴趣的读者可以找一本相关书籍学习一下)那样支持可视化设计,对话框的外貌完全是通过“.r”文件中一行行代码来订制设计的。而且其在处理用户与后台交互的方式也是偏向于“C Style”风格的,在窗口消息处理函数中,根据各种不同的窗口消息做不同的处理。如果你是用的Addin方式的话,就可以用WinForm来实现你的界面。通过微软的VS集成开发环境,我们可以可视化地设计WinForm窗体,在跟用户交互时,也是通过各种事件来完成。例如如果你要在用户点击按钮时执行某些操作,只要在可视化的界面上双击这个按钮,就会进入到这个事件处理函数中,在这个函数中去编写你的程序即可,很容易就能实现。如果你学过混合编程的话,就可以在C/C++的代码中使用WinForm界面。本章就以拷贝元素工具为例,通过混合编程的方式演示一下如何在DgnTool中使用WinForm在ToolSetting窗口上显示界面供用户输入额外的参数。

下面的链接是拷贝元素工具的实现代码,下载编译后会生成DgnToolToolSettings.dll文件。

communities.bentley.com/.../DgnToolToolSettings.7z

在Mstn中打开一个dgn文件,加载我们的程序后,执行Key-in命令:dgntooltoolsettings copyelement,可以看到我们的拷贝元素工具被激活,在ToolSetting窗口上会显示如下所示的界面:

通过光标在视图中选中一个元素,此时会看到选中的元素会随着光标在视图中移动,我们在ToolSetting窗口的“Copies:”输入域输入:5,此时光标在视图中移动时会看到有五个等间距的元素。再次在视图中单击鼠标左键,会看到有五个新拷贝出来的元素。

在VS2015中打开我们的项目,我们的项目是一个VS CLR的项目,在VS中可以可视化地设计我们的界面。由于要挂接到ToolSetting窗口上,所以我们的对话框类需要继承于Bentley::MstnPlatformNET::WinForms::Adapter。VS的可视化设计器不能识别这个类,所以如果要查看对话框的设计器,需要临时将这个类改成System::Windows::Forms::Form。此时在文档中单击右键,选择“View Designer”菜单可以看到我们的窗体设计器,如下图所示:

可以看到在右侧的Toolbox窗口中有各式各样的预定义控件供我们使用,需要哪种控件只要用光标拖拽到我们的窗体设计器上,并移动到合适的位置即可,非常直观方便。

接下来我们看一下我们是如何在DgnTool中使用这个WinForm界面的。Mstn中每一个需要用户输入参数的交互式工具都会把界面显示到ToolSetting窗口上。Mstn中每当启动一个新的交互式工具时,当前激活的交互式工具就会被强制退出。这里有一个例外就是视图工具,从DgnViewTool派生出来的工具就是一个视图工具,其不会强制退出当前的交互式工具,只是临时暂停了,当你结束视图工具(通常是在视图中单击鼠标右键)时,就会恢复先前的交互式工具继续执行。当前激活的交互式工具被强制退出时,会从ToolSetting窗口上卸载掉其挂接的界面,然后新的激活工具会往ToolSetting窗口上挂接新的界面。这个过程如果你的界面是用“.r”的方式来实现的话,不需要自己在程序中去控制,只要将资源ID与命令关联起来就可以(具体如何使用可以参考本论坛系列博客:一步一步学习MDL-CE[7])。但是如果你用的是WinForm的话,就需要在我们前面介绍的_OnPostInstall和_OnCleanup函数中往ToolSetting窗口上挂接以及卸载我们的界面。前几章我们已经介绍过_OnPostInstall函数会在工具真正被激活成为当前工具后被调用,而_OnCleanup函数会在工具退出时被调用。在我们的代码中,我们在CopyElementTool类中定义了一个gcroot<FormCopyElement^>类型的成员变量m_form,我们在重写的_OnPostInstall中对其初始化后挂接到ToolSetting窗口上。在重写的_OnCleanup函数中将m_form从ToolSetting上卸载。CopyElementTool类的其他内容我们在前几章已经讲解过,这里就不再一一复述了。

可以看到通过混合编程来实现界面的设计是非常直观的,可以减少大部分在设计界面时耗费的时间。不过混合编程在Mstn二次开发的所有开发方式中也是难度最大的,需要我们非常了解C/C++、C#中是如何对对象声明周期进行管理的,在此基础上还要去学习C++/CLI这门编程语言。如果没有这些基础就贸然使用的话,想必会碰到各种让自己无法解决的问题,最终没有节省设计界面的时间,反而在解决这些问题时又变成了事倍功半的结局。