MSCE C#官网一步步学习搬运9 第九章、用C++/CLI编写Addins
2021-05-14 09:30
标签:app uil 基类 mod alt 如何获取 处理 内容 利用 上一章中简单演示了如何在Addins端封装调用NativeCode端导出的函数,虽然通过PInvoke可以调用到大部分NativeCode端导出的函数,但是C/C++中一些特殊的函数是无法通过PInvoke进行封装的,例如构造函数,本章演示的例子就属于这种情况。在第零章中已经提到过CE版本上Addins中有两套开发框架,在第二章中简单演示了分别在两套开发框架下如何创建元素。在实际开发过程中,我们有时候会遇到要将元素转换到另一套开发框架下的情况。这个时候您会发现,Addins中并没有接口去完成这样的功能。但是如果您仔细研究的话,会发现两套开发框架下的Element对象都留有接口能获取到NativeCode端与元素构造相关的对象,以及从NativeCode端元素相关的对象构造其对象实例。COM框架下的Element对象有MdlElementRef和MdlElementDescrP两个成员函数可以获取到NativeCode端元素的ElementRefP和MSElementDescrP指针。Bentley.Interop.MicroStationDGN.Application 下的MdlCreateElementFromElementDescrP成员函数可以从MSElementDescrP构造出COM框架下的Element。而新的开发框架下的Element有一个ElementHandle的属性能获取到NativeCode端ElementHandle的指针。其有一个保护类型的成员函数InitializeFromElementHandle可以从NativeCode端ElementHandle的指针构造出其对象实例。在NativeCode端,ElementHandle的几个重载构造函数中有接收ElementRefP或者MSElementDescrP为参数的构造函数,且ElementHandle也有获取ElementRefP和MSElementDescrP的成员函数。所以以NativeCode的对象ElementHandle为桥梁我们就可以完成两套编程框架下的元素相互转换。如果我们用PInvoke的技术来实现的话,就需要在NativeCode端导出这样两个转换函数,一个以ElementRefP或者MSElementDescrP指针为参数以ElementHandleP指针为返回值的转换函数实现从COM框架下的Element到新的编程框架下的Element的转换。另外一个是以ElementHandleP指针为参数,以MSElementDescrP指针为返回值的转换函数实现从新的编程框架下的Element到COM框架下的Element的转换。不管是哪个方向的转换,我们都需要在Addins端有一个接收返回的指针并将其最终转换为Element对象实例。如果在C++/CLI中我们可以在一个代码块里边同时使用托管和非托管的对象,所以不管是哪个方向的转换我们只需要一个函数就能实现。 在学习本章例子之前,需要安装好Mstn CE SDK。如何获取Mstn CE SDK请参考另一篇NativeCode的学习博客。接下来就让我们来一步一步实现这两个转换函数吧。 1、在D盘建立:D:\Files\BentleyMstn\MstnCE\Mixed\SampleMixed目录。 2、启动一个文本编辑器(当然可以启动VS2015用作编辑器),在其中键入如下内容并保存为文件D:\Files\BentleyMstn\MstnCE\Mixed\SampleMixed\SampleMixed.h。该文件中含有转换函数所在类的类型声明。以及一个继承与Bentley.DgnPlatformNET.Elements.Element的类ElementDerive。 这里定义了一个ElementDerive类,是因为我们要借助于Bentley.DgnPlatformNET.Elements.Element的InitializeFromElementHandle函数来初始化构造Bentley.DgnPlatformNET.Elements.Element。因为InitializeFromElementHandle是保护类型的成员函数,不能从类的外边访问此成员函数,所以从Bentley.DgnPlatformNET.Elements.Element派生出ElementDerive类。在ElementDerive的成员函数中我们可以访问到基类的保护类型成员,所以可以通过InitializeFromElementHandle初始化基类Bentley.DgnPlatformNET.Elements.Element的成员。而ElementDerive是从Bentley.DgnPlatformNET.Elements.Element派生出来的,当然可以作为Bentley.DgnPlatformNET.Elements.Element来使用了。 3. 在文本编辑器中再另建一个新文件,在其中键入如下内容并保存为文件D:\Files\BentleyMstn\MstnCE\Mixed\SampleMixed\SampleMixed.cpp。该文件中包含有ElementDerive和两个转换函数的实现。 ConvertToDgnNetEle实现从COM框架下的Element到新的编程框架下的Element的转换。这个函数通过COM框架下Element的MdlElementRef或者MdlElementDescrP获取到ElementRefP或者MSElementDescrP指针,通过这两个指针可以初始化构造非托管类型EditElementHandle。ElementDerive的构造函数需要一个ElementHandle的指针作为参数,而EditElementHandle派生于ElementHandle。所以我们通过EditElementHandle就可以初始化构造ElementDerive对象了,最后返回ElementDerive对象实例即可。ConvertToInteropEle实现从新的编程框架下的Element到COM框架下的Element的转换。函数中通过新的编程框架下的Element的ElementHandle属性获取到ElementHandle的指针。因为.Net中的对象实例在垃圾回收过程中会被重定位,所以我们使用C++/CLI中的类型cli::pin_ptr告诉编译器,在此cli::pin_ptr的作用域中ele->ElementHandle在垃圾回收时不被重新定位。这样就可以保证我们的ElementHandle指针一直有效。然后我们通过ElementHandle获取到元素的MSElementDesrP指针,进而去调用Bentley.Interop.MicroStationDGN.Application 下的MdlCreateElementFromElementDescrP成员函数的到COM框架下的Element实例。 4. 在文本编辑器中再另建一个新文件,在其中键入如下内容并保存为文件D:\Files\BentleyMstn\MstnCE\Mixed\SampleMixed\SampleMixed.mke。该文件是SDK下的bmake工具用来编译源码来使用的,.mke文件的格式可以参考另一篇NativeCode的学习博客。 4. 右键选择“开始>Bentley>MicroStation CONNECT Edition SDK”,选择“More>Run as administrator”启动bmake工具。在命令提示符后键入cd /d D:\Files\BentleyMstn\MstnCE\Mixed\SampleMixed并回车进入我们的源码所在目录,然后再键入bmake –a来生成SampleMixed.dll。生成的文件位于…\MicroStation\mdlapps目录下。 至此我们的两个转换函数已经封装好了,接下来我们在csAddins项目中去验证我们这两个函数。在csAddins项目中添加引用SmaleMixed.dll,具体添加方法参考第一章。打开commands.xml文件,新增命令两个命令csAddins CreateElement TestConvertToDgnNetEle和csAddins CreateElement TestConvertToInteropEle并指定其处理函数为csAddins.CreateElement. TestConvertToDgnNetEle和csAddins.CreateElement. TestConvertToInteropEle。如果您对XML格式的命令表文件还不熟悉,请参考第四章的相关主题。打开CreateElement.cs文件,CreateElement类的最后加入如下两个函数。 选VS菜单Build > Build Solution来生成本解决方案。启动Mstn,打开key-in窗口,输入csAddins CreateElement TestConvertToDgnNetEle,可以看到在生成了如图所示的元素。 元素我们是通过COM框架下的接口生成的,然后转换成新的编程框架下的元素,然后设置其颜色及线宽属性,最后添加到dgn文件中。接下来验证另一个函数,在key-in窗口,输入csAddins CreateElement TestConvertToInteropEle,可以看到在生成了如图所示的元素。 元素我们是通过新的编程框架下的接口生成的,颜色及线宽我们是通过COM框架下的接口设置的。本章例子只是简单演示了C++/CLI的用途,实际上C++/CLI能为我们做很多东西。当然其难度也是Mstn平台主要的三种开发语言中最高的,要想掌握C++/CLI必须先对C#和C/C++中对象的生命周期管理以及内存回收机制有很深的了解才行。建议读者要先熟练使用C#和C/C++之后,再开始利用C++/CLI进行开发。完整的csAddins解决方案源文件下载链接如下。非常欢迎大家批评指正,非常欢迎与他人分享该博客。 MSCE C#官网一步步学习搬运9 第九章、用C++/CLI编写Addins 标签:app uil 基类 mod alt 如何获取 处理 内容 利用 原文地址:https://www.cnblogs.com/JolinZH/p/13125157.html第九章、用C++/CLI编写Addins
#pragma once
#pragma managed
#using
using namespace System::Reflection;
#include
DemoSrcDir = $(_MakeFilePath)
PolicyFile = MicroStationPolicy.mki
appName = SampleMixed
ASSEMBLY_NAME = $(appName)
RIGHTSCOMPLIANT = false
MDLMKI = $(MSMDE)mki/
mdlLibs = $(MSMDE)library/
%include mdl.mki
outputDir = $(MS)Mdlapps/
always:
~mkdir $(o)
objList = $(o)SampleMixed$(oext)
%include compileForCLRStart.mki
CCompDebugOptions = $(CCompDebugOffSwitch)
CCompDebugOptions =% $[CCompDebugDefault]
CCompOpts + -AI$(MS)Assemblies -AI$(MS)Assemblies/ECFramework -AI$(MS) -AI$(o)
dirToSearch = ${msPrivInc}
$(o)SampleMixed$(oext) : $(baseDir)SampleMixed.cpp
%include compileForCLRStop.mki
DLM_OBJECT_DEST = $(o)
DLM_NAME = $(appname)
RIGHTSCOMPLIANT = true
DLM_DEST = $(outputDir)
DLM_OBJECT_FILES = $(objList)
DLM_NO_DEF = 1
DLM_NO_DLS = 1
DLM_NO_IMPLIB = 1
DLM_NO_SIGN = 1
ASSEMBLY_VERSION = 1.0.0.0
ASSEMBLY_TITLE = $(appName)
ASSEMBLY_DESCRIPTION = MixedMode Test Application
ASSEMBLY_PRODUCT_NAME = $(appName)
ASSEMBLY_FILE_VERSION = 1.0.0.0
ASSEMBLY_COMPANY_NAME = Bentley Systems
ASSEMBLY_COPYRIGHT = Copyright: (c) 2019 Bentley Systems, Incorporated. All rights reserved.
LINKER_LIBRARIES + $(mdlLibs)BentleyAllocator.lib
LINKER_LIBRARIES + $(mdlLibs)DgnPlatform.lib
%include linkMixedAssembly.mki
public static void TestConvertToDgnNetEle(string unparsed)
{
BIM.Application app = Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp;
BIM.Point3d ptStart = app.Point3dZero();
BIM.Point3d ptEnd = ptStart;
ptStart.X = 10;
BIM.LineElement lineEle = app.CreateLineElement2(null, ref ptStart, ref ptEnd);
Element ele = SampleMixed.ElementOperation.ConvertToDgnNetEle(lineEle);
ElementPropertiesSetter elePropSetter = new ElementPropertiesSetter();
elePropSetter.SetColor(1);
elePropSetter.SetWeight(2);
elePropSetter.Apply(ele);
ele.AddToModel();
}
public static void TestConvertToInteropEle(string unparsed)
{
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
ModelInfo modelInfo = dgnModel.GetModelInfo();
DPoint3d[] ptArr = new DPoint3d[5];
ptArr[0] = new DPoint3d(0 * UorPerMas, 10 * UorPerMas, 0 * UorPerMas);
ptArr[1] = new DPoint3d(1 * UorPerMas, 12 * UorPerMas, 0 * UorPerMas);
ptArr[2] = new DPoint3d(3 * UorPerMas, 8 * UorPerMas, 0 * UorPerMas);
ptArr[3] = new DPoint3d(5 * UorPerMas, 12 * UorPerMas, 0 * UorPerMas);
ptArr[4] = new DPoint3d(6 * UorPerMas, 10 * UorPerMas, 0 * UorPerMas);
CurvePrimitive curPri = CurvePrimitive.CreateLineString(ptArr);
Element ele = DraftingElementSchema.ToElement(dgnModel, curPri, null);
BIM.Element eleInterop = SampleMixed.ElementOperation.ConvertToInteropEle(ele);
eleInterop.Color = 3;
eleInterop.LineWeight = 4;
ele.AddToModel();
}
文章标题:MSCE C#官网一步步学习搬运9 第九章、用C++/CLI编写Addins
文章链接:http://soscw.com/index.php/essay/85555.html