Posted on 2008-07-15 10:44
JustDI 阅读(882)
评论(40) 编辑 收藏 网摘 所属分类:
.Net CompactFramework应用编程
在网上经常看见有人询问Windows Mobile下的九宫格控件的做法,我曾经也多次上网搜索,但找到的大部分都是c++版本的,于是萌发了自己写一个的念头,先上图片。
选中后。

选中的效果其实是两张图片的交替结果,因为只针对了240×320这种样式,所以可能很多地方写死了,下面对部分源码的解析。
先定义一个继承自Control的类FlexStartMenu
public class FlexStartMenu : System.Windows.Forms.Control
定义一个选项子类,因为这个控件中的图片中包含文字,因此我没有将子项的文字画到控件当中去,如果你们有需求的话可以修改OnPain事件,添加一个画文字的方法。

子项类
public class FlexStartItem

{

/**//// <summary>
/// 显示文本
/// </summary>
public string ItemText

{
get;
set;
}

/**//// <summary>
/// 选项图片
/// </summary>
public Image Icon

{
get;
set;
}

/**//// <summary>
/// 选中时的图片
/// </summary>
public Image PressIcon

{
get;
set;
}

/**//// <summary>
/// 选项距离顶部的距离
/// </summary>
public int Top

{
get;
set;
}

/**//// <summary>
/// 选项距离左边栏的距离
/// </summary>
public int Left

{
get;
set;
}

/**//// <summary>
/// 选项编号
/// </summary>
public int Index

{
get;
set;
}

/**//// <summary>
/// 是否被选中
/// </summary>
public bool Press

{
get;
set;
}
}
用泛型的方法,比数组的方式效率要高多了,原先我是采用数组的方式,但在两百条数据的加载效率差得非常明显,具体的时间我没有去测试过,但可以肯定的是装箱拆箱这一步能跳过去的就尽量跳过去。

FlexStartItemCollections
public class FlexStartItemCollections : CollectionBase

{
public void Remove(FlexStartItem value)

{
List.Remove(value);
}
public bool Contains(FlexStartItem value)

{
return (List.Contains(value));
}
public void Insert(int index, FlexStartItem value)

{
List.Insert(index, value);
}
public int IndexOf(FlexStartItem value)

{
return (List.IndexOf(value));
}
public int Add(FlexStartItem value)

{
return (List.Add(value));
}
public FlexStartItem this[int index]

{

get
{ return (FlexStartItem)List[index]; }

set
{ List[index] = value; }
}
}
核心部分来了:

核心部分
public class FlexStartMenu : System.Windows.Forms.Control

{
public FlexStartMenu()

{
this.Items = new FlexStartItemCollections();
}
public FlexStartItemCollections Items

{
get;
set;
}

/**//// <summary>
/// 被选中的项
/// </summary>
public FlexStartItem SelectedItem

{
get

{
FlexStartItem m_item = null;
for (int i = 0; i < this.Items.Count; i++)

{
if (Items[i].Press == true)

{
m_item = Items[i];
break;
}
}
return m_item;
}
}
//定义一个Bitmap变量用双缓冲的方式防止闪烁
protected Bitmap backBuffer;
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)

{
if (backBuffer != null)

{
Graphics gOffScreen = Graphics.FromImage(backBuffer);
gOffScreen.Clear(this.BackColor);
for (int i = 0; i < this.Items.Count; i++)

{
DrawItem(this.Items[i], i, gOffScreen);
}
e.Graphics.DrawImage(backBuffer, 0, 0);
}
else
e.Graphics.Clear(this.BackColor);
}
protected override void OnResize(EventArgs e)

{
base.OnResize(e);
if (backBuffer != null)
backBuffer.Dispose();
backBuffer = new Bitmap(this.Width, this.Height, PixelFormat.Format32bppRgb);
}
private void DrawItem(FlexStartItem m_item, int index, Graphics gOffScreen)

{
m_item.Index = index + 1;
TopAndLeft(m_item);
Bitmap bmp = null;
//选中时的图片
if (m_item.Press && m_item.PressIcon != null)
bmp = new Bitmap(m_item.PressIcon);
else
bmp = new Bitmap(m_item.Icon);
ImageAttributes ia = new ImageAttributes();
ia.SetColorKey(bmp.GetPixel(0, 0), bmp.GetPixel(0, 0));
Rectangle imgRect = new Rectangle(m_item.Left * 11 / 12 + this.Width / 12, m_item.Top * 11 / 12 + this.Height / 12, bmp.Width, bmp.Height);
gOffScreen.DrawImage(bmp, imgRect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, ia);
bmp.Dispose();
}
private void DynamicIcon()

{
Timer m_timer = new Timer();
m_timer.Interval = 1000;
m_timer.Tick += new EventHandler(ChangeIcon);
}
private void ChangeIcon(object sender, EventArgs e)

{

}

/**//// <summary>
/// 捕获点击动作
/// </summary>
/// <param name="e"></param>
protected override void OnMouseDown(MouseEventArgs e)

{
for (int i = 0; i < this.Items.Count; i++)

{
Rectangle itemRec = new Rectangle(this.Items[i].Left, this.Items[i].Top, this.Width / 3, this.Height / 3);
if (itemRec.Contains(e.X, e.Y))

{
this.Items[i].Press = true;
for (int j = 0; j < this.Items.Count; j++)

{
if (j != i)

{
this.Items[j].Press = false;
}
}
this.Invalidate();
break;
}
}
base.OnMouseDown(e);
}

/**//// <summary>
/// 计算九宫格的长宽高
/// </summary>
/// <param name="m_item"></param>
private void TopAndLeft(FlexStartItem m_item)

{
if ((double)m_item.Index / 3 > 2)
m_item.Top = this.Height * 2 / 3;
else if ((double)m_item.Index / 3 > 1)
m_item.Top = this.Height / 3;
else
m_item.Top = 0;
if (m_item.Index % 3 == 0 && m_item.Index != 1)
m_item.Left = this.Width * 2 / 3;
else if (m_item.Index == 2 || m_item.Index == 5 || m_item.Index == 8)
m_item.Left = this.Width / 3;
else
m_item.Left = 0;
}
protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e)

{
// base.OnPaintBackground(e);
//e.Graphics.DrawRectangle(new Pen(Color.Black), 0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1);
}

