如何在 C# (Winform) 中只用鼠标制作多选列表框?

How to make multiselect listbox only with mouse in C# (Winform)?

我有 listbox 里面有一些东西,我要找的是:

总是之前的项目保持选中状态,如果我单击未选中的项目,它被选中 也是,但如果它已经被选中 ,它就会被取消选中 。 我使用了这些代码,但效果不是很好! 这是我的代码(这个根本不起作用):

public partial class Options_Form : Form
{
    public Options_Form()
    {
        InitializeComponent();
    }

    private void Options_Load(object sender, EventArgs e)
    {
        AceMP_Class cl = new AceMP_Class();
        listBox1.Items.AddRange(cl.SupportedFiles_stringarray());
        listBox1.SelectionMode = SelectionMode.MultiExtended;
        listBox1.Size = listBox1.PreferredSize;
        listboxitemsState_array = new bool[cl.SupportedFiles_stringarray().Length];
    }

    private void button2_Click(object sender, EventArgs e)
    {
        listBox1.ClearSelected();
        //selecteditemsindex_list.Clear();
    }

    //List<int> selecteditemsindex_list = new List<int>();

    bool[] listboxitemsState_array;

    private void listBox1_MouseDown(object sender, MouseEventArgs e)
    {
        for (int i = 0; i < listboxitemsState_array.Length; i++)
        {
            if (listboxitemsState_array[i])
            {
                listBox1.SetSelected(i, true);
            }
            else
            {
                listBox1.SetSelected(i, false);
            }
        }

        //if (listBox1.GetSelected(listBox1.IndexFromPoint(e.X, e.Y)))
        if (listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)])
        {
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), false);
            listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)] = false;
        }
        else
        {
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), true);
            listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)] = true;
        }

    }

    private void listBox1_MouseUp(object sender, MouseEventArgs e)
    {

        for (int i = 0; i < listboxitemsState_array.Length; i++)
        {
            if (listboxitemsState_array[i])
            {
                listBox1.SetSelected(i, true);
            }
            else
            {
                listBox1.SetSelected(i, false);
            }
        }

        //if (listBox1.GetSelected(listBox1.IndexFromPoint(e.X, e.Y)))
        if (listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)])
        {
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), false);
            listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)] = false;
        }
        else
        {
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), true);
            listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)] = true;
        }

    }

}

但是这个效果不是很好!

public partial class Options_Form : Form
{
    public Options_Form()
    {
        InitializeComponent();
    }

    private void Options_Load(object sender, EventArgs e)
    {
        AceMP_Class cl = new AceMP_Class();
        listBox1.Items.AddRange(cl.SupportedFiles_stringarray());
        listBox1.SelectionMode = SelectionMode.MultiExtended;
        listBox1.Size = listBox1.PreferredSize;
    }

    private void button2_Click(object sender, EventArgs e)
    {
        listBox1.ClearSelected();
        selecteditemsindex_list.Clear();
    }

    List<int> selecteditemsindex_list = new List<int>();

    private void listBox1_Click(object sender, EventArgs e)
    {
        listBox1.ClearSelected();
    }

    private void listBox1_MouseDown(object sender, MouseEventArgs e)
    {
        for (int i = 0; i < selecteditemsindex_list.Count; i++)
        {
            listBox1.SetSelected(selecteditemsindex_list[i], true);
        }
    }

    private void listBox1_MouseUp(object sender, MouseEventArgs e)
    {

        for (int i = 0; i < selecteditemsindex_list.Count; i++)
        {
            listBox1.SetSelected(selecteditemsindex_list[i], true);
        }
        if (listBox1.GetSelected(listBox1.IndexFromPoint(e.X, e.Y)))
        {
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), false);
        }
        else
        {
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), true);
            selecteditemsindex_list.Add(listBox1.IndexFromPoint(e.X, e.Y));
        }
    }

}

我该如何解决!?

我想提一下,您使用 SelectionMode.MultiExtended 实现了此功能,但您需要按 CTRL + ClickSHIFT + Click

实现这个只用鼠标:

1) 当我与@ACE 讨论时(他提出了使用 virtualkey 的想法)是 press CTRL key当您点击时。在 MouseDown 上按 CTRL,在 MouseUp 上松开 CTRL 键。

public partial class Options_Form : Form
{
    public Options_Form()
    {
        InitializeComponent();
    }

    private void Options_Load(object sender, EventArgs e)
    {
        AceMP_Class cl = new AceMP_Class();
        listBox1.Items.AddRange(cl.SupportedFiles_stringarray());
        listBox1.SelectionMode = SelectionMode.MultiSimple;
        listBox1.Size = listBox1.PreferredSize;
    }

    [DllImport("user32.dll", SetLastError = true)]
    static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);

    public const uint KEYEVENTF_KEYUP = 0x02;
    public const uint VK_CONTROL = 0x11;

    private void listBox1_MouseDown(object sender, MouseEventArgs e)
    {
        keybd_event(Convert.ToByte(VK_CONTROL), 0, 0, 0);
    }

    private void listBox1_MouseUp(object sender, MouseEventArgs e)
    {
        keybd_event(Convert.ToByte(VK_CONTROL), 0, Convert.ToByte(KEYEVENTF_KEYUP), 0);
    }
}

2) 我想到的最简单的解决方案(如果你按得非常快,会有一些缺点)是在 MouseClick 事件上使用,并且有bool 的数组,该数组中的每个 index 都会告诉我是否被选中。

selecteditemsindex_list[selectedIndex] = !selecteditemsindex_list[selectedIndex];

如何运作?

取 ​​ 当前索引 并取反 (!) 该索引处的值。这样你就可以用鼠标获得select/unselect特性。

因为我只使用当前索引,数组中的其他值保持不变我可以对数组中的所有值使用 SetSelected。这样就可以用鼠标多选

public partial class Options_Form : Form
{
    public Options_Form()
    {
        InitializeComponent();
    }
    bool[] selecteditemsindex_list;

    private void Options_Load(object sender, EventArgs e)
    {
        AceMP_Class cl = new AceMP_Class();
        listBox1.Items.AddRange(cl.SupportedFiles_stringarray());
        listBox1.SelectionMode = SelectionMode.MultiExtended;
        listBox1.Size = listBox1.PreferredSize;
        selecteditemsindex_list = new bool[listBox1.Items.Count];
    }

    private void listBox1_MouseDown(object sender, MouseEventArgs e)
    {
        var selectedIndex = listBox1.SelectedIndex;
        selecteditemsindex_list[selectedIndex] = !selecteditemsindex_list[selectedIndex];
        for (int i = 0; i < selecteditemsindex_list.Count(); i++)
        {
            listBox1.SetSelected(i, selecteditemsindex_list[i]);
        }
    }
}

ListBox 控件有一个 属性 'SelectionMode' 您可以将其设置为:

  1. 一个
  2. 多重简单
  3. 多扩展

查看此link了解详情