有没有办法区分控件上的Enter
事件是通过键盘(Tab,Shift + Tab)还是通过直接鼠标点击引发的?
我只有在用户使用Tab移动到控件时才需要执行操作,但是当用户直接单击控件时则不需要。我试图直接拦截鼠标点击,但似乎在Enter
之前引发Click
事件。
答案 0 :(得分:2)
您可以使用WM_MOUSEACTIVATE message来检测用鼠标激活控件,而不是跟踪Tab
键。您可以对您使用的每种控件类型进行子类化,并覆盖WndProc
方法或使用如下所示的NativeWindow侦听器类。根据您使用的控件类型,只需对这些控件进行子类化以提供指示使用鼠标选择控件的属性,可能会减少工作量和混乱。这是你的决定,但模式将是相同的。
此代码稍微修改了MS文档中显示的示例。
public class MouseActivateListener : NativeWindow
{
private Control parent;
public MouseActivateListener(Control parent)
{
parent.HandleCreated += this.OnHandleCreated;
parent.HandleDestroyed += this.OnHandleDestroyed;
parent.Leave += Parent_Leave;
this.parent = parent;
if (parent.IsHandleCreated)
{
AssignHandle(parent.Handle);
}
}
private void Parent_Leave(object sender, EventArgs e)
{
MouseActivated = false;
}
private void OnHandleCreated(object sender, EventArgs e)
{
AssignHandle(((Form)sender).Handle);
}
private void OnHandleDestroyed(object sender, EventArgs e)
{
ReleaseHandle();
}
public bool MouseActivated { get; set; }
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message m)
{
const Int32 WM_MouseActivate = 0x21;
base.WndProc(ref m);
if (m.Msg == WM_MouseActivate && m.Result.ToInt32() < 3)
{
MouseActivated = true;
}
}
}
示例用法:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MouseActivateListener textBox1Listener;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
textBox1Listener = new MouseActivateListener(textBox1);
}
private void textBox1_Enter(object sender, EventArgs e)
{
if (textBox1Listener.MouseActivated)
{
MessageBox.Show("Mouse Enter");
}
else
{
MessageBox.Show("Tab Enter");
}
}
}
答案 1 :(得分:0)
您可以使用Form.KeyPreview事件并将最后一次按键存储在变量中。然后在您的控件的Enter
事件中,检查最后按下的键的值。如果这是一个标签,请执行以下操作:
private Keys lastKeyCode;
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
this.lastKeyCode = e.KeyCode;
}
然后在Enter
事件中,检查它:
if (lastKeyCode == Keys.Tab)
{
// Whatever...
}
答案 2 :(得分:0)
直接使用邮件过滤器拦截WM_KEYUP
和WM_KEYDOWN
,以检索Tab键的状态。对于这样一个看似简单的任务来说,这似乎是过分的,但显然Tab键是从大多数Windows窗体事件中被禁止的。
很乐意采取更清晰的答案,但就目前而言,就是这样:
class TabMessageFilter : IMessageFilter
{
public bool TabState { get; set; }
public bool PreFilterMessage(ref Message m)
{
const int WM_KEYUP = 0x101;
const int WM_KEYDOWN = 0x100;
switch (m.Msg)
{
case WM_KEYDOWN:
if ((Keys)m.WParam == Keys.Tab) TabState = true;
break;
case WM_KEYUP:
if ((Keys)m.WParam == Keys.Tab) TabState = false;
break;
}
return false;
}
}
class MainForm : Form
{
TabMessageFilter tabFilter;
public MainForm()
{
tabFilter = new TabMessageFilter();
Application.AddMessageFilter(tabFilter);
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
Application.RemoveMessageFilter(tabFilter);
base.OnFormClosed(e);
}
void control_Enter(object sender, EventArgs e)
{
if (tabFilter.TabState) // do something
else // do domething else
}
}