Register the global shortcut key implementation idea and code in Winform and WPF

  • 2020-05-09 19:11:36
  • OfStack

Shortcut helper class

 
class HotKey 
{ 
/// <summary> 
///  If the function executes successfully, the return value is not 0 .  
///  If the function fails, the return value is 0 . To get an extended error message, call GetLastError . .NET methods :Marshal.GetLastWin32Error() 
/// </summary> 
/// <param name="hWnd"> Handle to the window to define the hotkey </param> 
/// <param name="id"> Define hotkeys ID Not with others ID Repeated)  </param> 
/// <param name="fsModifiers"> Identifies whether the hotkey is being pressed Alt , Ctrl , Shift , Windows It doesn't take effect until you wait for the key </param> 
/// <param name="vk"> Define the contents of the hotkeys ,WinForm Can be used in Keys Enumeration conversion,  
/// WPF In the Key Enumeration is incorrect , You should use System.Windows.Forms.Keys Enumeration, or customizing the correct enumeration or int constant </param> 
/// <returns></returns> 
[DllImport("user32.dll", SetLastError = true)] 
public static extern bool RegisterHotKey( 
IntPtr hWnd, 
int id, 
KeyModifiers fsModifiers, 
int vk 
); 
/// <summary> 
///  Unregister hotkeys  
/// </summary> 
/// <param name="hWnd"> Handle to the window to cancel the hotkey </param> 
/// <param name="id"> You want to cancel the hotkeys ID</param> 
/// <returns></returns> 
[DllImport("user32.dll", SetLastError = true)] 
public static extern bool UnregisterHotKey( 
IntPtr hWnd, 
int id 
); 
/// <summary> 
///  Add to the global atom table 1 , and returns only that string 1 identifier , On success, the return value is the newly created atom ID, Failure to return 0 
/// </summary> 
/// <param name="lpString"></param> 
/// <returns></returns> 
[DllImport("kernel32", SetLastError = true)] 
public static extern short GlobalAddAtom(string lpString); 
[DllImport("kernel32", SetLastError = true)] 
public static extern short GlobalDeleteAtom(short nAtom); 
/// <summary> 
///  Defines the name of the secondary key (converts Numbers to characters for easy memory, or USES numeric values instead of this enumeration)  
/// </summary> 
[Flags()] 
public enum KeyModifiers 
{ 
None = 0, 
Alt = 1, 
Ctrl = 2, 
Shift = 4, 
WindowsKey = 8 
} 
/// <summary> 
///  The message corresponding to the hotkey ID 
/// </summary> 
public const int WM_HOTKEY = 0x312; 
} 

WinForm method:
Register the event in onload in, and then override WndProc to process the returned message
 
int alts,altd; 
protected override void OnLoad(EventArgs e) 
{ 
alts= HotKey.GlobalAddAtom("Alt-S"); 
altd= HotKey.GlobalAddAtom("Alt-D"); 
HotKey.RegisterHotKey(this.Handle, alts, HotKey.KeyModifiers.Alt, (int)Keys.S); 
HotKey.RegisterHotKey(this.Handle, altd, HotKey.KeyModifiers.Alt, (int)Keys.D); 
} 
protected override void WndProc(ref Message m)//  monitoring Windows The message  
{ 
switch (m.Msg) 
{ 
case HotKey.WM_HOTKEY: 
ProcessHotkey(m);// Called when the hotkey is pressed ProcessHotkey() function  
break; 
} 
base.WndProc(ref m); // Passing system messages from the parent class WndProc 
} 
private void ProcessHotkey(Message m) // This function is called when the set key is pressed  
{ 
IntPtr id = m.WParam;//IntPtr A platform-specific type used to represent a pointer or handle  
int sid=id.ToInt32(); 
if(sid==alts) 
{ 
MessageBox.Show(" Press the Alt+S"); 
} 
else if(sid==altd) 
{ 
MessageBox.Show(" Press the Alt+D"); 
} 
} 

You can also use AddMessageFilter to add processing in Application instead of overloading WndProc. You can make form itself implement IMessageFilter interface.
Registration method
 
[STAThread] 
static void Main() 
{ 
Application.EnableVisualStyles(); 
Application.SetCompatibleTextRenderingDefault(false); 
var form = new Form1(); 
Application.AddMessageFilter(form); 
Application.Run(form); 
} 

Implementing an interface
 
bool IMessageFilter.PreFilterMessage(ref Message m) 
{ 
const int WM_HOTKEY = 0x0312;// if m.Msg The value of 0x0312 So the user pressed the hotkey  
switch (m.Msg) 
{ 
case WM_HOTKEY: 
ProcessHotkey(m);// Called when the hotkey is pressed ProcessHotkey() function  
break; 
} 
// If the message is filtered and prevented from being scheduled  true ; If the message is allowed to continue down 1 Is a filter or control  false 
return false ; 
} 

If messages are processed at both AddMessageFilter and WndProc, the order is IMessageFilter first, then WndProc
WPF method:
WPF the registration methods and Winform1 sample, just WPF Key enumeration values that can not correctly to monitor, to quote System. Windows. Forms. Keys or definition can be correctly registered, window handle also needs to use WindowInteropHelper to get, processing function to join and Winform is different, also need HwndSource to add handlers.
Registration and processing methods
 
int alts, altd; 
private void Window_Loaded(object sender, RoutedEventArgs e) 
{ 
HwndSource hWndSource; 
WindowInteropHelper wih = new WindowInteropHelper(this); 
hWndSource = HwndSource.FromHwnd(wih.Handle); 
// Add handler  
hWndSource.AddHook(MainWindowProc); 
alts = HotKey.GlobalAddAtom("Alt-S"); 
altd = HotKey.GlobalAddAtom("Alt-D"); 
HotKey.RegisterHotKey(wih.Handle, alts, HotKey.KeyModifiers.Alt, (int)System.Windows.Forms.Keys.S); 
HotKey.RegisterHotKey(wih.Handle, altd, HotKey.KeyModifiers.Alt, (int)System.Windows.Forms.Keys.D); 
} 
private IntPtr MainWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
{ 
switch (msg) 
{ 
case HotKey.WM_HOTKEY: 
{ 
int sid = wParam.ToInt32(); 
if (sid == alts) 
{ 
MessageBox.Show(" Press the Alt+S"); 
} 
else if (sid == altd) 
{ 
MessageBox.Show(" Press the Alt+D"); 
} 
handled = true; 
break; 
} 
} 
return IntPtr.Zero; 
} 

Note:
If you register the keyboard shortcut, fsModifiers parameter in RegisterHotKey is 0, that is, None option. Some security software will alert you, which may cause security problems because you can listen to the keyboard globally
The code download


Related articles: