0

I am trying to register a global hotkey in Visual c# 2012, build target framework .NET3, after using http://www.dreamincode.net/forums/topic/180436-global-hotkeys/ as a tutorial, I got the following (abbreviated) files:

  1. GlobalHotkey.cs

    using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace barcodelabel
    {
        public class GlobalHotkey
        {
            private int modifier;
            private int key;
            private IntPtr hWnd;
            private int id;
    
            public GlobalHotkey(int modifier, Keys key, Form form)
            {
                this.modifier = modifier;
                this.key = (int)key;
                this.hWnd = form.Handle;
                id = this.GetHashCode();
            }
    
            public bool Register()
            {
                return RegisterHotKey(hWnd, id, modifier, key);
            }
    
            public bool Unregister()
            {
                return UnregisterHotKey(hWnd, id);
            }
    
            public override int GetHashCode()
            {
                return modifier ^ key ^ hWnd.ToInt32();
            }
    
            [DllImport("user32.dll")]
            private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
    
            [DllImport("user32.dll")]
            private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
        }
    }
    
  2. GlobalHotkeyConstants.cs

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace barcodelabel
    {
        class GlobalHotkeyConstants
        {
            public const int NOMOD = 0x0000;
            public const int ALT = 0x0001;
            public const int CTRL = 0x0002;
            public const int SHIFT = 0x0004;
            public const int WIN = 0x0008;
    
            //windows message id for hotkey
            public const int WM_HOTKEY_MSG_ID = 0x0312;
    
        }
    }
    
  3. My Form1.cs

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Windows;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using Microsoft.Win32;
    
    namespace barcodelabel
    {
        public partial class Form1 : Form
        {
    
            private GlobalHotkey ghk;
    
             protected override void WndProc(ref Message m)
            {
                if (m.Msg == GlobalHotkeyConstants.WM_HOTKEY_MSG_ID) {
                    MessageBox.Show("HOTKEY PRESSED");
    
                }
                base.WndProc(ref m);
            }
    
           public Form1()
           {
               InitializeComponent();
               this.ghk = new GlobalHotkey(GlobalHotkeyConstants.SHIFT,  Keys.F10, this);
           }
    
           private void Form1_Load(object sender, EventArgs e)
           {
               if (!this.ghk.Register()) 
               {
                   MessageBox.Show("Hotkey could not be registered");
               }
           }
    
           private void Form1_FormClosing(object sender, FormClosingEventArgs e)
           {
               this.ghk.Unregister();
           }
       }
    

No matter what hotkey I want to choose, it can not be registered. I tried using Hotkey Explorer from http://hkcmdr.anymania.com/ to check if the hotkey already was taken, but it only told me it was free.

What can I do to solve this?

ty812
  • 3,284
  • 17
  • 36
  • This code has many deep flaws. Keep looking for something better. – Hans Passant Jul 22 '14 at 13:48
  • Hi Hans ... can you give me a hint where these flaws are so I can identify "better ways"? – ty812 Jul 22 '14 at 13:50
  • 1
    Using a hash for the id is nonsense, a hash collision produces undiagnosable failure. Just use a counter. The pinvoke declarations are wrong, SetLastError = true is necessary to provide a decent error message when the code fails. Not throwing a Win32Exception when a winapi call fails makes failure very hard to diagnose. There is no hint at all that this code needs to be called from the form's OnHandleCreated() override. Which certainly *can* run multiple times, your hotkey simply stops working when it does. – Hans Passant Jul 22 '14 at 13:57

1 Answers1

3

I've wrote down your code in my VS and it worked properly. If you want to find the error, don't check a Boolean returned form API only. if it returns False, try using GetLastError API. Then you will have an error code. Refer to MSDN and get the error's description.

Mohammad Mirmostafa
  • 1,439
  • 1
  • 13
  • 26
  • Thank you so very much for that hint... Turns out I tried using a window handle that did not exist at that time. After moving the "new GlobalHotkey" line to Form1_Load, it works like a charm. – ty812 Jul 22 '14 at 13:47