GetTextExtentPoint 导致别名

Posted

技术标签:

【中文标题】GetTextExtentPoint 导致别名【英文标题】:GetTextExtentPoint causes aliasing 【发布时间】:2021-01-01 07:36:33 【问题描述】:

它可能与谁有关,

GetTextExtentPoint 和 GetTextExtentPoint32 给我带来了糟糕的一天。

它们是 MSDN 提供的唯一测量文本的方法,但它们有两个缺陷,但似乎没有其他人有这些问题。

首先,他们不考虑换行符。他们将测量视为一根长一根线。

其次,最重要的是,当我执行 DrawText() 时,它们会导致锯齿。我正在为 HFONT 使用 ClearType,但仍在绘制别名文本。

请让我确切知道是什么问题。或者我可能必须创建自己的测量文本函数。

编辑_________

// note font is created with CLEAR_TYPE_QUALITY
// so it should be antialiased
HFONT createFont(const char *face_name,int height)

 return CreateFont(height,cHeight,0,0,0,FW_NORMAL,false,false,false,0,0,0,CLEAR_TYPE_QUALITY,0,face_name);


RECT box0,0,640,480);
POINT pos;
HFONT font = createFont("MyFavouriteFont",30);
HDC canvas = CreateCompatableDC(NULL);
HBITMAP bmp = CreateCompatibleBitmap(NULL,640,480);

SelectBitmap(canvas,bmp);
SelectFont(canvas,font);
SelectBrush(canvas,GetStockObject(DC_BRUSH));

SetDCBrushColor(RGB(255,255,255));
SetBkMode(TRANSPARENT);

SIZE measureText_Msdn(const char *s,HDC font)

 SIZE sz;
 GetTextExtentPoint(font,s,strlen(s),&sz);
 return sz;


SIZE measureText_Custom(const char *s,HDC font)

     SIZE sz;
     TEXTMETRICSA metrics;
     INT char_width, line_width;
 
     // get char height
     GetTextMetrics(font,&metrics);

     while(*it)
     
          if(*it == '\n' || *it == '\r')
          
           if(line_width > sz.cx) sz.cx = line_width; // sz.cx stores max width
           sz.cy += metrics.tmHeight;
           line_width = 0;
          

          else
          
           GetCharWidth32(font,*it,*it,&char_width);
           line_width += char_width;
          

          ++it;
     

     if(line_width > sz.cx) sz.cx = line_width;
     if(line_width > 0) sz.cy += metrics.tmHeight; // If there are no chars on this line, the line has no size

     return sz;


void drawText(HDC dest_ctx)

 auto s = ,"Text will look blocky";
 measureText_Msdn(s,font);
 // or measureText_Custom(s,font); will cause font to look blocky and ugly
 // If you comment out measureText_* text will be drawn smooth.

 FillRect(canvas, &box,(HBRUSH)GetCurrentObject(canvas,OBJ_BRUSH));
 DrawTextA(canvas,s,-1,&box,DT_LEFT);

BitBlt(dest_ctx,pos.x,pos.y,box.right,box.bottom,
           canvas,0,0,SRCCOPY);

解决方案_____ 我已经发布了一个解决方案作为答案。我不喜欢这样做。正如我之前所说,似乎没有其他人有这个问题,所以没有其他人需要解决方案。

【问题讨论】:

展示你的作品。在没有证据的情况下说“这行不通”在这里并没有多大意义。 既然the documentation 说计算高度时不考虑换行符,为什么会认为这是个问题呢?其次,通过“导致锯齿”,您是指适用于文本的标准抗锯齿 Windows 吗? @Andy 感谢您的 cmets。将在问题中添加我的工作。正如我所说,换行是我的问题,因为文本在一行上。但是,调用 GetTextExtent 函数然后调用 DrawText 会使文本看起来好像没有使用抗锯齿。我将提供一个示例代码。表达我使用 GetTextMetrics 和 GetCharWidth32 创建测量 gdi 文本的函数时的情况。我发现这两个问题也会导致问题。 【参考方案1】:

正如我之前所说,在使用任何文本测量功能时,似乎没有人会得到块状文本。我在使用其中任何一个时都会得到它。

我注意到调用这些函数需要上下文,而这些函数似乎正在破坏上下文。即使我在上下文中选择了一种新字体,我仍然会得到块状文本输出。

因此,我动态创建了一个上下文并将所需的字体添加到其中。并使用该上下文进行测量,收集结果并删除该上下文。我对此进行了测试,我的文本绘制得很流畅,因为我的原始上下文不受影响。

我讨厌这种方法的原因: - 我害怕动态创建和删除上下文的开销。

- I dont think GetTextExtent should currupt my context in the first place.

如果你们有更好的方法,或者知道我的问题,或者为什么我不应该遇到这个问题,请发帖。

编辑_________ 在查看了 MSDN 上的使用键盘教程后,我看到作者在哪里使用窗口上下文而不是内存上下文来调用 GetTextExtent。看来 GetTextExtent 和其他测量功能仅适用于窗口上下文。这对我来说非常好,因为我不喜欢创建内存上下文。

【讨论】:

以上是关于GetTextExtentPoint 导致别名的主要内容,如果未能解决你的问题,请参考以下文章

在 WebStorm 中使用 Webpack 别名导致 ESLint 错误导入别名

RETURNING 的别名导致 jooq

AWS Route 53 别名记录导致 301

别名可变原始指针 (*mut T) 会导致未定义的行为吗?

使用路径别名指向文件夹会导致 Gradle 错误

SQL Server配置管理器的“别名”功能好处,实现内外网统一以及加了端口号导致的限制