C#在ListBox上禁用Ctrl键

时间:2014-05-06 15:01:24

标签: c# forms

我希望禁用ListBox上的Ctrl键。 我跟着Disable list box CTRL+C & CTRL+X in D&D的例子。 这需要一些游戏,因为我using System.Windows.Inputusing System.Windows.Forms。 除e对象外,我能够解析引用。 它告诉我Handled内没有System.Windows.Forms.PreviewKeyDownEventArgs定义。 我在这里错过了什么?谢谢!

  private void lbSigns_PreviewKeyDown(object sender, 
                System.Windows.Forms.PreviewKeyDownEventArgs e)
    {
        //
        // This if statement detects if the Control Key is pressed.
        //
        if ((System.Windows.Input.Keyboard.Modifiers & 
          System.Windows.Input.ModifierKeys.Control) == 
                 System.Windows.Input.ModifierKeys.Control)
        {
            e.Handled = true;
        }
    }

好的,我与@Tsukasa的代码越来越近了。这就是我现在所拥有的。

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

    private void lbSigns_SelectedIndexChanged(object sender, EventArgs e)
    {

        TrackSelection((ListBox)sender, alreadySelectedIndexes);

        bool allowSelection = false;

        int currentSelectedIndex = -1;

        //make sure we have an item selected
        if (!lbSigns.SelectedIndex.Equals(-1))
        {
            //if first selection we allow it
            if (alreadySelectedIndexes.Count.Equals(1))
            {
                allowSelection = true;
            }
            else
            {
                //get the last item index that was selected from our list
                currentSelectedIndex = alreadySelectedIndexes[alreadySelectedIndexes.Count - 1];

                //make sure we have a previous index item
                if ((currentSelectedIndex - 1) >= 0)
                {
                    //check if previous item before currently selected is checked
                    if (lbSigns.GetSelected(currentSelectedIndex - 1))
                    {
                        allowSelection = true;
                    }
                }

                //make sure we have a next index item
                if ((currentSelectedIndex + 1) <= lbSigns.Items.Count - 1)
                {
                    //check if next item after currently selected is checked
                    if (lbSigns.GetSelected(currentSelectedIndex + 1))
                    {
                        allowSelection = true;
                    }
                }
                //make sure we have both a next and a previous item
                if (((currentSelectedIndex - 1) >= 0) && ((currentSelectedIndex + 1) <= lbSigns.Items.Count - 1))
                {
                    //if both are selected, deny the selection
                    if (lbSigns.GetSelected(currentSelectedIndex - 1) && lbSigns.GetSelected(currentSelectedIndex + 1))
                    {
                        allowSelection = false;
                    }
                }
            }
        }

        //unselect item because it wasn't before or after an already selected item
        if (!allowSelection && !currentSelectedIndex.Equals(-1))
        {
            lbSigns.SetSelected(currentSelectedIndex, false);
        }
    }

    private void TrackSelection(ListBox listBox, List<int> alreadySelectedList)
    {
        ListBox.SelectedIndexCollection indexCollection = listBox.SelectedIndices;

        foreach (int index in indexCollection)
        {
            if (!alreadySelectedList.Contains(index))
            {
                alreadySelectedList.Add(index);
            }
        }

        foreach (int index in new List<int>(alreadySelectedList))
        {
            if (!indexCollection.Contains(index))
            {
                alreadySelectedList.Remove(index);
            }
        }
    }

但是,这是让我取消选择2个所选项目所包围的项目。一旦取消选择,它就不会让我重新选择该项目,即使它已在其两侧选择了项目。我在评论后面的部分添加了//make sure we have both a next and a previous item

2 个答案:

答案 0 :(得分:1)

更新2

好的,这不允许在所选项目之间取消选择,但还有另一个问题。

问题:您可以按住鼠标按钮并向左或向左/向左拖动。直到完成后才会调用该事件。我不确定要尝试纠正的事件是什么。

