我的目标是实现一个自定义控件+S键处理程序,以连接到winforms应用程序中的自定义保存方法。
根据我的研发,有几种方法可以实现这一点--首先,我尝试了明显的KeyPress事件处理程序。这不够强大,无法捕获我需要的按键(在编辑器级别上没有调用它,这正是我所需要的)。
第二个更好的选项是保护覆盖bool ProcessCmdKey(ref Message msg,Keys keyData)覆盖。这是有效的--它拦截CTRL键单击,但显然我需要编写额外的代码来坚持按下CTRL键的事实,并拦截下一个按键(在我的例子中是S),然后执行自定义操作。
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.S | Keys.Control))
{
// This is never called
}
else if (keyData == (Keys.Menu | Keys.Alt))
{
// this is called each time I hit CTRL
}
return true;
}ProcessCmdKey似乎是在我点击CTRL键后立即被调用的。
这篇文章建议创建一个KeyTracker类,它将持久化按下的键并执行它需要做的事情:
Capture Key Sequence via ProcessCmdKey
这似乎是一个很好的选择,但在我深入研究实现纪念品跟踪模式之前,是否有人对如何完成这一看似常见的特性有意见呢?
另一种模式使用GetKeyboardState API函数:
Capture multiple key downs in C#
这似乎很有趣,虽然我不确定它能满足我的需求。
[DllImport ("user32.dll")]公开静态GetKeyboardState( byte[] keystate );
private void Form1_KeyDown( object sender, KeyEventArgs e )
{
byte[] keys = new byte[255];
GetKeyboardState (keys);
if( keys[(int)Keys.Up] == 129 && keys[(int)Keys.Right] == 129 )
{
Console.WriteLine ("Up Arrow key and Right Arrow key down.");
}
}谢谢你看我的问题。
更新
我在我的DataPanel中添加了三个用于密钥处理的事件。当我在事件中设置断点时,这些事件都没有被VS捕获,所以这就是我认为ProcessCmdKey是我最好的选择的原因。
如果我能让这些活动发挥作用,那也会很好:
// Ctrl + S: Save Support
this.ParentForm.KeyPreview = true;
this.KeyPress += new KeyPressEventHandler(DataPanel_KeyPress);
this.KeyDown += new KeyEventHandler(DataPanel_KeyDown);
this.PreviewKeyDown += new PreviewKeyDownEventHandler(DataPanel_PreviewKeyDown);在按任何键时,这些事件似乎都没有被捕捉到:
void DataPanel_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == (Keys.S | Keys.Control))
{
SessionManager.Trace.AddTrace("You Hit Save!!");
}
}
void DataPanel_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == (Keys.S | Keys.Control))
{
SessionManager.Trace.AddTrace("You Hit Save!!");
}
}
void DataPanel_KeyPress(object sender, KeyPressEventArgs e)
{
var key = e.KeyChar;
}更新
我通过使用一个简单的KeyUp事件和KeyPreview标志解决了这个问题:
void ShipmentDataPanel_KeyUp(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.S)
{
MessageBox.Show("Control + S Key Hit!");
}
}谢谢。
发布于 2011-12-10 19:18:37
将表单的KeyPreview属性设置为true。该属性的摘要表示:“获取或设置一个值,该值指示窗体在事件传递到具有焦点的控件之前是否将接收关键事件。”然后使用KeyUp事件。除非是KeyPressed,否则它也会给出诸如控制键之类的特殊密钥的信息。
发布于 2017-12-19 09:32:34
我通过这样做解决了这个问题
if(e.KeyData==(Keys.S | Keys.Control))发布于 2021-09-04 07:20:36
虽然这是一个很老的问题,但我还是想补充一下我的答案。
OP写道,他不能使用ProcessCmdKey,因为它会在他一命中Control键就会触发,并且也不会等到他按下S键。
我没有这个问题,下面的代码运行良好,只有当我第一次按Ctrl,然后按S时,才会调用Delete()方法
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
bool bHandled = false;
// switch case is the easy way, a hash or map would be better, but more work to get set up.
switch (keyData)
{
case Keys.F5:
RefreshList("", "", false); // call my refresh method
bHandled = true;
break;
case Keys.S | Keys.Control: // call my delete method
Delete(false);
bHandled = true;
break;
default:
base.ProcessCmdKey(ref msg, keyData);
break;
}
return bHandled;
}
protected virtual void Delete(bool handled)
{
if (handled == false)
{
MessageBox.Show("delete");
}
}https://stackoverflow.com/questions/8459067
复制相似问题