Winapi 在控制台模拟器中尝试绘制水平线时卡住

Winapi 在控制台模拟器中尝试绘制水平线时卡住,winapi,rust,Winapi,Rust,Windows,直接使用Win32 API调用 我正在尝试创建一个模拟控制台应用程序行为的windows应用程序。所以我使用的是Cascadia Mono,这是Windows终端附带的一种很好的新字体(如果我使用Courier new或ConsoleAs,这对我的问题没有影响)。要求我写东西的应用程序正在尝试使用线条绘制字符绘制一个方框。它使用的水平线字符是u2500,标准的灯光水平线 在我的应用程序中,我计算了字体的宽度和高度,并在WM_PAINT消息处理中一次绘制一个字符

Windows,直接使用Win32 API调用

我正在尝试创建一个模拟控制台应用程序行为的windows应用程序。所以我使用的是Cascadia Mono,这是Windows终端附带的一种很好的新字体(如果我使用Courier new或ConsoleAs,这对我的问题没有影响)。要求我写东西的应用程序正在尝试使用线条绘制字符绘制一个方框。它使用的水平线字符是u2500,标准的灯光水平线

在我的应用程序中,我计算了字体的宽度和高度,并在WM_PAINT消息处理中一次绘制一个字符

        for row in 0..ws.rows {
            for col in 0..ws.cols {
                let ch = sb.buffer[offset];
                trace!("paint {:?}", ch);
                offset += 1;
                if ch.ch != ' ' {
                    if ch.fg == Color::Reset {
                        SetTextColor(hdc, RGB(255, 255, 255));
                    } else {
                        let rgb = color(ch.fg);
                        SetTextColor(hdc, rgb);
                    }

                    let u = ch.ch.encode_utf16(&mut b);
                    trace!("ch = {0:0x} ", u[0]);
                    assert!(
                        TextOutW(hdc, col * ws.ch_width, row * ws.ch_height, u.as_ptr(), 1)
                            != 0
                    );
                }
            }
        }
对不起,这是锈,不是C++,但你可以看到我正在做什么调用。一切正常,但水平线出现错误。这是一个屏幕截图,3个屏幕堆叠在一起

  • Top是我的应用程序
  • 接下来是windows终端中的原始控制台应用程序
  • 最后,将文本从Windows终端剪切粘贴到记事本中

你可以看到,在我的应用程序中,虚线在两端都被截断,所以我得到了一条虚线。你也可以看到,左上角紧靠着真实事物中的第一个“k”,但在我的作品中有一个明确的间隙。还请注意,我的最后一个“k”的右侧被第一个破折号的不可见边界框截断

我无法减少代码中的字符间距以将破折号挤压在一起,因为这样其他字符就会重叠

我在字体和字符处理方面是个新手,所以我不知所措。我已经检查过了,我肯定会将0x2500作为角色。我天真的期望是,固定间距字体中的所有字符都是相同的,并且它们都很好地保留在边界框中

注意:rust utf16调用采用utf32格式的字符(rust标准字符内部表示法)并将其转换为utf16

编辑:这里是一个简单的无代码winforms c#应用程序屏幕,相同的文本从控制台应用程序复制并粘贴到文本框中。请注意,图示符是全宽的

这是显示相同字符的chrome,全宽\e2\94\80是utf8,表示2500。似乎每个人都知道一个我不知道的把戏

您应该查看
ExtTextOutA
,特别是
lpDx
参数。这看起来不对。如果您正在编写控制台应用程序,那么处理
WM_PAINT
或调用
textouth
似乎不合适。这些是供GUI应用程序使用的。这将有助于看到一个更完整的系统。另外,Rust的
char
类型使用UTF-32。UTF-8用于字符串和字符串片段。不确定,但我认为这是因为终端使用DirectWrite(通过使用Xaml/WinUI等现代Windows UI编程直接或间接地)来输出文本。DirectWrite支持字体功能(连字等)。卡斯卡迪亚是专门为这些特点而设计的。见和。不确定您是否可以使用旧的Windows API执行相同的操作。@IInspectable我正在编写模拟文本ui抽象库控制台界面的GUI应用程序。我特别希望它是一个win32 gui应用程序,这是我的意图。因此,我创建了一个窗口并直接在其上绘制。@SimonMourier,所有windows应用程序都显示#2500个字符的全宽(字符地图、字体浏览器、记事本等)。另外,如前所述,其他固定宽度字体(例如Courier)也会发生同样的情况。我开始研究WT源代码,它肯定使用WPF