public class ReadOnlyListBox : ListBox
{
private bool _readOnly = false;
public bool ReadOnly
{
get { return _readOnly; }
set { _readOnly = value; }
}
protected override void DefWndProc(ref Message m)
{
// If ReadOnly is set to true, then block any messages
// to the selection area from the mouse or keyboard.
// Let all other messages pass through to the
// Windows default implementation of DefWndProc.
if (!_readOnly || ((m.Msg <= 0x0200 || m.Msg >= 0x020E)
&& (m.Msg <= 0x0100 || m.Msg >= 0x0109)
&& m.Msg != 0x2111
&& m.Msg != 0x87))
{
base.DefWndProc(ref m);
}
}
}
public class XCheckListBox : ListBox
{
public XCheckListBox()
{
this.DrawMode = DrawMode.OwnerDrawFixed;
}
public Pen ForeColorPen => new Pen(ForeColor);
[Category("Misc"), Description("是否多选"), Browsable(true), DefaultValue(false)]
public bool MultiCheck { get => base.SelectionMode != SelectionMode.One; set => base.SelectionMode = value ? SelectionMode.MultiSimple : SelectionMode.One; }
protected override void OnDrawItem(DrawItemEventArgs e)
{
if (e.Index < 0) return;
var @checked = e.State.HasFlag(DrawItemState.Selected);
var g = e.Graphics;
var rectOfItem = e.Bounds;
//g.FillRectangle(BackColorBrush, rectOfItem);//e.DrawBackground();
//if the item state is selected them change the back color
if (@checked)
e = new DrawItemEventArgs(e.Graphics,
e.Font,
e.Bounds,
e.Index,
e.State ^ DrawItemState.Selected,
e.ForeColor,
Color.LightSteelBlue);// SystemColors.InactiveBorder Color.Yellow Choose the color
// Draw the background of the ListBox control for each item.
e.DrawBackground();
var rectOfCheckBox = rectOfItem.CenterSquareBox().Padding(2, 2).SetX(1);
g.DrawRectangle(ForeColorPen, rectOfCheckBox);
var sizeBeforeText = new Size(1 + rectOfCheckBox.RightTop().X + 3, rectOfItem.Height);
var rectOfText = new Rectangle(rectOfItem.X + sizeBeforeText.Width, rectOfItem.Y, rectOfItem.Width - sizeBeforeText.Width, rectOfItem.Height);
var itemText = "";
itemText = this.DesignMode ?
this.Text
: this.Items.Count > e.Index ?
this.Items[e.Index]?.ToString() ?? ""
: "";
var cbxSize = rectOfCheckBox.Padding(3, 3);
//CheckBoxRenderer.GetGlyphSize
if (@checked && !DisableList.Contains(itemText))
TextRenderer.DrawText(g, "✔", e.Font, rectOfCheckBox, this.ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
//ControlPaint.DrawCheckBox(e.Graphics, rectOfCheckBox, @checked ? ButtonState.Checked : ButtonState.Normal);
////CheckBoxRenderer.DrawCheckBox(g, cbxSize.Location, CheckBoxState.MixedNormal);
TextRenderer.DrawText(g, itemText, e.Font, rectOfText, this.ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
// If the ListBox has focus, draw a focus rectangle around the selected item.
e.DrawFocusRectangle();
}
protected override void OnSelectedValueChanged(EventArgs e)
{
var uncheckedIdx = new List<int>();
foreach (var selectItem in this.SelectedIndices)
{
var ckdIdx = selectItem as int?;
if (ckdIdx == null || ckdIdx.Value < 0) continue;
var ckdItem = this.Items[ckdIdx.Value] as string;
if (ckdItem == null) continue;
if (DisableList.Contains(ckdItem))
uncheckedIdx.Add(ckdIdx.Value);
}
foreach (var ckIdx in uncheckedIdx)
this.SetSelected(ckIdx, false);
base.OnSelectedValueChanged(e);
}
public void SetDisable(string item, bool enable)
{
if (!enable)
DisableList.AddOrIgnore(item);
else
DisableList.Remove(item);
}
public List<string> DisableList = new List<string>();
}
public static class SharpEx
{
public static Point AddX(this Point _this, int x) => new Point(_this.X + x, _this.Y);
public static Point AddY(this Point _this, int y) => new Point(_this.X, _this.Y + y);
public static Point SetX(this Point _this, int x) => new Point(x, _this.Y);
public static Point SetY(this Point _this, int y) => new Point(_this.X, y);
public static Point[] CenterLineInLine(this Point[] _this, decimal persent)
{
var poffset = (1 - persent) / 2;
var need = poffset;
var remain = 1 - poffset;
var p1 = _this[0];
var p2 = _this[1];
var pX1 = (int)(p1.X * remain + p2.X * need);
var pY1 = (int)(p1.Y * remain + p2.Y * need);
var pX2 = (int)(p1.X * need + p2.X * remain);
var pY2 = (int)(p1.Y * need + p2.Y * remain);
return new Point[] { new Point(pX1, pY1), new Point(pX2, pY2) };
}
public static Size AddWidth(this Size _this, int width)
{
return new Size(_this.Width + width, _this.Height);
}
public static Size AddHeight(this Size _this, int height)
{
return new Size(_this.Width, _this.Height + height);
}
public static Size AddWidthHeight(this Size _this, int width = 0, int height = 0)
{
return new Size(_this.Width + width, _this.Height + height);
}
public static Point Start(this Rectangle _this) => _this.Location;
public static Point End(this Rectangle _this) => _this.Location.AddX(_this.Width).AddY(_this.Height);
public static Point LeftDown(this Rectangle _this) => _this.Location.AddY(_this.Height);
public static Point RightTop(this Rectangle _this) => _this.Location.AddX(_this.Width);
public static Point[] StartEnd(this Rectangle _this) => new Point[] { _this.Start(), _this.End() };
public static Line[] XLine(this Rectangle _this, int paddingLeftRight, decimal lengthPersend) => _this.DiagonalLine(paddingLeftRight, lengthPersend);
public static Point[] LeftDownRightTop(this Rectangle _this) => new Point[] { _this.LeftDown(), _this.RightTop() };
public static Point[] CenterLine(this Rectangle _this, bool HorizontalOrVertical, decimal lengthPersend)
{
var length = (int)(HorizontalOrVertical ? lengthPersend * _this.Width : lengthPersend * _this.Height);
if (HorizontalOrVertical)
{
return CenterLineInLine(new Point[]{ _this.Location.AddY(_this.Height / 2),
_this.Location.AddX(_this.Width).AddY(_this.Height / 2) }, lengthPersend);
}
else
{
return CenterLineInLine(new Point[]{ new Point(_this.X+ _this.Width / 2, _this.Y ),
new Point(_this.X+_this.Height / 2, _this.Y +_this.Height ) }, lengthPersend);
}
}
public static Rectangle CenterSquareBox(this Rectangle _this)
{
if (_this.Width == _this.Height) return _this;
var centerSquareBoxWidth = Math.Min(_this.Width, _this.Height);
var location = _this.OffsetX((_this.Width - centerSquareBoxWidth) / 2).OffsetY((_this.Height - centerSquareBoxWidth) / 2).Location;
return new Rectangle(location, new Size(centerSquareBoxWidth, centerSquareBoxWidth));
}
public static Rectangle CenterSameBox(this Rectangle _this, Size size)
{
var x = _this.X + (_this.Width / 2 - size.Width / 2);
var y = _this.Y + (_this.Height / 2 - size.Height / 2);
return new(new(x, y), size);
}
public static Point CenterPoint(this Rectangle _this)
{
var x = _this.X + _this.Width / 2;
var y = _this.Y + _this.Height / 2;
return new(x, y);
}
/// <summary>
/// 对角线
/// </summary>
/// <param name="_this"></param>
/// <param name="paddingLeftRight"></param>
/// <param name="lengthPersend"></param>
/// <returns></returns>
public static Line[] DiagonalLine(this Rectangle _this, int paddingLeftRight, decimal lengthPersend)
{
_this = _this.Padding(paddingLeftRight);
return new Line[] { new(_this.StartEnd().CenterLineInLine(lengthPersend)), new(_this.LeftDownRightTop().CenterLineInLine(lengthPersend)) };
}
public static Rectangle MarginKeepLocation(this Rectangle _this, int marginLeftRight = 0, int marginTopButtom = 0)
{
return _this.Padding(-marginLeftRight, -marginTopButtom).OffsetXY(marginLeftRight, marginTopButtom);
}
public static Rectangle Margin(this Rectangle _this, int marginLeftRight = 0, int marginTopButtom = 0)
{
return _this.Padding(-marginLeftRight, -marginTopButtom);
}
public static Rectangle Margin2(this Rectangle _this, int left = 0, int right = 0, int top = 0, int buttom = 0)
{
return _this.Padding2(-left, -right, top, buttom);
}
public static Rectangle Margin2KeepLocation(this Rectangle _this, int left = 0, int right = 0, int top = 0, int buttom = 0)
{
return _this.Padding2(-left, -right, top, buttom).OffsetXY(left, top);
}
public static Rectangle Padding(this Rectangle _this, int paddingLeftRight = 0, int paddingTopButtom = 0)
{
return new Rectangle(_this.Location.AddX(paddingLeftRight).AddY(paddingTopButtom),
new Size(_this.Width - paddingLeftRight * 2, _this.Height - paddingTopButtom * 2));
}
public static Rectangle Padding2(this Rectangle _this, int left = 0, int right = 0, int top = 0, int buttom = 0)
{
return new Rectangle(_this.Location.AddX(left).AddY(top),
new Size(_this.Width - (left + right), _this.Height - (top + buttom)));
}
public static Rectangle Padding(this Rectangle _this, Padding padding)
{
return new Rectangle(_this.Location.AddX(padding.Left).AddY(padding.Top),
new Size(_this.Width - (padding.Left + padding.Right), _this.Height - (padding.Top + padding.Bottom)));
}
public static Rectangle SetX(this Rectangle _this, int setX) => new Rectangle(new Point(setX, _this.Location.Y), _this.Size);
public static Rectangle SetY(this Rectangle _this, int setY) => new Rectangle(new Point(_this.Location.X, setY), _this.Size);
public static Rectangle OffsetX(this Rectangle _this, int offsetX) => new Rectangle(_this.Location.AddX(offsetX), _this.Size);
public static Rectangle OffsetY(this Rectangle _this, int offsetY) => new Rectangle(_this.Location.AddY(offsetY), _this.Size);
public static Rectangle OffsetWidth(this Rectangle _this, int offsetWidth) => new Rectangle(_this.Location, new Size(_this.Size.Width + offsetWidth, _this.Size.Height));
public static Rectangle OffsetHeight(this Rectangle _this, int offsetHeight) => new Rectangle(_this.Location, new Size(_this.Size.Width, _this.Size.Height + offsetHeight));
public static Rectangle OffsetSize(this Rectangle _this, int offsetWidth, int offsetHeight) => _this.OffsetWidthHeight(offsetWidth, offsetHeight);
public static Rectangle OffsetWidthHeight(this Rectangle _this, int offsetWidth, int offsetHeight) => new Rectangle(_this.Location, new Size(_this.Size.Width + offsetWidth, _this.Size.Height + offsetHeight));
public static Rectangle OffsetXY(this Rectangle _this, int offsetX, int offsetY) => new Rectangle(_this.Location.AddX(offsetX).AddY(offsetY), _this.Size);
public static Padding SetLeft(this Padding _this, int left) => new Padding(left, _this.Top, _this.Right, _this.Bottom);
public static Padding SetTop(this Padding _this, int top) => new Padding(_this.Left, top, _this.Right, _this.Bottom);
public static Padding SetRight(this Padding _this, int right) => new Padding(_this.Left, _this.Top, right, _this.Bottom);
public static Padding SetBottom(this Padding _this, int bottom) => new Padding(_this.Left, _this.Top, _this.Right, bottom);
public static Padding OffsetLeft(this Padding _this, int offsetLeft) => _this.SetLeft(_this.Left + offsetLeft);
public static Padding OffsetTop(this Padding _this, int offsetTop) => _this.SetTop(_this.Top + offsetTop);
public static Padding OffsetRight(this Padding _this, int offsetRight) => _this.SetRight(_this.Right + offsetRight);
public static Padding OffsetBottom(this Padding _this, int offsetBottom) => _this.SetBottom(_this.Left + offsetBottom);
}
public struct Line
{
public Line(int xStart, int yStart, int xEnd, int yEnd)
{
XStart = xStart;
YStart = yStart;
XEnd = xEnd;
YEnd = yEnd;
}
public Line(Point start, Point end)
{
XStart = start.X;
YStart = start.Y;
XEnd = end.X;
YEnd = end.Y;
}
public Line(Point[] startEnd)
{
XStart = startEnd[0].X;
YStart = startEnd[0].Y;
XEnd = startEnd[1].X;
YEnd = startEnd[1].Y;
}
public int XStart;
public int YStart;
public int XEnd;
public int YEnd;
public Point Start => new Point(XStart, YStart);
public Point End => new Point(XEnd, YEnd);
public static implicit operator Point[](Line line)
{
return new Point[2] { line.Start, line.End };
}
}
public static class ObjectEx
{
public static ICollection<T> AddOrIgnore<T>(this ICollection<T> _this, params T[] items)
{
foreach (var item in items)
if (!_this.Contains(item))
_this.Add(item);
return _this;
}
}
5条答案
按热度按时间wbrvyc0a1#
我也想要一个只读列表框,最后,经过大量的搜索,从http://ajeethtechnotes.blogspot.com/2009/02/readonly-listbox.html找到了这个:
4zcjmb1e2#
将Listbox.SelectionMode属性切换为SelectionMode.None
编辑如我所见,设置为SelectionMode.None取消选择所有以前选择的项目,并抛出一个异常,如果SetSelected是在列表框中调用。
我认为想要的行为是不可能的(如果不想用
Enabled=false
灰色化项目)。r9f1avp53#
创建一个从Listbox中移除焦点的事件处理程序,并将该处理程序订阅到Listbox的GotFocus事件。这样,用户将永远无法选择列表框中的任何内容。下面的代码行使用内联匿名方法来实现这一点:
bjg7j2ky4#
如果你子类化ListBox并覆盖OnMouseClick方法,你可能会有一些运气:
当然,你可能想做更好的信息隐藏或类设计,但这是基本的功能。您可能还需要覆盖其他方法。
wtzytmuj5#
因为提问者需要的是防止个别选项被点击,而不是全面禁用它们。
这是我的方式: