【问题标题】:Easy way to tell if unicode character is supported in current font?判断当前字体是否支持 unicode 字符的简单方法?
【发布时间】:2016-03-20 14:25:42
【问题描述】:

我正在使用 Borland C++ Builder 2009,并显示左右指向箭头,如下所示:

Button2->Hint = L"Ctrl+\u2190" ;
Button3->Hint = L"Ctrl+\u2192" ; 

这在 Windows 7 上运行良好,应用程序使用字体“Segoe UI”。

在 XP 上我得到一个正方形而不是箭头,我在 XP 上使用字体“Tahoma”。 换句话说,提到的 Unicode 字符在 XP 上的 Tahoma 中不存在。

是否有一种简单快捷的方法可以简单地检查当前使用的字体是否支持请求的 Unicode 字符? 如果是这样,例如,我可以将箭头替换为“>”或“

感谢您的帮助。

【问题讨论】:

  • 这与特定的编程语言无关,而是与库有关。由于这些是特定于语言的,您应该提供您实际使用的语言,C 或 C++。请注意,绝对没有符合标准的方式。
  • @Olaf 因为可以在 C++ 中使用 C 解决方案,所以我认为在这种情况下使用这两个标签并不合适。不在标准中是无关紧要的,因为问题显然是关于 Windows 特定的解决方案,并且指定了编译器。
  • @MarkRansom:C 不是 C++。存在不兼容的语义和 C++ 所没有的特性。至少如果您使用标准 C q 这意味着 C11 - 或至少 C99(C11 主要添加了功能,但没有改变语义)。如果您的编译器不遵循标准,则它已损坏或至少被称为过时。请注意,您也可以很好地在 Windows 上使用其他编译器。
  • @Olaf Windows API 是纯 C,尽管有 C++ 包装器。 大多数 C 兼容的答案也可以在 C++ 中使用,包括当前带有复选标记的答案。如果问题更多是关于语言特性或标准库,我倾向于同意你的看法。
  • @MarkRansom:但事实并非如此。所以 C++ 标签是错误的。不过,这取决于代码的编译方式。如果编译为 C,他不能使用 C++ 特性。哎呀,这两种语言的公共子集(比许多人认为的要小)应该有一个标签。

标签: c++ c winapi c++builder


【解决方案1】:

您可以使用GetFontUnicodeRanges() 查看当前选择到 DC 中的字体支持哪些字符。请注意,此 API 需要您调用一次以了解缓冲区需要多大,然后再调用一次以实际获取数据。

DWORD dwSize = GetFontUnicodeRanges(hDC, nullptr);
BYTE* bBuffer = new BYTE[dwSize];
GLYPHSET* pGlyphSet = reinterpret_cast<GLYPHSET*>(bBuffer);
GetFontUnicodeRanges(hDC, pGlyphSet);
// use data in pGlyphSet, then free the buffer
delete[] bBuffer;

GLYPHSET 结构有一个名为 ranges 的成员数组,可让您确定字体支持的字符范围。

【讨论】:

  • 您可以使用std::vector 而不是new/delete 作为可变大小缓冲区。
  • @Peter 抱歉,我以为您已经拥有该代码。是的,GetDC() 然后选择有问题的字体进去。
  • @Peter 这些是 WinAPI 概念,如果你不熟悉它们,恐怕你需要做一些研究(或者也许对 c++ builder 有所了解的人可以提供帮助)。
  • Canvas-&gt;Handle 实际上是我需要让GetFontUnicodeRanges() 正常工作的hDC 句柄!我现在有工作代码,在 W7 和 XP 上确认。谢谢。
  • 还想指出 GetFontUnicodeRanges 在 Windows 8.1 和 Windows 10 上对我不起作用。它适用于简单的 Unicode 字符,但此 API 不包含任何新字符。例如,L'৳'。此外,执行相同操作的更简单的 API,即GetGlyphIndices,似乎也不起作用。所以如果有人可以发布一个更新的方法来解决这个问题会很好吗?
【解决方案2】:

仅供参考和谷歌之神:

bool UnicodeCharSupported(HWND Handle, wchar_t Char)
{
if (Handle)
    {
    DWORD dwSize = GetFontUnicodeRanges(Handle, NULL);
    if (dwSize)
        {
        bool Supported = false ;
        BYTE* bBuffer = new BYTE[dwSize];
        GLYPHSET* pGlyphSet = reinterpret_cast<GLYPHSET*>(bBuffer);
        if (GetFontUnicodeRanges(Handle, pGlyphSet))
            {
            for (DWORD x = 0 ; x < pGlyphSet->cRanges && !Supported ; x++)
                {
                Supported = (Char >= pGlyphSet->ranges[x].wcLow &&
                             Char < (pGlyphSet->ranges[x].wcLow + pGlyphSet->ranges[x].cGlyphs)) ;
                }
            }
        delete[] bBuffer;
        return Supported ;
        }
    }
return false ;
}

示例,与我的问题有关:

if (!UnicodeCharSupported(Canvas->Handle, 0x2190))
    { /* Character not supported in current Font, use different character */ }

【讨论】:

  • 在找到 Char 的匹配项时,您可能需要考虑从循环中考虑 break-ing。
猜你喜欢
  • 2014-01-03
  • 1970-01-01
  • 2019-12-20
  • 2012-03-30
  • 1970-01-01
  • 2016-11-04
  • 1970-01-01
  • 1970-01-01
  • 2012-01-24
相关资源
最近更新 更多