Windows 为什么垂直方向的字体大小不同

Windows 为什么垂直方向的字体大小不同,windows,winapi,fonts,gdi,Windows,Winapi,Fonts,Gdi,我创建了两个标尺-一个垂直标尺和一个水平标尺: 现在在垂直标尺中,文本的“大小”在视觉上更大(大约长5-6像素) 为什么? 相关代码: WM\u创建: LOGFONT Lf = {0}; Lf.lfHeight = 12; lstrcpyW(Lf.lfFaceName, L"Arial"); if (!g_pGRI->bHorizontal) { Lf.lfEscapement = 900; // <----For vertical ruler! } g_pGRI-

我创建了两个标尺-一个垂直标尺和一个水平标尺:

现在在垂直标尺中,文本的“大小”在视觉上更大(大约长5-6像素)

为什么?

相关代码:

WM\u创建:

LOGFONT Lf = {0};

Lf.lfHeight = 12;

lstrcpyW(Lf.lfFaceName, L"Arial");

if (!g_pGRI->bHorizontal)
{
    Lf.lfEscapement = 900; // <----For vertical ruler!
}

g_pGRI->hfRuler = CreateFontIndirectW(&Lf);

SelectFont(g_pGRI->hdRuler, g_pGRI->hfRuler);
    SetTextColor(g_pGRI->hdRuler, g_pGRI->cBorder);

    SetBkColor(g_pGRI->hdRuler, g_pGRI->cBackground);

    SetTextAlign(g_pGRI->hdRuler, TA_CENTER);

#define INCREMENT 10

    WCHAR wText[16] = {0};

    if (g_pGRI->bHorizontal)
    {
        INT ixTicks = RECTWIDTH(g_pGRI->rRuler) / INCREMENT;

        for (INT ix = 0; ix < ixTicks + 1; ix++)
        {
            MoveToEx(g_pGRI->hdRuler, INCREMENT * ix, 0, NULL);

            if (ix % INCREMENT == 0)
            {
                //This is major tick.

                LineTo(g_pGRI->hdRuler, INCREMENT * ix, g_pGRI->lMajor);

                wsprintfW(wText, L"%d", INCREMENT * ix);

                TextOutW(g_pGRI->hdRuler, INCREMENT * ix + 1, g_pGRI->lMajor + 1, wText, CHARACTERCOUNT(wText));
            }
            else
            {
                //This is minor tick.

                LineTo(g_pGRI->hdRuler, INCREMENT * ix, g_pGRI->lMinor);
            }
        }
    } 
    else
    {
        INT iyTicks = RECTHEIGHT(g_pGRI->rRuler) / INCREMENT;

        for (INT iy = 0; iy < iyTicks + 1; iy++)
        {
            MoveToEx(g_pGRI->hdRuler, 0, INCREMENT * iy, NULL);

            if (iy % INCREMENT == 0)
            {
                //This is major tick.

                LineTo(g_pGRI->hdRuler, g_pGRI->lMajor, INCREMENT * iy);

                wsprintfW(wText, L"%d", INCREMENT * iy);

                TextOutW(g_pGRI->hdRuler, g_pGRI->lMajor + 1, INCREMENT * iy + 1, wText, CHARACTERCOUNT(wText));
            }
            else
            {
                //This is minor tick.

                LineTo(g_pGRI->hdRuler, g_pGRI->lMinor, INCREMENT * iy);
            }
        }
    }
}
LOGFONT Lf={0};
Lf.lfHeight=12;
lstrcpyW(Lf.lfFaceName,L“Arial”);
如果(!g_pGRI->b水平)
{
Lf.lfscalement=900;//hfRuler=CreateFontIndirectW(&Lf);
选择字体(g_pGRI->hdRuler,g_pGRI->hfRuler);
WM_油漆:

LOGFONT Lf = {0};

Lf.lfHeight = 12;

lstrcpyW(Lf.lfFaceName, L"Arial");

if (!g_pGRI->bHorizontal)
{
    Lf.lfEscapement = 900; // <----For vertical ruler!
}

g_pGRI->hfRuler = CreateFontIndirectW(&Lf);

SelectFont(g_pGRI->hdRuler, g_pGRI->hfRuler);
    SetTextColor(g_pGRI->hdRuler, g_pGRI->cBorder);

    SetBkColor(g_pGRI->hdRuler, g_pGRI->cBackground);

    SetTextAlign(g_pGRI->hdRuler, TA_CENTER);

#define INCREMENT 10

    WCHAR wText[16] = {0};

    if (g_pGRI->bHorizontal)
    {
        INT ixTicks = RECTWIDTH(g_pGRI->rRuler) / INCREMENT;

        for (INT ix = 0; ix < ixTicks + 1; ix++)
        {
            MoveToEx(g_pGRI->hdRuler, INCREMENT * ix, 0, NULL);

            if (ix % INCREMENT == 0)
            {
                //This is major tick.

                LineTo(g_pGRI->hdRuler, INCREMENT * ix, g_pGRI->lMajor);

                wsprintfW(wText, L"%d", INCREMENT * ix);

                TextOutW(g_pGRI->hdRuler, INCREMENT * ix + 1, g_pGRI->lMajor + 1, wText, CHARACTERCOUNT(wText));
            }
            else
            {
                //This is minor tick.

                LineTo(g_pGRI->hdRuler, INCREMENT * ix, g_pGRI->lMinor);
            }
        }
    } 
    else
    {
        INT iyTicks = RECTHEIGHT(g_pGRI->rRuler) / INCREMENT;

        for (INT iy = 0; iy < iyTicks + 1; iy++)
        {
            MoveToEx(g_pGRI->hdRuler, 0, INCREMENT * iy, NULL);

            if (iy % INCREMENT == 0)
            {
                //This is major tick.

                LineTo(g_pGRI->hdRuler, g_pGRI->lMajor, INCREMENT * iy);

                wsprintfW(wText, L"%d", INCREMENT * iy);

                TextOutW(g_pGRI->hdRuler, g_pGRI->lMajor + 1, INCREMENT * iy + 1, wText, CHARACTERCOUNT(wText));
            }
            else
            {
                //This is minor tick.

                LineTo(g_pGRI->hdRuler, g_pGRI->lMinor, INCREMENT * iy);
            }
        }
    }
}
SetTextColor(g_pGRI->hdRuler,g_pGRI->cBorder);
设置颜色(g_pGRI->HD标尺,g_pGRI->CBbackground);
SetTextAlign(g_pGRI->HDRUNER,TA_中心);
#定义增量10
WCHAR wText[16]={0};
if(g_pGRI->B水平)
{
INT ixTicks=矩形宽度(g_pGRI->rRuler)/增量;
对于(INT-ix=0;ixhdRuler,增量*ix,0,NULL);
如果(ix%增量==0)
{
//这是蒂克少校。
LineTo(g_pGRI->hdRuler,INCREMENT*ix,g_pGRI->lMajor);
wsprintfW(wText,L“%d”,增量*ix);
文本输出(g_pGRI->hdRuler,增量*ix+1,g_pGRI->lMajor+1,wText,CHARACTERCOUNT(wText));
}
其他的
{
//这是小滴答声。
LineTo(g_pGRI->hdRuler,增量*ix,g_pGRI->lMinor);
}
}
} 
其他的
{
INT iyTicks=垂直高度(g_pGRI->rRuler)/增量;
对于(INT-iy=0;iyhdRuler,0,增量*iy,NULL);
如果(iy%增量==0)
{
//这是蒂克少校。
LineTo(g_pGRI->hdRuler,g_pGRI->lMajor,增量*iy);
wsprintfW(wText,L“%d”,增量*iy);
文本输出(g_pGRI->hdRuler,g_pGRI->lMajor+1,增量*iy+1,wText,CHARACTERCOUNT(wText));
}
其他的
{
//这是小滴答声。
LineTo(g_pGRI->hdRuler,g_pGRI->lMinor,增量*iy);
}
}
}
}

