using System;
|
using System.Collections;
|
using System.Collections.Generic;
|
using System.ComponentModel;
|
using System.Data;
|
using System.Drawing;
|
using System.Windows.Forms;
|
using WinApi;
|
|
|
|
namespace DPumpHydr.WinFrmUI.WenSkin.Controls
|
{
|
[ToolboxBitmap(typeof(ListView))]
|
public partial class WenListView : ListView
|
{
|
public WenListView()
|
{
|
this.View = View.Details;
|
this.FullRowSelect = true;
|
|
base.SetStyle(
|
//ControlStyles.UserPaint |
|
ControlStyles.DoubleBuffer |
|
ControlStyles.OptimizedDoubleBuffer |
|
ControlStyles.AllPaintingInWmPaint |
|
ControlStyles.ResizeRedraw |
|
ControlStyles.SupportsTransparentBackColor, true);
|
base.UpdateStyles();
|
OwnerDraw = true;
|
this.BackColor = Color.FromArgb(37, 37, 38);
|
this.BorderStyle = BorderStyle.FixedSingle;
|
itemlistInstance();
|
this.ForeColor = Color.White;
|
}
|
|
#region 私有属性
|
|
private int itemHeight = 30;
|
private Size itemIconSize = new Size(30, 30);
|
private WenListViewColumnHeaderCollection columns;
|
|
private WenListViewItemCollection items;
|
|
#endregion
|
|
#region 公有属性
|
|
[Category("Wen"), Description("当imagelist无值 默认图标"), DefaultValue(null)]
|
public Image ItemIcon { get; set; }
|
|
[Category("Wen"), Description("没有图标情况,项高度"), DefaultValue(30)]
|
public int ItemHeight
|
{
|
get => itemHeight;
|
set
|
{
|
itemHeight = value;
|
itemIconSize = new Size(value, value);
|
itemlistInstance();
|
this.Invalidate();
|
}
|
}
|
|
public Color HeadColor { get; set; }
|
#endregion
|
|
#region 重写属性
|
|
[Category("Wen"), Description("是否显示复选框"), DefaultValue(false)]
|
public new bool CheckBoxes { get => base.CheckBoxes; set => base.CheckBoxes = value; }
|
public new ImageList SmallImageList { get; set; }
|
|
[Category("Wen"), Description("项集合")]
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
public new WenListViewItemCollection Items => items ?? (items = new WenListViewItemCollection(this));
|
|
[Category("Wen"), Description("列集合")]
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
[Editor(typeof(Design.Editor.WenCollectionEditor), typeof(System.Drawing.Design.UITypeEditor))]
|
public new WenListViewColumnHeaderCollection Columns => columns ?? (columns = new WenListViewColumnHeaderCollection(this));
|
#endregion
|
|
#region 委托
|
|
public delegate void WenListViewItemEventHandler(object sender, WenListViewItemEventArgs e);
|
public class WenListViewItemEventArgs: EventArgs
|
{
|
public WenListViewItemEventArgs(WenListViewItem wenListViewItem)
|
{
|
WenListViewItem = wenListViewItem;
|
}
|
|
public WenListViewItem WenListViewItem { get; set; }
|
}
|
|
[Category("Wen"), Description("Item 项鼠标点击事件")]
|
public event WenListViewItemEventHandler WenListViewItemClick;
|
|
#endregion
|
|
#region 绑定数据
|
|
|
private object dataSource { get; set; }
|
[Browsable(false)]
|
public object DataSource
|
{
|
get => dataSource;
|
set
|
{
|
if (value != null)
|
{
|
dataSource = value;
|
DataBind();
|
}
|
}
|
}
|
private void DataBind()
|
{
|
if (dataSource == null)
|
return;
|
this.Items.Clear();
|
|
switch (dataSource)
|
{
|
case DataSet ds:
|
DataBind(ds.Tables[0]);
|
break;
|
case DataTable dt:
|
DataBind(dt);
|
break;
|
case IList ilist:
|
{
|
foreach (var li in ilist)
|
{
|
WenListViewItem item = new WenListViewItem(this)
|
{
|
Tag = ilist,
|
ImageIndex = 0
|
};
|
foreach (WenColumnHeader cl in Columns)
|
{
|
List<System.Reflection.PropertyInfo> propertyInfos = new List<System.Reflection.PropertyInfo>(li.GetType().GetProperties());
|
string value = propertyInfos
|
.Find(a => a.Name.ToUpper() == cl.CloumnName.ToUpper())?.GetValue(li, null)?.ToString();
|
|
item.Cells.Add(cl.CloumnName, value);
|
|
if (Columns.IndexOf(cl) == 0)
|
item.Text = value;
|
else
|
item.SubItems.Add(value);
|
}
|
Items.Add(item);
|
}
|
break;
|
}
|
}
|
//绑定DataTable 数据
|
void DataBind(DataTable dt)
|
{
|
foreach (DataRow dr in dt.Rows)
|
{
|
WenListViewItem item = new WenListViewItem(this)
|
{
|
Tag = dr,
|
ImageIndex = 0
|
};
|
foreach (WenColumnHeader cl in Columns)
|
{
|
string value = dr[cl.CloumnName]?.ToString();
|
item.Cells.Add(cl.CloumnName,value);
|
|
if (Columns.IndexOf(cl) == 0)
|
item.Text = value;
|
else
|
item.SubItems.Add(value);
|
}
|
Items.Add(item);
|
}
|
}
|
}
|
|
private ImageList itemlistInstance()
|
{
|
ImageList imageList = new ImageList() { ImageSize = itemIconSize };
|
if (ItemIcon != null)
|
imageList.Images.Add(ItemIcon);
|
else
|
imageList.Images.Add(Properties.Resources.itemImage);
|
base.SmallImageList = imageList;
|
return imageList;
|
}
|
|
#endregion
|
|
#region 重绘项目
|
|
protected override void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e)
|
{
|
Graphics g = e.Graphics;
|
g.SetGDIHigh();
|
Rectangle rec = e.Bounds;
|
|
using Brush b = new SolidBrush(Color.FromArgb(45, 45, 48));
|
using Brush bstr = new SolidBrush(Color.FromArgb(199, 199, 199));
|
using Pen p = new Pen(Color.FromArgb(199, 199, 199));
|
|
//画背景
|
g.FillRectangle(b, new Rectangle(rec.X , rec.Y, rec.Width, rec.Height - 1));
|
//画分割线
|
g.DrawLine(p, rec.X + rec.Width-1, rec.Y, rec.X + rec.Width-1, rec.Y + rec.Height);
|
//画文字
|
g.DrawString(e.Header.Text, this.Font, bstr, rec, ControlHelper.StringConters);
|
}
|
protected override void OnDrawItem(DrawListViewItemEventArgs e)
|
{
|
Graphics g = e.Graphics;
|
g.ResetClip();
|
g.SetGDIHigh();
|
|
Rectangle rec = new Rectangle(0, e.Bounds.Y, this.Width, e.Bounds.Height);
|
using Pen pen = new Pen(Color.FromArgb(70, 70, 70));
|
g.DrawLine(pen, 0, rec.Y + rec.Height - 1, rec.Width, rec.Y + rec.Height - 1);
|
}
|
protected override void OnDrawSubItem(DrawListViewSubItemEventArgs e)
|
{
|
if (e.Item.ImageIndex < 0)
|
{
|
e.Item.ImageIndex = 0;
|
}
|
|
Graphics g = e.Graphics;
|
g.SetGDIHigh();
|
Rectangle rec = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width+1, e.Bounds.Height);
|
Rectangle recStr = rec;
|
|
g.SetClip(new Rectangle(rec.X, rec.Y+1, rec.Width, rec.Height - 3));
|
//当为最后一列数据时事件
|
if (e.ColumnIndex + 1 == this.Columns.Count)
|
{
|
g.SetClip(new Rectangle(rec.X, rec.Y + 1, rec.Width - 1, rec.Height - 3));
|
}
|
|
using Brush bSelected = new SolidBrush(Color.FromArgb(63, 63, 70));
|
using Brush bNone = new SolidBrush(Color.FromArgb(37,37,38));
|
|
DrawBackdrop(g, rec);
|
|
|
//画背景
|
void DrawBackdrop(Graphics g,Rectangle rec)
|
{
|
if (e.Item.Selected)
|
g.FillRectangle(bSelected, rec);//选中
|
else
|
g.FillRectangle(bNone, rec);//普通
|
}
|
|
//判定为第一列,画图标
|
using Brush brush = new SolidBrush(this.ForeColor);
|
|
Image image = e.Item.ImageList.Images[e.Item.ImageIndex];
|
|
//获取文字宽度
|
if (e.ColumnIndex == 0)
|
{
|
var numFormat = "d" + this.Items.Count.ToString().Length;
|
|
int indexWidth = TextRenderer.MeasureText((e.ItemIndex + 1).ToString(numFormat), e.Item.Font).Width + 2;
|
Rectangle recItemLine = new Rectangle(rec.X, rec.Y, indexWidth, rec.Height);
|
Rectangle recImage = new Rectangle(rec.X + indexWidth + 3,
|
rec.Y + (rec.Height - image.Height / 2) / 2,
|
image.Width / 2,
|
image.Height / 2);
|
//重置绘制文字区域
|
recStr = new Rectangle(recImage.X + recImage.Width + 3,
|
rec.Y,
|
rec.Width - recItemLine.Width - recImage.Width,
|
rec.Height);
|
if (this.CheckBoxes)
|
{
|
int checkWidth = 15;
|
recItemLine.Offset(checkWidth, 0);
|
recImage.Offset(checkWidth, 0);
|
recStr.Offset(checkWidth, 0);
|
|
int checkY = (rec.Height - checkWidth) / 2 + rec.Y;
|
|
if (e.Item.Checked)
|
{
|
CheckBoxRenderer.DrawCheckBox(g,
|
new Point(rec.X, checkY),
|
System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal);
|
}
|
else
|
{
|
CheckBoxRenderer.DrawCheckBox(g,
|
new Point(rec.X, checkY),
|
System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
|
}
|
}
|
g.DrawImage(image, recImage);
|
g.DrawString((e.ItemIndex + 1).ToString(numFormat), e.Item.Font, brush, recItemLine, ControlHelper.StringConters);
|
}
|
g.DrawString(e.SubItem.Text, e.Item.Font, brush, recStr, ControlHelper.StringConters);
|
}
|
|
#endregion
|
|
#region 项点击事件
|
protected override void OnMouseClick(MouseEventArgs e)
|
{
|
base.OnMouseClick(e);
|
if(GetItemAt(e.X, e.Y) is WenListViewItem item)
|
{
|
WenListViewItemClick?.Invoke(this, new WenListViewItemEventArgs(item));
|
}
|
}
|
|
#endregion
|
|
#region 空白区域美化
|
|
protected override void CreateHandle()
|
{
|
base.CreateHandle();
|
if (headerNativeWindow == null)
|
{
|
headerNativeWindow = new HeaderNativeWindow(this);
|
}
|
}
|
|
protected override void DestroyHandle()
|
{
|
base.DestroyHandle();
|
if (headerNativeWindow != null)
|
{
|
headerNativeWindow = null;
|
}
|
}
|
|
IntPtr headerWnd => WindowsAPI.FindWindowEx(this.Handle, IntPtr.Zero, "SysHeader32", null);
|
|
private Rectangle HeaderEndRect()
|
{
|
RECT rect = new RECT();
|
RECT rect2 = new RECT();
|
WindowsAPI.SendMessage(headerWnd, 0x1207, Columns.Count - 1, ref rect);
|
WindowsAPI.GetWindowRect(headerWnd, ref rect2);
|
return new Rectangle(rect.X + rect.Width , rect.Y, this.Width - (rect.X + rect.Width), rect.Height);
|
}
|
|
HeaderNativeWindow headerNativeWindow;
|
private class HeaderNativeWindow : NativeWindow
|
{
|
public WenListView owner;
|
IntPtr header;
|
public HeaderNativeWindow(WenListView owner)
|
{
|
this.owner = owner;
|
header = owner.headerWnd;
|
base.AssignHandle(header);
|
}
|
protected override void WndProc(ref Message m)
|
{
|
base.WndProc(ref m);
|
if (m.Msg == 0xF || m.Msg == 0x47)
|
{
|
IntPtr hdc = WindowsAPI.GetDC(m.HWnd);
|
try
|
{
|
using Graphics g = Graphics.FromHdc(hdc);
|
Rectangle rec = owner.HeaderEndRect();
|
owner.ReHeader(g, rec);
|
}
|
finally
|
{
|
WindowsAPI.ReleaseDC(m.HWnd, hdc);
|
}
|
}
|
}
|
}
|
private void ReHeader(Graphics g, Rectangle rec)
|
{
|
g.FillRectangle(new SolidBrush(Color.FromArgb(45, 45, 48)), rec);
|
}
|
#endregion
|
|
public class WenListViewColumnHeaderCollection : ColumnHeaderCollection
|
{
|
private readonly WenListView owner;
|
public WenListViewColumnHeaderCollection(WenListView owner) : base(owner)
|
{
|
this.owner = owner;
|
|
}
|
public new WenColumnHeader this[string key]
|
{
|
get
|
{
|
foreach (WenColumnHeader item in this)
|
{
|
if (item.Text.ToUpper() == key.ToUpper())
|
{
|
return item;
|
}
|
}
|
return null;
|
}
|
}
|
|
|
public void Add(WenColumnHeader value)
|
{
|
base.Add(value);
|
}
|
public void AddRange(WenColumnHeader[] values)
|
{
|
base.AddRange(values);
|
}
|
}
|
public class WenListViewItemCollection : ListViewItemCollection
|
{
|
public WenListViewItemCollection(WenListView owner) : base(owner)
|
{
|
}
|
|
public new WenListViewItem this[int index] => (base[index] is WenListViewItem item) ? item : null;
|
public void Add(WenListViewItem value)
|
{
|
base.Add(value);
|
}
|
}
|
|
}
|
}
|