【问题标题】:Find the height of text in a panel查找面板中文本的高度
【发布时间】:2010-06-12 03:37:24
【问题描述】:

我有自定义的面板。我用它来显示文本。但有时该文本太长并换行到下一行。有什么方法可以自动调整面板大小以显示所有文本?

我正在使用 C# 和 Visual Studio 2008 以及紧凑型框架。


这是我要调整大小的代码:
(注意:HintBox 是我自己的类,继承自面板。因此我可以根据需要对其进行修改。

public void DataItemClicked(ShipmentData shipmentData)
{
    // Setup the HintBox
    if (_dataItemHintBox == null)
        _dataItemHintBox = HintBox.GetHintBox(ShipmentForm.AsAnObjectThatCanOwn(),
                                             _dataShipSelectedPoint,
                                             new Size(135, 50), shipmentData.LongDesc,
                                             Color.LightSteelBlue);


    _dataItemHintBox.Location = new Point(_dataShipSelectedPoint.X - 100,
                                          _dataShipSelectedPoint.Y - 50);
    _dataItemHintBox.MessageText = shipmentData.LongDesc;
    // It would be nice to set the size right here
    _dataItemHintBox.Size = _dataItemHintBox.MethodToResizeTheHeightToShowTheWholeString()
    _dataItemHintBox.Show();

}

我将向 Will Marcouiller 给出答案,因为他的代码示例最接近我的需要(并且看起来可以工作)。但是,这是我认为我会使用的:

public static class CFMeasureString
{
    private struct Rect
    {
        public readonly int Left, Top, Right, Bottom;
        public Rect(Rectangle r)
        {
            this.Left = r.Left;
            this.Top = r.Top;
            this.Bottom = r.Bottom;
            this.Right = r.Right;
        }
    }

    [DllImport("coredll.dll")]
    static extern int DrawText(IntPtr hdc, string lpStr, int nCount, 
                               ref Rect lpRect, int wFormat);
    private const int DT_CALCRECT = 0x00000400;
    private const int DT_WORDBREAK = 0x00000010;
    private const int DT_EDITCONTROL = 0x00002000;

    static public Size MeasureString(this Graphics gr, string text, Rectangle rect, 
                                     bool textboxControl)
    {
        Rect bounds = new Rect(rect);
        IntPtr hdc = gr.GetHdc();
        int flags = DT_CALCRECT | DT_WORDBREAK;
        if (textboxControl) flags |= DT_EDITCONTROL;
        DrawText(hdc, text, text.Length, ref bounds, flags);
        gr.ReleaseHdc(hdc);
        return new Size(bounds.Right - bounds.Left, bounds.Bottom - bounds.Top + 
                        (textboxControl ? 6 : 0));
    }
}

这使用操作系统级别的调用来绘制文本。通过 P-Invoking 它,我可以获得我需要的功能(多行换行)。请注意,此方法不包括任何边距。只是文本占用的实际空间。

这段代码不是我写的。我是从http://www.mobilepractices.com/2007/12/multi-line-graphicsmeasurestring.html 那里得到的。那篇博客文章有我的确切问题和这个修复。 (虽然我确实做了一些小调整以使其成为扩展方法。)

【问题讨论】:

  • +1 因为 Compact Framework 问题可能会带来与完整框架本身不同的解决方案。

标签: c# visual-studio-2008 compact-framework


【解决方案1】:

您可以使用Graphics.MeasureString() 方法。

将文本分配的代码示例放到面板上,如果需要,我或许可以使用MeasureString() 方法提供代码示例。

我无法知道 Graphics.MeasureString() 方法是否是 Compact Framework 的一部分,因为在我链接的页面上没有说明。

编辑#1

Here's a link 我回答了另一个与文本大小相关的问题,同时我正在寻找为您编写示例。 =)

编辑#2

Here's another link related 回答您的问题。 (下一个编辑是示例代码。=P)

编辑#3

public void DataItemClicked(ShipmentData shipmentData) { 
    // Setup the HintBox 
    if (_dataItemHintBox == null) 
        _dataItemHintBox = HintBox.GetHintBox(ShipmentForm.AsAnObjectThatCanOwn(), 
                                             _dataShipSelectedPoint, 
                                             new Size(135, 50), shipmentData.LongDesc, 
                                             Color.LightSteelBlue); 

    // Beginning to measure the size of the string shipmentData.LongDesc here.

    // Assuming that the initial font size should be 30pt.
    Single fontSize = 30.0F;
    Font f = new Font("fontFamily", fontSize, FontStyle.Regular);

    // The Panel.CreateGraphics method provides the instance of Graphics object 
    // that shall be used to compare the string size against.
    using (Graphics g = _dataItemHintBox.CreateGraphics()) {
        while (g.MeasureString(shipmentData.LongDesc, f).Width > _dataItemHintBox.Size.Width - 5) {
            --fontSize;
            f = new Font("fontFamily", fontSize, FontStyle.Regular);
        }
    }

    // Font property inherited from Panel control.
    _dataItemHintBox.Font = f;

    // End of font resizing to fit the HintBox panel.

    _dataItemHintBox.Location = new Point(_dataShipSelectedPoint.X - 100, 
                                          _dataShipSelectedPoint.Y - 50); 
    _dataItemHintBox.MessageText = shipmentData.LongDesc; 
    // It would be nice to set the size right here 
    _dataItemHintBox.Size = _dataItemHintBox.MethodToResizeTheHeightToShowTheWholeString() 
    _dataItemHintBox.Show(); 
} 

免责声明:此代码未经测试,我无法理解。一些更改可能是强制性的,以便您对其进行测试。这提供了实现您似乎想要完成的目标的指南。可能有更好的方法可以做到这一点,但我知道这个方法有效。好吧,该算法有效,正如您在我的其他答案中看到的那样。

代替行:

SizeF fontSize = 30.0F;

您还可以执行以下操作:

var fontSize = _dataItemHintBox.Font.Size;

这是为什么?

因为Font.Size 属性是只读的。因此,每次Font.Size 发生变化时,您都需要创建System.Drawing.Font 类的新实例。

在你的比较中,没有这条线:

while (g.MeasureString(shipmentData.LongDesc, f)...)

你也可以:

while (g.MeasureString(shipmentData.LongDesc, _dataItemHintBox.Font)...)

这样就不需要第二个Font 类实例,即f

请随时发布反馈,因为我可以根据收到的反馈更改我的示例以适应您的实际情况,以便更好地帮助您。 =)

