有关GDI画字体高度和所设定的高度不一致的问题

xiaolizi 2007-08-15 06:23:25

问题是这样的,用CreateFontIndirect创建的HFONT,使用TextOut画的字体的高度和LOGFONT中所设定的高度不一致。这个情况只存在与个别字库中,比如我正在使用的微软雅黑字库。
代码如下:

LOGFONT lf;
ZeroMemory(&lf, sizeof(lf));
lf.lfHeight = -24;
lf.lfWidth = 0;
lf.lfEscapement = 0;
lf.lfOrientation = 0;
lf.lfStrikeOut = FALSE;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = ANTIALIASED_QUALITY;
lf.lfPitchAndFamily = VARIABLE_PITCH;
lstrcpy(lf.lfFaceName, "微软雅黑");

hfont = CreateFontIndirect(&lf);

//Draw
CString str = "中国人";
TextOut(dc, 0, 0, (LPCTSTR)str, str.GetLength());


这里画出的字体的高度是28,而我在LOGFONT中设定的高度是24。
有谁知道如何解决这个问题?
先谢了~~~
...全文
1140 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
emptyness 2007-08-20
  • 打赏
  • 举报
回复
帮顶..接分 这个应该google百度下就有了吧..
xiaolizi 2007-08-20
  • 打赏
  • 举报
回复
产生问题的原因已经找到了,有些字库在原有设定的高度上额外增加一些空间,通过TEXTMETRIC 结构里面的tmInternalLeading变量可以获得增加的高度。在上面提到的雅黑字库增加了6个像素(其中4个像素为顶部,2个像素为底部)。但是我没有找到有哪个函数可以获得这6个像素是如何分派给顶部和底部的。如下是MSDN的TEXTMETRIC 结构说明:
Members
tmHeight
Specifies the height (ascent + descent) of characters.
tmAscent
Specifies the ascent (units above the base line) of characters.
tmDescent
Specifies the descent (units below the base line) of characters.

似乎可以通过tmAscent 获得顶部额外增加的空间,但是这个“units above the base line”表示的是什么意义呢?

期待字体高手出现~~~
xiaolizi 2007-08-20
  • 打赏
  • 举报
回复
发现是另外一个问题,我用相同高度的雅黑和宋体TextOut相同的字符串,然后在PS里面比较。原因是雅黑的字符串像素不是置顶的,而是往下偏了4个像素,不管用多少的高度都这样。其他字库都是正常置顶的
lyg_zy 2007-08-20
  • 打赏
  • 举报
回复
因为一般的是字库都不是矢量字库,而是固定的有n套不同大小的字体图库,所以就会有一个匹配过程,所以就可能不是你想要的值了。如果在Cordraw,Illustrator等软件中,他们的字体就是真正的矢量字库,任意大小的字体都能精确得到。
long2icc 2007-08-20
  • 打赏
  • 举报
回复
是否与字体属性有关?
《windows程序设计》中对字体有很详细的介绍,摘录一部分:

Windows支援两大类字体,即所谓的「GDI字体」和「设备字体」。GDI字体储存在硬碟的档案中,而设备字体是输出设备本来就有的。例如,通常印表机都具有内建的设备字体集。

GDI字体有三种样式:点阵字体,笔划字体和TrueType字体。

点阵字体的每个字元都以点阵图图素图案的形式储存,每种点阵字体都有特定的纵横比和字元大小。Windows通过简单地复制图素的行或列就可以由GDI点阵字体产生更大的字元。然而,只能以整数倍放大字体,并且不能超过一定的限度。由於这种原因,GDI点阵字体又称为「不可缩放的」字体。它们不能随意地放大或缩小。点阵字体的主要优点是显示性能(显示速度很快)和可读性(因为是手工设计的,所以尽可能清晰)。

每个点阵字体只有几种大小(不超过6种)。Courier字体是定宽字体,外形与用打字机打出的字体相似。「Serif」指字体字母笔划在结束时拐个小弯。「sans serif」字体不是serif类的字体。在Windows的早期版本中,MS(Microsoft)Serif和MS Sans Serif字体被称为Tms Rmn(指它与Times Roman相似)和Helv(与Helvetica相似)。Small Fonts是专为显示小字设计的。