然而,我确实有一个更好的方式可以发布。我会在左右控制键上创建一个全局键盘钩子。如果在检测到该密钥时触发。如果ListBox具有输入焦点,那么我们处理该键,导致只能使用shift按钮来选择多个项目。你想确保它只在输入焦点位于ListBox上时,否则你会吃掉所有其他应用程序的密钥,因为它是一个全局钩子。

        //hold already selected items. Last item will be last selected
    List<int> alreadySelectedIndexes = new List<int>();

    //used to skip listBox1_SelectedIndexChanged on TrackSelection
    bool ignoreSelectedChanged = false;

    private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        //prevent overflow of caused by TrackSelection
        if (!ignoreSelectedChanged)
        {
            TrackSelection((ListBox)sender, alreadySelectedIndexes);

            bool allowSelection = false;

            int currentSelectedIndex = -1;

            //make sure we have an item selected
            if (!listBox1.SelectedIndex.Equals(-1))
            {
                //if first selection we allow it
                if (alreadySelectedIndexes.Count.Equals(1))
                {
                    allowSelection = true;
                }
                else
                {
                    //get the last item index that was selected from our list
                    if ((alreadySelectedIndexes.Count - 1) >= 0)
                    {
                        currentSelectedIndex = alreadySelectedIndexes[alreadySelectedIndexes.Count - 1];

                        //make sure we stay in array range
                        if ((currentSelectedIndex - 1) >= 0)
                        {
                            //check if previous item before currently selected is checked
                            if (listBox1.GetSelected(currentSelectedIndex - 1))
                            {
                                allowSelection = true;
                            }
                        }

                        //make sure we stay in array range
                        if ((currentSelectedIndex + 1) <= listBox1.Items.Count - 1)
                        {
                            //check if next item after currently selected is checked
                            if (listBox1.GetSelected(currentSelectedIndex + 1))
                            {
                                allowSelection = true;
                            }
                        }
                    }
                }

                bool isSelected = false;
                if (currentSelectedIndex >= 0)
                {
                    isSelected = listBox1.GetSelected(currentSelectedIndex);

                    if (!isSelected)
                    {
                        //we can remove it from the list now
                        alreadySelectedIndexes.Remove(currentSelectedIndex);

                        //reselect it if in the middle of already selected items
                        if (alreadySelectedIndexes.Contains(currentSelectedIndex + 1) && alreadySelectedIndexes.Contains(currentSelectedIndex - 1))
                        {
                            ignoreSelectedChanged = true;
                            allowSelection = true;
                            listBox1.SetSelected(currentSelectedIndex, true);
                        }
                    }
                }
            }

            if (!currentSelectedIndex.Equals(-1) && !allowSelection)
            {
                ignoreSelectedChanged = true;
                listBox1.SetSelected(currentSelectedIndex, false);
            }

            //unselect item because it wasn't before or after the last selected item

        }
        ignoreSelectedChanged = false;
    }

    private void TrackSelection(ListBox listBox, List<int> alreadySelectedList)
    {
        ListBox.SelectedIndexCollection indexCollection = listBox.SelectedIndices;

            foreach (int index in indexCollection)
            {
                if (!alreadySelectedList.Contains(index))
                {
                    alreadySelectedList.Add(index);
                }
            }

        foreach (int index in new List<int>(alreadySelectedList))
        {
            if (!indexCollection.Contains(index))
            {
                //remove first index in list
                alreadySelectedList.Remove(index);
                //add index back to end of list so we know what was deselected
                alreadySelectedList.Add(index);
            }
        }
    }

答案 1 :(得分:0)

            using System;
            using System.Collections.Generic;
            using System.ComponentModel;
            using System.Data;
            using System.Drawing;
            using System.Linq;
            using System.Text;
            using System.Threading.Tasks;
            using System.Windows.Forms;

            namespace listBoxWinforms
            {
                public partial class Form1 : Form
                {
                    public Form1()
                    {
                        InitializeComponent();
                    }

                    private void listBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
                    {
                        if (e.Control)
                        {
                            return;
                        }
                    }
                }
            }