VARIANT的使用方法

本文深入探讨了VARIANT结构体的内部构造及其在COM中的应用。详细解释了如何通过VARIANT来传递各种类型的数据,并提供了具体的使用案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VARIANT结构体主要是使用在COM(组件对象模型)中用于传递参数使用,它的存在主要是为了保持一个在COM参数传递方法的统一性,它几乎包含了所有普通常用类型的数据类型的传递,如整型,浮点型,布尔型等等,以及相应类型的指针类型,如整型指针。它的使用也比较方便。先来看看这个结构体它的结构:

typedef struct tagVARIANT {
  union {
    struct __tagVARIANT {
      VARTYPE vt;
      WORD    wReserved1;
      WORD    wReserved2;
      WORD    wReserved3;
      union {
        LONGLONG            llVal;
        LONG                lVal;
        BYTE                bVal;
        SHORT               iVal;
        FLOAT               fltVal;
        DOUBLE              dblVal;
        VARIANT_BOOL        boolVal;
        _VARIANT_BOOL       bool;
        SCODE               scode;
        CY                  cyVal;
        DATE                date;
        BSTR                bstrVal;
        IUnknown            *punkVal;
        IDispatch           *pdispVal;
        SAFEARRAY           *parray;
        BYTE                *pbVal;
        SHORT               *piVal;
        LONG                *plVal;
        LONGLONG            *pllVal;
        FLOAT               *pfltVal;
        DOUBLE              *pdblVal;
        VARIANT_BOOL        *pboolVal;
        _VARIANT_BOOL       *pbool;
        SCODE               *pscode;
        CY                  *pcyVal;
        DATE                *pdate;
        BSTR                *pbstrVal;
        IUnknown            **ppunkVal;
        IDispatch           **ppdispVal;
        SAFEARRAY           **pparray;
        VARIANT             *pvarVal;
        PVOID               byref;
        CHAR                cVal;
        USHORT              uiVal;
        ULONG               ulVal;
        ULONGLONG           ullVal;
        INT                 intVal;
        UINT                uintVal;
        DECIMAL             *pdecVal;
        CHAR                *pcVal;
        USHORT              *puiVal;
        ULONG               *pulVal;
        ULONGLONG           *pullVal;
        INT                 *pintVal;
        UINT                *puintVal;
        struct __tagBRECORD {
          PVOID       pvRecord;
          IRecordInfo *pRecInfo;
        } __VARIANT_NAME_4;
      } __VARIANT_NAME_3;
    } __VARIANT_NAME_2;
    DECIMAL             decVal;
  } __VARIANT_NAME_1;
} VARIANT, *LPVARIANT, VARIANTARG, *LPVARIANTARG;

这个结构体呢,有5个成员,分别是VARTYPE vt ,WORD wReserved1,WORD wReserved2,WORD wReserved3,和最后一个共用体。其中vt用以指明最后一个共用体中哪一个成员有效,wReserved1,wReserved2,wReserved3,这三个我们使用的时候不用管,系统保留,最后一个共用体根据vt的提示,对相应的成员进行值的存储。我们从两个不同的角度来理解,首先是使用VARIANT来存储参数,首先是声明一个这个结构体的对象,然后对对象的vt进行赋值,它可接受的值是一个枚举值,也就说只能在枚举这个范围内取值,比如我要用VARIANT传递一个整数,现在我对vt的赋值为VT_INT,这样就说明了我要使用这个结构体中共用体的整型变量,接着对INT变量进行赋值,赋我们要传递的值。这样就完成VARIANT的传递。现在我们从另外一个角度来理解VARIANT,刚才是我们对VARIANT对象进行赋值传递,现在我们是这个VARIANT对象的接收者,我们从参数中获得这个对象之后,我们首先检查这个结构体的vt成员,看它哪个类型的变量有效,比如就这个例子而言,检查到vt的值是VT_INT,因此,我直接去获取这个结构体中VT_INT所对应的变量,获取它的值。这样,我们从传递到使用两个角度来理解了VARIANT结构体,概括起来说,就是vt指明了我要传递的变量的类型,结构体中共用体的成员用来存储vt指明的类型的值。

下面来看看具体VARIANT结构体是如何使用赋值的,首先是第一种方法:


