Winforms - 如何防止 Listbox 项选择

6
在WinForms中,我经常会有一个循环运行在一个Listbox上选择项目。
在此期间,我不希望用户使用鼠标或键盘选择该列表框中的项目。
我查看了MyListbox.enabled=false,但它会使所有项目变灰。我不想要那个。
如何防止选择Listbox中的项目?
5个回答

7

我也想要一个只读的列表框,最终,在经过长时间的搜索后,我从http://ajeethtechnotes.blogspot.com/2009/02/readonly-listbox.html找到了这个:

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);
        }
    }
}

1
完美运作 - 我想你会希望 ReadOnlyListBox 默认将 _readOnly 设置为 true,不是吗? - Mani5556

6

如果我这样做,正在运行的循环将无法选择项目。请记住,我希望循环选择项目而不是用户。 - tomfox66
这在我的情况下有效:我不希望用户能够检查项目,但必须能够通过编程方式检查它们。谢谢。 - Peter van Kekem

2

创建一个事件处理程序,使其在Listbox失去焦点时取消选定项,并将该处理程序订阅到Listbox的GotFocus事件。这样,用户就永远无法选择Listbox中的任何内容。以下代码行使用内联匿名方法实现:

txtBox.GotFocus += (object anonSender, EventArgs anonE) => { txtBox.Parent.Focus(); };

*编辑: 代码解释


1

如果你子类化ListBox并重写OnMouseClick方法,可能会有一些好运:

public class CustomListBox : ListBox
{
    public bool SelectionDisabled = false;

    protected override void OnMouseClick(MouseEventArgs e)
    {
        if (SelectionDisabled)
        {
            // do nothing.
        }
        else
        {
            //enable normal behavior
            base.OnMouseClick(e);
        }
    }
}

当然,您可能希望进行更好的信息隐藏或类设计,但这是基本功能。您可能还需要覆盖其他方法。


-1
因为问题提出者需要的是防止单个选项被点击,而不是禁用它们整体。
这是我的方法:
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;
    }
}

请尽量将您的回答集中在问题本身上。不要担心被踩,这种情况时有发生。 - undefined
好的,谢谢你提醒我。 - undefined
你的回答没有提到那些CenterSquareBoxAddOrIgnore扩展。 - undefined
我添加了剩下的代码。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接