【发布时间】:2019-07-07 22:28:17
【问题描述】:
我正在 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,导致选择向前跳转。通过InvokeHelper 函数调用检查vaCount 变体,VS 调试器将.iVal 值显示为-1,但vaCount 变体的“值”显示为65535。
为了将负整数作为 COM 函数调用的一部分适当地传递,我缺少什么?
【问题讨论】:
-
底层函数应该不支持负值。也许是其他方法或不同的
Unit参数... -
使用
int16_t(65535)获取-1,或使用VT_I2(而不是VT_I4)指定16 位整数。 -
vaCount使用VT_INT而不是VT_I4,就像vaUnit使用一样。如果将VT_INT更改为VT_I4,问题会消失吗?.iVal字段仅对VT_I2有效,VT_I4使用.lVal和VT_INT使用.intVal。在.lVal或.intVal中存储 32 位-1将用所有 1 位填充所有 4 个字节,当在.iVal中截断为 16 位时,它们仍然是全 1,因此仍然是-1。 signed 16bit-1与 unsigned 16bit65535的位相同。因此,您需要弄清楚为什么您的 signed 值被 interpretted 为 unsigned 值。 -
原始辅助函数使用
VT_I4替换vaCount,结果如上所述。我发布的代码来自一个实验,看看如果我切换到使用VT_INT会发生什么,上面的代码没有按预期运行。但是,当我修复.iVal/.lVal错误时,代码现在可以按预期运行!至于为什么VT_I4不允许我传递一个负整数,这仍然是一个谜……但是@RemyLebeau 如果您将评论移至答案,我很乐意将其标记为正确! -
@user986713 完成