codeproject.com 上有很多例子源码
DotNet(C#)自定义WinForm界面控件之Window消息
写在前面:要自定义WinForm界面控件,WndProc方法的重写恐怕是必不可少了,它是对系统消息的捕获和处理方法,自定义控件时,可以捕获重画,鼠标移动等消息,然后重画控件,从而改变控件的外观,这样就可以达到自定义的功能,特别是美化控件,就一定要捕获系统消息,下面介绍一些重要的系统消息,这些消息基本上是继承.Net基础控件(如TextBox,Button之类)之后必不可少的需要捕获的消息。如WM_PAINT,WM_NCPAINT等,你可以不知道吗?如果你真的不知道,你可以说,你是个入门的GUI编程者吗?下面,只简单地列举消息和说明意思,但并不举例子说明。
WM_PAINT = 0x000F
其中0x000F是C#中表示int的一种写法,可以定义为const
要求一个窗口重画自己
WM_NCPAINT = 0x0085
当某个窗口的框架必须被绘制时,程序发送此消息给窗口
WM_ACTIVATE = 0x0006
一个窗口被激活或失去激活状态
WM_KILLFOCUS = 0x0008
失去焦点
WM_NCCALCSIZE = 0x0083
当某个窗口的客户区域必须被核算时发送此消息
WM_NCACTIVATE = 0x0086
此消息发送给某个窗口 仅当它的非客户区需要被改变来显示是激活还是非激活状态
WM_SETTEXT = 0x000C
应用程序发送此消息来设置一个窗口的文本
WM_LBUTTONDOWN = 0x0201
按下鼠标左键
WM_LBUTTONUP = 0x0202
释放鼠标左键
WM_LBUTTONDBLCLK = 0x0203
双击鼠标左键
WM_MOUSEMOVE = 0x0200
移动鼠标
WM_SYSCOMMAND = 0x0112
当用户选择窗口菜单的一条命令或当用户选择最大化或最小化时那个窗口会收到此消息
WM_SIZE = 5
改变一个窗口的大小
WM_SIZING = 0x0214
当用户正在调整窗口大小时发送此消息给窗口;通过此消息应用程序可以监视窗口大小和位置也可以修改他们
WM_ERASEBKGND = 0x0014
当窗口背景必须被擦除时(例在窗口改变大小时)
WM_SHOWWINDOW = 0x18
当隐藏或显示窗口是发送此消息给这个窗口
WM_NCCREATE = 0x0081
当某个窗口第一次被创建时,此消息在WM_CREATE消息发送前发送
WM_WINDOWPOSCHANGING = 0x0046
发送此消息给那个窗口的大小和位置将要被改变时,来调用setwindowpos函数或其它窗口管理函数
WM_WINDOWPOSCHANGED = 0x0047
发送此消息给那个窗口的大小和位置已经被改变时,来调用setwindowpos函数或其它窗口管理函数
DotNet(C#)自定义界面控件常用Design属性
写在前面:在开发自定义控件件时,有好些Design属性是要使用的,如ToolboxItem, ToolboxBitmap, Category, Description等等,不知道这些属性其实也可以将控件搞出来,不过,知道了,会令事件更加简单,令控件更加专业和实用。有时,不知道用法,会令到项目的其他同事好烦,因为这个控件是你提供的。下面对一些常用的Design属性做一个简单的生产介绍。
ToolboxItem
有没有试过写一个用户控件后,想它不出现在工具箱中,当然有,有时候是控件的Designer部分没有写好或没写,有时候是控件一拖出来就报错,有时候是内部使用的控件,不想别人一引用DLL就出现控件。其它设置方法可以很简单。
[ToolboxItem(false)] public class MyPanel : UserControl
这样就可以了。“可恶”的用户控件就自动隐藏了,不出现在工具箱中。不过,如果你不知道这样的话,可以会引来一大堆的烦事。
ToolboxBitmap
写好一个用户控件后,在工具箱中出来的是一个蓝色的齿轮,这就不是很漂亮了,也不能够直观地表达自己的意图。如果更不幸的你的控件的名称好难认的话,其它的开发者会很麻烦的。怎样才能让用户控件在工具箱中显示不同的图标呢?
[ToolboxItem(false)] public class MyPanel : UserControl
这样就可以了,表示,你所做的用户控件使用的图标是Panel的图标。
如果不想用系统的图标,要使用自己的图标,可以这样
[ToolboxBitmap(typeof(MyPanel), "WindowsApplication1.Images.MyPanel.bmp")]
public class MyPanel : UserControl
不过,一定要注意路径,WindowsApplication1.Images.MyPanel.bmp表示,解决方案是WindowsApplication1,目录是Images,文件名是MyPanel.bmp,同时,这个图片必须是“嵌入的资源”(点击文件,右键,属性,有一个文件属性,其中,在生成操作中,可以选择"嵌入的资源")
Category与Description
[Category("Appearance"), Description("阴影色")]
public System.Drawing.Color ShadowColor { get { …} set { …} }
这两个是经常都会写在一起的属性,Category表示类型,如属性框中所显示的外观,布局等,当然,你可以自己写一个,叫“自定义属性”,而Description就是这个属性的描述,用来说明属性有什么用途。这两个的设置相对都比较简单,可以说,一看就知道,不过提一下,Appearance是特殊的词,在属性面板中,它就是外观一栏。
DefaultValue
[DefaultValue(typeof(Color), "DarkGray")]
public System.Drawing.Color ShadowColor { get { …} set { …} }
用于设置默认的值,对于string,bool,int,可以直接写出来,如[DefaultValue(10)],这是可以的,不过,不是这三种类型的话,就比较麻烦,一定要先转化为string才能设置成功。如上面的DarkGray,这是系统定义的颜色,这还是比较好处理的。不过,如果是一些自定义的颜色,如颜色是128,0,128,你应该将128转为16进制,写成0x800080,前缀0x是一定要加的。最后就这样
[DefaultValue(typeof(Color), "0x800080")]
Browsable
表示,是否在属性面板中显示这个属性
[Browsable(true)]
表示,将在属性面板中显示这个属性。
DesignerSerializationVisibility
表示,是否在*.Designer.cs文件中将设置的代码写出来,也就是是否要实现序列化
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
表示需要实现序列化。
DotNet(C#)自定义WinForm控件之XPPanel
写在前面:WindowsXP的好多的界面或功能都非常受欢迎的,下面,介绍一下文件夹选项-常见任务功能,一些优秀的程序员把它写成了一个控件,这就是XPPanel控件。这是一个可收缩的Panel,而收缩的空间会被其它的Panel自己填充,多个Panel组成一个Group,于是就有两个控件表达这个效果,它们分别是XPPanel和XPPanelGroup,本文对控件作简单的功能和设置介绍。
效果图
原网址
介绍些款控件的源网站:http://www.codeproject.com/KB/miscctrl/TgXPPanel.aspx
设置介绍
先将一个XpPanelGroup控件拖放到Form上面,设置Dock为Left,这样,XpPanelGroup就自动靠到左边。然后把XpPanel直接拖到XpPanelGroup上面,这时,注意到,XpPanel的Anchor属性自动被设置为Top,Left,Right,Anchor是一个与Dock互斥的属性,表示对所在的父控件的四周的锚定。这里,每个XpPanel都对Top,Left,Right进行锚定,保证了当SizeChange时,控件也会自动地变化。
设置XpPanel
可以设置XpPanel 的标题Caption,随之而来的,还有CaptionCornerTpe属性,表示标题部份椭圆弧度的类型,CaptionGridient渐变颜色,通常,这是
System.Drawing.Drawing2D.LinearGradientBrush类型的设置,设置两个颜色,这两个颜色可以自动过渡,CaptionGradientMode就是LinearGradientBrush的颜色过渡方位,如上下,左右,左上到右下,左下到右上。
可以设置XpPanel的Panel部分,跟Caption一样,可以设置渐变色,过渡方位等。
其它的控件
在标题上面,是可以设置图片的,对鼠标的MouseOn和 MouseLeft支持图片的过渡,而在Panel内部,可以放任务的控件和使用小图标等。
.Net(C#)自定义WinForm控件之屏幕捕捉(Teboscreen)
写在前面:屏幕捕捉有好多的产品,如HyperSnap,红蜻蜓等等,都非常好用,不过,如果你要在自己的程序上面增加屏幕捕捉功能,这些产品都用不上了,这时候,你要自定义一个屏幕捕捉的功能,这样的捉图功能,在.Net中,其实,真是可以很容易,下面就介绍一个自定义的屏幕捕捉功能。
初评
其界面是相当的简单,运行之后就是这样的,只提供捉全屏幕,捉部分区域的功能,不过,它提供了好的程序,可以参考它,做出好多你想要的功能。
原网址
介绍此款软件的原网址:http://www.codeproject.com/KB/cs/TeboScreen.aspx
你可以在那里获取更加详细的信息
内容
只有三个重要的文件
ScreenShot.cs
Form1.cs
ControlPanel.cs
其中,ControlPanel就是上面所展示的Form,而Form1是点击Capture Area之后,出现的半透明的Form(同时ControlPanel会暂时不出现),在这个Form之中,你可以拖动鼠标选择你感兴趣的区域,之后,再单击,就可以捕捉下面了,这时,会提示要你提供保存文件的位置,然后ControlPanel会再出来。
下面介绍一下ScreenShot.cs,它只提供了一个方面,而这个方法就是枋心的捉图方面,传入的参数为捕捉的区域和保存的文件名,然后,调用CopyFromScreen方法就临时保存了BitMap,再使用BitMap的Save方法就可以了。
事实上,事情,就是这么的简单:)第一个想代码的时候,就不一定简单了:(
扩展WinForm的ComboBox
个人认为 winform 的 combobox 不是那么的好用,所以自己扩展了一下。
重新定义 Items 属性,并且支持树结构。
为每项加入了 CheckBox 状态。
丰富的列表项类 ListItem。
效果如图:
代码清单:
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design;
namespace FaibClass.Windows.Forms
{
[Designer(typeof(ControlDesigner))]
public class ComboBox : System.Windows.Forms.ComboBox
{
// Fields
private bool blnIsChange = false;
private int m_ImageIndex = -1;
private ImageList m_ImageList;
private ListItemCollection m_items;
private object objSource;
private Color m_ItemHoverBackColor;
private Color m_ItemHoverGradientBackColor = Color.Empty;
private Color m_ItemHoverColor;
private int m_Indent = 16;
private bool m_CheckBoxes = false;
private bool isUpdate = false;
private ComboBoxWindow wnd = null;
internal static int nextId = 0;
Methods#region Methods
public ComboBox()
{
m_ItemHoverBackColor = SystemColors.Highlight;
m_ItemHoverColor = SystemColors.HighlightText;
base.Sorted = false;
}
/**//// <summary>
/// 绑定数据。
/// </summary>
public void DataBind()
{
if ((this.DataSource != null) && (base.DisplayMember != null))
{
switch (this.DataSource.GetType().Name)
{
case "DataTable":
{
DataTable dtblTmp = (DataTable)this.DataSource;
foreach (DataRow drowTmp in dtblTmp.Rows)
{
string strText = drowTmp[base.DisplayMember].ToString();
string strValue = (base.ValueMember == null) ? null : drowTmp[base.ValueMember].ToString();
ListItem item = new ListItem(strText, strValue, this.ImageIndex);
this.m_items.Add(item);
}
break;
}
}
}
}
//锁定更新
public new void BeginUpdate()
{
base.BeginUpdate();
isUpdate = true;
}
//解除更新
public new void EndUpdate()
{
InsertItem(m_items);
base.EndUpdate();
isUpdate = false;
}
//绘制项
protected override void OnDrawItem(DrawItemEventArgs e)
{
if(e.Index == -1)return;
Rectangle trect = new Rectangle(0, 0, 0, 0), crect = new Rectangle(0, 0, 0, 0);
ListItem item = getItem(e.Index);
if(item == null)return;
bool isEdit = (e.State & DrawItemState.ComboBoxEdit) == DrawItemState.ComboBoxEdit;
if(m_CheckBoxes) //复选框的区域
{
crect = new Rectangle(m_Indent * item.level, e.Bounds.Top + ((e.Bounds.Height - 16) / 2), 16, 16);
if(isEdit)
crect.Offset(2, 0);
}
else
{
crect.X = m_Indent * item.level + 2;
}
//if(isEdit)
DrawBackground(e, e.Bounds, item);
//else
// DrawBackground(e, new Rectangle(crect.Left - 1, e.Bounds.Top, e.Bounds.Width - crect.Left + 1, e.Bounds.Height), item);
Rectangle irect = new Rectangle(crect.Right, 0, 0, 0);
if(ImageList != null && item.ImageIndex != -1)//画图象
{
Image sIcon = ImageList.Images[item.ImageIndex];
irect = new Rectangle(crect.Right, e.Bounds.Top + ((e.Bounds.Height - sIcon.Height) / 2), sIcon.Width, sIcon.Height);
//图象太大
if(irect.Height > e.Bounds.Height)
{
irect = new Rectangle(crect.Right, e.Bounds.Top, e.Bounds.Height, e.Bounds.Height);
}
e.Graphics.DrawImage(sIcon, irect);
}
trect = new Rectangle(irect.Right, e.Bounds.Top, e.Bounds.Width - irect.Width, e.Bounds.Height);
if(m_CheckBoxes) //画复选框
{
if(item.checkboxLeft == -1)
item.checkboxLeft= crect.Left;
ControlPaint.DrawCheckBox(e.Graphics, crect , item.Checked ? ButtonState.Checked | ButtonState.Flat : ButtonState.Flat);
}
DrawString(e, item, trect); //输出文本
e.Graphics.Dispose();
}
//重设项大小
protected override void OnMeasureItem(MeasureItemEventArgs e)
{
base.OnMeasureItem(e);
if (this.ImageList != null)
{
e.ItemHeight = this.ImageList.ImageSize.Height;
}
}
protected override void WndProc(ref Message m)
{
if(m.Msg == 0x134)//WM_CTLCOLORLISTBOX
{
if(m_CheckBoxes && wnd == null)
{
wnd = new ComboBoxWindow(base.Items, Handle); //钩子
wnd.AssignHandle(m.LParam);
}
}
else if(wnd != null && m.Msg == 0x2)//WM_DESTROY
{
wnd.ReleaseHandle();
}
else if(m.Msg == 0x400 + 0x105) //自定消息 设置checked
{
int index = m.WParam.ToInt32();
ListItem item = FindRealListItem(getItem(index));
if(item != null)
{
item.Checked = !item.Checked;
}
}
base.WndProc (ref m);
}
//画背景
private void DrawBackground(DrawItemEventArgs e, Rectangle rect, ListItem item)
{
if((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
if(m_ItemHoverGradientBackColor != Color.Empty)
{
//渐变
Rectangle r = new Rectangle(rect.Left, rect.Top, rect.Width, rect.Height / 2);
e.Graphics.FillRectangle(new LinearGradientBrush(r, m_ItemHoverBackColor, m_ItemHoverGradientBackColor, 90f), r);
r = new Rectangle(rect.Left, rect.Top + rect.Height / 2, rect.Width, rect.Height / 2);
if(r.Height % 2 == 0){r.Y -= 2; r.Height += 2;}
e.Graphics.FillRectangle(new LinearGradientBrush(r, m_ItemHoverBackColor, m_ItemHoverGradientBackColor, 270f), r);
ControlPaint.DrawBorder(e.Graphics, rect, m_ItemHoverGradientBackColor, ButtonBorderStyle.Solid);
}
else
e.Graphics.FillRectangle(new SolidBrush(m_ItemHoverBackColor), rect);
}
else
{
e.Graphics.FillRectangle(new SolidBrush(item.BackColor), rect);
}
}
//画文本
private void DrawString(DrawItemEventArgs e, ListItem item, Rectangle rect)
{
StringFormat sf = new StringFormat();
sf.LineAlignment = StringAlignment.Center;
rect.Offset(0, 1);
SolidBrush sb = null;
if(!item.ForeColor.Equals(SystemColors.WindowText) || m_ItemHoverGradientBackColor != Color.Empty)
{
sb = new SolidBrush(item.ForeColor);
}
else if((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
sb = new SolidBrush(m_ItemHoverColor);
}
else
{
sb = new SolidBrush(SystemColors.WindowText);
}
e.Graphics.DrawString(item.Text, item.Font, sb, rect, sf);
sb.Dispose();
}
//插入整个根集合
private void InsertItem(ListItemCollection items)
{
foreach(ListItem item in items)
{
ListItem lit = item.CloneData();
lit.Items = null;
lit.level = item.level;
if(item.Parent.GetType() == typeof(ListItem))
{
ListItem parent = (ListItem)item.Parent;
lit.Parent = parent;
}
base.Items.Add(lit);
InsertItem(item.Items);
}
}
//插入新项
internal int InsertItem(int index, ListItem item, int method)
{
if(isUpdate)return 0;
ListItem lit = item.CloneData();
lit.Items = null;
lit.level = item.level;
int count = 0;
if(item.Parent.GetType() == typeof(ListItem))
{
ListItem parent = (ListItem)item.Parent;
foreach(ListItem lt1 in parent.Items)
{
GetItemLocation(lt1.Items, lit, ref count);
}
lit.Parent = parent;
int i = 0;
for(; i < base.Items.Count; i++)
{
if(getItem(i).id == parent.id)
{
break;
}
}
base.Items.Insert(i + 1 + index + count, lit);
}
else
{
foreach(ListItem lt1 in ((ComboBox)item.Parent).Items)
{
GetItemLocation(lt1.Items, lit, ref count);
}
base.Items.Insert(index + count, lit);
}
return base.Items.Count - 1;
}
private void GetItemLocation(ListItemCollection items, ListItem owner, ref int count)
{
foreach(ListItem lt in items)
{
if(owner.id != lt.id && CheckIsInItems(lt.id))
{
count ++;
GetItemLocation(lt.Items, owner, ref count);
}
}
}
private bool CheckIsInItems(int id)
{
foreach(object o in base.Items)
{
if(((ListItem)o).id == id)
{
return true;
}
}
return false;
}
internal void RemoveItem(ListItem item)
{
if(isUpdate)return;
int index = FindItem(item.id);
if(index != -1)
base.Items.RemoveAt(index);
}
internal void ClearItem()
{
base.Items.Clear();
}
private int FindItem(int id)
{
if(this.DesignMode)return -1;
for(int i = 0; i < base.Items.Count; i++)
{
if(getItem(i).id == id)
return i;
}
return -1;
}
private void FindItem(int id, ListItem item, ref ListItem find)
{
foreach(object lt in item.Items)
{
ListItem lt1 = (ListItem)lt;
if(lt1.id == id)
{
find = lt1;
break;
}
FindItem(id, lt1, ref find);
}
}
private void FindCheckedItem(ListItemCollection items, ref CheckedListItemCollection checkeditems)
{
foreach(object lt in items)
{
ListItem lt1 = (ListItem)lt;
if(lt1.Checked)checkeditems.Add(lt1);
FindCheckedItem(lt1.Items, ref checkeditems);
}
}
private ListItem FindRealListItem(ListItem item)
{
if(item.Parent == null) //为根节点
{
foreach(ListItem lt in this.m_items)
{
if(lt.id == item.id)
return lt;
}
return null;
}
else
{
ListItem temp = item;
while(true) // 找到根级
{
if(temp.Parent == null)break;
if(temp.Parent.GetType() == typeof(ComboBox))break;
temp = (temp.Parent as ListItem);
}
ListItem find = null;
//找子项里
FindItem(item.id, temp, ref find);
return find;
}
}
internal void setText(int id, string text)
{
int index = FindItem(id);
if(index != -1)
{
getItem(index).Text = text;
}
}
internal void setImageIndex(int id, int imageIndex)
{
int index = FindItem(id);
if(index != -1)
getItem(index).ImageIndex = imageIndex;
}
internal void setForeColor(int id, Color foreColor)
{
int index = FindItem(id);
if(index != -1)
getItem(index).ForeColor = foreColor;
}
internal void setBackColor(int id, Color backColor)
{
int index = FindItem(id);
if(index != -1)
getItem(index).BackColor = backColor;
}
internal void setFont(int id, Font font)
{
int index = FindItem(id);
if(index != -1)
getItem(index).Font = font;
}
internal void setChecked(int id, bool check)
{
int index = FindItem(id);
if(index != -1)
getItem(index).Checked = check;
}
internal void setItem(int id, ListItem item)
{
int index = FindItem(id);
if(index != -1)
base.Items[index] = item.CloneData();
}
private ListItem getItem(int index)
{
if(index < 0 || index > base.Items.Count - 1)
throw new ArgumentNullException("索引值超出集合的范围");
return (ListItem)base.Items[index];
}
#endregion
Properties#region Properties
[Category("Data"), Description("用于绑定的数据源。")]
public new object DataSource
{
get
{
return this.objSource;
}
set
{
this.objSource = value;
base.DataSource = null;
}
}
[Category("Appearance"),
Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design", typeof(UITypeEditor)),
TypeConverter(typeof(ImageIndexConverter)),
DefaultValue(-1)]
public int ImageIndex
{
get
{
return this.m_ImageIndex;
}
set
{
this.m_ImageIndex = value;
}
}
[Description("组合框中的项的图象所使用的ImageList控件。"),
Browsable(true),
DefaultValue((string)null)]
public ImageList ImageList
{
get
{
return this.m_ImageList;
}
set
{
this.m_ImageList = value;
}
}
[Category("Behavior"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Editor(typeof(CollectionEditor), typeof(UITypeEditor)),
MergableProperty(false),
Description("组合框中的项。"),
DefaultValue((string)null),
Localizable(true)]
public new ListItemCollection Items
{
get
{
if(m_items == null)
m_items = new ListItemCollection(this, this);
return this.m_items;
}
}
[Browsable(false)]
public new ListItem SelectedItem
{
get
{
if (this.SelectedIndex == -1)
{
return null;
}
return FindRealListItem(getItem(this.SelectedIndex));
}
}
[Browsable(false)]
public new string SelectedText
{
get
{
if (this.SelectedIndex == -1)
{
return null;
}
return SelectedItem.Text;
}
set
{
if ((this.SelectedIndex != -1) && !this.blnIsChange)
{
SelectedItem.Text = value;
}
}
}
[Browsable(false)]
public new object SelectedValue
{
get
{
if (this.SelectedIndex == -1)
{
return null;
}
return SelectedItem.Value;
}
set
{
if (this.SelectedIndex != -1)
{
SelectedItem.Value = value;
}
}
}
[Browsable(false)]
public CheckedListItemCollection CheckedItems
{
get{
CheckedListItemCollection checkitems = new CheckedListItemCollection();
if(m_CheckBoxes)
FindCheckedItem(this.m_items, ref checkitems);
return checkitems;
}
}
[Category("Appearance"),
Description("获取或设置鼠标移上列表项时的前景景颜色。")]
public Color ItemHoverColor
{
get{return m_ItemHoverColor;}
set{m_ItemHoverColor = value;}
}
[Category("Appearance"),
Description("获取或设置鼠标移上列表项时的背景颜色。")]
public Color ItemHoverBackColor
{
get{return m_ItemHoverBackColor;}
set{m_ItemHoverBackColor = value;}
}
[Category("Appearance"),
DefaultValue((string)null),
Description("获取或设置鼠标移上列表项时的背景颜色。")]
public Color ItemHoverGradientBackColor
{
get{return m_ItemHoverGradientBackColor;}
set{m_ItemHoverGradientBackColor = value;}
}
[DefaultValue(16),
Description("子节点的缩进宽度。")]
public int Indent
{
get{return m_Indent;}
set{m_Indent = value;}
}
[DefaultValue(false),
Description("是否显示复选框。")]
public bool CheckBoxes
{
get{return m_CheckBoxes;}
set{m_CheckBoxes = value;}
}
#endregion
ListItemCollection#region ListItemCollection
public class ListItemCollection : IList, ICollection, IEnumerable
{
private ComboBox owner;
private object parent;
private ArrayList items;
private bool inserted = true;
internal byte level = 0;
// Methods
internal ListItemCollection(ComboBox comboBox, object parent)
{
items = new ArrayList();
this.owner = comboBox;
this.parent = parent;
}
public ListItemCollection()
{
items = new ArrayList();
}
internal ListItemCollection(bool inserted)
{
items = new ArrayList();
this.inserted = inserted;
}
public ListItem this[int index]
{
get{
if(index < 0 || index > items.Count - 1)
throw new ArgumentNullException("索引值超出集合的范围");
return items[index] as ListItem;
}
set
{
if(index < 0 || index > items.Count - 1)
throw new ArgumentNullException("索引值超出集合的范围");
ListItem item = (ListItem)items[index];
value.id = item.id;
value.level = item.level;
items[index] = value;
if(owner != null)owner.setItem(value.id, value);
}
}
public int Count
{
get{return items.Count;}
}
public int Add(string Text)
{
return Insert(-1, new ListItem(Text));
}
public int Add(string Text, object Value)
{
return Insert(-1, new ListItem(Text, Value));
}
public int Add(string Text, int ImageIndex)
{
return Insert(-1, new ListItem(Text, ImageIndex));
}
public int Add(string Text, object Value, int ImageIndex)
{
return Insert(-1, new ListItem(Text, Value, ImageIndex));
}
public int Add(ListItem item)
{
return Insert(-1, item);
}
public void AddRange(ListItem[] items)
{
for(IEnumerator e = items.GetEnumerator(); e.MoveNext();)
Insert(-1, (ListItem)e.Current);
}
public int Insert(int index, ListItem item)
{
int ret = 0;
if(inserted)
item.level = level;
int m = 1;
if(index == -1)
{
index = this.Count;
m = 0; //为添加
}
item.Host(owner);
item.Parent = parent;
item.Text = (item.Text.Length == 0) ? item.GetType().Name : item.Text;
items.Insert(index, item);
if(inserted)
{
item.id = ComboBox.nextId ++;
if(owner != null)
{
ret = item.Index = owner.InsertItem(index, item, m);
AddItem(item, item.Items);
}
}
return ret;
}
internal void Host(ComboBox comboBox, object parent)
{
this.owner = comboBox;
this.parent = parent;
}
private void AddItem(ListItem parent, ListItemCollection items)
{
int i = 0;
foreach (ListItem item in items)
{
item.Host(owner);
item.Parent = parent;
item.level = items.level;
item.Index = owner.InsertItem(i, item, 0);
i++;
}
}
public void Remove(ListItem item)
{
if(owner != null)owner.RemoveItem(item);
items.Remove(item);
}
public void RemoveAt(int index)
{
if(owner != null)owner.RemoveItem(this[index]);
items.RemoveAt(index);
}
public int IndexOf(ListItem item)
{
return items.IndexOf(item);
}
public bool Contains(ListItem item)
{
return items.Contains(item);
}
public void Clear()
{
items.Clear();
owner.ClearItem();
}
public IEnumerator GetEnumerator()
{
return items.GetEnumerator();
}
ICollection Members#region ICollection Members
void ICollection.CopyTo(Array array, int index)
{
for (IEnumerator e = this.GetEnumerator(); e.MoveNext();)
array.SetValue(e.Current, index++);
}
bool ICollection.IsSynchronized
{
get { return false; }
}
object ICollection.SyncRoot
{
get { return this; }
}
#endregion
IList Members#region IList Members
object IList.this[int index]
{
get { return this[index]; }
set { this[index] = (ListItem)value; }
}
bool IList.Contains(object item)
{
return Contains((ListItem)item);
}
int IList.Add(object item)
{
return Add((ListItem)item);
}
bool IList.IsFixedSize
{
get {return false;}
}
int IList.IndexOf(object item)
{
return IndexOf((ListItem)item);
}
void IList.Insert(int index, object item)
{
Insert(index, (ListItem)item);
}
void IList.Remove(object item)
{
Remove((ListItem)item);
}
void IList.RemoveAt(int index)
{
RemoveAt(index);
}
void IList.Clear()
{
Clear();
}
bool IList.IsReadOnly
{
get{return false;}
}
#endregion
}
#endregion
CheckedListItemCollection#region CheckedListItemCollection
public class CheckedListItemCollection : CollectionBase
{
public void Add(ListItem item)
{
List.Add(item);
}
public void Remove(ListItem item)
{
List.Remove(item);
}
public ListItem this[int index]
{
get{
if(index < 0 || index > List.Count - 1)
throw new ArgumentNullException("索引值超出集合的范围");
return List[index] as ListItem;
}
}
}
#endregion
ComboBoxWindow#region ComboBoxWindow
internal class ComboBoxWindow : NativeWindow
{
private System.Windows.Forms.ComboBox.ObjectCollection items;
private IntPtr handle = IntPtr.Zero;
internal ComboBoxWindow(System.Windows.Forms.ComboBox.ObjectCollection items, IntPtr handle)
{
this.items = items;
this.handle = handle;
}
protected override void WndProc(ref Message m)
{
if(m.Msg == 0x201)//WM_LBUTTONDOWN
{
Win32.RECT rect = new Win32.RECT();
Win32.GetClientRect(m.HWnd, ref rect);
Win32.POINTAPI pt = new Win32.POINTAPI();
pt.x = Win32.LOWORD(m.LParam.ToInt32());
pt.y = Win32.HIWORD(m.LParam.ToInt32());
//如果在区域内
if(new Rectangle(rect.Left, rect.Top,rect.Left + rect.Right, rect.Top + rect.Bottom).Contains(new Point(pt.x, pt.y)))
{
int nItemHeight = Win32.SendMessage(m.HWnd, 0x1A1, 0, 0);//LB_GETITEMHEIGHT
//获得顶部项的索引
int nTopIndex = Win32.SendMessage(m.HWnd, 0x18E, 0, 0); //LB_GETTOPINDEX
int nIndex = nTopIndex + pt.y / nItemHeight;
if (items.Count == 0)
{
base.WndProc (ref m);
return;
}
//判断是否在复选框处
if(pt.x > ((ListItem)items[nIndex]).checkboxLeft && pt.x < ((ListItem)items[nIndex]).checkboxLeft + 16)
{
Win32.RECT re = new Win32.RECT();
//取位置
Win32.SendMessage(m.HWnd, 0x198, nIndex, ref re); //LB_GETITEMRECT
//重画
Win32.InvalidateRect(m.HWnd, re, 0);
//发送自定消息勾选复选框
Win32.SendMessage(handle, 0x400 + 0x105, nIndex, 0);
return;
}
}
}
base.WndProc (ref m);
}
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Drawing;
namespace FaibClass.Windows.Forms
{
[Serializable,
DesignTimeVisible(false),
DefaultProperty("Text"),
TypeConverter(typeof(ListItemConverter))]
public class ListItem : Component
{
// Fields
private int m_ImageIndex = -1;
private int m_Index;
private object m_Tag;
private string m_Text = string.Empty;
private object m_Value;
private bool m_Checked = false;
private Font m_Font;
private ComboBox comboBox;
private ComboBox.ListItemCollection m_items = new ComboBox.ListItemCollection();
private Color m_ForeColor, m_BackColor;
private object parent;
internal int id = -1;
internal int checkboxLeft = -1;
internal byte level = 0;
// Methods
public ListItem()
{
this.m_ImageIndex = -1;
}
public ListItem(string Text) : this (Text, Text, -1)
{
}
public ListItem(string Text, int ImageIndex) : this (Text, Text, ImageIndex)
{
}
public ListItem(string Text, object Value) : this (Text, Value, -1)
{
}
public ListItem(string Text, object Value, int ImageIndex)
{
this.m_Text = Text;
this.m_Value = Value;
this.m_ImageIndex = ImageIndex;
}
internal ListItem CloneData()
{
ListItem lt = new ListItem();
lt.Text = this.Text;
lt.ImageIndex = this.ImageIndex;
lt.Font = this.Font;
lt.ForeColor = this.ForeColor;
lt.BackColor = this.BackColor;
lt.Checked = this.Checked;
lt.id = id;
return lt;
}
public override string ToString()
{
return this.Text;
}
internal void Host(ComboBox comboBox)
{
this.comboBox = comboBox;
m_items.Host(comboBox, this);
m_items.level = (byte)(level + 1);
}
Properties#region Properties
[Category("Appearance"),
Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design", typeof(UITypeEditor)),
TypeConverter(typeof(ImageIndexConverter)),
DefaultValue(-1)]
public int ImageIndex
{
get
{
return this.m_ImageIndex;
}
set
{
this.m_ImageIndex = value;
if(comboBox != null && id != -1)
comboBox.setImageIndex(id, value);
}
}
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int Index
{
get
{
return this.m_Index;
}
set
{
this.m_Index = value;
}
}
[Browsable(true),
TypeConverter(typeof(StringConverter)),
DefaultValue((string)null),
Description("获取或设置包含数据的对象以与该项关联。")]
public object Tag
{
get
{
return this.m_Tag;
}
set
{
this.m_Tag = value;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
Localizable(true),
Description("获取或设置该项显示的文本。")]
public string Text
{
get
{
return this.m_Text;
}
set
{
this.m_Text = value;
if(comboBox != null && id != -1)
comboBox.setText(id, value);
}
}
[Description("获取或设置该项显示的值。"),
TypeConverter(typeof(StringConverter)),
DefaultValue((string)null),
Browsable(true)]
public object Value
{
get
{
return this.m_Value;
}
set
{
this.m_Value = value;
}
}
[Browsable(false)]
public ImageList ImageList
{
get
{
if(this.comboBox != null)
{
return this.comboBox.ImageList;
}
return null;
}
}
[Category("Appearance")]
public Font Font
{
get{
if(m_Font == null)
{
if(comboBox != null)
{
return comboBox.Font;
}
return Control.DefaultFont;
}
return m_Font;
}
set{m_Font = value;}
}
[Category("Appearance")]
public Color ForeColor
{
get
{
if(m_ForeColor == Color.Empty)
{
if(comboBox != null)
{
return comboBox.ForeColor;
}
return Control.DefaultForeColor;
}
return m_ForeColor;
}
set{
m_ForeColor = value;
if(comboBox != null && id != -1)
comboBox.setForeColor(id, value);
}
}
[Category("Appearance")]
public Color BackColor
{
get
{
if(m_BackColor == Color.Empty)
{
if(comboBox != null)
{
return comboBox.BackColor;
}
return Control.DefaultBackColor;
}
return m_BackColor;
}
set{
m_BackColor = value;
if(comboBox != null && id != -1)
comboBox.setBackColor(id, value);
}
}
[Category("Behavior"),
DefaultValue(false)]
public bool Checked
{
get{return m_Checked;}
set{
m_Checked = value;
if(comboBox != null && id != -1)
comboBox.setChecked(id, value);
}
}
[Category("Behavior"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Editor(typeof(CollectionEditor), typeof(UITypeEditor)),
MergableProperty(false),
Description("组合框中的项。"),
DefaultValue((string)null),
Browsable(false),
Localizable(true)]
public ComboBox.ListItemCollection Items
{
get
{
return this.m_items;
}
set
{
m_items = value;
}
}
internal object Parent
{
get{return parent;}
set{parent = value;}
}
#endregion
}
}
using System;
using System.Drawing.Design;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Reflection;
namespace FaibClass.Windows.Forms
{
internal sealed class ListItemConverter: ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if(destinationType == typeof(System.ComponentModel.Design.Serialization .InstanceDescriptor))
return true;
else
return base.CanConvertTo (context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if(destinationType == typeof(System.ComponentModel.Design.Serialization.InstanceDescriptor))
{
Type valueType = value.GetType();
ConstructorInfo ci = valueType.GetConstructor(System.Type.EmptyTypes);
ListItem item = (ListItem)value;
return new InstanceDescriptor(ci,null,false);
}
else
return base.ConvertTo (context, culture, value, destinationType);
}
}
}
using System;
using System.Runtime.InteropServices;
namespace FaibClass.Windows.Forms
{
internal class Win32
{
[DllImport("user32", EntryPoint="GetClientRect")]
public static extern int GetClientRect (
IntPtr hwnd,
ref RECT lpRect
);
[DllImport("user32", EntryPoint="GetWindowRect")]
public static extern int GetWindowRect (
IntPtr hwnd,
ref RECT lpRect
);
[DllImport("user32", EntryPoint="PtInRect")]
public static extern int PtInRect (
ref RECT lpRect,
ref POINTAPI pt
);
[DllImport("user32", EntryPoint="SendMessage")]
public static extern int SendMessage (
IntPtr hwnd,
int wMsg,
int wParam,
int lParam
);
[DllImport("user32", EntryPoint="SendMessage")]
public static extern int SendMessage (
IntPtr hwnd,
int wMsg,
int wParam,
ref RECT rect
);
[DllImport("user32", EntryPoint="InvalidateRect")]
public static extern int InvalidateRect (
IntPtr hwnd,
RECT lpRect,
int bErase
);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINTAPI
{
public int x;
public int y;
}
public static int HIWORD(int lparam)
{
return ((lparam >> 16) & 0xffff);
}
public static int LOWORD(int lparam)
{
return (lparam & 0xffff);
}
public static int MakeLParam(int LoWord, int HiWord)
{
return (HiWord << 16) | (LoWord & 0xffff);
}
}
}
浙公网安备 33010602011771号