当前位置: 动力学知识库 > 问答 > 编程问答 >

winforms - C# replace enter with tab on application level

问题描述:

I'm working on a large C# winforms project. After explaining thousands of times to my end users that they have to press tab instead of enter in textboxes, datagrids, and wherever, I decided to add a checkbox somewhere, so users can optionally set if they want to replace enter with tab. I don't like it myself, because I think weird stuff will happen, but I'd like to try it.

The thing is that I have lots of forms, and lots of places where I would have to set a keydown event or similar. I would like to put all of this in one place, on application level. Is there a way for this?

网友答案:

I guess this is not possible, since some controls will expose the keydown event diverently (for example in cells of the gridview). You could iterate through all controls in a form recursively and assign the event for the basic controls though. The event itself then could be handled in a central place

网友答案:

I'll advice you to create a separate class that the constructor accept the parameters you need (like the textbox), You create global variables and assign the parameters to the variables in the constructor.

Then Create the event handler in the class and then you can put your code in the event handler using the variables.

You can then call the class wherever you need the keydown event

网友答案:

Form level (you can implement the behaviour in the base form and inherit from it):

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;
        }

It probably can be done on application level too: In your main form you'll have to prefilter messages from the message loop (using message filter: Application.AddMessageFilter(your filter)), check for message WM_KEYDOWN = 0x100, check if the pressed key was ENTER, then handle it same as above.You do it only once, in your main form, it'll work on all your child forms.

In your main form class:

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;
            }
        }

sources:

http://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

网友答案:

It's much simpler to use a MessageFilter in combination with 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;
    }
}
分享给朋友:
您可能感兴趣的文章:
随机阅读: