我有自定义的面板。我用它来显示文字。但有时文本太长并且包含在下一行。有什么方法可以自动调整面板大小以显示所有文本吗?
我正在使用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));
}
}
这使用os级别调用来绘制文本。通过P-Invoking它我可以得到我需要的功能(多线包装)。请注意,此方法不包含任何边距。只是文本占用的实际空间。
我没有写这段代码。我是从http://www.mobilepractices.com/2007/12/multi-line-graphicsmeasurestring.html得到的。那个博文有我的确切问题和这个修复。 (虽然我做了一个小调整,使其成为一种扩展方法。)
答案 0 :(得分:4)
您可以使用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 。
请随时发布反馈,因为我可以根据收到的反馈更改我的样本以适应您的实际情况,以便更好地帮助您。 =)
我希望这有帮助! =)
答案 1 :(得分:2)
您可以使用适合您的TextRenderer.MeasureText
重载中的任何一个。使用此功能,您可以确定字符串的实际渲染大小,并相应地调整面板的大小。
如果您尝试在Paint
事件中进行衡量,那么您可以使用MeasureString
对象上的e.Graphics
函数,但在Paint
内调整大小是不明智的。使用TextRenderer
可以避免您必须使用Graphics
创建CreateGraphics()
对象,并在完成后将其丢弃。
修改强>
由于紧凑框架不支持TextRenderer
(我第一次看到问题时错过了标记),您必须在Graphics
对象上使用MeasureString()
函数。像这样:
public Size GetStringSize(string text)
{
using(Graphics g = yourPanel.CreateGraphics())
{
return g.MeasureString(text, yourPanel.Font);
}
}