Mfc 字体绑定和 Rich Edit 控件 RICHEDIT50W 无法正确显示 Unicode

Mfc Font binding and Rich Edit Control RICHEDIT50W does not display Unicode Properly

最新更新:

好吧,我发现 a 某种罪魁祸首。我将控件从 50W 更改为 RichEdit20W,它现在显示 Hangul(韩语)。除了 init,我不需要更改任何其他代码,添加了 AfxInitRichEdit2(),并注释掉了 LoadLibrary(L"MsftEdit.dll")。 AfxInitRichEdit5() 不适用于 VS2010。在所有条件相同的情况下,Rich Edit 4.1 自 VS2005 以来就可用,它应该可以工作。我现在无法升级到 VS2015,所以我被卡住了。不过,我将为任何可以使 Hangul 在 50W 和 VS2010 上工作的人悬赏。


我有一个似乎无法解决的难题。

我有一个使用 CEdit 和 CRicheditCtrl 的 mfc Unicode 应用程序。
Rich Edit 是 50W 从 MsftEdit.dll 加载并使用 Spy++
验证 class 名称是 RICHEDIT50W。

我的问题:

我为 CEditCRichEditCtrl 使用相同的字体 Courier New

作为测试,我使用了一些韩文符号来查看两者的输出
控制。

C编辑输出ᄀᄁᄂᄃᄄᄅᄆᄇᄈ

CRichEditCtrl 为每个字符输出一个 box ,就像没有字形一样。

如果他们使用相同的字体,我不应该看到相同的输出字符吗?

我认为字体绑定不是问题,两者具有相同的默认字体。

谁能解开这个谜语?

提前致谢!

请注意,其他一些字符集也会发生这种情况,而不仅仅是韩语


更新

我查看了 VS2010 写字板示例,它使用 CRichEditView 但它
提供包装器以访问嵌入式 CRichEditCtrl。

我想我可以收集一些信息,但我看不到他们是怎么做的
Rich Edit 控件调用。

这就是我为两个控件生成字体的方式。
但是,我特别展示了 Rich Edit 部分。

文档说字体绑定应该处理默认设置的切换
字体到当前插入点的字体。

我主要在结尾使用
进行插入 ctrl.SetSel(-1,-1);
ctrl.ReplaceSel( str );

而且,根据文档,这应该根据需要更改为正确的字体,
如果不是默认字体。

在写字板示例中,如果我粘贴韩文文本,字体会切换为
Gulim

这是我的代码:

LOGFONT lf;
int pitch = 10;
memset(&lf, 0, sizeof(LOGFONT));

HDC hdc = ::GetDC(NULL);
lf.lfHeight = -MulDiv( pitch, GetDeviceCaps(hdc, LOGPIXELSY), 72);
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
lstrcpy(lf.lfFaceName, _T("Courier New") );
lf.lfWeight = FW_NORMAL;
lf.lfCharSet = ANSI_CHARSET;  // English, but use DEFAULT_CHARSET if not
lf.lfQuality = DEFAULT_QUALITY;


if ( !m_Font.CreateFontIndirect(&lf) )
{   // Ours didn't work, create a system default fixed font
    // ( Ignore, example for post only. Never gets called though )
    //memset(&lf, 0, sizeof(LOGFONT));
    //::GetObject(GetStockObject(ANSI_FIXED_FONT), sizeof(LOGFONT), &lf);
    //m_Font.CreateFontIndirect(&lf);
}


// Save the generated Font LOGFONT 
m_lf = lf;

// Set the default Font CHARFORMAT2
memset( &m_cfDefaultFont, 0, sizeof(m_cfDefaultFont) );
m_cfDefaultFont.cbSize = sizeof(m_cfDefaultFont);
m_cfDefaultFont.dwMask = CFM_CHARSET | CFM_FACE | CFM_WEIGHT ;
m_cfDefaultFont.bCharSet = m_lf.lfCharSet;
lstrcpy( m_cfDefaultFont.szFaceName, m_lf.lfFaceName );
m_cfDefaultFont.wWeight = m_lf.lfWeight;

// Finally set the font in the controls
m_RichEdit.SetFont( &m_Font );

// Same effect as m_RichEdit.SetFont()
//m_RichEdit.SendMessage(EM_SETCHARFORMAT, SCF_ALL, &m_cfDefaultFont);

// This displays nothing but 'box' glyphs
m_RichEdit.SetWindowTextW(_T("ᄃᄄᄅᄆᄇᄈᄉᄊᄋᄌᄍᄎ"));

更新 2

这就是我在应用程序中初始化 Rich Edit 的方式。
并在对话框控件中显示了 50W 的用法。

-- winapp.cpp
BOOL CMyApp::InitInstance()
{
    // ...... //

    CString strRichEdit = _T("Msftedit.dll");
    m_hMsfteditDll = AfxLoadLibrary( strRichEdit );
    if ( m_hMsfteditDll == NULL )
    {
        CString str;
        str.Format(_T("Error: Cannot find Rich Edit component %s"), strRichEdit );
        AfxMessageBox(str);
        return FALSE;
    }
    return TRUE;
}
int CRegexFormatApp::ExitInstance() 
{
    if ( m_hMsfteditDll != NULL )
        AfxFreeLibrary( m_hMsfteditDll );
    return CWinAppEx::ExitInstance();
}

// =========================

-- .rc 
CONTROL         "",IDC_RICH_EDIT,"RICHEDIT50W",WS_VSCROLL | WS_HSCROLL,40,15,148,28

-- Dlg.h
CRichEditCtrl m_RichEdit;

-- Dlg.cpp
void Dlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_RICH_EDIT, m_RichEdit); // Use .rc setting to Create/Attach
}

BOOL Dlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    CreateAndSetRichFont();  // Code shown above
    m_RichEdit.SetWindowTextW( ... );
}

此代码应适用于 Unicode 项目:

BOOL CMyApp::InitInstance()
{
    CWinApp::InitInstance();
    LoadLibrary(L"MsftEdit.dll");
    ...
}

BOOL CMyDialog::OnInitDialog()
{
    CDialog::OnInitDialog();

    static CRichEditCtrl redit;
    CWnd *wnd = &redit;
    wnd->Create(MSFTEDIT_CLASS, L"ᄃᄄᄅᄆᄇᄈᄉᄊᄋᄌᄍᄎ",
            WS_CHILD | WS_VISIBLE, CRect(0,0,300,300), this, 1001, 0);
    ...
    //redit is not to be mixed up with controls created in dialog editor.
}

编辑----------------

NONCLIENTMETRICS info = { sizeof(info) };
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
LOGFONT logfont = info.lfMessageFont;

//CClientDC has automatic cleanup, use it instead of GetDC
CClientDC dc(this);
logfont.lfHeight = -MulDiv(abs(logfont.lfHeight), dc.GetDeviceCaps(LOGPIXELSY), 76);

CFont font;
font.CreateFontIndirect(&logfont);
m_RichEdit.SetFont(&font);

m_RichEdit.SetWindowText(L"ᄃᄄᄅᄆᄇᄈᄉᄊᄋᄌᄍᄎ");

m_RichEdit.SetSel(1, 1);

CString test = L"(Test, ελληνικά)";

//Test to make sure we can see Unicode text
AfxMessageBox(test);
m_RichEdit.ReplaceSel(test);

//optional:
//get default CHARFORMAT
CHARFORMAT2 charFormat;
//m_RichEdit.GetSelectionCharFormat(charFormat);
m_RichEdit.GetDefaultCharFormat(charFormat);