自定义屏幕键盘和过滤下拉菜单播放效果不佳
Custom on-screen keyboard and filtered dropdown not playing nicely
我的 winforms 应用程序中有一个自定义的屏幕十键键盘,它似乎在任何地方都可以正常工作,除了具有一些自定义过滤代码的单个下拉菜单。我竭尽全力让这个键盘以我能想象到的所有方式成为非交互式的。这是代码隐藏(numpad0、numpad1 等都是标签,如果重要的话)
public partial class TenKeyForm : Form
{
private const int WM_NCLBUTTONDOWN = 0xA1;
private const int HT_CAPTION = 0x2;
private const int WM_MOUSEACTIVATE = 0x0021, MA_NOACTIVATE = 0x0003;
private const int WS_EX_NOACTIVATE = 0x08000000;
protected override bool ShowWithoutActivation { get { return true; } }
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEACTIVATE)
{
m.Result = (IntPtr)MA_NOACTIVATE;
return;
}
base.WndProc(ref m);
}
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= WS_EX_NOACTIVATE;
return createParams;
}
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool ReleaseCapture();
public TenKeyForm()
{
InitializeComponent();
MouseDown += MouseDownHandler;
numpad0.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("0"); });
numpad1.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("1"); });
numpad2.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("2"); });
numpad3.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("3"); });
numpad4.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("4"); });
numpad5.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("5"); });
numpad6.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("6"); });
numpad7.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("7"); });
numpad8.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("8"); });
numpad9.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("9"); });
numpadDot.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("."); });
numpadBack.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("+{TAB}"); });
numpadForward.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("{TAB}"); });
numpadBackspace.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("{BS}"); });
SetStyle(ControlStyles.Selectable, false);
}
private void MouseDownHandler(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
}
同样,这对各种文本框、屏蔽输入等都适用,但单个组合框除外。这个 ComboBox 有一些额外的验证,以防止输入无效的选择。基本上,如果它有一个条目“500”和“550”,键入“5”会跳转到列表中的“500”,并留下除您键入的“5”之外的所有内容突出显示,以便下一次击键将替换它,即 500
。此时它将拒绝除“5”或“0”以外的任何内容。输入另外 5 个突出显示 550
等等。这是该位的隐藏代码:
private void ValidateDropDown(object sender, KeyPressEventArgs e)
{
ToolStripComboBox tcb = (ToolStripComboBox)sender;
ComboBox cb = tcb.ComboBox;
cb.DroppedDown = true;
string strFindStr = "";
if (e.KeyChar == (char)8)
{
if (cb.SelectionStart <= 1)
{
cb.Text = "";
return;
}
if (cb.SelectionLength == 0)
strFindStr = cb.Text.Substring(0, cb.Text.Length - 1);
else
strFindStr = cb.Text.Substring(0, cb.SelectionStart - 1);
}
else
{
if (cb.SelectionLength == 0)
strFindStr = cb.Text + e.KeyChar;
else
strFindStr = cb.Text.Substring(0, cb.SelectionStart) + e.KeyChar;
}
int intIdx = -1;
// Search the string in the ComboBox list.
intIdx = cb.FindString(strFindStr);
if (intIdx != -1)
{
cb.SelectedText = "";
cb.SelectedIndex = intIdx;
cb.SelectionStart = strFindStr.Length;
cb.SelectionLength = cb.Text.Length;
e.Handled = true;
}
else
e.Handled = true;
}
现在十键在任何地方都可以正常工作,但这个组合框除外,如果您使用实际键盘打字,这个组合框可以完美工作。屏幕键盘甚至可以在第一次按键时正常工作,但 tenkey 表单上的任何后续 mousedown 事件似乎都会在 ComboBox 上执行类似 SelectAll()
的操作,从而否定精心设置的选择。在上面的示例中键入“55”,不会导航到 550
,而是导航到 500
两次,每次单击都会替换整个文本。
是什么导致了这种奇怪的行为,我该如何阻止它?
更新: 这似乎是 ToolStrip ComboBoxes 特有的问题,应该考虑将其包含在此处。另外:AutoCompleteMode = AutoCompleteMode.SuggestAppend
如何设置AutoCompleteMode
?
我做了测试,设置了:
AutoCompleteMode = AutoCompleteMode.Suggest;
已解决所描述的问题。
编辑 1
我已经找到解决该问题的方法,您可以添加:
toolStripComboBox1.SelectionLength=0;
在 SendKey
功能之前。
我的 winforms 应用程序中有一个自定义的屏幕十键键盘,它似乎在任何地方都可以正常工作,除了具有一些自定义过滤代码的单个下拉菜单。我竭尽全力让这个键盘以我能想象到的所有方式成为非交互式的。这是代码隐藏(numpad0、numpad1 等都是标签,如果重要的话)
public partial class TenKeyForm : Form
{
private const int WM_NCLBUTTONDOWN = 0xA1;
private const int HT_CAPTION = 0x2;
private const int WM_MOUSEACTIVATE = 0x0021, MA_NOACTIVATE = 0x0003;
private const int WS_EX_NOACTIVATE = 0x08000000;
protected override bool ShowWithoutActivation { get { return true; } }
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEACTIVATE)
{
m.Result = (IntPtr)MA_NOACTIVATE;
return;
}
base.WndProc(ref m);
}
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= WS_EX_NOACTIVATE;
return createParams;
}
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool ReleaseCapture();
public TenKeyForm()
{
InitializeComponent();
MouseDown += MouseDownHandler;
numpad0.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("0"); });
numpad1.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("1"); });
numpad2.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("2"); });
numpad3.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("3"); });
numpad4.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("4"); });
numpad5.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("5"); });
numpad6.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("6"); });
numpad7.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("7"); });
numpad8.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("8"); });
numpad9.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("9"); });
numpadDot.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("."); });
numpadBack.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("+{TAB}"); });
numpadForward.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("{TAB}"); });
numpadBackspace.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("{BS}"); });
SetStyle(ControlStyles.Selectable, false);
}
private void MouseDownHandler(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
}
同样,这对各种文本框、屏蔽输入等都适用,但单个组合框除外。这个 ComboBox 有一些额外的验证,以防止输入无效的选择。基本上,如果它有一个条目“500”和“550”,键入“5”会跳转到列表中的“500”,并留下除您键入的“5”之外的所有内容突出显示,以便下一次击键将替换它,即 500
。此时它将拒绝除“5”或“0”以外的任何内容。输入另外 5 个突出显示 550
等等。这是该位的隐藏代码:
private void ValidateDropDown(object sender, KeyPressEventArgs e)
{
ToolStripComboBox tcb = (ToolStripComboBox)sender;
ComboBox cb = tcb.ComboBox;
cb.DroppedDown = true;
string strFindStr = "";
if (e.KeyChar == (char)8)
{
if (cb.SelectionStart <= 1)
{
cb.Text = "";
return;
}
if (cb.SelectionLength == 0)
strFindStr = cb.Text.Substring(0, cb.Text.Length - 1);
else
strFindStr = cb.Text.Substring(0, cb.SelectionStart - 1);
}
else
{
if (cb.SelectionLength == 0)
strFindStr = cb.Text + e.KeyChar;
else
strFindStr = cb.Text.Substring(0, cb.SelectionStart) + e.KeyChar;
}
int intIdx = -1;
// Search the string in the ComboBox list.
intIdx = cb.FindString(strFindStr);
if (intIdx != -1)
{
cb.SelectedText = "";
cb.SelectedIndex = intIdx;
cb.SelectionStart = strFindStr.Length;
cb.SelectionLength = cb.Text.Length;
e.Handled = true;
}
else
e.Handled = true;
}
现在十键在任何地方都可以正常工作,但这个组合框除外,如果您使用实际键盘打字,这个组合框可以完美工作。屏幕键盘甚至可以在第一次按键时正常工作,但 tenkey 表单上的任何后续 mousedown 事件似乎都会在 ComboBox 上执行类似 SelectAll()
的操作,从而否定精心设置的选择。在上面的示例中键入“55”,不会导航到 550
,而是导航到 500
两次,每次单击都会替换整个文本。
是什么导致了这种奇怪的行为,我该如何阻止它?
更新: 这似乎是 ToolStrip ComboBoxes 特有的问题,应该考虑将其包含在此处。另外:AutoCompleteMode = AutoCompleteMode.SuggestAppend
如何设置AutoCompleteMode
?
我做了测试,设置了:
AutoCompleteMode = AutoCompleteMode.Suggest;
已解决所描述的问题。
编辑 1
我已经找到解决该问题的方法,您可以添加:
toolStripComboBox1.SelectionLength=0;
在 SendKey
功能之前。