首先我们声明一个VARIANT结构体的对象vr1,然后使用VariantInit函数对其进行初始化,它的作用就是对vt赋VT_EMPTY,对别的变量值附空,否则就是一个随机值,这个过程和我们声明一个int变量一样,如果声明的时候不初始化,就是一个随机值。编程过程中,不管是指针还是什么变量,都应该在声明之后对其进行初始化。接着就是我赋VT_INT给vt,这里的V_VT就是代表要对vr1结构体中的vt成员进行幅值,接着对vr1中的INT成员赋值,这里的V_INT就是表示要对INT赋值,因此这里有一个规律,就是V_,它的后面加成员类型就可以对相应的成员赋值,而这里的成员类型有一个对照表,在文章的最后给出,比如,我要对BSTR成员赋值,我就用V_BSTR。这时候,就可以使用vr1了,使用完成之后,我们应该调用VariantClear函数,这个函数的作用就是将vt赋值为VT_EMPTY,以及释放使用这个结构体中的内存中的内容,如果是com对象,该函数是不会进行对象的release操作的,不管怎么样,我们都应该在使用完了VARIANT结构体之后,调用这个函数。

下面是第二种方法,原理和过程和地中方法类似,有一点微小的区别,就是VARIANT结构体的赋值上面来说,有点不同,如下:


接下来是字符串的操作,BSTR,我们不能直接将字符串传递一个VARIANT结构体对象,而是要用到函数SysAllocString,它的返回值就是一个BSTR,由它分配一个字符串,供VARIANT,对于为什么要这么做,可以自己查看MSDN COM的Automation那部分:


完成之后,我们还应该调用SysFreeString来释放由SysAllocString分配的内存。

另外,我们可以在类型与变量的对照表中发现,同一类型,对应了两种不同的变量,如,INT对应了变量有intVal和pintVal,其实这很简单,后者是指针性,如果要使用,说明我们赋值的对象是一个指针,如下:


最后给出类型与变量的对照表,如果是使用地中方法用V_加类型,就直接使用下表中VT_后的名称就可以了:

Member nameDescription
 VT_EMPTYIndicates that a value was not specified.
 VT_NULLIndicates a null value, similar to a null value in SQL.
 VT_I2Indicates a short integer.
 VT_I4Indicates a long integer.
 VT_R4Indicates a float value.
 VT_R8Indicates a double value.
 VT_CYIndicates a currency value.
 VT_DATEIndicates a DATE value.
 VT_BSTRIndicates a BSTR string.
 VT_DISPATCHIndicates an IDispatch pointer.
 VT_ERRORIndicates an SCODE.
 VT_BOOLIndicates a Boolean value.
 VT_VARIANTIndicates a VARIANT far pointer.
 VT_UNKNOWNIndicates an IUnknown pointer.
 VT_DECIMALIndicates a decimal value.
 VT_I1Indicates a char value.
 VT_UI1Indicates a byte.
 VT_UI2Indicates an unsignedshort.
 VT_UI4Indicates an unsignedlong.
 VT_I8Indicates a 64-bit integer.
 VT_UI8Indicates an 64-bit unsigned integer.
 VT_INTIndicates an integer value.
 VT_UINTIndicates an unsigned integer value.
 VT_VOIDIndicates a C style void.
 VT_HRESULTIndicates an HRESULT.
 VT_PTRIndicates a pointer type.
 VT_SAFEARRAYIndicates a SAFEARRAY. Not valid in a VARIANT.
 VT_CARRAYIndicates a C style array.
 VT_USERDEFINEDIndicates a user defined type.
 VT_LPSTRIndicates a null-terminated string.
 VT_LPWSTRIndicates a wide string terminated by nullNothingnullptra null reference (Nothing in Visual Basic).
 VT_RECORDIndicates a user defined type.
 VT_FILETIMEIndicates a FILETIME value.
 VT_BLOBIndicates length prefixed bytes.
 VT_STREAMIndicates that the name of a stream follows.
 VT_STORAGEIndicates that the name of a storage follows.
 VT_STREAMED_OBJECTIndicates that a stream contains an object.
 VT_STORED_OBJECTIndicates that a storage contains an object.
 VT_BLOB_OBJECTIndicates that a blob contains an object.
 VT_CFIndicates the clipboard format.
 VT_CLSIDIndicates a class ID.
 VT_VECTORIndicates a simple, counted array.
 VT_ARRAYIndicates a SAFEARRAY pointer.
 VT_BYREFIndicates that a value is a reference.
更多详细信息,请参考msdn

或是有任何编程问题,到http://www.panshy.com提问或是查阅。

