查找面板中文本的高度

发布于 2024-09-05 11:59:54 字数 2659 浏览 0 评论 0原文

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

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


这是我想要调整大小的代码:
(注意:HintBox 是我自己的类,继承自 panel。因此我可以根据需要修改它。

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 调用它,我可以获得我需要的功能(多行换行)。请注意,此方法不包括任何边距。只是文本占用的实际空间。

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

I have panel that I have customized. I use it to display text. But sometimes that text is too long and wraps to the next line. Is there some way I can auto resize the panel to show all the text?

I am using C# and Visual Studio 2008 and the compact framework.


Here is the code I am wanting to adjust the size for:
(Note: HintBox is my own class that inherits from panel. So I can modify it as needed.)

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();

}

I am going to give the answer to Will Marcouiller because his code example was the closest to what I needed (and looks like it will work). However, this is what I think I will use:

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));
    }
}

This uses the os level call to draw text. By P-Invoking it I can get the functionality I need (multi line wrapping). Note that this method does not include any margins. Just the actual space taken up by the text.

I did not write this code. I got it from http://www.mobilepractices.com/2007/12/multi-line-graphicsmeasurestring.html. That blog post had my exact problem and this fix. (Though I did make a minor tweak to make it a extension method.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏有森光若流苏 2024-09-12 11:59:54

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

通过将文本分配到面板上的代码示例,如果您需要的话,我也许可以使用 MeasureString() 方法提供一个代码示例。

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

编辑 #1

这是一个链接,我在其中回答了另一个与文本大小相关的问题,同时我正在寻找为您编写示例。 =)

编辑#2

这是与您的问题相关的另一个链接。 (下一个编辑是示例代码。=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)的需要。

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

我希望这有帮助! =)

You could use the Graphics.MeasureString() method.

With a code sample of your text assignment onto your panel, I could perhaps provide a code sample using the MeasureString() method, if you need it.

I have no way to know whether the Graphics.MeasureString() method is part of the Compact Framework, as it is not said on the page I linked.

EDIT #1

Here's a link where I answered to another text-size related question, while I look for writing a sample for you. =)

EDIT #2

Here's another link related to your question. (Next edit is the sample code. =P)

EDIT #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(); 
} 

Disclaimer: This code has not been tested and is off the top of my head. Some changes might be obligatory in order for you to test it. This provides a guideline to achieve what you seem to want to accomplish. There might be a better way to do this, but I know this one works. Well, the algorithm works, as you can see in my other answers.

Instead of the line:

SizeF fontSize = 30.0F;

You could as well do the following:

var fontSize = _dataItemHintBox.Font.Size;

Why is this?

Because Font.Size property is readonly. So, you need to create a new instance of the System.Drawing.Font class each time the Font.Size shall change.

In your comparison, instead of having the line:

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

you could also have:

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

This would nullify the need for a second Font class instance, that is f.

Please feel free to post feedbacks as I could change my sample to fit your reality upon the feedbacks received, so that it better helps you. =)

I hope this helps! =)

温柔嚣张 2024-09-12 11:59:54

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

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

编辑

由于紧凑框架不支持TextRenderer(我第一次看到这个问题时错过了标签),因此您必须使用MeasureString() 函数 <代码>图形对象。像这样的东西:

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

You can use whichever of the TextRenderer.MeasureText overloads is appropriate for you. Using this function, you can determine the actual rendered size of a string and adjust your panel's size accordingly.

If you're trying to measure inside the Paint event, then you could use the MeasureString function on your e.Graphics object, but resizing inside Paint is not wise. Using TextRenderer avoids your having to create a Graphics object with CreateGraphics() and disposing of it when you're finished.

EDIT

Since TextRenderer is not supported on the compact framework (I missed the tag the first time I saw the question), you'll have to use MeasureString() function on the Graphics object. Something like this:

public Size GetStringSize(string text)
{
    using(Graphics g = yourPanel.CreateGraphics())
    {
        return g.MeasureString(text, yourPanel.Font);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文