C# 取消控件上的某些键盘事件
我有一个带有KeyDown和KeyUp处理程序的DataGridView。在某些情况下,我想禁用Enter键的默认行为(取消选择文本并聚焦于下一行),非常类似于这样:C# 取消控件上的某些键盘事件,c#,.net,datagridview,event-handling,C#,.net,Datagridview,Event Handling,我有一个带有KeyDown和KeyUp处理程序的DataGridView。在某些情况下,我想禁用Enter键的默认行为(取消选择文本并聚焦于下一行),非常类似于这样: private void View_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter && Condition) { // Special flow - d
private void View_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && Condition)
{
// Special flow - do logic and CANCEL default event effect
SpecialFlow = true;
...
e.Handled = true; // That doesn't do the job
}
}
private void View_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && Condition && SpecialFlow)
{
// Special flow - do logic and continue normally
SpecialFlow = false;
...
}
}
我找到了一些似乎不符合我需要的解决方案:
- 用钩子截取应用程序中的所有键盘事件-我需要更多的检查才能做到这一点
- 删除所有事件处理程序-但我需要在密钥启动后将它们返回
- 实施一项新的控制措施-溢流
private void View_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (Condition)
EndEditFlag = true;
}
private void View_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && Condition)
{
if (EndEditFlag)
{
EndEditFlag = false;
// Select by previously saved selection data - revert CellEndEdit
View.CurrentCell = View.Rows[...].Cells[...];
SelectText(...);
}
// Special flow - do logic
}
}
我不确定我是否正确理解了你的问题。但是如果我没有错的话,您所需要的只是KeyEventArgs对象上的“Handled”属性 在事件处理程序中将该属性设置为“true”时,不会调用该特定事件的进一步处理:
public void Test()
{
DataGridView view = new DataGridView();
view.KeyDown += view_KeyDown;
}
void view_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter /* && some other conditions */)
{
//Do some custom logic
e.Handled = true; //Cencel event. Avoid any other processing. Like the button was never pressed.
}
}
我不确定我是否正确理解了你的问题。但是如果我没有错的话,您所需要的只是KeyEventArgs对象上的“Handled”属性 在事件处理程序中将该属性设置为“true”时,不会调用该特定事件的进一步处理:
public void Test()
{
DataGridView view = new DataGridView();
view.KeyDown += view_KeyDown;
}
void view_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter /* && some other conditions */)
{
//Do some custom logic
e.Handled = true; //Cencel event. Avoid any other processing. Like the button was never pressed.
}
}
对此的深入解决方案可能会变得相当复杂。我建议首先尝试一下
KeyEventArgs
的SuppressKeyPress
属性。如果在视图中将其设置为true\u KeyDown
,则可能不会触发标准行为。如果是这样,就离开这里
否则,您将不得不在按键时搞乱windows消息的处理方式。我正是在做这个,在一个我正在做的项目中
我的方法简介:
将有问题的控件放入从UserControl
下降的容器中。这允许通过一些自定义代码覆盖ProcessKeyPreview
方法,在这些自定义代码中,前面提到的与windows消息的混淆已经完成。实际上,user32.dll中的PeekMessage用于在不需要的windows消息被重写ProcessKeyPreview
处理后,将其从消息队列中取出
让我们深入了解容器的代码:
public class baseKeyControl : UserControl
{
private const int WM_KEYDOWN = 0x100;
private const int WM_KEYUP = 0x101;
const int WM_CHAR = 0x102;
const int WM_SYSCHAR = 0x106;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
const int WM_IME_CHAR = 0x286;
private struct MSG
{
public IntPtr hwnd;
public int message;
public IntPtr wParam;
public IntPtr lParam;
public int time;
public int pt_x;
public int pt_y;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool PeekMessage([In, Out] ref MSG msg,
HandleRef hwnd, int msgMin, int msgMax, int remove);
/// <summary>
/// Trap any keypress before child controls get hold of them
/// </summary>
/// <param name="m">Windows message</param>
/// <returns>True if the keypress is handled</returns>
protected override bool ProcessKeyPreview(ref Message m)
{
KeyEventArgs e = null;
if ((m.Msg != WM_CHAR) && (m.Msg != WM_SYSCHAR) && (m.Msg != WM_IME_CHAR))
{
e = new KeyEventArgs(((Keys)((int)((long)m.WParam))) | ModifierKeys);
if ((m.Msg == WM_KEYDOWN) || (m.Msg == WM_SYSKEYDOWN))
{
this.DoTrappedKeyDown(e);
}
else if ((m.Msg == WM_KEYUP) || (m.Msg == WM_SYSKEYUP))
{
this.DoTrappedKeyUp(e);
}
// Remove any WM_CHAR type messages if supresskeypress is true.
if (e.SuppressKeyPress)
{
this.RemovePendingMessages(WM_CHAR, WM_CHAR);
this.RemovePendingMessages(WM_SYSCHAR, WM_SYSCHAR);
this.RemovePendingMessages(WM_IME_CHAR, WM_IME_CHAR);
}
if (e.Handled)
{
return e.SuppressKeyPress;
}
}
return base.ProcessKeyPreview(ref m);
}
private void RemovePendingMessages(int msgMin, int msgMax)
{
if (!this.IsDisposed)
{
MSG msg = new MSG();
IntPtr handle = this.Handle;
while (PeekMessage(ref msg,
new HandleRef(this, handle), msgMin, msgMax, 1))
{
}
}
}
public void DoTrappedKeyDown(KeyEventArgs e)
{
// Do your key down work here
}
public void DoTrappedKeyUp(KeyEventArgs e)
{
// Do your key up work here
}
}
公共类baseKeyControl:UserControl
{
私有常量int WM_KEYDOWN=0x100;
私有常量int WM_KEYUP=0x101;
常量int WM_CHAR=0x102;
常量int WM_SYSCHAR=0x106;
常量int WM_SYSKEYDOWN=0x104;
常量int WM_SYSKEYUP=0x105;
常量int WM_IME_CHAR=0x286;
私有结构消息
{
公共IntPtr hwnd;
公共信息;
公共IntPtr wParam;
公共IntPtr LPRAM;
公共整数时间;
公共int pt_x;
公共国际部;
}
[DllImport(“user32.dll”,CharSet=CharSet.Auto)]
私有静态外部bool peek消息([In,Out]ref MSG,
HandleRef hwnd、int msgMin、int msgMax、int remove);
///
///在子控件抓住任何按键之前,将其捕获
///
///Windows消息
///如果已处理按键,则为True
受保护的覆盖布尔ProcessKeyPreview(参考消息m)
{
KeyEventArgs e=null;
if((m.Msg!=WM\u CHAR)&&&(m.Msg!=WM\u SYSCHAR)&&&(m.Msg!=WM\u IME\u CHAR))
{
e=新的KeyEventArgs(((键)((int)((长)m.WParam)))| ModifierKeys);
if((m.Msg==WM_KEYDOWN)| |(m.Msg==WM_SYSKEYDOWN))
{
这个。DoTrappedKeyDown(e);
}
else if((m.Msg==WM_-KEYUP)| |(m.Msg==WM_-SYSKEYUP))
{
这是DoTrappedKeyUp(e);
}
//如果SupersKeyPress为true,则删除任何WM_字符类型的消息。
如果(如按下按键)
{
这个.removependengmessages(WM_CHAR,WM_CHAR);
这个.removependengmessages(WM_SYSCHAR,WM_SYSCHAR);
这个.removependengmessages(WM_IME_CHAR,WM_IME_CHAR);
}
如果(如已处理)
{
返回e.suppress按键;
}
}
返回base.ProcessKeyPreview(参考m);
}
私有void RemovePendingMessages(int-msgMin,int-msgMax)
{
如果(!this.IsDisposed)
{
MSG=new MSG();
IntPtr handle=this.handle;
while(peek)消息(参考消息,
新的HandleRef(这个,handle),msgMin,msgMax,1))
{
}
}
}
public void DoTrappedKeyDown(KeyEventArgs e)
{
//你的钥匙在这里工作吗
}
public void DoTrappedKeyUp(KeyEventArgs e)
{
//你的钥匙在这里工作吗
}
}
请注意错误,因为我已经从我现有的代码中快速复制并粘贴了这段代码,这段代码做的更多,是根据我的特定用例定制的。出于可读性原因,不希望在此处显示此内容。对此的深入解决方案可能会变得相当复杂。我建议首先尝试一下
KeyEventArgs
的SuppressKeyPress
属性。如果在视图中将其设置为true\u KeyDown
,则可能不会触发标准行为。如果是这样,就离开这里
否则,您将不得不在按键时搞乱windows消息的处理方式。我正是在做这个,在一个我正在做的项目中
我的方法简介:
将有问题的控件放入从UserControl
下降的容器中。这允许覆盖ProcessKeyPre