[英]how to create non window bound keyboard shortcuts
我正在創建一個C#應用程序,可能是WinForm,但最好是控制台應用程序,即使應用程序不在前台,它也需要捕獲鍵盤快捷鍵。 如何做到這一點,我知道這是可能的,因為Songbird可以做到這一點。
這個鍵盤快捷鍵的形式是ctrl + - >我到目前為止還沒有任何代碼,因為我甚至沒有關於如何全局注冊鍵盤快捷鍵的任何想法。
您應該使用RegisterHotkey而不是鍵盤鈎子。
當你只想要一個全局熱鍵時使用全局鍵盤鈎是濫用api。 它還具有負面的性能影響,因為每個密鑰在到達目標程序之前都需要由程序處理。
這里有一個示例代碼,我希望能幫助...(祝你好運!)
用法:
_hotKey0 = new HotKey(Key.F9, KeyModifier.Shift | KeyModifier.Win, OnHotKeyHandler);
...
// ******************************************************************
private void OnHotKeyHandler(HotKey hotKey)
{
SystemHelper.SetScreenSaverRunning();
}
類:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Mime;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
namespace UnManaged
{
public class HotKey : IDisposable
{
private static Dictionary<int, HotKey> _dictHotKeyToCalBackProc;
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, UInt32 fsModifiers, UInt32 vlc);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
public const int WmHotKey = 0x0312;
private bool _disposed = false;
public Key Key { get; private set; }
public KeyModifier KeyModifiers { get; private set; }
public Action<HotKey> Action { get; private set; }
public int Id { get; set; }
// ******************************************************************
public HotKey(Key k, KeyModifier keyModifiers, Action<HotKey> action, bool register = true)
{
Key = k;
KeyModifiers = keyModifiers;
Action = action;
if (register)
{
Register();
}
}
// ******************************************************************
public bool Register()
{
int virtualKeyCode = KeyInterop.VirtualKeyFromKey(Key);
Id = virtualKeyCode + ((int)KeyModifiers * 0x10000);
bool result = RegisterHotKey(IntPtr.Zero, Id, (UInt32)KeyModifiers, (UInt32)virtualKeyCode);
if (_dictHotKeyToCalBackProc == null)
{
_dictHotKeyToCalBackProc = new Dictionary<int, HotKey>();
ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
}
_dictHotKeyToCalBackProc.Add(Id, this);
Debug.Print(result.ToString() + ", " + Id + ", " + virtualKeyCode);
return result;
}
// ******************************************************************
public void Unregister()
{
HotKey hotKey;
if (_dictHotKeyToCalBackProc.TryGetValue(Id, out hotKey))
{
UnregisterHotKey(IntPtr.Zero, Id);
}
}
// ******************************************************************
private static void ComponentDispatcherThreadFilterMessage(ref MSG msg, ref bool handled)
{
if (!handled)
{
if (msg.message == WmHotKey)
{
HotKey hotKey;
if (_dictHotKeyToCalBackProc.TryGetValue((int)msg.wParam, out hotKey))
{
if (hotKey.Action != null)
{
hotKey.Action.Invoke(hotKey);
}
handled = true;
}
}
}
}
// ******************************************************************
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// ******************************************************************
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be _disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be _disposed.
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!this._disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
// Dispose managed resources.
Unregister();
}
// Note disposing has been done.
_disposed = true;
}
}
}
// ******************************************************************
[Flags]
public enum KeyModifier
{
None = 0x0000,
Alt = 0x0001,
Ctrl = 0x0002,
NoRepeat = 0x4000,
Shift = 0x0004,
Win = 0x0008
}
// ******************************************************************
}
這可以通過Windows Hook捕獲WH_KEYBOARD_LL通過低級鍵盤掛鈎來完成 。
以下是關於在C#中設置Global Hook的CodeProject文章,該文章演示了整個過程。
一種可能的方法是使用Windows Hook。 但是為了做到這一點,你需要創建一個本機DLL,並在其中編寫你的回調函數作為鈎子安裝。
查找SetWindowsHookEx作為起點。 關於如何使用它的網上樣本也很多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.