Разбор UnregisterHotkey из usercontrol в родительскую форму - PullRequest
0 голосов
/ 10 апреля 2020

Поэтому я пытаюсь получить пользовательские входы, когда кто-то нажимает горячие клавиши, также за пределами формы (в данном случае SHIFT + A). Теперь, так как я хотел добавить вкладки в свое приложение форм, я решил go с usercontrols, теперь проблема в том, что я не могу получить доступ к событию formclosing (из form1) в usercontrol, то есть мне придется каким-то образом анализировать все Я хотел выполнить в форме закрытия мероприятия.

Usercontrol (по имени home)

public partial class Home : UserControl
    { 
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        enum KeyModifier
        {
            None = 0,
            Alt = 1,
            Control = 2,
            Shift = 4,
            WinKey = 8
        }

        public Home()
        {
            InitializeComponent();

            int id = 0;     // The id of the hotkey. 
            RegisterHotKey(this.Handle, id, (int)KeyModifier.Shift, Keys.A.GetHashCode());       //Register Shift + A as global hotkey. 
        }

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

            if (m.Msg == 0x0312)
            {
                /* Note that the three lines below are not needed if you only want to register one hotkey.
                 * The below lines are useful in case you want to register multiple keys, which you can use a switch with the id as argument, or if you want to know which key/modifier was pressed for some particular reason. */

                Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);                  // The key of the hotkey that was pressed.
                KeyModifier modifier = (KeyModifier)((int)m.LParam & 0xFFFF);       // The modifier of the hotkey that was pressed.
                int id = m.WParam.ToInt32();                                        // The id of the hotkey that was pressed.


                MessageBox.Show("Hotkey has been pressed!");
                // do something
            }
        }
    }

Теперь я могу sh проанализировать метод unregisterHotKey, чтобы очистить все горячие клавиши после закрытия программы (таким образом вы не сможете нажимать SHIFT-A, когда приложение закрыто)

UnregisterHotKey(this.Handle, 0);

Теперь мой вопрос: почему вы анализируете вышеизложенное из usercontrol для события formclosing в моей основной форме, чтобы все ключи будут успешно очищены, если это имеет смысл ...

Ответы [ 2 ]

0 голосов
/ 11 апреля 2020

Вот как я предлагаю справиться:

, поскольку вы уже переопределяете WndProc для обработки WM_HOTKEY, также обрабатывайте WM_DESTROY . Это сообщение отправляется, когда UserControl Windows собирается уничтожить, поскольку его родительская форма закрывается.
Вы можете позвонить UnregisterHotKey(), когда ваш UserControl получит это сообщение.

UserControls не нужно ничего знать о его контейнере ParentForm: HotKey регистрируется при создании UserControl и незарегистрирован при его разрушении.

Это лучше, чем обработка Dispose(), поскольку UserControl не может быть фактически утилизирован до закрытия приложения, если родительская форма явно не вызывает Dispose().

Я сделал несколько модификаций исходного кода, так как в нем отсутствовали несколько частей.

public partial class Home : UserControl
{ 
    [DllImport("user32.dll")]
    private static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifier fsModifiers, int vk);

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

    private const int WM_DESTROY = 0x0002;
    private const int WM_HOTKEY = 0x0312;
    private const int baseHotKeyID = 0x100;

    enum KeyModifier : int
    {
        None = 0,
        Alt = 1,
        Control = 2,
        Shift = 4,
        WinKey = 8,
        NoRepeat = 0x4000
    }

    public Home() => InitializeComponent();

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (!RegisterHotKey(this.Handle, baseHotKeyID, KeyModifier.Shift | KeyModifier.NoRepeat, (int)Keys.F11)) {
            MessageBox.Show("RegisterHotKey Failed");
        }
    }

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        switch (m.Msg) {

            case WM_DESTROY:
                UnregisterHotKey(this.Handle, baseHotKeyID);
                m.Result = IntPtr.Zero;
                break;

            case WM_HOTKEY:
                int hotKeyID = m.WParam.ToInt32();
                var keyPressed = (Keys)(m.LParam.ToInt32() >> 16);
                var modifier = (KeyModifier)(m.LParam.ToInt32() & 0xFF);
                switch (hotKeyID) {
                    case baseHotKeyID:  // Identifier of the SHIFT+F11 HotKey just registered
                        // Handle single HotKey
                        if (modifier == KeyModifier.Shift) {
                            MessageBox.Show("Hotkey SHIFT+F11 has been pressed!");
                        }
                        break;
                    //case baseHotKeyID + 1:
                    // Handle another HotKey
                    //    break;

                }
                m.Result = IntPtr.Zero;
                break;
        }
    }
}
0 голосов
/ 11 апреля 2020

Я нашел решение (которое работает частично).

Я просто добавил publi c void, который отменял бы регистрацию ключей, и вызвал его из mainform внутри события formclosing

In IDE, это иногда не будет работать. Но при создании решения кажется, что он работает безупречно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...