2015-05-28 4 views
1

Я унаследовал старое приложение, которое использует элемент управления CppWebBrowser.
Приложение всегда использовало метод :: Navigate для запросов GET, но теперь мне нужно начать использовать его для POST; однако существующий код не работает для POST. У меня ограниченные знания, работающие с этими типами данных, но я подозреваю, что это связано с преобразованием CString в VT_ARRAY | VT_UI1.Как преобразовать 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); 
} 
+0

Значит ли [** это **] (Http: //edn.embarcadero. com/article/27519) help? – abelenky

+0

Я предполагаю, что у вас есть сборка Unicode (может быть, нет, особенно, это старый проект), и в этом случае значение 'CString' будет строкой Unicode, и вы хотите, чтобы ASCII или UTF-8 для' memcpy' в массив байтов. –

+0

Эта статья выглядит как точное место, где исходный разработчик скопировал код, за исключением того, что они изменили параметр sPostData из String в CString. Кроме того, в некоторых комментариях к этой статье говорится, что она не работает для сообщений. – ddrjca

ответ

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, String является либо ANSI (C++ Builder 3-2007), либо UTF-16 (C++ Builder 2009+). В последнем случае существует прекомпилятор _DELPHI_STRING_UNICODE.

Тип application/x-www-form-urlencoded обычно не отправляется как UTF-16, и нет гарантии, что веб-сервер сможет его обработать. Поэтому я предлагаю вам преобразовать данные sPostData в UTF-8, то вы можете создать массив VT_UI1 из UTF-8 байт:

#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); 
}