

Imgui最后字符乱码问题
source link: http://pkxpp.github.io/2020/09/21/Imgui最后字符乱码问题/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

[TOC]
用Imgui显示中文的时候,最后一个字符偶尔乱码~
描述
- 打印了一下十六进制
int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) { #ifdef IMGUI_USE_STB_SPRINTF int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args); #else int w = vsnprintf(buf, buf_size, fmt, args); #endif if (buf == NULL) return w; // test if (w == -1) { for (int i = 0; i < strlen(fmt); ++i) { printf("%2X ", fmt[i]); } printf("err(%d) %d\n", errno, buf_size); } // test end if (w == -1 || w >= (int)buf_size) w = (int)buf_size - 1; buf[w] = 0; return w; } #endif // #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
打印结果,找到一个查编码的网页[4],不错
FFFFFFE6 FFFFFF97 FFFFFFB6 FFFFFFE9 FFFFFF97 FFFFFFB4 FFFFFFE9 FFFFFF80 FFFFFF9F FFFFFFE5 FFFFFFBA FFFFFFA6 FFFFFFEF FFFFFFBC FFFFFF9A err(22) 3073 时:xE6\x97\xB6 间:xE9\x97\xB4 速:\xE9\x80\x9F 度:\xE5\xBA\xA6 中文冒号:\xEF\xBC\x9A
原因
- 看到错误码是22 == EINVAL,就知道原因了。因为调用到 vsnprintf 的时候,格式化后面没有参数,如下所示:
ImGui.Text("时间速度:");
这就导致 ImFormatStringV 函数返回了整个buf_size,而Imgui把这整个size都显示到界面上,就GG了
errno
参考[2][3],还有errno.h
// Error codes used in the Secure CRT functions #ifndef RC_INVOKED #define _SECURECRT_ERRCODE_VALUES_DEFINED #define EINVAL 22 #define ERANGE 34 #define EILSEQ 42 #define STRUNCATE 80 #endif
解决
- 方法1:修改 ImFormatStringV 中vsnprintf返回-1,主要是(errno==EINVAL)的情况,再取源字符串的长度判断一下
if (w == -1 || w >= (int)buf_size) { w = strlen(fmt); w = w < buf_size - 1 ? w : (int)buf_size - 1; }
看ImGui::TextEx里面其实也做了一层判断,只是再ImFormatStringV的时候走不到而已
void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; IM_ASSERT(text != NULL); const char* text_begin = text; if (text_end == NULL) text_end = text + strlen(text); // FIXME-OPT
- 方法2:把buf清0
理论上把 g.TempBuffer 格式化就可以了,没测试过,不知道有木有影响~
void ImGui::TextV(const char* fmt, va_list args) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); TextEx(g.TempBuffer, text_end, ImGuiTextFlags_NoWidthForLargeClippedText); }
- 方法3:使用Imgui.TextUnformatted显示没有参数的文本
参考
[1] vsnprintf、_vsnprintf、_vsnprintf_l、_vsnwprintf、_vsnwprintf_l
[2] vsnprintf
[3] errno
[4] 在线编码插叙
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK