using System; using System.Linq; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Drawing; using System.Drawing.Imaging; using System.Collections; namespace SmartDeviceProjectTemp { class CMenuListII : CMenuListParent { const int Column1Left = 5;//条目位图X位置 const int Column2Left = 25;//条目文字X位置 public CMenuListII() { // We need a total of 5 rows, so the height is 180/5=36 Graphics g = this.CreateGraphics(); Font font = new Font(this.Font.Name, 10, FontStyle.Bold); // Calc line height to be height of letter A plus 10% int fontHeight = (int)(g.MeasureString("国", font).Height*1.1);//计算当前字体的高度*1.1作为字体高度 this.ItemHeight = fontHeight; //每一条目为两行汉字,因此为字体高度*2 g.Dispose(); } 键盘处理流程。上/下键已由基类处理,这里只处理回车键 //protected override void OnKeyDown(KeyEventArgs e) //{ // switch (e.KeyCode) // { // case Keys.Return: // //MessageBox.Show("You selected item " + this.SelectedIndex.ToString(), // // "Item selected", // // MessageBoxButtons.OK, // // MessageBoxIcon.Asterisk, // // MessageBoxDefaultButton.Button1); // //if (EnterItem != null) // //{ // // EnterItemEventArgs enterItem = new EnterItemEventArgs(); // // enterItem.index = this.SelectedIndex; // // EnterItem(this, enterItem); // //} // break; // } // base.OnKeyDown(e); //} /// <summary> /// 自定义绘图事件。绘制ListView的条目 /// </summary> /// <param name="e"></param> protected override void OnPaint(PaintEventArgs e) { // Declare vars Font font; Color fontColor; // 从控件位图中产生控件绘图区,注:控件位图为控件不含滚动条的可显示区域图像,即条目显示部分 Graphics gOffScreen = Graphics.FromImage(this.OffScreen); //以控件背景色填充绘图区 gOffScreen.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle); int itemTop = 0;//当前条目的Y坐标 // 绘制可显示的条目,从滚动条当前位置绘制DrawCount个条目 for (int n = this.VScrollBar.Value; n < this.VScrollBar.Value + DrawCount; n++) { //如果该条目为当前选中条目,则要高亮显示 if (n == this.SelectedIndex) { //用高亮色填出该条目区域 gOffScreen.FillRectangle(new SolidBrush(SystemColors.Highlight), 0, itemTop, //如果滚动条可显,则要减去滚动条的宽度 this.ClientSize.Width - (this.VScrollBar.Visible ? this.VScrollBar.Width : 0), this.ItemHeight); //字体颜色为高亮色的对比色 //fontColor = CalcTextColor(SystemColors.Highlight); fontColor = Color.White; } else fontColor = this.ForeColor; //否则,字体颜色为控件前景色 if (GridLine) { // 用灰色绘制分割线 gOffScreen.DrawLine(new Pen(Color.DarkGray), 1, itemTop + this.ItemHeight, this.ClientSize.Width - (this.VScrollBar.Visible ? this.VScrollBar.Width : 2), itemTop + this.ItemHeight); } // 取得当前条目 MenuItem lvi = (MenuItem)this.Items[n]; font = new Font(this.Font.Name, 7, FontStyle.Regular); //设置图片的透明颜色 ImageAttributes ia = new ImageAttributes(); //ia.SetColorKey(Color.Transparent, Color.Transparent); ; ia.SetColorKey(Color.Black, Color.Black); if (n == this.SelectedIndex) { //设置位图绘图区域 Rectangle imgRectIconLight = new Rectangle(Column1Left, itemTop +3 , lvi.IconLight.Width, lvi.IconLight.Height); // 绘制条目位图 gOffScreen.DrawImage(lvi.IconLight, imgRectIconLight, 0, 0, lvi.IconLight.Width, lvi.IconLight.Height, GraphicsUnit.Pixel, ia); } else { //设置位图绘图区域 Rectangle imgRectIcon = new Rectangle(Column1Left, itemTop +3, lvi.Icon.Width, lvi.Icon.Height); // 绘制条目位图 gOffScreen.DrawImage(lvi.Icon, imgRectIcon, 0, 0, lvi.Icon.Width, lvi.Icon.Height, GraphicsUnit.Pixel, ia); } // 绘制条目文字 gOffScreen.DrawString(lvi.Item, font, new SolidBrush(fontColor), Column2Left, itemTop + 2 ); // 清理 font.Dispose(); // 设置下一个条目的Y位置=当前条目的Y位置+条目高度 itemTop += this.ItemHeight; } // 将整个绘图位图绘制到控件上 e.Graphics.DrawImage(this.OffScreen, 0, 0); gOffScreen.Dispose(); } // Draws the external border around the control. //protected override void OnPaintBackground(PaintEventArgs e) //{ // e.Graphics.DrawRectangle(new Pen(Color.Black), 0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1); //} } class CMenuListParent:Control { int scrollWidth; int itemHeight = -1; int selectedIndex = -1; Bitmap offScreen; //控件位图为控件不含滚动条的可显示区域图像,即条目显示部分 VScrollBar vs; //竖向滚动条 ArrayList items;//菜单数组 Boolean gridLine = true; public CMenuListParent() { this.vs = new VScrollBar(); //产生滚动条 scrollWidth = this.vs.Width; //设定滚动条宽度=控件默认宽度 this.vs.Parent = this; //滚动条的父窗口为控件 this.vs.Visible = false; //不可见 this.vs.SmallChange = 1; //最小变化量为1 this.vs.ValueChanged += new EventHandler(this.ScrollValueChanged);//设置滚动变化事件 // Items to draw this.items = new ArrayList();//产生Item数组 } public Boolean GridLine { get { return gridLine; } set { gridLine = value; } } /// <summary> /// 条目数组 /// </summary> public ArrayList Items { get { return this.items; } } /// <summary> /// 控件位图 /// </summary> protected Bitmap OffScreen { get { return this.offScreen; } } /// <summary> /// 控件滚动条 /// </summary> protected VScrollBar VScrollBar { get { return this.vs; } } public event EventHandler SelectedIndexChanged; // Raise the SelectedIndexChanged event protected virtual void OnSelectedIndexChanged(EventArgs e) { if (this.SelectedIndexChanged != null) //如果设置了选中Item变化的事件,则执行 this.SelectedIndexChanged(this, e); } // 获取或设置当前选中项目索引 public int SelectedIndex { get { return this.selectedIndex; } //返回索引 set { this.selectedIndex = value; //设置新索引值,并调用索引改变事件 this.OnSelectedIndexChanged( EventArgs.Empty); } } protected void ScrollValueChanged(object o, EventArgs e) { this.Refresh(); } protected virtual int ItemHeight { get { return this.itemHeight; } set { this.itemHeight = value; } } // If the requested index is before the first visible index then set the // first item to be the requested index. If it is after the last visible // index, then set the last visible index to be the requested index. public void EnsureVisible(int index) {//计算滚动条的当前位置 if (index < this.vs.Value) {//如果新位置<原有滚动条位置 this.vs.Value = index; this.Refresh(); } else if (index >= this.vs.Value + this.DrawCount) { this.vs.Value = index - this.DrawCount + 1; this.Refresh(); } } // 键盘事件,处理上下键 protected override void OnKeyDown(KeyEventArgs e) { switch (e.KeyCode) { case Keys.Down: //Down键时,如果当前选中索引<滚动条的最大值,则当前选中索引+1,并显示 if (this.SelectedIndex < this.vs.Maximum) { EnsureVisible(++this.SelectedIndex); this.Refresh(); } break; case Keys.Up://Up键时,如果当前选中索引>滚动条的最小值,则当前选中索引-1,并显示 if (this.SelectedIndex > this.vs.Minimum) { EnsureVisible(--this.SelectedIndex); this.Refresh(); } break; } base.OnKeyDown(e); //调用基类的键盘事件 } //计算实际需要绘制条目数量 protected int DrawCount { get { if (this.vs.Value + this.vs.LargeChange > this.vs.Maximum)//如果从当前位置到最尾+可显示最大栏目数量>总栏目数量 return this.vs.Maximum - this.vs.Value + 1; //返回实际栏目数量 else return this.vs.LargeChange; //否则,返回可显示最大栏目数量 } } //控件尺寸调整事件 protected override void OnResize(EventArgs e) { int viewableItemCount = this.ClientSize.Height / this.ItemHeight; //可显示栏目数量=控件高度/条目高度 this.vs.Bounds = new Rectangle(this.ClientSize.Width - scrollWidth,//重新调整滚动条大小 0, scrollWidth, this.ClientSize.Height); //重新计算控件位图的大小 //判断是否需要滚动条 if (this.items.Count > viewableItemCount) { //如果条目数大于可显示条目数,则显示滚动条,并把滚动条最大变化量设置为可显示条目数 this.vs.Visible = true; this.vs.LargeChange = viewableItemCount; //产生一个控件可显示区位图 //宽度=控件宽度-滚动条宽度 //高度=控件高度 this.offScreen = new Bitmap(this.ClientSize.Width - scrollWidth, this.ClientSize.Height); } else { //如果不需要滚动条 this.vs.Visible = false; this.vs.LargeChange = this.items.Count; //产生一个控件可显示区位图 this.offScreen = new Bitmap(this.ClientSize.Width, this.ClientSize.Height); } this.vs.Maximum = this.items.Count - 1; //计算滚动条的最大值=条目个数-1 } //决定什么颜色作为高亮选中条目的字体颜色 protected Color CalcTextColor(Color backgroundColor) { if (backgroundColor.Equals(Color.Empty)) return Color.Black; //如果背景颜色为空,则返回黑色 int sum = backgroundColor.R + backgroundColor.G + backgroundColor.B; if (sum > 256) //如果红绿蓝颜色大于256,则返回黑色 return Color.Black; else return Color.White; //否则返回白色 } } class MenuItem { Image icon,iconlight; String item; public MenuItem(Image Icon,Image IconLight,string Item) { icon = Icon; iconlight = IconLight; item = Item; } public Image Icon { get { return icon; } } public Image IconLight { get { return iconlight; } } public string Item { get { return item; } } } } //--------------------------------------------------------------------------- CMenuListII MenuList = new CMenuListII(); MenuList.Parent = this; MenuList.GridLine = false; MenuList.Bounds = new Rectangle(10, 10, this.ClientSize.Width - 20, this.ClientSize.Height - 20); MenuList.Items.Add(new MenuItem(Resources._0, Resources.ArrowRight, "1")); MenuList.Items.Add(new MenuItem(Resources._1, Resources.ArrowRight, "2")); MenuList.Items.Add(new MenuItem(Resources._2, Resources.ArrowRight, "3")); MenuList.Items.Add(new MenuItem(Resources._3, Resources.ArrowRight, "4")); MenuList.Items.Add(new MenuItem(Resources._4, Resources.ArrowRight, "5")); MenuList.Items.Add(new MenuItem(Resources._5, Resources.ArrowRight, "6")); MenuList.SelectedIndex = 0; MenuList.EnsureVisible(MenuList.SelectedIndex);