* UIListBox: 增加滚动条颜色设置
This commit is contained in:
parent
1c97f500c6
commit
2ce63dfa9c
120
SunnyUI/Controls/UIImageListBox.resx
Normal file
120
SunnyUI/Controls/UIImageListBox.resx
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
@ -28,6 +28,7 @@
|
||||
* 2022-02-23: V3.1.1 按键上下移动选择项目时,滚动条跟随
|
||||
* 2022-03-08: V3.1.1 修复在选中某一项后,清除选中项需要两次操作
|
||||
* 2022-03-19: V3.1.1 重构主题配色
|
||||
* 2022-05-15: V3.1.8 增加滚动条颜色设置
|
||||
******************************************************************************/
|
||||
|
||||
using System;
|
||||
@ -93,6 +94,44 @@ namespace Sunny.UI
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
private Color scrollBarColor = Color.FromArgb(80, 160, 255);
|
||||
|
||||
/// <summary>
|
||||
/// 填充颜色,当值为背景色或透明色或空值则不填充
|
||||
/// </summary>
|
||||
[Description("填充颜色"), Category("SunnyUI")]
|
||||
[DefaultValue(typeof(Color), "80, 160, 255")]
|
||||
public Color ScrollBarColor
|
||||
{
|
||||
get => scrollBarColor;
|
||||
set
|
||||
{
|
||||
scrollBarColor = value;
|
||||
bar.HoverColor = bar.PressColor = bar.ForeColor = value;
|
||||
_style = UIStyle.Custom;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private Color scrollBarBackColor = Color.FromArgb(243, 249, 255);
|
||||
|
||||
/// <summary>
|
||||
/// 填充颜色,当值为背景色或透明色或空值则不填充
|
||||
/// </summary>
|
||||
[Description("填充颜色"), Category("SunnyUI")]
|
||||
[DefaultValue(typeof(Color), "243, 249, 255")]
|
||||
public Color ScrollBarBackColor
|
||||
{
|
||||
get => scrollBarBackColor;
|
||||
set
|
||||
{
|
||||
scrollBarBackColor = value;
|
||||
bar.FillColor = value;
|
||||
_style = UIStyle.Custom;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void Listbox_DrawItem(object sender, DrawItemEventArgs e)
|
||||
{
|
||||
DrawItem?.Invoke(sender, e);
|
||||
@ -393,12 +432,15 @@ namespace Sunny.UI
|
||||
public override void SetStyleColor(UIBaseStyle uiColor)
|
||||
{
|
||||
base.SetStyleColor(uiColor);
|
||||
|
||||
if (bar != null)
|
||||
{
|
||||
bar.ForeColor = uiColor.ListBarForeColor;
|
||||
bar.ForeColor = uiColor.PrimaryColor;
|
||||
bar.HoverColor = uiColor.ButtonFillHoverColor;
|
||||
bar.PressColor = uiColor.ButtonFillPressColor;
|
||||
bar.FillColor = uiColor.ListBarFillColor;
|
||||
bar.FillColor = uiColor.GridBarFillColor;
|
||||
scrollBarColor = uiColor.PrimaryColor;
|
||||
scrollBarBackColor = uiColor.GridBarFillColor;
|
||||
}
|
||||
|
||||
hoverColor = uiColor.ListItemHoverColor;
|
||||
@ -600,405 +642,4 @@ namespace Sunny.UI
|
||||
return GetItemText(Items[index]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ListBox
|
||||
/// </summary>
|
||||
[ToolboxItem(false)]
|
||||
public sealed class ListBoxEx : ListBox
|
||||
{
|
||||
private UIScrollBar bar;
|
||||
|
||||
/// <summary>
|
||||
/// Tag字符串
|
||||
/// </summary>
|
||||
[DefaultValue(null)]
|
||||
[Description("获取或设置包含有关控件的数据的对象字符串"), Category("SunnyUI")]
|
||||
public string TagString { get; set; }
|
||||
|
||||
[Browsable(false), DefaultValue(false)]
|
||||
public bool IsScaled { get; set; }
|
||||
|
||||
public void SetDPIScale()
|
||||
{
|
||||
if (!IsScaled)
|
||||
{
|
||||
this.SetDPIScaleFont();
|
||||
IsScaled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public UIScrollBar Bar
|
||||
{
|
||||
get => bar;
|
||||
set
|
||||
{
|
||||
bar = value;
|
||||
SetScrollInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public int Count => Items.Count;
|
||||
|
||||
public ListBoxEx()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
SetStyle(ControlStyles.DoubleBuffer, true);
|
||||
UpdateStyles();
|
||||
this.DoubleBuffered();
|
||||
|
||||
BorderStyle = BorderStyle.None;
|
||||
ForeColor = UIFontColor.Primary;
|
||||
IntegralHeight = false;
|
||||
Version = UIGlobal.Version;
|
||||
SetScrollInfo();
|
||||
}
|
||||
|
||||
public event EventHandler ItemsClear;
|
||||
public event EventHandler ItemsAdd;
|
||||
public event EventHandler ItemsRemove;
|
||||
public event EventHandler ItemsInsert;
|
||||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
if (IsDisposed || Disposing) return;
|
||||
if (IsHandleCreated)
|
||||
{
|
||||
const int LB_ADDSTRING = 0x0180;
|
||||
const int LB_INSERTSTRING = 0x0181;
|
||||
const int LB_DELETESTRING = 0x0182;
|
||||
const int LB_RESETCONTENT = 0x0184;
|
||||
if (m.Msg == LB_RESETCONTENT)
|
||||
{
|
||||
ItemsClear?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
if (m.Msg == LB_DELETESTRING)
|
||||
{
|
||||
ItemsRemove?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
if (m.Msg == LB_ADDSTRING)
|
||||
{
|
||||
ItemsAdd?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
if (m.Msg == LB_INSERTSTRING)
|
||||
{
|
||||
ItemsInsert?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
//if (m.Msg == Win32.User.WM_ERASEBKGND)
|
||||
//{
|
||||
// m.Result = IntPtr.Zero;
|
||||
// return;
|
||||
//}
|
||||
}
|
||||
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
|
||||
protected override void OnSizeChanged(EventArgs e)
|
||||
{
|
||||
if (Bar != null && Bar.Visible)
|
||||
{
|
||||
if (Bar.Value != 0)
|
||||
{
|
||||
ScrollBarInfo.SetScrollValue(Handle, Bar.Value);
|
||||
}
|
||||
}
|
||||
//SetScrollInfo();
|
||||
}
|
||||
|
||||
protected override void OnSelectedIndexChanged(EventArgs e)
|
||||
{
|
||||
base.OnSelectedIndexChanged(e);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public string Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义主题风格
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[Description("获取或设置可以自定义主题风格"), Category("SunnyUI")]
|
||||
public bool StyleCustomMode { get; set; }
|
||||
|
||||
#region 组件设计器生成的代码
|
||||
|
||||
/// <summary>
|
||||
/// 设计器支持所需的方法 - 不要
|
||||
/// 使用代码编辑器修改此方法的内容。
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
SuspendLayout();
|
||||
//
|
||||
// UIListBox
|
||||
//
|
||||
BorderStyle = BorderStyle.FixedSingle;
|
||||
DrawMode = DrawMode.OwnerDrawFixed;
|
||||
Font = UIFontColor.Font();
|
||||
IntegralHeight = false;
|
||||
ItemHeight = 25;
|
||||
Size = new Size(150, 200);
|
||||
ResumeLayout(false);
|
||||
}
|
||||
|
||||
#endregion 组件设计器生成的代码
|
||||
|
||||
private UIStyle _style = UIStyle.Blue;
|
||||
private Color _itemSelectBackColor = UIColor.Blue;
|
||||
private Color _itemSelectForeColor = Color.White;
|
||||
|
||||
/// <summary>
|
||||
/// 主题样式
|
||||
/// </summary>
|
||||
[DefaultValue(UIStyle.Blue), Description("主题样式"), Category("SunnyUI")]
|
||||
public UIStyle Style
|
||||
{
|
||||
get => _style;
|
||||
set => SetStyle(value);
|
||||
}
|
||||
|
||||
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.ScrollMax ? nposnum : si.ScrollMax);
|
||||
}
|
||||
SetScrollInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetStyle(UIStyle style)
|
||||
{
|
||||
if (!style.IsCustom())
|
||||
{
|
||||
SetStyleColor(style.Colors());
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
_style = style;
|
||||
}
|
||||
|
||||
public void SetStyleColor(UIBaseStyle uiColor)
|
||||
{
|
||||
ItemSelectBackColor = uiColor.ListItemSelectBackColor;
|
||||
ItemSelectForeColor = uiColor.ListItemSelectForeColor;
|
||||
}
|
||||
|
||||
[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 delegate void OnBeforeDrawItem(object sender, ObjectCollection items, DrawItemEventArgs e);
|
||||
|
||||
public event OnBeforeDrawItem BeforeDrawItem;
|
||||
|
||||
public event OnBeforeDrawItem AfterDrawItem;
|
||||
|
||||
private StringAlignment textAlignment = StringAlignment.Near;
|
||||
|
||||
public StringAlignment TextAlignment
|
||||
{
|
||||
get => textAlignment;
|
||||
set
|
||||
{
|
||||
textAlignment = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDrawItem(DrawItemEventArgs 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;
|
||||
}
|
||||
|
||||
StringFormat sStringFormat = new StringFormat();
|
||||
sStringFormat.LineAlignment = StringAlignment.Center;
|
||||
sStringFormat.Alignment = textAlignment;
|
||||
|
||||
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);
|
||||
string showText = DisplayMember.IsNullOrEmpty() ? Items[e.Index].ToString() : GetItemText(Items[e.Index]);
|
||||
|
||||
if (!otherState)
|
||||
{
|
||||
e.Graphics.FillRectangle(BackColor, e.Bounds);
|
||||
e.Graphics.FillRectangle(backColor, rect);
|
||||
e.Graphics.DrawString(showText, e.Font, foreColor, e.Bounds, sStringFormat);
|
||||
}
|
||||
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.FillRectangle(backColor, rect);
|
||||
e.Graphics.DrawString(showText, e.Font, foreColor, e.Bounds, sStringFormat);
|
||||
}
|
||||
|
||||
AfterDrawItem?.Invoke(this, Items, e);
|
||||
|
||||
base.OnDrawItem(e);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMeasureItem(MeasureItemEventArgs e)
|
||||
{
|
||||
base.OnMeasureItem(e);
|
||||
e.ItemHeight += ItemHeight;
|
||||
}
|
||||
|
||||
public void SelectedFirst()
|
||||
{
|
||||
if (Items.Count > 0 && SelectedIndex < 0)
|
||||
{
|
||||
SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private int lastIndex = -1;
|
||||
private int mouseIndex = -1;
|
||||
|
||||
[Browsable(false)]
|
||||
public int MouseIndex
|
||||
{
|
||||
get => mouseIndex;
|
||||
set
|
||||
{
|
||||
if (mouseIndex != value)
|
||||
{
|
||||
if (lastIndex >= 0 && lastIndex >= 0 && lastIndex < Items.Count && lastIndex != SelectedIndex)
|
||||
{
|
||||
OnDrawItem(new DrawItemEventArgs(CreateGraphics(), Font, GetItemRectangle(lastIndex), lastIndex, DrawItemState.Grayed));
|
||||
}
|
||||
|
||||
mouseIndex = value;
|
||||
if (mouseIndex >= 0 && mouseIndex >= 0 && mouseIndex < Items.Count && mouseIndex != SelectedIndex)
|
||||
{
|
||||
OnDrawItem(new DrawItemEventArgs(CreateGraphics(), Font, GetItemRectangle(value), value, DrawItemState.HotLight));
|
||||
}
|
||||
|
||||
lastIndex = mouseIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
if (SelectionMode != SelectionMode.One) return;
|
||||
MouseIndex = IndexFromPoint(e.Location);
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
if (SelectionMode != SelectionMode.One) return;
|
||||
MouseIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
408
SunnyUI/Controls/UIListBoxEx.cs
Normal file
408
SunnyUI/Controls/UIListBoxEx.cs
Normal file
@ -0,0 +1,408 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Sunny.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// ListBox
|
||||
/// </summary>
|
||||
[ToolboxItem(false)]
|
||||
internal sealed class ListBoxEx : ListBox
|
||||
{
|
||||
private UIScrollBar bar;
|
||||
|
||||
/// <summary>
|
||||
/// Tag字符串
|
||||
/// </summary>
|
||||
[DefaultValue(null)]
|
||||
[Description("获取或设置包含有关控件的数据的对象字符串"), Category("SunnyUI")]
|
||||
public string TagString { get; set; }
|
||||
|
||||
[Browsable(false), DefaultValue(false)]
|
||||
public bool IsScaled { get; set; }
|
||||
|
||||
public void SetDPIScale()
|
||||
{
|
||||
if (!IsScaled)
|
||||
{
|
||||
this.SetDPIScaleFont();
|
||||
IsScaled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public UIScrollBar Bar
|
||||
{
|
||||
get => bar;
|
||||
set
|
||||
{
|
||||
bar = value;
|
||||
SetScrollInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public int Count => Items.Count;
|
||||
|
||||
public ListBoxEx()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
SetStyle(ControlStyles.DoubleBuffer, true);
|
||||
UpdateStyles();
|
||||
this.DoubleBuffered();
|
||||
|
||||
BorderStyle = BorderStyle.None;
|
||||
ForeColor = UIFontColor.Primary;
|
||||
IntegralHeight = false;
|
||||
Version = UIGlobal.Version;
|
||||
SetScrollInfo();
|
||||
}
|
||||
|
||||
public event EventHandler ItemsClear;
|
||||
public event EventHandler ItemsAdd;
|
||||
public event EventHandler ItemsRemove;
|
||||
public event EventHandler ItemsInsert;
|
||||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
if (IsDisposed || Disposing) return;
|
||||
if (IsHandleCreated)
|
||||
{
|
||||
const int LB_ADDSTRING = 0x0180;
|
||||
const int LB_INSERTSTRING = 0x0181;
|
||||
const int LB_DELETESTRING = 0x0182;
|
||||
const int LB_RESETCONTENT = 0x0184;
|
||||
if (m.Msg == LB_RESETCONTENT)
|
||||
{
|
||||
ItemsClear?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
if (m.Msg == LB_DELETESTRING)
|
||||
{
|
||||
ItemsRemove?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
if (m.Msg == LB_ADDSTRING)
|
||||
{
|
||||
ItemsAdd?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
if (m.Msg == LB_INSERTSTRING)
|
||||
{
|
||||
ItemsInsert?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
//if (m.Msg == Win32.User.WM_ERASEBKGND)
|
||||
//{
|
||||
// m.Result = IntPtr.Zero;
|
||||
// return;
|
||||
//}
|
||||
}
|
||||
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
|
||||
protected override void OnSizeChanged(EventArgs e)
|
||||
{
|
||||
if (Bar != null && Bar.Visible)
|
||||
{
|
||||
if (Bar.Value != 0)
|
||||
{
|
||||
ScrollBarInfo.SetScrollValue(Handle, Bar.Value);
|
||||
}
|
||||
}
|
||||
//SetScrollInfo();
|
||||
}
|
||||
|
||||
protected override void OnSelectedIndexChanged(EventArgs e)
|
||||
{
|
||||
base.OnSelectedIndexChanged(e);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public string Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义主题风格
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[Description("获取或设置可以自定义主题风格"), Category("SunnyUI")]
|
||||
public bool StyleCustomMode { get; set; }
|
||||
|
||||
#region 组件设计器生成的代码
|
||||
|
||||
/// <summary>
|
||||
/// 设计器支持所需的方法 - 不要
|
||||
/// 使用代码编辑器修改此方法的内容。
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
SuspendLayout();
|
||||
//
|
||||
// UIListBox
|
||||
//
|
||||
BorderStyle = BorderStyle.FixedSingle;
|
||||
DrawMode = DrawMode.OwnerDrawFixed;
|
||||
Font = UIFontColor.Font();
|
||||
IntegralHeight = false;
|
||||
ItemHeight = 25;
|
||||
Size = new Size(150, 200);
|
||||
ResumeLayout(false);
|
||||
}
|
||||
|
||||
#endregion 组件设计器生成的代码
|
||||
|
||||
private UIStyle _style = UIStyle.Blue;
|
||||
private Color _itemSelectBackColor = UIColor.Blue;
|
||||
private Color _itemSelectForeColor = Color.White;
|
||||
|
||||
/// <summary>
|
||||
/// 主题样式
|
||||
/// </summary>
|
||||
[DefaultValue(UIStyle.Blue), Description("主题样式"), Category("SunnyUI")]
|
||||
public UIStyle Style
|
||||
{
|
||||
get => _style;
|
||||
set => SetStyle(value);
|
||||
}
|
||||
|
||||
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.ScrollMax ? nposnum : si.ScrollMax);
|
||||
}
|
||||
SetScrollInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetStyle(UIStyle style)
|
||||
{
|
||||
if (!style.IsCustom())
|
||||
{
|
||||
SetStyleColor(style.Colors());
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
_style = style;
|
||||
}
|
||||
|
||||
public void SetStyleColor(UIBaseStyle uiColor)
|
||||
{
|
||||
ItemSelectBackColor = uiColor.ListItemSelectBackColor;
|
||||
ItemSelectForeColor = uiColor.ListItemSelectForeColor;
|
||||
}
|
||||
|
||||
[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 delegate void OnBeforeDrawItem(object sender, ObjectCollection items, DrawItemEventArgs e);
|
||||
|
||||
public event OnBeforeDrawItem BeforeDrawItem;
|
||||
|
||||
public event OnBeforeDrawItem AfterDrawItem;
|
||||
|
||||
private StringAlignment textAlignment = StringAlignment.Near;
|
||||
|
||||
public StringAlignment TextAlignment
|
||||
{
|
||||
get => textAlignment;
|
||||
set
|
||||
{
|
||||
textAlignment = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDrawItem(DrawItemEventArgs 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;
|
||||
}
|
||||
|
||||
StringFormat sStringFormat = new StringFormat();
|
||||
sStringFormat.LineAlignment = StringAlignment.Center;
|
||||
sStringFormat.Alignment = textAlignment;
|
||||
|
||||
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);
|
||||
string showText = DisplayMember.IsNullOrEmpty() ? Items[e.Index].ToString() : GetItemText(Items[e.Index]);
|
||||
|
||||
if (!otherState)
|
||||
{
|
||||
e.Graphics.FillRectangle(BackColor, e.Bounds);
|
||||
e.Graphics.FillRectangle(backColor, rect);
|
||||
e.Graphics.DrawString(showText, e.Font, foreColor, e.Bounds, sStringFormat);
|
||||
}
|
||||
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.FillRectangle(backColor, rect);
|
||||
e.Graphics.DrawString(showText, e.Font, foreColor, e.Bounds, sStringFormat);
|
||||
}
|
||||
|
||||
AfterDrawItem?.Invoke(this, Items, e);
|
||||
|
||||
base.OnDrawItem(e);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMeasureItem(MeasureItemEventArgs e)
|
||||
{
|
||||
base.OnMeasureItem(e);
|
||||
e.ItemHeight += ItemHeight;
|
||||
}
|
||||
|
||||
public void SelectedFirst()
|
||||
{
|
||||
if (Items.Count > 0 && SelectedIndex < 0)
|
||||
{
|
||||
SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private int lastIndex = -1;
|
||||
private int mouseIndex = -1;
|
||||
|
||||
[Browsable(false)]
|
||||
public int MouseIndex
|
||||
{
|
||||
get => mouseIndex;
|
||||
set
|
||||
{
|
||||
if (mouseIndex != value)
|
||||
{
|
||||
if (lastIndex >= 0 && lastIndex >= 0 && lastIndex < Items.Count && lastIndex != SelectedIndex)
|
||||
{
|
||||
OnDrawItem(new DrawItemEventArgs(CreateGraphics(), Font, GetItemRectangle(lastIndex), lastIndex, DrawItemState.Grayed));
|
||||
}
|
||||
|
||||
mouseIndex = value;
|
||||
if (mouseIndex >= 0 && mouseIndex >= 0 && mouseIndex < Items.Count && mouseIndex != SelectedIndex)
|
||||
{
|
||||
OnDrawItem(new DrawItemEventArgs(CreateGraphics(), Font, GetItemRectangle(value), value, DrawItemState.HotLight));
|
||||
}
|
||||
|
||||
lastIndex = mouseIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
if (SelectionMode != SelectionMode.One) return;
|
||||
MouseIndex = IndexFromPoint(e.Location);
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
if (SelectionMode != SelectionMode.One) return;
|
||||
MouseIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user