gpt4 book ai didi

c# - 如何获取 TextRenderer 使用的确切文本边距

转载 作者:IT王子 更新时间:2023-10-29 04:13:14 48 4
gpt4 key购买 nike

System.Windows.Forms.TextRenderer.DrawText 方法呈现带或不带左右填充的格式化文本,具体取决于 flags 参数的值:

  • TextFormatFlags.NoPadding - 将文本紧密地放入边界框,
  • TextFormatFlags.GlyphOverhangPadding - 添加一些左右边距,
  • TextFormatFlags.LeftAndRightPadding - 添加更大的边距。

现在,我的问题是对于给定的设备上下文、字符串、字体等?

我用 .NET Reflector 深入研究了 .NET 4,发现 TextRenderer 计算“悬垂填充”,它是字体高度的 1/6,然后乘以该值以使用这些系数计算左右边距:

  • TextFormatFlags.GlyphOverhangPadding 左 1.0,右 1.5,
  • TextFormatFlags.LeftAndRightPadding 左 2.0,右 2.5。

结果值被四舍五入并传递给 DrawTextExADrawTextExW native API 函数。很难重新创建此过程,因为字体的高度不是从 System.Drawing.Font 而是从 System.Windows.Forms.Internal.WindowsFont 获取的,并且这些类返回不同的值相同的字体。还涉及 System.Windows.Forms.Internal 命名空间中的许多其他内部 BCL 类。反编译它们并在我的应用程序中重用它们的代码不是一种选择,因为那将是一个严重的 .NET 实现依赖项。这就是为什么我需要知道 WinForms 中是否有一些公共(public) API,或者至少我可以使用哪些 Windows 函数来获取左右边距的值。


注意:我尝试使用和不使用填充来 TextRenderer.MeasureText 并比较结果,但这只给了我左右边距的总和,我需要他们分开。


注意 2:如果您想知道我为什么需要这个:我想用多种字体/颜色绘制一个字符串。这涉及使用 NoPadding 选项为每个统一格式的子字符串调用一次 DrawText(这样文本就不会展开),但我还想手动添加正常的 GlyphOverhangPadding 在整个多格式文本的开头和结尾。

最佳答案

计算左右边距所需的值是 TEXTMETRIC.tmHeight,可以使用 Win32 API 获得。 .

但是,我发现 tmHeight 只是字体的行高(以像素为单位),因此这三种方法将为您提供相同的值(您可以在代码中使用任何您喜欢的值):

int apiHeight = GetTextMetrics(graphics, font).tmHeight;
int gdiHeight = TextRenderer.MeasureString(...).Height;
int gdipHeight = (int)Math.Ceiling(font.GetHeight(graphics));

为了获得左边距和右边距,我们使用与 TextRenderer 相同的代码:

private const float ItalicPaddingFactor = 0.5f;

...

float overhangPadding = (gdiHeight / 6.0f);

//NOTE: proper margins for TextFormatFlags.LeftAndRightPadding flag
//int leftMargin = (int)Math.Ceiling(overhangPadding);
//int rightMargin = (int)Math.Ceiling(overhangPadding * (2 + ItalicPaddingFactor));

//NOTE: proper margins for TextFormatFlags.GlyphOverhangPadding flag
int leftMargin = (int)Math.Ceiling(overhangPadding);
int rightMargin = (int)Math.Ceiling(overhangPadding * (1 + ItalicPaddingFactor));

Size sizeOverhangPadding = TextRenderer.MeasureText(e.Graphics, "ABC", font, Size.Empty, TextFormatFlags.GlyphOverhangPadding);
Size sizeNoPadding = TextRenderer.MeasureText(e.Graphics, "ABC", font, Size.Empty, TextFormatFlags.NoPadding);

int overallPadding = (sizeOverhangPadding.Width - sizeNoPadding.Width);

现在你可以很容易地检查

(leftMargin + rightMargin) == overallPadding

请注意:

我需要解决这个问题才能在 ListView-based control 中实现“搜索突出显示”功能使用 GDI 文本呈现:

enter image description here

工作起来很有魅力:)

关于c# - 如何获取 TextRenderer 使用的确切文本边距,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4428335/

48 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com