感悟生活

Life is like a box of chocolates. You never know what you're gonna get.
随笔 - 97, 评论 - 983, 引用 - 46

导航

关于

标签

每月存档

最新留言

  • re:SharePoint的小秘密
    <p>☆                    &deg;∵☆       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
    by jackielongteng(注册) on 2009/6/14 13:02:55
  • re:SharePoint的小秘密
    <p>@开心就好:测试2</p>
    by 开心就好(注册) on 2009/1/8 22:36:27
  • re:SharePoint的小秘密
    <p>@开心就好:测试</p>
    by 开心就好(注册) on 2009/1/8 22:30:45
  • 回复: 微软拼音输入法2003
    你好,我需要下载,谢谢
    by 李鑫龙(匿名) on 2008/2/20 12:56:00
  • 回复: 微软拼音输入法2003
    你好,我需要下载,谢谢
    by ヤ偽妳變儍い(匿名) on 2008/2/18 16:07:00
  • 回复: 微软拼音输入法2003
    我要用反体字聊QQ
    by 郝语情(匿名) on 2008/2/14 3:33:00
  • 回复: 微软拼音输入法2003
    我要下载
    by ﹏賎侽魜▓(匿名) on 2008/1/23 1:04:00
  • 回复: 有限状态机 理论联系实际
    写程序没理论指导,不重视基础,到现在才发现问题,本末倒置的学习过程。要是有正确的学习方法,水平远应比现在高。
    by wr(匿名) on 2008/1/15 18:08:00
  • SOA基本介绍
    Webservice已经不再是新婚的娘子。众多企业都已经创建各种实验性WebServices项目,事实证明,这项新兴的分布式计算技术确实能够降低集成和开发的成本。另外,一些关键的WebServ...
    by IamV(匿名) on 2007/12/31 16:31:00
  • 回复: SharePoint的小秘密
    在管理中心可以查看Site Collection使用哪个Content DB!
    by it(匿名) on 2007/12/25 11:10:00

广告

 

为偶的NotesManager小程序写了一个带滚动条的Label控件,效果看起来象下面这样:

 

这个控件的实现思路说起来很简单,就是使用的一般Windows桌面程序中的窗口(Window)和视口(View)的概念。

考虑到Label本身不需要支持编辑的功能,出于效率的考虑,我在ScrollLabel控件中用一个Bitmap对象来保存Window的所有内容。在OnPaint中,如果发现Bitmap对象是空值(通常是第一次Paint),则根据当前Text的内容判断是否需要显示ScrollBar,并创建Bitmap对象,然后根据View的位置来显示应当显示在界面上的内容。以后每次Paint的时候,都只是根据滚动条的位置来计算View的位置,然后显示相应的Bitmap上的内容即可。当Text或者Font改变时,将原有的Bitmap销毁重新计算即可。整个OnPaint方法看起来象下面这样:

         protected override void OnPaint(PaintEventArgs e)

         {

              base.OnPaint (e);

 

              if(bmpWindow == null)

              {

                   Rectangle drawRect;

 

                   // Calculate the height of the window

                   SizeF size = e.Graphics.MeasureString(this.Text, this.Font);

                   rowHeight = size.Height;

                   float height = (size.Width / ClientSize.Width + 1) * rowHeight;

 

                   // Indicate if the scrollbar need to be shown.

                   if(height > ClientRectangle.Height)

                   {

                       // Recalculate the height of window.

                       height = (size.Width / (ClientSize.Width - scrollWidth)) * rowHeight + ClientSize.Height / 2;

 

                       // Show scrollbar

                       vs.Bounds = new Rectangle(this.ClientSize.Width - scrollWidth, 0,

                            scrollWidth, ClientSize.Height);

                       vs.LargeChange = (int)(ClientSize.Height / rowHeight);

                       vs.Maximum = (int)(height / rowHeight);

                       vs.Visible = true;

 

                       // Create window bitmap.

                       bmpWindow = new Bitmap(ClientSize.Width - scrollWidth, (int)height + 1);

                       drawRect = new Rectangle(0, 0, ClientSize.Width - scrollWidth, (int)height + 1);

                   }

                   else

                   {

                       bmpWindow = new Bitmap(ClientSize.Width, ClientSize.Height);

                       drawRect = this.ClientRectangle;

                   }

 

                   // Paint on the window bitmap.

                   Graphics g = Graphics.FromImage(bmpWindow);

                   g.FillRectangle(new SolidBrush(this.BackColor), drawRect);

                   g.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), drawRect);

                   g.Dispose();

              }

 

              // Draw view.

              e.Graphics.DrawImage(bmpWindow, 0, 0 - (int)rowHeight * vs.Value);

         }

这个ScrollLabel的代码可以从这里下载。

