调试字体链接

时间:2012-08-08 09:08:33

标签: c++ mfc localization fonts

我对正在开发的程序有疑问。它是使用MFC编写的,但不使用unicode。我们翻译成简体中文。到目前为止,这是我们的第一个也是唯我们已将所有字符串移动到资源以使其可转换。一切似乎在我们的计算机上运行良好(Win7和XP)但是对于一些客户运行Windows XP的计算机我们遇到了问题:

在这些计算机上,除了我们输入树cotrols(直接使用CTreeCtrl)之外,所有翻译的字符串都有效。我不确定它是树控件还是我们输入的导致问题的文本,但字体似乎没有在这些控件中被替换。我的猜测是,它可能不会被替换,因为一些字符串也包含拉丁字符。尽管如此,这种替换似乎在程序的其他地方起作用,并且输入树中的所有字符串都不包含这些字符。

所以我的第一个问题是:有没有办法知道控件内部发生了什么?我们可以远程访问发生问题的计算机,但在它们上运行调试器可能有点棘手。可以使用哪种工具来诊断这个问题?

我想到的一个可能的解决方案是对树控件进行子类化以获得对实际文本绘制的更多控制,可能使用http://blogs.msdn.com/b/oldnewthing/archive/2004/07/16/185261.aspx中的方法来解决问题。这可能是有效的,还是只是一项无用的工作?

非常感谢!

1 个答案:

答案 0 :(得分:0)

好吧,在他们的系统上似乎有一个树控件实现中的错误,或者他们有一些系统范围的插件以某种方式挂钩到绘图中。我最终做的是在树视图中通过通知自定义绘图,然后使用字体链接来解析字体。我不认为字体链接是必要的,因为我认为大多数时候它最终只使用预选字体进行TextOutW()。

以下是我最终得到的一些简化的代码示例:

void MyDlg::OnCustomDrawTreeItem( NMHDR* pNMHDR, LRESULT* pResult )
{

if (!mpFontLink)
{
    *pResult = CDRF_DODEFAULT;
    return;
}

LPNMTVCUSTOMDRAW pCustomdraw = (LPNMTVCUSTOMDRAW) pNMHDR;
switch(pCustomdraw->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
    {
        // Ask to do custom draw
        *pResult = CDRF_NOTIFYITEMDRAW;
        break;
    }
case CDDS_ITEMPREPAINT:
    {
        // Ask for post paint notification
        *pResult = CDRF_NOTIFYPOSTPAINT;
        break;
    }
case CDDS_ITEMPOSTPAINT:
    {
        // Get the rect of only the item, not the tree stuff
        RECT rcItem;
        m_pageTree.GetItemRect((HTREEITEM) pCustomdraw->nmcd.dwItemSpec, &rcItem, TRUE);

        // Erase the item background in case the previous string drawn was wider
        HDC hDC = pCustomdraw->nmcd.hdc;
        FillRect( hDC, &rcItem, (HBRUSH) GetClassLongPtr(m_pageTree.GetSafeHwnd(), GCLP_HBRBACKGROUND));

        pageStruct *pS = (pageStruct*) pCustomdraw->nmcd.lItemlParam;
        DWORD dwFontCodepages = 0, dwStrCodepages = 0;

        HFONT hOriginalFont = (HFONT)GetCurrentObject(hDC, OBJ_FONT);
        HRESULT hr = mpFontLink->GetFontCodePages( hDC, hOriginalFont, &dwFontCodepages);
        OML_CStringW tData = pS->csCaption.GetBuffer();

        // Set up position etc
        DWORD dwAlignOrig = GetTextAlign(hDC);
        if (!(dwAlignOrig & TA_UPDATECP)) {
            SetTextAlign(hDC, dwAlignOrig | TA_UPDATECP);
        }

        POINT ptOrig;
        MoveToEx(hDC, 2 + rcItem.left, 1 + rcItem.top, &ptOrig);
        SetTextColor( hDC, pCustomdraw->clrText );
        SetBkColor( hDC, pCustomdraw->clrTextBk );

        // Loop over the parts of the text
        TuInt32 nIndex = 1;
        while (nIndex <= tData.GetLength())
        {
            long nActualChars = 0;
            wchar_t *pStr = (wchar_t*)tData.BaseGetItemP( nIndex );
            TuInt32 nChars = 1 + tData.GetLength() - nIndex;
            hr = mpFontLink->GetStrCodePages(pStr, nChars,
                                             dwFontCodepages, &dwStrCodepages, &nActualChars);

            if (dwStrCodepages & dwFontCodepages)
            {
                // We end up here almost every time, that is why TextOutW would probably be enough.
                // This part is supported by the original font (or the GDI can help us switch automatically)
                TextOutW(hDC, 0, 0, pStr, nActualChars);
            }
            else
            {
                // We need to link
                HFONT hLinked;
                if (FAILED(hr = mpFontLink->MapFont(hDC, dwStrCodepages, 0, &hLinked)))
                {
                    // Fail: Output the rest without linking
                    TextOutW( hDC, 0, 0, pStr, nChars );
                    break;
                }

                // Output with linked font
                SelectObject(hDC, hLinked);
                TextOutW( hDC, 0, 0, pStr, nActualChars);
                SelectObject(hDC, hOriginalFont);
                mpFontLink->ReleaseFont( hOriginalFont );
            }
            nIndex += nActualChars;
        }
        OML_LOG_1( "_END:");

        // Reset alignment mode
        if (!(dwAlignOrig & TA_UPDATECP)) {
            SetTextAlign(hDC, dwAlignOrig);
            MoveToEx(hDC, ptOrig.x, ptOrig.y, NULL);
        }

        *pResult = CDRF_SKIPDEFAULT;
    }
default:
    {
        *pResult = CDRF_DODEFAULT;
        break;
    }
}
} /* OnCustomDrawTreeItem */