1

我正在开发一个大型 C# winforms 项目。在向我的最终用户解释了数千次他们必须按 Tab 而不是在文本框、数据网格和任何地方输入之后,我决定在某处添加一个复选框,以便用户可以选择设置是否想用 Tab 替换输入。我自己不喜欢它,因为我认为会发生奇怪的事情,但我想尝试一下。

问题是我有很多表格,还有很多我必须设置 keydown 事件或类似事件的地方。我想把所有这些放在一个地方,在应用程序级别。有办法吗?

4

4 回答 4

0

MessageFilter将 a与 结合使用要简单得多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;
    }
}
于 2013-09-06T07:35:12.117 回答
0

我想这是不可能的,因为某些控件会以不同的方式公开 keydown 事件(例如在 gridview 的单元格中)。您可以递归地遍历表单中的所有控件,并为基本控件分配事件。然后可以在中心位置处理事件本身

于 2013-09-05T10:42:21.283 回答
0

我建议您创建一个单独的类,构造函数接受您需要的参数(如textbox),您创建global variables参数并将其分配给构造函数中的变量。

然后在类中创建事件处理程序,然后您可以使用变量将代码放入事件处理程序中。

然后,您可以在需要keydown事件的任何地方调用课程

于 2013-09-05T10:44:31.353 回答
0

表单级别(您可以在基本表单中实现行为并从中继承):

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

于 2013-09-05T11:06:39.657 回答