不过这里使用的方法也有一些小缺陷,主要是源于目前版本的.NET CF不支持的一些功能。比如,为了得到作为Window的Bitmap的宽度和高度,我使用了MeasureString这个方法。但是目前版本的.NET CF中,MeasureString并不支持按给定宽度度量所需要的高度的功能,只能量出将所有的字画在一行上的宽度和高度。我的解决办法是,用MeasureString得到的高度作为行高,用MeasureString得到的宽度和整个ClientSize的宽度比值作为所有的行数,从而得到Window所需的高度。但是这样一来,就无法顾及由于英文的分词所带来的误差。比如MeasureString这个词,如果恰好在行尾,在Paint的时候它不会被截断,而时候整个的被放到下一行来显示。这样不断的叠加,最终在行数上是会产生一定的误差的。我暂时使用的解决方法是,对我用MeasureString得到的Window高度进行了1/2个ClientSize高度的误差补偿,这样你会发现,ScrollBar在滚动时并不是精确地滚动到最后一行,而是还会向下滚动一段空白区域。在大多数情况下,这段误差补偿是可以解决问题的,但是对于包含很多非常长的单词的情况,可能仍然会有问题。

更新后的NotesManager可以在这里下载。

 

打印 | 张贴于 2004-11-08 13:49:00 | Tag:学习

留言反馈

#回复: ScrollLabel for Smartphone 2003 编辑
如何在一个form中调用ScrollLabel控件.
2007-11-13 13:52:00 | [匿名用户:Andy]
#re: ScrollLabel for Smartphone 2003 编辑
MeasureString并不支持按给定宽度度量所需要的高度的功能,只能量出将所有的字画在一行上的宽度和高度。

此言差矣!

请看:

public void MeasureStringSizeFFormat(Graphics g)
{
// Set up string.
string measureString = "Measure String Measure String Measure String Measure StringMeasure String Measure String Measure String Measure StringMeasure String Measure String Measure String Measure StringMeasure String Measure String Measure String Measure String";
Font stringFont = new Font("Arial", 16);
// Set maximum layout size.
SizeF layoutSize = new SizeF(300.0F,100.0F);
// Set string format.
StringFormat newStringFormat = new StringFormat();
newStringFormat.Alignment = StringAlignment.Near;
newStringFormat.LineAlignment = StringAlignment.Near;
// Measure string.
SizeF stringSize = new SizeF();
stringSize = g.MeasureString(measureString, stringFont, (int)layoutSize.Width, newStringFormat);
// Draw rectangle representing size of string.
g.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height);
// Draw string to screen.
g.DrawString(measureString, stringFont, Brushes.Black,
new RectangleF(new PointF(0, 0),stringSize), newStringFormat);
}
2006-01-24 16:21:00 | [匿名用户:johnsuna]
#re:ScrollLabel for Smartphone 2003 编辑
^_~,pretty good!18showsseeoo
2005-04-26 02:26:00 | [匿名用户:万能材料试验机]
#re:ScrollLabel for Smartphone 2003 编辑
^_^,Pretty Good!
2005-04-14 17:12:00 | [匿名用户:空气质量传感器]
#re:ScrollLabel for Smartphone 2003 编辑
^_^,Pretty Good!
2005-04-10 19:41:00 | [匿名用户:toho搅拌机]
#re: ScrollLabel for Smartphone 2003 编辑
一打开Smartphone就能看到,whole OS都是。
开心的那个listview简直就是garbage,MS的那个是undocumented的。
2004-11-09 10:29:00 | [匿名用户:leighsword]
#re: ScrollLabel for Smartphone 2003 编辑
@leighsword:

这个只是一个带有ScrollBar的Label,用来显示多行Text用的,并非要模仿什么MS_VIRTUAL_LIST_VIEW。

恕我无知,没听说过什么是MS_VIRTUAL_LIST_VIEW,刚才google了一下,发现这个东东也只有你在开心的一个随笔评论中提到过。其实如果我没有说错的话,开心用到的那个ListView应当是MSDN上的一个例子,它已经包含在Mobile Application Development Toolkit 2004中了,有兴趣的话可以down一个研究下。

能不能说说MS_VIRTUAL_LIST_VIEW到底长得什么样子呀?:)
2004-11-08 18:25:00 | [匿名用户:sam1111]
#re: ScrollLabel for Smartphone 2003 编辑
想模仿MS_VIRTUAL_LIST_VIEW,嘿嘿,it's not enough.
2004-11-08 17:27:00 | [匿名用户:leighsword]
#re: ScrollLabel for Smartphone 2003 编辑
Cool!
2004-11-08 15:48:00 | [匿名用户:开心就好]
对不起,目前本随笔不允许发表新评论.

Powered by: Joycode.MVC引擎 0.5.1.8