c++ - 在 CHtmlEditCtrl::SetDocumentHTML 中使用 Unicode

标签 c++ mfc

我如何使用 CHtmlEditCtrl::SetDocumentHTML正确显示 Unicode(UTF-16 或 UTF-8 输入)

程序以 Unicode 编译。

例如,给定以下带有 charset=utf-8 元标记的输入:

CString u16 = LR"(<!DOCTYPE><html>
    <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head>
    <body>ελληνικά 华语 😃</body></html>)";

m_htmledit.SetDocumentHTML(u16) 没有正确显示字符。

相反,我必须调用 m_htmledit.SetDocumentHTML(CA2W(CW2A(u16, CP_UTF8), CP_ACP));

我不明白为什么它会这样工作,或者它是否在所有系统上都工作。

最小示例:

#include "afxhtml.h"
...
CHtmlEditCtrl m_htmledit;
...
BOOL CMyDialog::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    m_htmledit.Create(0, 0, CRect(10, 10, 300, 300), this, 0, 0);

    //wait for the control, this is not directly related to the question
    CComPtr<IHTMLDocument2> document;
    if(m_htmledit.GetDHtmlDocument(&document))
    {
        CComBSTR ready;
        while(document->get_readyState(&ready) == S_OK)
            if(wcscmp(ready, L"complete") == 0 || !AfxPumpMessage())
                break;
    }

    //send html data:
    CString utf16 = LR"(<!DOCTYPE><html>
        <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head>
        <body>ελληνικά 华语 😃</body></html>)";

    //m_htmledit.SetDocumentHTML(utf16); <- outputs garbage characters
    m_htmledit.SetDocumentHTML(CA2W(CW2A(utf16, CP_UTF8), CP_ACP)); //<- correct output
    return TRUE;
}

UTF-8 输入也有类似的问题。

m_htmledit_ctrl.SetDocumentHTML(CA2W(utf8, CP_UTF8)); 没有正确显示字符。

m_htmledit_ctrl.SetDocumentHTML(CA2W(utf8, CP_ACP)); 确实有效。但是在这里使用 CP_ACP 很奇怪。

例子:

CStringA utf8 = u8R"(<!DOCTYPE><html>
    <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head>
    <body>ελληνικά 华语 😃</body></html>)";
m_htmledit.SetDocumentHTML(CA2W(utf8, CP_ACP)); //<= correct output

最佳答案

CHtmlEditCtrl::SetDocumentHTML 使用名为 CStreamOnCString 的类。

CStreamOnCString 在某些时候调用

m_strAnsi = m_strStream;

其中m_strAnsi是一个存储缓冲区,m_strStreamCStringW源。我认为这是一个错误,因为它不会将源代码复制到缓冲区。而是使用 CW2A(m_strStream, CP_ACP)

进行转换

可以在发送数据之前通过另一个 CP_ACP 转换来纠正此错误。

或者我们可以如下编写自己的函数:

class CMyHtmlEditCtrl : public CHtmlEditCtrl
{
    public:
    template <class Type>
    HRESULT SetDocumentHTML_unicode(CStringT<Type, StrTraitMFC<Type>> html)
    {
        HRESULT hr = E_NOINTERFACE;
        CComPtr<IHTMLDocument2> document;
        if(!GetDHtmlDocument(&document))
            return hr;
        IStream *istream = SHCreateMemStream(
          reinterpret_cast<const BYTE*>(html.GetBuffer()), sizeof(Type)*html.GetLength());
        if(istream)
        {
            CComQIPtr<IPersistStreamInit> psi = document;
            if(psi)
                hr = psi->Load(istream);
            istream->Release();
        }
        html.ReleaseBuffer();
        return hr;
    }
};

现在我们可以调用 SetDocumentHTML_unicode(utf8_string)SetDocumentHTML_unicode(utf16_string)

关于c++ - 在 CHtmlEditCtrl::SetDocumentHTML 中使用 Unicode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59360395/

相关文章:

c++ - 尝试计算 pi 时不断得到 0

visual-studio-2015 - 将阿拉伯语字符转换为大写

winapi - CListCtrl:如何保持水平滚动位置?

c++ - C++ 标准库线程安全吗?

c++ - 如何使用按引用传递 C++ 将二维 vector 传递给函数

c++ - CImageList 是否删除资源?

C++如何在通过同一MFC应用程序的系统命令打开excel文件后关闭cmd exe

c++ - 笔记本电脑和固定电脑上的结果不同

C++ - 如何将静态数组放入我的数组中?

c++ - 为什么可以连接 2 个字符串文字而不是两个字符串变量?