我希望禁用ListBox上的Ctrl键。
我跟着Disable list box CTRL+C & CTRL+X in D&D的例子。
这需要一些游戏,因为我using System.Windows.Input
和using 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
答案 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;
}
}
}
}