windows中有没有方法能设置ansi系列api的默认编码换成utf-8?

发布于 2022-08-24 00:40:50 字数 522 浏览 20 评论 0

我遇到的状况是这样:
我手上有一个别人做的2d绘图库, 可以理解为gdi的封装. 但是他只做了ansi版本, 比如TextOut这样的函数, 只能输入ansi字符串, 而不是utf-16le宽字符串. 我现在的上层应用可以选择utf-8或者utf-16le作为内部编码, 那么就面临一个问题, 就是当我要渲染字符串的时候, win32的ansi系列api接受的是"本地编码", 就是GetACP返回的CodePage. 如果我每次渲染之前都使用转换函数转换的话, 比如我用utf-8, 就会执行这样的过程----先把utf-8转换成utf-16le, 再把utf-16le转换成本地ansi编码比如GBK, 然后传递给TextOut, TextOut内部会自动把GBK再传换成utf-16le再显示. 来来回回绕了一大圈, 未免太复杂了.

我想请教的就是, 有没有方法把进程内的ansi系列api默认编码全部换成utf-8? 比如"SetACP"这样类似的方法. 这样我就可以在应用中使用utf-8传给TextOut, 由TextOut执行一次转换, 就可以显示了.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

黯然 2022-08-31 00:40:51

Windows API 都有两个版本,你直接用 Unicode 版本不就得了。为什么非要转两次呢?你转成本地编码,系统内部最终还是转成 Unicode 并调用了 Unicode 版本的 API,纯属折腾。比如 TextOut,你可以显式调用 TextOutW,调用之前,使用 MultiByteToWideChar 将 UTF-8 转换为 Windows Unicode (UTF-16LE)。例如,将 TextOut 包装为 GdiTextOut,分别包装为 UTF-8 和 UTF-16LE 两个版本:

BOOL WINAPI GdiTextOut(
    HDC hdc,
    int nXStart,
    int nYStart,
    PCWSTR lpString,
    int cchString
)
{
    return ::TextOutW(hdc, nXStart, nYStart, lpString, cchString);
}

BOOL WINAPI GdiTextOut(
    HDC hdc,
    int nXStart,
    int nYStart,
    PCSTR lpString,
    int cchString
)
{
    WCHAR wszBuffer[1024] = { 0 };
    DWORD cchBuffer = sizeof(wszBuffer) / sizeof(WCHAR);
    int cchResult = MultiByteToWideChar(CP_UTF8, 0, lpString, -1, wszBuffer, cchBuffer);
    if (cchResult > 0)
    {
        return GdiTextOut(hdc, nXStart, nYStart, wszBuffer, cchResult);
    }
    BOOL bResult = FALSE;
    int cchNeeded = MultiByteToWideChar(CP_UTF8, 0, lpString, -1, NULL, 0);
    if (cchNeeded > 0)
    {
        HANDLE hHeap = GetProcessHeap();
        PWSTR lpBuffer = (PWSTR)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cchNeeded * sizeof(WCHAR));
        if (lpBuffer != NULL)
        {
            int cchResult = MultiByteToWideChar(CP_UTF8, 0, lpString, -1, lpBuffer, cchNeeded);
            if (cchResult > 0)
            {
                bResult = GdiTextOut(hdc, nXStart, nYStart, lpBuffer, cchResult);
            }
            HeapFree(hHeap, 0, (void *)lpBuffer);
        }
    }
    return bResult;
}
我乃一代侩神 2022-08-31 00:40:50

貌似只能在这个DLL外面再封装一层了。

长亭外,古道边 2022-08-31 00:40:50

每次转换一下也不会太麻烦,性能影响不大。貌似没办法设置默认

恏ㄋ傷疤忘ㄋ疼 2022-08-31 00:40:50

对已有的库进行改造是不现实的。对方需要什么cp,你就转成什么吧。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文