我在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);
什么可能导致这个问题?
(抱歉可能出现语言错误。)