辣手问题:字符串的显示

rcyboom 2009-03-20 11:16:28
近来无事可做,想到了关于字体,文本的显示问题。发现一个问题但是始终得不到很好的解决,希望得到大家的帮助或提供下思路。
现有一任意字符串
string str;(可能为一行也可能为n行,每行的大小不一定)
我现在要显示出来,目标可以为label,textbox,panel或直接绘制到某一界面,并绘制一个矩形边框包围所有字符串。
限制就是:
1、显示字符串的区域(或者说矩形边框)的宽度 int mywidth是有限的或者是固定的。
2、不管基于什么字体,必须保证所有字符串不能被截断也就是完全显示。因此肯定会涉及到自动换行。(假设字体不会大到指定宽度下连一个字也显示不了的情况)
3、所有字符串必须是完全立即可见的,也就是说不能像textbox那样有滚动条。(假设在指定的最大高度 maxheight【如400像素】下肯定可以完全显示)
4、所绘制的矩形边框不能过大,要刚好能够包围所有字符串。

形象的图例如下(包括三行的字符串):
|---------|
|我们的祖国|
|是花园 |
|花园的花朵|
|真鲜艳 |
|你好 |
——————
从程序上讲就是在指定的矩形中绘制字符串,字符串要完全显示。
那么在宽度mywidth固定的情况下,程序要能根据不同的字符串 首先处理自动换行,其次要处理高度myheight的变化,以便完全显示字符串。
先说textbox,它可以自动换行但是不会自动增加高度,而是通过滚动来包容字符串。
label呢,它不能自动换行,只能处理字符串本身中有换行的情况。
所以需要:自己去获得需要的高度myheight。

textrender类中提供了测量字符串显示所需要的size方法MeasureText ,但也有局限性。
可是不管是单行还是多行,它只能在不自动换行的情况下,提供出高度和宽度。
比如字符串s中包含
line1=“你好!”
line2=“你吃饭了么?”这两个子字符串,它返回的高度仅仅是显示两行所需的高度,
宽度呢则是显示单行最长子字符串【line2】的宽度.可我们的宽度mywidth固定的情况下肯定行不通了。

我试验过几种方法,有的失败有的太繁琐。
方法1:
测试指定字体font1下单个字符的宽度iw,用mywidth/iw得到每行可以显示多少个字符,然后使用substring方法去分部分显示。
但这个iw显然不能应对所有字符,比如 【中、w、W、;i】它不是一样宽的,所以不可行。
方法2:
定义一个List<string> mylist
使用textrender提供的方法MeasureText()
首先使用substr=str.substring(0,j)
【j=1,j++直到MeasureText(substr)返回的宽度大于mywidth,然后mylist.add(str.substring(0,j-1))并从str中去掉刚增加到mylist中的子字符串】
重复该过程直到把str中所有内容增加到mylist中。
这样我们得到一个经过人工换行处理的字符串列表mylist,且该字符串不会显示到mywidth以外
剩下的就是使用MeasureText(mylist.Item[0])得到一个size,循环显示mylis内容即可,drawstring(0,y,mylist.Item[i]),y+=size.height
最后绘制矩形 drawRectangle(0,0,size.width,y)即可
该方法很麻烦,不是么?
方法3:直接使用带指定矩形的drawstring函数,虽然他会自动换行处理,但是:1、他对字母的换行是以单词为单元的,2、无法得知矩形的高度,行不通
...全文
170 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
rcyboom 2009-03-30
  • 打赏
  • 举报
回复
10 楼和13楼误解我的意思了,我是想要在任意地方绘制。关键问题不是要用矩形包围起字符,而是要绘制的字符能够自动换行,能够明确知道任意字符串所占的面积问题。
这么久了,该结贴了。呵呵。欢迎继续讨论!
zzxap 2009-03-21
  • 打赏
  • 举报
回复

<DIV ID="a" STYLE="border-left:1px solid #E87269; border-right:1px solid #E87269;" > 我们的祖国 </div>


结果 |我们的祖国|
jiyan1221 2009-03-21
  • 打赏
  • 举报
回复
先放着,等下回来看~~
三傻云梦 2009-03-21
  • 打赏
  • 举报
回复
学习楼上的。
zzxap 2009-03-21
  • 打赏
  • 举报
回复
STYLE=" border-top:1px solid #E87269; border-left:1px solid #E87269; border-right:1px solid #E87269;"


css这样就能用四条线条把某个id的div围起来。
Harvey_He 2009-03-21
  • 打赏
  • 举报
回复
方法1:
测试指定字体font1下单个字符的宽度iw,用mywidth/iw得到每行可以显示多少个字符,然后使用substring方法去分部分显示。
但这个iw显然不能应对所有字符,比如 【中、w、W、;i】它不是一样宽的,所以不可行。

你可以调用windowsAPI创建字符等宽的字体,就可以实现了:

public struct FONT_INFO
{
public Int32 nHeight; //字体的高度
public Int32 nWidth; //字体的宽度
public Int32 nEscapement//字符的间隔
public Int32 nOrientation;
public Int32 nWeight;
public bool bItalic;
public bool bUnderline;
public bool cStrikeOut;
public Int32 nCharSet;
public Int32 nOutPrecision;
public Int32 nClipPrecision;
public Int32 nQuality;
public Int32 nPitchAndFamily;
public string facename; //字体的名字
};
[DllImport("gdi32.dll", EntryPoint = "CreateFont")]
public static extern IntPtr CreateFont(FONT_INFO fontex);

//然后在Label里面的字体引用
FONT_INFO fontinfo = new FONT_INFO();
fontinfo.nHeight = 20;
fontinfo.nWidth = 20;
fontinfo.facename = "Arial"

Label1.Font = Font.FromHfont(CreateFont(fontinfo));
Label1.Text = "我们的祖国"
.......



ZJ159 2009-03-21
  • 打赏
  • 举报
回复
rcyboom 2009-03-21
  • 打赏
  • 举报
回复
自己顶起、。
rcyboom 2009-03-20
  • 打赏
  • 举报
回复
有一种字体叫等宽字体,不过没试验过,不知道中英文标点混排的情况下还等宽否?
oyljerry 2009-03-20
  • 打赏
  • 举报
回复
关键中文,英文字符宽度差别太大,很难有统一的方法获得合适的字符个数...
只能自己计算长度等来决定是否换行
rcyboom 2009-03-20
  • 打赏
  • 举报
回复
谢谢,虽然功能可以实现,但我只想进一步优化或者还有我不知道的方法。
放出来并写的这么详细就是为了集思广益,长长见识。
希望大家能够发表自己的见解或思路,虽然分不重要,但我保证只要在这个问题上确实思考过的人都有分。
再次感谢两位高人的眷顾,谢谢!
oyljerry 2009-03-20
  • 打赏
  • 举报
回复
你这种需求,估计只有用第二种方法等,自己来计算,换行等,可以把算法提取出来,提供统一的方法,以后字符串就可以都处理了
rcyboom 2009-03-20
  • 打赏
  • 举报
回复
自己定下,忘记向专家提问了。可是现在论坛好像不提供帖子的修改功能了啊,我点修改总是说权限不够,为何?
wuyi8808 2009-03-20
  • 打赏
  • 举报
回复
up

111,126

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