<think>好的,我现在需要帮助用户解决在Vue2中使用Variant Form的问题。首先,我需要确认用户的需求是什么。用户提到“how to use variant form in vue2”,看起来他们想了解如何在Vue2项目中集成和使用Variant Form。不过,Variant Form可能是一个第三方库或者特定的表单组件,我需要先验证这个库是否存在,并且是否有适用于Vue2的版本。 首先,我应该回想一下常见的Vue表单库。比如Element UI、Vuetify、Vue Formulate等,但Variant Form这个名字不太常见。或者可能用户指的是动态表单生成,比如根据配置生成表单,这种通常称为动态表单或表单生成器。比如Vue Form Generator,或者可能是某个特定项目中的组件库,如Variant Form。 不过,根据用户提供的参考引用,他们可能已经在项目中使用了BootstrapVue的组件,比如b-modal,并且引用了.env.development的配置。这可能意味着他们的项目是基于Vue2,并且可能使用BootstrapVue或其他UI框架。因此,Variant Form可能是基于BootstrapVue或其他库的表单组件。 接下来,我需要检查用户提供的引用内容。引用[1]提到在Vue组件中注册b-modal组件和v-b-modal指令,这说明用户可能在使用BootstrapVue。而引用[2]是关于开发环境配置的,可能和API基础路径有关,但暂时和表单使用关系不大。 假设Variant Form是某个特定的表单库,比如可能是指vue-variant-form,或者可能是一个内部组件库。但根据常见的资源,可能用户指的是动态表单生成,比如通过JSON配置生成表单。例如,使用vue-form-generator这个库,或者类似的解决方案。 由于用户的问题可能涉及到动态表单,我需要给出一个通用的步骤,指导如何在Vue2中集成这样的表单库。例如,安装库,注册组件,创建表单配置,绑定数据,处理提交等。 可能的步骤包括: 1. 安装相关的表单库,比如vue-form-generator。 2. 在Vue项目中引入并注册组件。 3. 定义表单的字段配置(schema)。 4. 在组件中使用表单生成器组件,并绑定数据和事件。 5. 处理表单提交和验证。 另外,用户提供的引用[1]中提到了注册组件和指令的方法,这可能与如何在Vue2中正确注册第三方组件有关,因此在回答中需要包含类似的步骤,确保用户正确注册表单组件。 需要确保回答符合用户的要求,即使用Vue2,并且结合他们可能使用的BootstrapVue或其他库。同时,需要提供具体的代码示例,比如如何定义表单结构,如何处理数据绑定和提交事件。 可能存在的一些问题点: - 用户可能不清楚如何安装和引入第三方库。 - 表单配置的schema结构可能比较复杂,需要简单示例。 - 表单验证的处理方式。 - 如何与后端API交互,特别是在他们的环境配置中提到的API路径。 因此,在回答中需要分步骤说明,并给出代码示例,确保用户能够按照步骤操作。同时,生成的相关问题需要围绕表单库的使用、配置优化、验证处理等方面展开。</think>在Vue2中使用Variant Form(动态表单生成器)的步骤如下: ### 1. 安装依赖 ```bash npm install vue-variant-form@2.x --save # 或若使用动态表单生成器 npm install vue-form-generator@2.6.1 --save ``` ### 2. 基础配置 在入口文件`main.js`中注册组件: ```javascript import Vue from 'vue' import VariantForm from 'vue-variant-form' Vue.use(VariantForm) // 自动注册<variant-form>组件[^1] ``` ### 3. 定义表单结构 创建表单配置文件`formSchema.js`: ```javascript export const userFormSchema = { fields: [ { type: 'input', inputType: 'text', label: '用户名', model: 'username', required: true }, { type: 'select', label: '角色', model: 'role', values: ['admin', 'user', 'guest'] } ] } ``` ### 4. 组件使用 ```vue <template> <variant-form :schema="formSchema" v-model="formData" @submit="handleSubmit" /> </template> <script> import { userFormSchema } from './formSchema' export default { data() { return { formSchema: userFormSchema, formData: { username: '', role: 'user' } } }, methods: { handleSubmit(isValid) { if (isValid) { this.$http.post(this.$env.VITE_APP_BASE_API_SIMULATION, this.formData) // 使用环境变量配置[^2] } } } } </script> ``` ### 5. 验证配置 通过`validator`属性添加自定义验证规则: ```javascript { type: 'input', model: 'email', validator: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值