RegisterHotKey fails and GetLastWin32Error returns ERROR_INVALID_FLAGS

134 views Asked by At

I am trying to write a C# script that runs in background in tray and when triggered by a global hotkey it does some job but I cannot get around setting a hotkey.

The problem is RegisterHotKey returns false and fails no matter what hotkey combination I choose. I tried getting the error code using GetLastWin32Error and it returned 0x000003EC which is ERROR_INVALID_FLAGS but I don't know what flag is actually invalid.

The script:

using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MyScript
{
    public static class Program
    {
        [DllImport("user32.dll"), SetLastError = true]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);

        [DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        private const int HOTKEY_ID = 1;

        public static void Main()
        {
            ToolStripMenuItem exitMenuItem = new("Exit", null, (sender, e) => { Application.Exit(); });

            using NotifyIcon notifyIcon = new()
            {
                Visible = true,
                Icon = SystemIcons.Application,
                ContextMenuStrip = new ContextMenuStrip()
                {
                    Items = { exitMenuItem },
                },
            };

            using Form form = new()
            {
                ShowInTaskbar = false,
                WindowState = FormWindowState.Minimized,
            };
            form.Load += (sender, e) => { form.Visible = false; };

            var formHandle = form.Handle;
            var hotkeyModifiers = (uint)(Keys.Control | Keys.Alt);
            var hotkeyKey = (uint)Keys.Z;

            if (RegisterHotKey(formHandle, HOTKEY_ID, hotkeyModifiers, hotkeyKey))
            {
                form.FormClosing += (sender, e) => { UnregisterHotKey(formHandle, HOTKEY_ID); };
                Application.AddMessageFilter(new HotkeyMessageFilter(formHandle, async () => await Run()));
            }
            else
            {
                MessageBox.Show($"Could not register hotkey. error code: {Marshal.GetLastWin32Error()}");
            }

            Application.Run(form);
        }

        private static async Task Run()
        {
            // do the job
        }

        private class HotkeyMessageFilter : IMessageFilter
        {
            private const int WM_HOTKEY = 0x0312;
            private readonly IntPtr _formHandle;
            private readonly Action _hotkeyAction;

            public HotkeyMessageFilter(IntPtr formHandle, Action hotkeyAction)
            {
                _formHandle = formHandle;
                _hotkeyAction = hotkeyAction;
            }

            public bool PreFilterMessage(ref Message m)
            {
                if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == HOTKEY_ID && m.HWnd == _formHandle)
                {
                    _hotkeyAction();
                    return true;
                }

                return false;
            }
        }
    }
}

I would greatly appreciate your help.

0

There are 0 answers