ScrollLabel for Smartphone 2003

时间:2004-11-08 13:49:00  类别:smartphone2003  作者:sam1111

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

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

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

protectedoverridevoid 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可以在这里下载。


特别推荐

广而告之