在Windows3.1以前,除了GDI字体外,Windows所提供的字体只有笔划字体。笔划字体是以「连结点」的方式定义的一系列线段,笔划字体可以连续地缩放,这意味著同样的字体可以用於具有任何解析度的图形输出设备,并且字体可以放大或缩小到任意尺寸。不过,它的性能不好,小字体的可读性也很糟,而大字体由於笔划是单根直线而显得很单薄。笔划字体有时也称为绘图机字体,因为它们特别适合於绘图机,但是不适合於别的场合。笔划字体的字样有:Modern、Roman和Script。

对於GDI点阵字体和GDI笔划字体,Windows都可以「合成」粗体、斜体、加底线和加删除线,而不需要为每种属性另外储存字体。例如,对於斜体,Windows只需要将字元的上部向右移动就可以了。

接下来是Truetype,我将在本章的剩部分主要讨论它。

TrueType字体 

TrueType字体的单个字元是通过填充的直线和曲线的轮廓来定义的。Windows可以通过改变定义轮廓的座标对TrueType字体进行缩放。

当程式开始使用特定大小的TrueType字体时,Windows「点阵化」字体。这就是说Windows使用TrueType字体档案中包括的「提示」对每个字元的连结直线和曲线的座标进行缩放。这些提示可以补偿误差,避免合成的字元变得很难看(例如,在某些字体中,大写H的两竖应该一样宽,但盲目地缩放字体可能会导致其中一竖的图素比另一竖宽。有了提示就可以避免这些现象发生)。然後,每个字元的合成轮廓用於建立字元的点阵图,这些点阵图储存在记忆体以备将来使用。

emptyness 2007-08-19
  • 打赏
  • 举报
回复
那就说明 雅黑 正好就没24这个值咯...
字体貌似就是一张张图.. 象素都不是连续的...雅黑也许是20 28 6个6个一跳呢...
而其他字体正好有对应的24象素高度的字体图..
dyw 2007-08-18
  • 打赏
  • 举报
回复
把24改为其他值效果怎样呢?比如:16、32、48等
xiaolizi 2007-08-18
  • 打赏
  • 举报
回复
我给的是代码片断,当然是选择了HFONT的,也同时指定了MM_TEXT 模式,所以才会觉得很奇怪。因为我用“宋体”,“方正”等字体都没有这个问题,但是“微软雅黑”就反应出来。
lyg_zy 2007-08-17
  • 打赏
  • 举报
回复
msdn对字体高度的解释:
lfHeight
Specifies the height, in logical units, of the font's character cell or character. The character height value (also known as the em height) is the character cell height value minus the internal-leading value. The font mapper interprets the value specified in lfHeight in the following manner. Value Meaning
> 0 The font mapper transforms this value into device units and matches it against the cell height of the available fonts.
0 The font mapper uses a default height value when it searches for a match.
< 0 The font mapper transforms this value into device units and matches its absolute value against the character height of the available fonts.


For all height comparisons, the font mapper looks for the largest font that does not exceed the requested size.

This mapping occurs when the font is used for the first time.

For the MM_TEXT mapping mode, you can use the following formula to specify a height for a font with a specified point size:

lfHeight = -MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);

大概意思就是说:
如果你用SetMapMode(hdc, MM_TEXT),这样你的字体高度就为像素,当然如果你没设,那么默认的也就是MM_TEXT.
至于字体高度,字库有个匹配过程,一般说来应该<=你指定的高度。
mynamelj 2007-08-17
  • 打赏
  • 举报
回复
你有没有选择进去啊?

dc.SelectObject(CFont::FromHandle(hFont));
xiaolizi 2007-08-17
  • 打赏
  • 举报
回复
To Mackz,
我希望的单位的是像素,不知道哪个api可以设置单位?请指教

To GeoPeeker,
我用“宋体”,或者“方正”等字体,我设定的高度数值是多少,TextOut出来的高度就是多少,而用“微软雅黑”则不一样,所以比较奇怪
nadine 2007-08-17
  • 打赏
  • 举报
回复
mynamelj(风动,帆动,仁者心动) 说的对,你没有把字体选入设备描述表
GeoPeeker 2007-08-15
  • 打赏
  • 举报
回复
字体高度不可能你设多少就是多少的
系统会匹配你设置的高度与系统字体中哪一个最接近,就用哪一个
不要以为字库是万能的
菜牛 2007-08-15
  • 打赏
  • 举报
回复
你的单位是什么?

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