【问题标题】:How to Convert CString to VT_ARRAY|VT_UI1如何将 CString 转换为 VT_ARRAY|VT_UI1
【发布时间】:2015-05-28 19:43:17
【问题描述】:

我继承了一个使用 CppWebBrowser 控件的旧应用程序。
该应用程序一直使用 ::Navigate 方法进行 GET 请求,但现在我需要开始将其用于 POST;但是,现有代码不适用于 POST。我对使用这些数据类型的知识有限,但我怀疑它与 CString 到 VT_ARRAY|VT_UI1 的转换有关。

void WebPostData(TCppWebBrowser *CppWebBrowser, CString sURL, CString sPostData)
{
    BSTR bstrHeaders = NULL;
    TVariant vFlags = { 0 }, vTargetFrameName = { 0 }, vPostData = { 0 }, vHeaders = { 0 };
    LPSAFEARRAY psa;
    LPCTSTR cszPostData = sPostData;
    UINT cElems = lstrlen(cszPostData);
    LPSTR pPostData;
    LPVARIANT pvPostData;

        bstrHeaders = SysAllocString(L"Content-Type: application/x-www-form-urlencodedrn");
        if (!bstrHeaders){
            Application->MessageBox("Could not allocate bstrHeaders", "Warning", MB_OK | MB_ICONWARNING);
            return;
        }

        V_VT(&vHeaders) = VT_BSTR;
        V_BSTR(&vHeaders) = bstrHeaders;

        pvPostData = vPostData;

        if (pvPostData){
            VariantInit(pvPostData);

            psa = SafeArrayCreateVector(VT_UI1, 0, cElems);
            if (!psa){
                return;
            }

            SafeArrayAccessData(psa, (LPVOID*)&pPostData);
            memcpy(pPostData, cszPostData, cElems);
            SafeArrayUnaccessData(psa);

            V_VT(pvPostData) = VT_ARRAY | VT_UI1;
            V_ARRAY(pvPostData) = psa;
        }

        CppWebBrowser->Navigate((TVariant)sURL, &vFlags, &vTargetFrameName, &vPostData, &vHeaders);
}

【问题讨论】:

  • this 有帮助吗?
  • 我想你有一个 Unicode 版本(可能不是,尤其是它是遗留项目),在这种情况下,CString 值将是 Unicode 字符串,并且你需要 ASCII 或 UTF-8 来表示 @ 987654324@ing 到字节数组中。
  • 那篇文章看起来就像原始开发人员复制代码的确切位置,只是他们将 sPostData 参数从 String 更改为 CString。此外,关于那篇文章的一些 cmets 声明它不适用于帖子。

标签: c++ mfc atl


【解决方案1】:

您展示的代码是从这个 C++Builder 示例中复制的:

How to post data using TCppWebBrowser in C++Builder

CString 是一个 MFC 类,但 C++Builder 不支持 MFC。原始代码使用了 System::String,它是一个 C++Builder 类。那么,您是否尝试将此代码转换为 Visual Studio?或者你真的在使用 C++Builder?你没说。

我假设您使用的是 C++Builder,否则您必须重新编写 Visual Studio 类的代码。

所以,让我们首先将CString 改回String。现在,根据您使用的 C++Builder 版本,StringANSI (C++Builder 3-2007) 或 UTF-16 (C ++Builder 2009+)。在后一种情况下有一个_DELPHI_STRING_UNICODE 预编译器定义。

application/x-www-form-urlencoded 类型通常不以 UTF-16 格式发送,并且无法保证 Web 服务器能够处理它。所以我建议你将sPostData数据转换为UTF-8,然后你可以创建一个UTF-8字节的VT_UI1数组:

#ifndef _DELPHI_STRING_UNICODE
inline bool NeedsUTF8(String s)
{
    // String is 1-indexed
    for (int i = 1; i <= s.Length(); ++i)
    {
        int ch = s[i];
        if (ch > 0x7F) return true;
    }
    return false;
}
#endif

void WebPostData(TCppWebBrowser *CppWebBrowser, String sURL, String sPostData)
{
    TVariant vFlags, vTargetFrameName, vPostData, vHeaders;

    // note: UTF8String was added in C++Builder 6,
    // use AnsiString in C++Builder 3-5 instead
    UTF8String utf8;

    #ifdef _DELPHI_STRING_UNICODE
    // C++Builder 2009+, convert from UTF-16 to UTF-8 directly
    utf8 = sPostData;
    #else
    // C++Builder 3-2007, check if ASCII or ANSI
    if (NeedsUTF8(sPostData))
    {
        // ANSI, so convert from ANSI to UTF-16 to UTF-8,
        // but you have to do the last step manually
        WideString wPostData(sPostData);
        int len = WideCharToMultiByte(CP_UTF8, wPostData.c_bstr(), wPostData.Length(), NULL, 0, NULL, NULL);
        utf8.SetLength(len);
        WideCharToMultiByte(CP_UTF8, wPostData.c_bstr(), wPostData.Length(), utf8.c_str(), len, NULL, NULL);
    }
    else
    {
        // ASCII, compatible with UTF-8 as-is
        utf8 = sPostData;
    }
    #endif

    LPSAFEARRAY psa = SafeArrayCreateVector(VT_UI1, 0, utf8.Length());
    if (!psa)
        return;

    // TVariant takes ownership of a safearray
    vPostData = psa;

    // TVariant takes ownership of a copy of a WideString's BSTR
    vHeaders = WideString("Content-Type: application/x-www-form-urlencoded;charset=utf-8\r\n");

    LPVOID pPostData;
    if (FAILED(SafeArrayAccessData(psa, &pPostData)))
        return;

    memcpy(pPostData, utf8.c_str(), utf8.Length());
    SafeArrayUnaccessData(psa);

    CppWebBrowser->Navigate((TVariant)sURL, &vFlags, &vTargetFrameName, &vPostData, &vHeaders);
}

【讨论】:

    猜你喜欢
    • 2023-04-01
    • 2011-11-23
    • 2012-03-07
    • 2011-07-29
    • 2014-11-27
    • 2011-04-30
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多