Return COM 接口中一个函数的多个值

Return multiple values from a function in COM Interfaces

我做了一项研究并为 GetWindowRect API 实现了一个包装函数,它运行良好。但它目前只能通过 SAFEARRAY return window 坐标。但是我在想我怎样才能 return 它的实际 return 值。

我是这样声明的:

[id(10)] HRESULT WinAPI_GetWindowRect([in] VARIANT hWnd, [out, retval] SAFEARRAY(VARIANT) *lpRect);

STDMETHOD(WinAPI_GetWindowRect)(VARIANT hWnd, SAFEARRAY **lpRect);

和实现:

STDMETHODIMP CWinAPI::WinAPI_GetWindowRect(VARIANT hWnd, SAFEARRAY **lpRect {

    CComSafeArray<VARIANT> CCSA_RECT;
    RECT Rect;
    HRESULT HResult;

    if (!lpRect) { return E_INVALIDARG; }

    *lpRect = nullptr;

    int Result = (int)GetWindowRect(VariantToHWND(hWnd), &Rect);
    //   ^ I ALSO WANT TO RETURN THIS RESULT TOO

    if (Result != 0)
    {
        HResult = CCSA_RECT.Create(4, 0);
        assert(HResult == S_OK);

        CCSA_RECT[0] = Rect.left;
        CCSA_RECT[1] = Rect.top;
        ...
    }
    else
    { ... }
}

但是,正如我所知,不能有多个 [out, retval] 值,因此非常感谢任何关于如何 return 这个值 (Result) 的建议。

更新

当我尝试 return 时,它是这样的:

[id(10)] HRESULT WinAPI_GetWindowRect([in] VARIANT hWnd, [out] SAFEARRAY(VARIANT) *lpRect, [out, retval] VARIANT *Result);

STDMETHOD(WinAPI_GetWindowRect)(VARIANT hWnd, SAFEARRAY **lpRect, VARIANT *Result);

分配如下:

Result->intVal = (int)GetWindowRect(VariantToHWND(hWnd), &Rect);

我在尝试使用它时在 VBScript 行下方收到 ​​Type mismatch 错误:

Dim lpRect, Result: Result = WINAPI.WinAPI_GetWindowRect(AutoItX3.WinGetHandle("[CLASS:ConsoleWindowClass]"), lpRect)

我希望这个 SAFEARRAY 成为 [out] 参数,Result 成为 return 值。

我通过使用 VARIANT 作为 [out] 参数在一定程度上解决了这个问题:

[id(10)] HRESULT WinAPI_GetWindowRect([in] VARIANT hWnd, [out] VARIANT *Result, [out, retval] SAFEARRAY(VARIANT) *lpRect);

STDMETHOD(WinAPI_GetWindowRect)(VARIANT hWnd, VARIANT *Result, SAFEARRAY **lpRect);

新实现:

STDMETHODIMP CWinAPI::WinAPI_GetWindowRect(VARIANT hWnd, VARIANT *Result, SAFEARRAY **lpRect) {

    CComSafeArray<VARIANT> CCSA_RECT;
    RECT Rect;
    HRESULT HResult;

    if (!lpRect) { return E_INVALIDARG; }

    *lpRect = nullptr;

    VariantInit(Result);
    Result->vt = VT_I2;

    Result->intVal = (int)GetWindowRect(VariantToHWND(hWnd), &Rect);

    if (Result->intVal != 0)
    {...}
    else
    {...}

}

已使用以下 VBScript 对此进行了测试:

Dim AutoItX3: Set AutoItX3 = WScript.CreateObject("AutoItX3.Control")
Dim WINAPI: Set WINAPI = WScript.CreateObject("WinAPIWrapperLib.WINAPI")

Dim lpRect, Result: lpRect = WINAPI.WinAPI_GetWindowRect(AutoItX3.WinGetHandle("[CLASS:ConsoleWindowClass]"), Result)

WScript.Echo "GetWindowRect returned: " + CStr(Result)

If CInt(Result) <> 0 Then
    For iNum = 0 To UBound(lpRect)
        WScript.Echo CStr(lpRect(iNum))
    Next
End If

WScript.Echo(CStr(WINAPI.WinAPI_GetLastErrorMessage))

但是,我仍然不能将 SAFEARRAY 用作仅 [out] 参数,将其用作 [out] 仅参数并将 Result 用作 [out, retval] 成员通过以下方式:

[id(10)] HRESULT WinAPI_GetWindowRect([in] VARIANT hWnd, [out] SAFEARRAY(VARIANT) *lpRect, [out, retval] VARIANT *Result);

仍然会导致 Type mismatch 错误。