如何将 std::variant 作为 VARIANT* 传递给 ExecWB?

And*_*kle 3 mfc code-analysis variant visual-c++

我看过这篇关于使用的文章std::variant。这是因为以下代码引发了代码分析警告:

void CChristianLifeMinistryHtmlView::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == ID_TIMER_ZOOM)
    {
        //get the zoom value
        VARIANT vZoom{};
        vZoom.vt = VT_I4;
        vZoom.lVal = 0;
        ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, nullptr, &vZoom);
        TRACE("zoom %d\n", vZoom.lVal);

        //kill the timer
        KillTimer(nIDEvent);

        GetParent()->PostMessage(UWM_HTMLVIEW_CHANGE_ZOOM_MSG, vZoom.lVal);
        return;
    }

    CHtmlView::OnTimer(nIDEvent);
}
Run Code Online (Sandbox Code Playgroud)

警告:

警告C26476:表达式/符号{{0, 0, 0, 0, {0}}}使用带有多个类型指针的裸联合“union”:variant改为使用 (type.7)。

我开始尝试更改代码:

void CChristianLifeMinistryHtmlView::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == ID_TIMER_ZOOM)
    {
        //get the zoom value
        std::variant<long> vZoom(0);

        ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, nullptr, &vZoom);
        TRACE("zoom %d\n", vZoom.lVal);

        //kill the timer
        KillTimer(nIDEvent);

        GetParent()->PostMessage(UWM_HTMLVIEW_CHANGE_ZOOM_MSG, vZoom.lVal);
        return;
    }

    CHtmlView::OnTimer(nIDEvent);
}
Run Code Online (Sandbox Code Playgroud)

但问题是ExecWB需要 aVARIANT *并且我不知道如何传递它std::variant

IIn*_*ble 5

尽管建议过于笼统而无用,但诊断是正确的。虽然std::variant一般来说,这是表示类型安全的可区分联合的VARIANT好方法,但它与COM 中使用的结构无关。

在这种情况下,您需要使用不同的类型,例如 Microsoft 的_variant_t类。它封装了 raw VARIANT,并处理其可区分联合的内部。

它提供了几个正确管理内部状态设置的构造函数,并从中派生,VARIANT以便任何实例的地址都可以传递给任何接受以下参数的函数VARIANT*

#include <comutil.h>
#pragma comment(lib, "comsuppw.lib")

int main() {
    auto zoom{ _variant_t(long{ 0 }) };
    ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, nullptr, &zoom);
}
Run Code Online (Sandbox Code Playgroud)

  • Microsoft 提供了一个 COM 支持库,由“_bstr_t”、“_com_error”、“_com_ptr”和“_variant_t”组成,提供资源管理和更强的类型安全性。这几乎涵盖了您在 COM 编程中看到的整个类型表面。由于“VARIANT”结构的复杂性,“_variant_t”特别有用。 (4认同)