c++ - 如何将负整数传递给 COM/OLE 函数?
问题描述
我正在使用 Visual Studio 2010 中基于 C++/ATL 的 Microsoft Word 加载项。我还使用基于 MFC 的COleDispatchDriver
支持类,并使用 Visual Studio 的 ClassWizard 从 Microsoft Word 类型库生成包装类。下面是由 ClassWizard 生成的 Selection.Move 函数的示例包装器。
long Move(VARIANT * Unit, VARIANT * Count)
{
long result;
static BYTE parms[] = VTS_PVARIANT VTS_PVARIANT ;
InvokeHelper(0x6d, DISPATCH_METHOD, VT_I4, (void*)&result, parms, Unit, Count);
return result;
}
对于上述函数,我还编写了辅助函数来处理 VARIANT 参数传递,如下所示。
long Move(int Unit, int Count)
{
long result;
static BYTE parms[] = VTS_PVARIANT VTS_PVARIANT ;
VARIANT vaUnit;
::VariantInit(&vaUnit);
vaUnit.vt = VT_I4;
vaUnit.iVal = Unit;
VARIANT vaCount;
::VariantInit(&vaCount);
vaCount.vt = VT_INT;
vaCount.iVal = Count;
InvokeHelper(0x6d, DISPATCH_METHOD, VT_I4, (void*)&result, parms, &vaUnit, &vaCount);
::VariantClear(&vaUnit);
::VariantClear(&vaCount);
return result;
}
当我用一个正整数作为参数调用我的函数时Count
,Word 会正确响应,例如,以下函数调用会将选择“向前”(朝向文档末尾)移动一个字符。
m_oSelection.Move(1 /* wdCharacter */, 1);
但是,如果我尝试使用以下函数调用将所选内容“向后”移动一个字符(朝向文档开头),Word 不会按预期响应。
m_oSelection.Move(1 /* wdCharacter */, -1);
它“似乎”像 Word 自动化将整数视为无符号整数,而我的 -1 值变为 65535 导致选择向前跳转。使用函数调用检查vaCount
行上的变体InvokeHelper
,VS 调试器将.iVal
值显示为 -1,但vaCount
变体的“值”显示为 65535。
在 COM 函数调用中适当地传递负整数,我缺少什么?
解决方案
问题是您在滥用VARIANT
.
您将vaCount
's vt
field 设置为VT_INT
1但随后将您的int
值分配给它的.iVal
字段而不是它的.intVal
字段。该.iVal
字段是 16 位short
,用于VT_I2
,而.intVal
32 位int
用于VT_INT
。
同样,您将vaUnit
's设置vt
为VT_I4
但随后也将您的int
值分配给它的.iVal
字段,而不是它的.lVal
字段,它是一个 32bit long
。
1:你为什么要使用VT_INT
,而不是更传统的VT_I4
?
试试这个:
long Move(int Unit, int Count)
{
long result;
static BYTE parms[] = VTS_PVARIANT VTS_PVARIANT ;
VARIANT vaUnit;
::VariantInit(&vaUnit);
vaUnit.vt = VT_I4;
vaUnit.lVal = Unit;
VARIANT vaCount;
::VariantInit(&vaCount);
vaCount.vt = VT_I4;
vaCount.lVal = Count;
InvokeHelper(0x6d, DISPATCH_METHOD, VT_I4, (void*)&result, parms, &vaUnit, &vaCount);
::VariantClear(&vaUnit);
::VariantClear(&vaCount);
return result;
}
话虽如此,我建议你使用CComVariant
or_variant_t
包装类而不是VARIANT
直接使用,让它为你处理这些细节。另外,因为InvokeHelper()
在失败时会抛出异常,所以让包装器VariantClear()
在超出范围时为您调用:
long Move(int Unit, int Count)
{
long result;
static BYTE parms[] = VTS_PVARIANT VTS_PVARIANT ;
CComVariant vaUnit(Unit);
CComVariant vaCount(Count);
InvokeHelper(0x6d, DISPATCH_METHOD, VT_I4, (void*)&result, parms, &vaUnit, &vaCount);
return result;
}
long Move(int Unit, int Count)
{
long result;
static BYTE parms[] = VTS_PVARIANT VTS_PVARIANT ;
_variant_t vaUnit(Unit);
_variant_t vaCount(Count);
InvokeHelper(0x6d, DISPATCH_METHOD, VT_I4, (void*)&result, parms, &vaUnit, &vaCount);
return result;
}
推荐阅读
- javascript - javascript:搜索包括 html 在内的文本并更改其 css 样式
- ios - JSQMessageViewController textview 不显示链接
- node.js - AWS Lambda 构造函数错误“找不到 API 配置 lambda-2015-03-31”
- powershell - 在文本文件中添加新的文本行
- android - 交错的相似回收者视图
- javascript - 带有数组和函数的待办事项列表
- linux - 移植 r5u870 驱动程序但 v4l2 合规性返回“VIDIO_QUERYCAP 失败,设备的 ioctl 不合适”
- javascript - 如何从另一个站点 src 获取文件大小?
- excel - 从数据库中查找重复数据
- vim - Yank 命令在 vim 编辑器中不起作用