/******************************************************************************
* SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
* CopyRight (C) 2012-2020 ShenYongHua(沈永华).
* QQ群:56829229 QQ:17612584 EMail:SunnyUI@qq.com
*
* Blog: https://www.cnblogs.com/yhuse
* Gitee: https://gitee.com/yhuse/SunnyUI
* GitHub: https://github.com/yhuse/SunnyUI
*
* SunnyUI.dll can be used for free under the GPL-3.0 license.
* If you use this code, please keep this note.
* 如果您使用此代码,请保留此说明。
******************************************************************************
* 文件名称: UIImageListBox.cs
* 文件说明: 图片列表框
* 当前版本: V2.2
* 创建日期: 2020-01-01
*
* 2020-01-01: V2.2.0 增加文件说明
* 2020-04-25: V2.2.4 更新主题配置类
* 2020-05-21: V2.2.5 增加鼠标滑过高亮
******************************************************************************/
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.IO;
using System.Windows.Forms;
namespace Sunny.UI
{
[DefaultEvent("ItemClick")]
public sealed partial class UIImageListBox : UIPanel
{
private readonly ImageListBox listbox = new ImageListBox();
private readonly UIScrollBar bar = new UIScrollBar();
public UIImageListBox()
{
InitializeComponent();
ShowText = false;
Padding = new Padding(2);
bar.ValueChanged += Bar_ValueChanged;
bar.Width = SystemInformation.VerticalScrollBarWidth + 2;
bar.Parent = this;
bar.Dock = DockStyle.None;
bar.Style = UIStyle.Custom;
bar.Visible = false;
listbox.Parent = this;
listbox.Dock = DockStyle.Fill;
listbox.Show();
listbox.Bar = bar;
listbox.SelectedIndexChanged += Listbox_SelectedIndexChanged;
listbox.SelectedValueChanged += Listbox_SelectedValueChanged;
listbox.Click += Listbox_Click;
listbox.DoubleClick += Listbox_DoubleClick;
listbox.BeforeDrawItem += Listbox_BeforeDrawItem;
}
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
listbox.Font = Font;
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
bar.Top = 2;
bar.Height = Height - 4;
bar.Left = Width - bar.Width - 2;
}
private void Listbox_BeforeDrawItem(object sender, ListBox.ObjectCollection items, DrawItemEventArgs e)
{
if (Items.Count != LastCount)
{
listbox.SetScrollInfo();
LastCount = Items.Count;
ItemsCountChange?.Invoke(this, null);
}
}
private void Listbox_DoubleClick(object sender, EventArgs e)
{
if (SelectedItem != null)
ItemDoubleClick?.Invoke(sender, e);
}
private void Listbox_Click(object sender, EventArgs e)
{
if (SelectedItem != null)
ItemClick?.Invoke(sender, e);
}
[Browsable(false)]
public int Count => Items.Count;
public event EventHandler ItemClick;
public event EventHandler ItemDoubleClick;
public event EventHandler ItemsCountChange;
public event EventHandler SelectedIndexChanged;
public event EventHandler SelectedValueChanged;
private void Listbox_SelectedValueChanged(object sender, EventArgs e)
{
SelectedValueChanged?.Invoke(sender, e);
Text = listbox.SelectedItem?.ToString();
}
private void Listbox_SelectedIndexChanged(object sender, EventArgs e)
{
SelectedIndexChanged?.Invoke(sender, e);
}
[DefaultValue(100)]
[Description("列表项高度"), Category("SunnyUI")]
public int ItemHeight
{
get => listbox.ItemHeight;
set => listbox.ItemHeight = value;
}
[DefaultValue(4)]
[Description("图片文字间间隔"), Category("SunnyUI")]
public int ImageInterval
{
get => listbox.ImageInterval;
set => listbox.ImageInterval = value;
}
[DefaultValue(true)]
[Description("显示说明文字"), Category("SunnyUI")]
public bool ShowDescription
{
get => listbox.ShowDescription;
set => listbox.ShowDescription = value;
}
public override void SetStyleColor(UIBaseStyle uiColor)
{
base.SetStyleColor(uiColor);
if (uiColor.IsCustom()) return;
if (bar != null)
{
bar.ForeColor = uiColor.PrimaryColor;
bar.HoverColor = uiColor.ButtonFillHoverColor;
bar.PressColor = uiColor.ButtonFillPressColor;
bar.FillColor = Color.White;
}
hoverColor = uiColor.TreeViewHoverColor;
if (listbox != null)
{
listbox.HoverColor = hoverColor;
listbox.SetStyleColor(uiColor);
}
}
private int LastCount;
private int lastBarValue = -1;
private void Bar_ValueChanged(object sender, EventArgs e)
{
if (listbox != null)
{
if (bar.Value != lastBarValue)
{
ScrollBarInfo.SetScrollValue(listbox.Handle, bar.Value);
lastBarValue = bar.Value;
}
}
}
protected override void OnRadiusChanged(int value)
{
base.OnRadiusChanged(value);
Padding = new Padding(Math.Max(2, value / 2));
}
protected override void OnPaintFill(Graphics g, GraphicsPath path)
{
g.Clear(Color.White);
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Localizable(true)]
[Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
[MergableProperty(false)]
[Browsable(false)]
[Description("列表项"), Category("SunnyUI")]
public ListBox.ObjectCollection Items => listbox.Items;
///
/// 增加图片
///
/// 图片对象
public void AddImage(ImageListItem record)
{
Items.Add(record);
}
///
/// 增加图片
///
/// 图片路径
/// 图片描述
public void AddImage(string imagePath, string description = "")
{
AddImage(new ImageListItem(imagePath, description));
}
public void SelectedFirst()
{
listbox.SelectedFirst();
}
[DefaultValue(typeof(Color), "80, 160, 255")]
[Description("选中项背景颜色"), Category("SunnyUI")]
public Color ItemSelectBackColor
{
get => listbox.ItemSelectBackColor;
set => listbox.ItemSelectBackColor = value;
}
[DefaultValue(typeof(Color), "White")]
[Description("选中项字体颜色"), Category("SunnyUI")]
public Color ItemSelectForeColor
{
get => listbox.ItemSelectForeColor;
set => listbox.ItemSelectForeColor = value;
}
[Browsable(false)]
[DefaultValue(-1)]
public int SelectedIndex
{
get => listbox.SelectedIndex;
set => listbox.SelectedIndex = value;
}
[Browsable(false)]
[DefaultValue(null)]
public ImageListItem SelectedItem
{
get => listbox.SelectedItem as ImageListItem;
set => listbox.SelectedItem = value;
}
[Browsable(false)]
[DefaultValue(null)]
public object SelectedValue
{
get => listbox.SelectedValue;
set => listbox.SelectedValue = value;
}
private Color hoverColor = Color.FromArgb(155, 200, 255);
[DefaultValue(typeof(Color), "155, 200, 255")]
[Description("鼠标移上颜色"), Category("SunnyUI")]
public Color HoverColor
{
get => hoverColor;
set
{
hoverColor = value;
listbox.HoverColor = hoverColor;
_style = UIStyle.Custom;
}
}
[ToolboxItem(false)]
private sealed class ImageListBox : ListBox, IStyleInterface
{
private UIScrollBar bar;
///
/// Tag字符串
///
[DefaultValue(null)]
[Description("获取或设置包含有关控件的数据的对象字符串"), Category("SunnyUI")]
public string TagString { get; set; }
public UIScrollBar Bar
{
get => bar;
set
{
bar = value;
SetScrollInfo();
}
}
public ImageListBox()
{
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
UpdateStyles();
BorderStyle = BorderStyle.None;
ForeColor = UIFontColor.Primary;
IntegralHeight = false;
ItemHeight = 100;
DrawMode = DrawMode.OwnerDrawFixed;
Version = UIGlobal.Version;
SetScrollInfo();
}
protected override void OnSizeChanged(EventArgs e)
{
if (Bar != null && Bar.Visible)
{
if (Bar.Value != 0)
{
ScrollBarInfo.SetScrollValue(Handle, Bar.Value);
}
}
//SetScrollInfo();
}
public void SetScrollInfo()
{
if (Bar == null)
{
return;
}
var si = ScrollBarInfo.GetInfo(Handle);
if (si.ScrollMax > 0)
{
Bar.Maximum = si.ScrollMax;
Bar.Visible = si.ScrollMax > 0 && si.nMax > 0 && si.nPage > 0;
Bar.Value = si.nPos;
}
else
{
Bar.Visible = false;
}
}
protected override void OnMeasureItem(MeasureItemEventArgs e)
{
e.ItemHeight = e.ItemHeight + ItemHeight;
}
///
/// 自定义主题风格
///
[DefaultValue(false)]
[Description("获取或设置可以自定义主题风格"), Category("SunnyUI")]
public bool StyleCustomMode { get; set; }
public string Version { get; }
private UIStyle _style = UIStyle.Blue;
private Color _itemSelectBackColor = UIColor.Blue;
private Color _itemSelectForeColor = Color.White;
private int imageInterval = 4;
private bool showDescription = true;
[Browsable(false)]
public int Count => Items.Count;
public void SelectedFirst()
{
if (Count > 0 && SelectedIndex < 0)
{
SelectedIndex = 0;
}
}
protected override void OnMouseWheel(MouseEventArgs e)
{
base.OnMouseWheel(e);
if (Bar != null && Bar.Visible)
{
var si = ScrollBarInfo.GetInfo(Handle);
int temp = Math.Abs(e.Delta / 120);
if (e.Delta > 10)
{
int nposnum = si.nPos - temp * SystemInformation.MouseWheelScrollLines;
ScrollBarInfo.SetScrollValue(Handle, nposnum >= si.nMin ? nposnum : 0);
}
else if (e.Delta < -10)
{
int nposnum = si.nPos + temp * SystemInformation.MouseWheelScrollLines;
ScrollBarInfo.SetScrollValue(Handle, nposnum <= si.nMax ? nposnum : si.nMax);
}
}
SetScrollInfo();
}
[DefaultValue(4)]
public int ImageInterval
{
get => imageInterval;
set
{
if (imageInterval != value)
{
imageInterval = value;
Invalidate();
}
}
}
[DefaultValue(true)]
public bool ShowDescription
{
get => showDescription;
set
{
if (showDescription != value)
{
showDescription = value;
Invalidate();
}
}
}
///
/// 主题样式
///
[DefaultValue(UIStyle.Blue), Description("主题样式"), Category("SunnyUI")]
public UIStyle Style
{
get => _style;
set => SetStyle(value);
}
public void SetStyle(UIStyle style)
{
SetStyleColor(UIStyles.GetStyleColor(style));
_style = style;
}
public void SetStyleColor(UIBaseStyle uiColor)
{
if (uiColor.IsCustom()) return;
ItemSelectBackColor = uiColor.ListItemSelectBackColor;
ItemSelectForeColor = uiColor.ListItemSelectForeColor;
Invalidate();
}
[Category("SunnyUI"), Description("The border color used to paint the control.")]
public Color ItemSelectBackColor
{
get => _itemSelectBackColor;
set
{
if (_itemSelectBackColor != value)
{
_itemSelectBackColor = value;
_style = UIStyle.Custom;
if (DesignMode)
Invalidate();
}
}
}
[Category("SunnyUI"), Description("The border color used to paint the control.")]
public Color ItemSelectForeColor
{
get => _itemSelectForeColor;
set
{
if (_itemSelectForeColor != value)
{
_itemSelectForeColor = value;
_style = UIStyle.Custom;
if (DesignMode)
Invalidate();
}
}
}
///
/// 增加图片
///
/// 图片对象
public void AddImage(ImageListItem record)
{
Items.Add(record);
}
///
/// 增加图片
///
/// 图片路径
/// 图片描述
public void AddImage(string imagePath, string description = "")
{
AddImage(new ImageListItem(imagePath, description));
}
public delegate void OnBeforeDrawItem(object sender, ObjectCollection items, DrawItemEventArgs e);
public event OnBeforeDrawItem BeforeDrawItem;
protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);
BeforeDrawItem?.Invoke(this, Items, e);
if (Items.Count == 0)
{
return;
}
bool otherState = e.State == DrawItemState.Grayed || e.State == DrawItemState.HotLight;
if (!otherState)
{
e.DrawBackground();
}
if (e.Index < 0 || e.Index >= Items.Count)
{
return;
}
bool isSelected = (e.State & DrawItemState.Selected) == DrawItemState.Selected;
Color backColor = isSelected ? ItemSelectBackColor : BackColor;
Color foreColor = isSelected ? ItemSelectForeColor : ForeColor;
Rectangle rect = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width - 1, e.Bounds.Height - 1);
if (!otherState)
{
e.Graphics.FillRectangle(BackColor, e.Bounds);
e.Graphics.FillRoundRectangle(backColor, rect, 5);
}
else
{
if (e.State == DrawItemState.Grayed)
{
backColor = BackColor;
foreColor = ForeColor;
}
if (e.State == DrawItemState.HotLight)
{
backColor = HoverColor;
foreColor = ForeColor;
}
e.Graphics.FillRectangle(BackColor, e.Bounds);
e.Graphics.FillRoundRectangle(backColor, rect, 5);
}
Graphics g = e.Graphics;
Matrix oldTransform = g.Transform;
Matrix newTransform = oldTransform.Clone();
newTransform.Translate(e.Bounds.X, e.Bounds.Y);
g.Transform = newTransform;
ImageListItem item = (ImageListItem)Items[e.Index];
SizeF sf = g.MeasureString("ImageListBox", Font);
int thumbnailSize = ShowDescription ? ((int)(ItemHeight - ImageInterval - sf.Height)) : (ItemHeight - ImageInterval * 2);
if (File.Exists(item.ImagePath))
{
Image image = new Bitmap(item.ImagePath);
if (image.Width <= thumbnailSize && image.Height <= thumbnailSize)
{
g.DrawImage(image, new Rectangle(ImageInterval, ImageInterval, image.Width, image.Height));
}
else
{
float scale = thumbnailSize * 1.0f / image.Height;
g.DrawImage(image, new Rectangle(ImageInterval, ImageInterval, (int)(image.Width * scale), (int)(image.Height * scale)));
}
image.Dispose();
}
if (ShowDescription && !string.IsNullOrEmpty(item.Description))
{
g.DrawString(item.Description, e.Font, foreColor, new Point(ImageInterval, thumbnailSize + ImageInterval));
}
g.Transform = oldTransform;
}
private Color hoverColor = Color.FromArgb(155, 200, 255);
[DefaultValue(typeof(Color), "155, 200, 255")]
public Color HoverColor
{
get => hoverColor;
set
{
hoverColor = value;
_style = UIStyle.Custom;
}
}
private int lastIndex = -1;
private int mouseIndex = -1;
[Browsable(false)]
public int MouseIndex
{
get => mouseIndex;
set
{
if (mouseIndex != value)
{
if (lastIndex >= 0 && lastIndex != SelectedIndex)
{
OnDrawItem(new DrawItemEventArgs(this.CreateGraphics(), Font, GetItemRectangle(lastIndex), lastIndex, DrawItemState.Grayed));
}
mouseIndex = value;
if (mouseIndex >= 0 && mouseIndex != SelectedIndex)
{
OnDrawItem(new DrawItemEventArgs(this.CreateGraphics(), Font, GetItemRectangle(value), value, DrawItemState.HotLight));
}
lastIndex = mouseIndex;
}
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
MouseIndex = IndexFromPoint(e.Location);
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
MouseIndex = -1;
}
}
public class ImageListItem
{
public string ImagePath { get; set; }
public string Description { get; set; }
public ImageListItem(string imagePath, string description = "")
{
ImagePath = imagePath;
Description = description;
}
public override string ToString()
{
return ImagePath;
}
}
}
}