TextFormatFlags.GlyphOverhangPadding的左1.0,右1.5, TextFormatFlags.LeftAndRightPadding的左2.0,右2.5.结果值将四舍五入并传递给DrawTextExA或DrawTextExW本机API函数.很难重新创建此过程,因为字体高度不是从System.Drawing.Font而是从System.Windows.Forms.Internal.WindowsFont获取,并且这些类为同一字体返回不同的值.并且还涉及到System.Windows.Forms.Internal名称空间中的许多其他内部BCL类.不能对它们全部进行反编译并在我的应用程序中重用它们的代码,因为这将是严重的.NET实现依赖性.这就是为什么我需要知道WinForms中是否有一些公共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 flagint 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的控件中实现搜索突出显示"功能使用GDI文本呈现:像魅力一样工作:)System.Windows.Forms.TextRenderer.DrawText method renders formatted text with or without left and right padding depending on the value of the flags parameter:TextFormatFlags.NoPadding - fits the text tightly into the bounding box,TextFormatFlags.GlyphOverhangPadding - adds some left and right margins,TextFormatFlags.LeftAndRightPadding - adds even bigger margins.Now, my question is how can I get the exact amount of padding (left and right) added by DrawText to the text for a given device context, string, font etc?I've dug into .NET 4 with .NET Reflector and found that TextRenderer calculates "overhang padding" which is 1/6 of the font's height and then multiplies this value to calculate left and right margins using these coefficients:left 1.0, right 1.5 for TextFormatFlags.GlyphOverhangPadding,left 2.0, right 2.5 for TextFormatFlags.LeftAndRightPadding.The resulting values are rounded up and passed to the DrawTextExA or DrawTextExW native API functions. It's difficult to recreate this process because font's height is taken not from System.Drawing.Font but from System.Windows.Forms.Internal.WindowsFont and these classes return different values for the same font. And a lot of other internal BCL classes from the System.Windows.Forms.Internal namespace are involved. Decompiling all of them and reusing their code in my app is not an option, because that would be a serious .NET implementation dependency. That's why I need to know if there is some public API in WinForms or at least which Windows functions I can use to get the values of left and right margins.Note: I've tried to TextRenderer.MeasureText with and without padding and compare the results but that gave me only the sum of left and right margins and I need them separately.Note 2: In case you wonder why I need this: I want to draw one string with multiple fonts/colors. That involves calling DrawText once for every uniformly formatted substring with NoPadding option (so that the text doesn't spread) but I also want to add manually normal GlyphOverhangPadding at the very beginning and very end of the whole multi-format text. 解决方案 The value you need for computing left and right margins is TEXTMETRIC.tmHeight, which is possible to obtain using Win32 API.However, I found that tmHeight is just a line height of a font in pixels, so these three approaches will give you the same value (you can use whichever you like in your code):int apiHeight = GetTextMetrics(graphics, font).tmHeight;int gdiHeight = TextRenderer.MeasureString(...).Height;int gdipHeight = (int)Math.Ceiling(font.GetHeight(graphics));To obtain left and right margins, we use the same code as TextRenderer does under the hood: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 flagint 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);Now you can easily check that(leftMargin + rightMargin) == overallPaddingJust to note:I needed to solve this problem in order to implement "Search Highlight" feature in a ListView-based control that uses GDI text rendering:Works like a charm :) 这篇关于如何获得TextRenderer使用的确切文本边距的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
09-02 09:55