我希望这会有所帮助! =)

【讨论】:

  • Graphics.MeasureString() 是紧凑框架的一部分。我的任务很简单。我有我的面板,我为它设置了文本。我会将代码添加到我的问题中。由于我不想在 Paint 方法中调整大小,我猜我将不得不以某种方式制作一个 Graphics 实例。
  • 在“使用”语句中使用 control.CreateGraphics()。
  • 感谢您对此的持续关注,但我不知道这是可能的(至少使用 MeasureString),因为您无法为紧凑框架中的方法提供宽度。我将不得不制作自己的自动换行算法。这听起来很复杂且容易出错。
  • 您不必提供宽度。 Size (height and width) 是您提供给 MeasureString() 方法的 Font 的一部分。然后,作为回报,你得到一个 Size 类实例,然后你可以得到 HeightWidth
【解决方案2】:

您可以使用任何适合您的TextRenderer.MeasureText 重载。使用此函数,您可以确定字符串的实际渲染大小并相应地调整面板的大小。

如果您尝试在 Paint 事件内进行测量,则可以在 e.Graphics 对象上使用 MeasureString 函数,但在 Paint 内调整大小并不明智。使用TextRenderer 避免了您必须使用CreateGraphics() 创建一个Graphics 对象并在完成后将其丢弃。

编辑

由于紧凑型框架不支持TextRenderer(我第一次看到这个问题时错过了标签),你必须在Graphics对象上使用MeasureString()函数。像这样的:

public Size GetStringSize(string text)
{
    using(Graphics g = yourPanel.CreateGraphics())
    {
        return g.MeasureString(text, yourPanel.Font);
    }
}

【讨论】:

  • 唉,TextRenderer 不是紧凑框架的一部分。但是很高兴知道我是否最终在正常的 .net 问题上遇到了这个问题。
  • 感谢示例代码。但是,您发布的第二个 MeasureString 也不是紧凑框架的一部分。此链接显示仅支持您使用的第一个(msdn.microsoft.com/en-us/library/…)(由移动设备图标指示)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-06
  • 2017-11-08
  • 2011-08-12
  • 2016-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多