C# 将 Enter 替换为应用程序级别的选项卡
本文关键字:选项 应用程序 Enter 替换 | 更新日期: 2023-09-27 18:30:18
我正在做一个大型的C# winforms项目。在向我的最终用户解释数千次他们必须按 tab 而不是在文本框、数据网格和任何地方输入之后,我决定在某处添加一个复选框,以便用户可以选择设置是否要将 enter 替换为选项卡。我自己不喜欢它,因为我认为会发生奇怪的事情,但我想尝试一下。
问题是我有很多表单,还有很多地方我必须设置键控事件或类似事件。我想把所有这些放在一个地方,在应用程序级别。有没有办法?
我想这是不可能的,因为某些控件会以不同的方式公开keydown事件(例如在网格视图的单元格中)。不过,您可以递归循环访问窗体中的所有控件,并为基本控件分配事件。然后,事件本身可以在一个中心位置处理
我建议您创建一个单独的类,构造函数接受您需要的参数(如textbox
),您创建global variables
并将参数分配给构造函数中的变量。
然后在类中创建事件处理程序,然后可以使用变量将代码放入事件处理程序中。
然后,您可以在需要keydown
事件的任何位置调用类
表单级别(您可以在基本表单中实现行为并从中继承):
this.KeyPreview = true;
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
PressedEnter();
base.OnKeyDown(e);
}
private bool PressedEnter()
{
bool res = false; // true if handled
Control ctr = GetFocusedControl();
if (ctr != null && ctr is TextBox)
{
res = this.SelectNextControl(ctr, true, true, true, true);
}
return res;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
internal static extern IntPtr GetFocus();
private Control GetFocusedControl()
{
Control focusedControl = null;
IntPtr focusedHandle = GetFocus();
if (focusedHandle != IntPtr.Zero)
// if control is not a .Net control will return null
focusedControl = Control.FromHandle(focusedHandle);
return focusedControl;
}
它可能也可以在应用程序级别完成:在您的主表单中,您必须从消息循环中预过滤消息(使用消息过滤器:Application.AddMessageFilter(您的过滤器)),检查消息WM_KEYDOWN = 0x100,检查按下的键是否为 ENTER,然后处理它与上面相同。您只需在主窗体中执行一次,它将适用于所有子窗体。
在主窗体类中:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.mouseMessageFilter = new MouseMoveMessageFilter();
this.mouseMessageFilter.TargetForm = this;
Application.AddMessageFilter(this.mouseMessageFilter);
}
protected override void OnClosed(EventArgs e)
{
Application.RemoveMessageFilter(this.mouseMessageFilter);
base.OnClosed(e);
}
private class MouseMoveMessageFilter : IMessageFilter
{
public FormMain TargetForm { get; set; }
public bool PreFilterMessage(ref Message m)
{
if (TargetForm.IsDisposed) return false;
int numMsg = m.Msg;
int VK_RETURN=0x0D;
if (m.Msg == 0x100 &&(int)m.WParam == VK_RETURN) // WM_KEYDOWN and enter pressed
{
if (TargetForm.PressedEnter()) return true;
}
return false;
}
}
来源:
https://stackoverflow.com/a/435510/891715
http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
http://www.autohotkey.com/docs/misc/SendMessageList.htm
MessageFilter
与SendKeys
结合使用要简单得多:
public partial class Form1 : Form, IMessageFilter
{
public Form1()
{
InitializeComponent();
Application.AddMessageFilter(this);
}
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == 0x100)//WM_KEYDOWN
{
if (m.WParam.ToInt32() == 0xd)//VK_RETURN = 0xd
{
SendKeys.Send("{TAB}");
return true; //Discard the Enter key
}
}
return false;
}
}