当使用
lfEscapement
时,您经常会遇到奇怪的行为,因为它使用完全不同的管道呈现文本

一个诀窍是为这两者设置
lf擒纵机构
。一个是900,另一个是非常低的值(例如
1
或甚至
10
。一旦使用擒纵机构进行了这两种渲染,就应该很好了

如果仍然存在平滑问题,请尝试执行以下操作:

BOOL bSmooth;
//Get previous smooth value.
SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &bSmooth, 0);
//Set no smoothing.
SystemParametersInfo(SPI_SETFONTSMOOTHING, 0, NULL, 0);
//Draw text.

//Return smoothing.
SystemParametersInfo(SPI_SETFONTSMOOTHING, bSmooth, NULL, 0);
背景 当文本相对于像素大小较小时,有几种不同的方案可用于以清晰的方式栅格化文本。例如,如果笔划宽度假定为1.25像素宽,则必须将其舍入为整数像素,使用抗锯齿,或使用亚像素渲染(如ClearType)。四舍五入通常由字体设计师在字体中内置的“提示”控制

提示是文本宽度不总是与文本高度精确缩放的主要原因。例如,如果由于舍入,小写
m
的左凸起比右凸起宽一个像素,提示可能会告诉渲染器将宽度向上舍入以使字母对称。结果是字符比右凸起宽一点与其说是理想人物,不如说是对其高度的乐观

本期 这里可能发生的情况是,当GDI水平渲染字符串时,每个后续字符可能从分数位置开始,这是由抗锯齿或亚像素(ClearType)模拟的渲染。但是,垂直渲染时,每个后续字符的起始位置似乎向上舍入到下一个整像素,这往往会使垂直文本比其水平文本“长”几个像素。实际上,字距总是向上舍入到下一个整像素

在水平文本呈现的常见情况下,可能会投入更多的精力,使其更易于阅读(并可能更快地呈现)。在任何其他角度呈现的一般情况可能以更简单的方式实现,一个字形一个字形地处理,而不是使用整个字符串

尝试的事情 如果你想让它们看起来一样,你可能必须在水平标签的视觉质量上做出一点妥协。以下是我可以考虑尝试的一些事情:

  • 使用常规抗锯齿而不是ClearType子像素渲染来渲染标签。(可以通过在LOGFONT中设置lfQuality字段来完成此操作。)然后,您将以正常方式绘制水平标签。对于垂直标签,将其水平绘制到屏幕外缓冲区,旋转它,然后将缓冲区blit到屏幕上。这会使标签看起来完全相同。我建议使用常规抗锯齿的原因是,它对旋转是不变的。ClearType渲染有一个固有的特性没有边缘就无法旋转。我用这种方法处理图形标签,效果很好

  • 逐字符渲染水平标签,将起始点四舍五入到下一个整像素。这会使水平标签看起来像垂直标签。从排版上看,它们看起来不太好,但对于这样的小标签,可能比在视觉上显示水平和垂直标签更容易分心斯梅奇

  • 另一个答案建议使用非常小但非零的擒纵和方向渲染水平标签,强制这些标签通过与垂直标签相同的渲染管道。对于像您这样的短标签,这可能是最简单的解决方案。如果您必须处理较长的文本字符串,我建议使用前两种方法之一方法


  • 这是一个ClearType抗锯齿工件。请使用类似SysInternals的ZoomIt to s这样的工具