全球热键叫了两次

时间:2015-07-31 09:18:15

标签: c# winapi registerhotkey

我在Windows中遇到了全局热键的问题。 我和我的朋友正在开发一个程序(在C#中),该程序使用通过User32.dll的RegisterHotkey函数调用注册的windows全局热键。

在我的电脑上一切正常,但是在我的朋友电脑上注册热键时,即使按下一次按键并指定了MOD_NOREPEAT标志,也会被称为ALWAYS两次。 我尝试注册两个相同的热键但是不可能(只允许一个寄存器调用指定的热键组合,第二个相同的组合被RegisterHotkey函数拒绝)。

这是代码。 我为已注册的热键创建了一个简单的包装器(用于管理我的代码中的已注册组合):

    public class HotkeyStructure
    {
        /// <summary>
        /// Id of registered hotkey structure
        /// </summary>
        public int HotkeyId { get; private set; }
        /// <summary>
        /// Hotkey modifiers (eg SHIFT + ALT etc)
        /// </summary>
        public int HotkeyModifiers { get; private set; }
        /// <summary>
        /// Virtual key code (all alphanumeric keys)
        /// </summary>
        public int VirtualKeyCode { get; private set; }

        /// <summary>
        /// Action executed when hotkey detected
        /// </summary>
        public Action OnHotkeyAction { get; set; }


        public HotkeyStructure(Modifiers hotkeyModifiers, VirtualKeyCode virtualKeyCode, int hotkeyId)
        {
            this.HotkeyModifiers = (int)hotkeyModifiers;
            this.VirtualKeyCode = (int)virtualKeyCode;
            this.HotkeyId = hotkeyId;
        }
    }

以下是管理注册处理程序的类的代码:

[Flags]
public enum Modifiers : int
{
    NONE = 0,
    MOD_ALT = 0x0001,
    MOD_CONTROL = 0x0002,
    MOD_NOREPEAT = 0x4000,
    MOD_SHIFT = 0x0004,
    MOD_WIN = 0x0008
}    


public sealed class HotkeyApi
{
    //Constant which detects hotkey message
    private const int WM_HOTKEY = 0x0312;
    //processhandle pointer
    IntPtr processHandle;
    //process handle object
    private HwndSource source;

    //static list of all registered hotkeys
    private static List<HotkeyStructure> _registeredHotkeys = new List<HotkeyStructure>();

    //external library function import
    [DllImport("User32.dll")]
    private static extern bool RegisterHotKey(IntPtr handle, int hotkeyId, int modifiers, int virtualKey);

    [DllImport("User32.dll")]
    private static extern bool UnregisterHotKey(IntPtr handle, int hotkeyId);

    public HotkeyApi(HwndSource source)
    {
        this.processHandle = source.Handle;
        this.source = source;
        //attaching hook to system message sources
        this.source.AddHook(WndProc);
    }

    //message handler
    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_HOTKEY)
        {
            HotkeyStructure structure = _registeredHotkeys.SingleOrDefault(h => h.HotkeyId == wParam.ToInt32());
            if (structure != null)
            {
                structure.OnHotkeyAction();
            }
        }
        return IntPtr.Zero;
    }

    /// <summary>
    /// Registers HotkeyStructure with custom Action passed in parameter (action can be changed during execution via public field in returned HotkeyStructure
    /// </summary>
    /// <param name="hotkeyModifiers">Which key should be pressed with other key to fire an event (option NONE causes disability for selected keycode)</param>
    /// <param name="keycode">Keycode which should be pressed with modifier</param>
    /// <param name="eventHadler">Action which will be fired with registered hotkey</param>
    /// <returns>null if register action failed (eg. registering new hotkey which is the same as one which already exist) otherwise new HotkeyStructure</returns>
    public HotkeyStructure RegisterHotkey(Modifiers hotkeyModifiers, VirtualKeyCode keycode, Action eventHadler)
    {
        int id = _registeredHotkeys.Count + 1;
        bool result = RegisterHotKey(processHandle, id, (int)hotkeyModifiers, (int)keycode);
        if (result)
        {
            HotkeyStructure structure = new HotkeyStructure(hotkeyModifiers, keycode, id);
            structure.OnHotkeyAction = eventHadler;
            _registeredHotkeys.Add(structure);
            return structure;
        }
        else
        {
            return null;
        }
    }

    /// <summary>
    /// Removes hotkey from the list 
    /// </summary>
    /// <param name="hotkeyId">Id of hotkey structure (obj.HotkeyId)</param>
    /// <returns>true if succeeds otherwise false</returns>
    public bool UnregisterHotkey(int hotkeyId)
    {
        if (UnregisterHotKey(processHandle, hotkeyId))
        {
            var str = _registeredHotkeys.SingleOrDefault(h => h.HotkeyId == hotkeyId);
            if (str != null)
            {
                _registeredHotkeys.Remove(str);
                return true;
            }
        }
        return false;
    }       }

这段代码在OnLoadCompleted方法的App.xaml.cs中调用:

               var source = PresentationSource.FromVisual(App.Current.MainWindow) as HwndSource;
               Hotkeys = new HotkeyApi(source);

什么可能导致这个问题?

(抱歉可能出现语言错误。)

0 个答案:

没有答案
相关问题