Search code examples
.netwinformskeypressmdi

It is possible to get any keystrokes in application regardless of active window?


My MDI application handles regular keystrokes (A-Z, 0-9 etc.) in handler of Main window with KeyPreview = true. It filters some sequences of incoming characters, hiding them from subsequent KeyPress handlers. This works fine in MDI windows, but the Main window's KeyPress is not invoked if modal window is active (because Main form is no longer focused). I open modal windows through simple ShowDialog().

Is there some way to universally catch and filter KeyPress events regardless of which application window has the focus (including modal windows?)

I'm searching for handling of KeyPresses on application level, not global level. => I don't want to be notified of KeyPresses if the application doesn't have focus.


Solution

  • Is there some way to universally catch and filter KeyPress events regardless of which application window has the focus (including modal windows?) I'm searching for handling of KeyPresses on application level ...

    This can be accomplished via IMessageFilter().

    Here's a quick example:

    public partial class MainMdiParent : Form
    {
    
        private MyFilter MF = new MyFilter();
    
        public MainMdiParent()
        {
            InitializeComponent();
        }
    
        private void MainMdiParent_Load(object sender, EventArgs e)
        {
            MF.EscapeKey += MF_EscapeKey;
            Application.AddMessageFilter(MF);
    
            childA a = new childA();
            a.MdiParent = this;
            a.Show();
    
            a = new childA();
            a.MdiParent = this;
            a.Show(); 
        }
    
        private void MF_EscapeKey()
        {
            Console.WriteLine("Escape Key Trapped in Main Form");
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
            Form dlg = new Form();
            dlg.ShowDialog();
        }
    
    }
    
    public class MyFilter : IMessageFilter
    {
    
        public delegate void EscapeKeyDelegate();
        public event EscapeKeyDelegate EscapeKey;
    
        private const int WM_KEYDOWN = 0x100;
    
        public bool PreFilterMessage(ref Message m)
        {
            switch (m.Msg )
            {
                case WM_KEYDOWN:
                    switch (m.WParam.ToInt32())
                    {
                        case (int)Keys.Escape:
                            if (EscapeKey != null)
                            {
                                EscapeKey();
                            }
                            return true; // suppress it?
                            break;
                    }
                    break;
    
            }
    
            return false; // returning false allows messages to be processed normally
        }
    
    }