查找面板中文本的高度
我有我定制的面板。我用它来显示文本。但有时该文本太长并换行到下一行。有什么方法可以自动调整面板大小以显示所有文本吗?
我使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用
Graphics.MeasureString()
方法。通过将文本分配到面板上的代码示例,如果您需要的话,我也许可以使用
MeasureString()
方法提供一个代码示例。我无法知道 Graphics.MeasureString() 方法是否是 Compact Framework 的一部分,因为我链接的页面上没有说明。
编辑 #1
这是一个链接,我在其中回答了另一个与文本大小相关的问题,同时我正在寻找为您编写示例。 =)
编辑#2
这是与您的问题相关的另一个链接。 (下一个编辑是示例代码。=P)
编辑#3
免责声明:此代码尚未经过测试,并且已关闭我的头顶。为了让您测试它,可能必须进行一些更改。这提供了实现您想要实现的目标的指南。可能有更好的方法来做到这一点,但我知道这个有效。嗯,该算法有效,正如您在我的其他答案中看到的那样。
除了行:
您还可以执行以下操作:
因为
Font.Size
属性是只读。因此,您需要创建的新实例每次
类。Font.Size
发生变化时,System.Drawing.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
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:
You could as well do the following:
Because
Font.Size
property is readonly. So, you need to create a new instance of theSystem.Drawing.Font
class each time theFont.Size
shall change.In your comparison, instead of having the line:
you could also have:
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! =)
您可以使用
TextRenderer.MeasureText
重载适合您。使用此函数,您可以确定字符串的实际渲染大小并相应地调整面板的大小。如果您尝试在
Paint
事件内进行测量,则可以在e.Graphics
对象上使用MeasureString
函数,但在内部调整大小Paint
并不明智。使用TextRenderer
可以避免您使用CreateGraphics()
创建Graphics
对象并在完成后将其释放。编辑
由于紧凑框架不支持
TextRenderer
(我第一次看到这个问题时错过了标签),因此您必须使用MeasureString()
函数 <代码>图形对象。像这样的东西: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 theMeasureString
function on youre.Graphics
object, but resizing insidePaint
is not wise. UsingTextRenderer
avoids your having to create aGraphics
object withCreateGraphics()
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 useMeasureString()
function on theGraphics
object. Something like this: