欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    VARIANT自动化技术.docx

    • 资源ID:78753271       资源大小:13.61KB        全文页数:6页
    • 资源格式: DOCX        下载积分:20金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要20金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    VARIANT自动化技术.docx

    Skyline开发中的VARIANT参数类型在二次开发中,无论是针对什么软件平台,甚或于在所有的软件开发活动中,人们都只在做一件事情:进行接口调用。用Win32 API写代码的人关注的是函数,写WinForm的人关注整套Framework的调用,针对Skyline做二次开发的我们则更关注COM接口的使用。 在这个过程中,调用规则是所有开发人员高度关注的。这里所说的调用规则主要包括:名称,参数,返回值。 Skyline中的调用规则有其一定的特殊性,因为Skyline提供了一整套COM自动化接口,调用的名称既可以是接口方法,也可以是DISPATCH ID,调用参数中又有几乎无处不在,却又令人无比陌生的类型,大多数的返回值不是某个接口的对象指针,就是HRESULT类型。以上这些对于将整套系统架构在C/S之上的开发人员来说都会产生一定的困惑,无论你使用的是C+还是C#,或者别的什么开发语言,都无法回避这一点。也许使用C#进行二次开发会很方便,快速,但明白些内部机制,对程序出错后的debug是相当有益的。基于此,我计划介绍一下Skyline开发中的参数类型。随便翻翻Skyline的开发文档就会发现,除过那些普通不起眼的小角色以外(我指的是类似于double, long这样的常规类型),出镜率最高的当属VARIANT类型和BSTR类型了,这两种类型也是COM开发中的常见类型。在这篇文章中我会全面介绍一下VARIANT类型,因此如果你不了解TE,可借此熟悉这一在COM相关开发中大量使用的数据类型。如果你是一名TE开发人员,那么你还会发现我的重点是解决一些开发中的问题,例如构造多维数组类型的VARIANT变量以及如何访问该变量的数据等等话题。在COM发展出来之后,虽然它标榜自己跨语言,分布式,但人们发现,这里所谓的跨语言仅仅是对那些含有指针机制的语言所说的,对于脚本类型的语言仍然无法使用,因此在COM的基础上又发展出了自动化(Automation),如何在各种类型的语言之间传递数据,或者说,各种开发语言如何以一套相同的调用规则去使用组件。这便是VARIANT类型应运而生的背景。因为它能够存储任意类型的数据。在VS的开发工具内,在VARIANT类型上点击”go to definition”,可以看到它的原型。大致是这个样子:struct tagVARIANT VARTYPE vt; union short iVal; / VT_I2. long lVal; / VT_I4. float fltVal; / VT_R4. double dblVal; / VT_R8. DATE date; / VT_DATE. BSTR bstrVal; / VT_BSTR. short * piVal; / VT_BYREF|VT_I2. long * plVal; / VT_BYREF|VT_I4. float * pfltVal; / VT_BYREF|VT_R4. double * pdblVal; / VT_BYREF|VT_R8. DATE * pdate; / VT_BYREF|VT_DATE. BSTR * pbstrVal; / VT_BYREF|VT_BSTR. ;可以看出,VARIANT是个结构体,该变量的类型保存在vt中,含有的不同类型的值保存在union中。我们注意到vt的类型是VARTYPE,这也是一个结构,借助开发工具,我们也能看到它的定义。例如long 是VT_I4,double 是VT_R8,long类型的指针是VT_BYREF与VT_I4的组合。下面通过一个简短的程序来演示一下它的基本用法。#include<comdef.h>#include<iostream>using std:cout;using std:endl;int main() VARIANT v1; VariantInit(&v1); v1.vt = VT_R8; v1.dblVal = 0.0001; cout << v1.dblVal << endl; VariantClear(&v1); return 0;从程序中可以看到,VARIANT类型使用起来很麻烦,使用前要初始化,用完后还要清空,一不留神也许就会出现错误。如果有面向对象编程经验,也许你会将这个类型封装为一个类,在构造函数中调用VariantInit,在析构函数中调用VaraiantClear进行清理。幸运的是,微软已经封装好了这样一个类:_variant_t,上述程序在使用了_variant_t类型后代码如下:#include<comdef.h>#include<iostream>using std:cout;using std:endl;int main() _variant_t v1 = 0.0001; cout << v1.dblVal << endl; return 0;有了_variant_t类型之后,我们就可以申请一个该类型的变量,甚至不用初始化,就可以作为参数使用,这篇文章中的代码就是一个很好的例子。有的时候,一些函数,比如CreatePolyline函数中需要一个VARIANT类型,但得是一个数组。自动化技术中的数组使用的是SAFEARRAY,它同样是一个结构体,与普通数组最大的区别就是这种数组有”自我意识”,所谓的自我意识就是,它知道所保存数据的维度,知道数组大小,知道是否还在被使用(内部有引用计数),与VARIANT类型一样,也有一套函数作为SAFEARRAY的支撑操作存在着,下面我以一个小程序来演示如何构建一个数组类型的_variant_t变量。#include<comdef.h>#include<iostream>#include<vector>using std:cout;using std:endl;using std:vector;int main() vector<double>vec; for(int i = 1; i < 11; i+) vec.push_back(i * 0.0001); SAFEARRAY* psa = NULL; SAFEARRAYBOUND rgsabound1; rgsabound0.lLbound = 0; rgsabound0.cElements = vec.size(); psa = SafeArrayCreate(VT_R8,1,rgsabound); for(long i = 0; i < 10; i+) SafeArrayPutElement(psa,&i,reinterpret_cast<void*>(&veci); _variant_t va; va.vt = VT_ARRAY | VT_R8; va.parray = psa; long size = va.parray->rgsabound0.cElements; for(long i = 0; i < size; i+) double tmp = 0.0; SafeArrayGetElement(va.parray,&i,reinterpret_cast<void*>(&tmp); cout << tmp << " " cout << endl; return 0;程序中首先创建一个SAFEARRAY的指针变量,然后声明一个SAFEARRAYBOUND类型的数组,这个数组用来指定SAFEARRAY每个维度的元素数目,如果有两个维度,那么就声明含有两个元素的SAFEARRAYBOUND数组,每个维度的元素数目在cElements域中指定。这段代码中我只使用一维数组,所以SAFEARRAYBOUND数组中只有一个元素。然后使用函数SafeArrayCreate创建,如果成功,它会返回一个SAFEARRAY的地址,到此为止,我们的数组中都还没有数据,所以接下来用SafeArrayPutElement填充数据。最后我创建一个SAFEARRAY数组类型的_variant_t变量。 VT_ARRAY|VT_R8表示该变量中保存的是double型的数组,parray域保存SAFEARRAY的地址。代码的最后部分演示了如何取用SAFEARRAY中的数据。这样我们就有了一个包含SAFEARRAY的VARIANT变量,可如何在TE中使用呢?空间某点的信息至少是三维,甚至多维数组才能表示的。也许通过前面的简短介绍你还是一头雾水,甚至去网上搜索看到的也几乎全是对一维数组构造VARIANT变量的介绍,下面我就用TerraExplorer Pro V6中的创建剖面功能来演示一下二维数组的VARIANT变量如何建立。创建剖面在TE V6中使用如下函数定义:HRESULT CreateTerrainProfile(VARIANT arrPoints)它的参数是一个数组型的VARIANT,数组的每一项是都是一个Point,我们创建一个4行2列的常规数组,接着声明一个含有两个元素的SAFEARRAYBOUND数组rgsabound,在rgsabound0中指定其cElements为4,在rgsabound1中指定cElements为2,然后创建一个二维的SAFEARRAY,代码如下:void CTEST_TEPV6View:OnTerrainProfile() SAFEARRAY* psa; SAFEARRAYBOUND rgsabound2; rgsabound0.lLbound = 0; rgsabound0.cElements = 4; rgsabound1.lLbound = 0; rgsabound1.cElements = 2; psa = SafeArrayCreate(VT_R8,2,rgsabound); assert(psa); long index2 = 0,0; double point42=100.0,200.0,300.0,500.0,400.0,900.0,500.0,100.0; HRESULT hr; for(int i = 0; i < 4; i+) index0 = i; for(int j = 0; j < 2; j+) index1 = j; hr = SafeArrayPutElement(psa,index,&pointij); assert(SUCCEEDED(hr); _variant_t pt; pt.vt = VT_ARRAY | VT_R8; pt.parray = psa; hr = m_pSGW->Analysis->CreateTerrainProfile(pt); assert(SUCCEEDED(hr);这里要注意的是向SAFEARRAY中填充数据的过程,SafeArrayPutElement有三个参数,其中第一个参数是要填充的数组的首地址,在这里就是指针psa,第二个参数也是一个指针,但是它是一个索引向量的指针,每一个索引指示一个维度,那么这个向量的指针说白了就相当于一个内存偏移量,如果你要在二维数组的哪个位置存入数据,那么这个索引就是那个位置的值,比如在本例中,因为是二维数组,所以首先声明一个包含两个元素的索引数组index2,如果此时你要在第1行第3列存入数据,那么就将index0指定为行号0,然后将index1指定为列号2,并将index数组的地址传入函数才行。在代码中我使用循环来为SAFEARRAY存入数据,所以就得不停的修正索引的值。第三个参数是欲传入数组的值的地址。以上的初始化过程完毕后,我们新建一个_variant_t类型的变量,并设置正确的类型,然后传入函数就可以了。大部分函数调用都是传入一个参数的值,但有时也会从函数传出一个值,比如在TE V6实现屏幕录像时用到的函数GetAvailableCodecs,它会返回一个SAFEARRAY的数组,这种情况下,仍然是新建一个_variant_t类型的变量,调用完成后,该变量会自动被设置为包含SAFEARRAY数组。我们根据文档中的说明,可以得知该数组的维数,如果是1维的,那么可以通过vt.parray->rgsabound0.cElements获得数组长度,如果是二维的,那么还要得到rgsabound1来得到cElements,以此确定二维数组的大小。下面的代码演示了读取编码信息的功能,更多细节参看:TE V6中屏幕录像功能的实现_variant_t vtCodeInfo;HRESULT hr = m_ptt->AviWriter->raw_GetAvailableCodecs(&vtCodeInfo);assert(SUCCEEDED(hr);ICodecInfo6* pCodec = NULL; /vtCodeInfo是从GetAvailableCodes()返回的VARIANT类型变量/下面这行代码用于获取该数组的大小unsigned int size = vtCodeInfo.parray->rgsabound0.cElements;/下面这个向量用于存放编码器名称std:vector<std:wstring> codeDesp;/用于存放编码器的IDispatch指针std:vector<IDispatch*> codeInfo; for(unsigned int i = 0; i < size;i+) _variant_t tmp; long index = static_cast<long>(i); hr = SafeArrayGetElement(vtCodeInfo.parray,&index,&tmp); assert(SUCCEEDED(hr); pCodec = reinterpret_cast<ICodecInfo6*>(tmp.pdispVal); std:wstring nmtmp(pCodec->GetName(); codeDesp.push_back(nmtmp); codeInfo.push_back(tmp.pdispVal);总结一下,有了_variant_t类型,我们基本上可以把它当做普通参数变量来看待了,如果是传入值的参数,一定要事前设置类型和值,从函数传出值的参数,就没有这个必要了。如果要使用SAFEARRAY,特别是多维数组的情况,要小心设置和读取SAFEARRAYBOUND中的值。

    注意事项

    本文(VARIANT自动化技术.docx)为本站会员(飞****2)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开