Wie kann ich mich registrieren oder Globale hot-key zu sagen STRG+UMSCHALT+(BRIEF) mit WPF und .NET 3.5?

StackOverflow https://stackoverflow.com/questions/48935

Frage

Ich Baue eine Anwendung in C# mit WPF.Wie kann ich die Bindung an ein paar Tasten?

Auch, wie kann ich binden Windows-Taste?

War es hilfreich?

Lösung

Ich bin mir nicht sicher, was Sie bedeuten, von "global" hier, aber hier geht es (ich nehme an, du meinst einen Befehl auf der Anwendungsebene, zum Beispiel, Speichern Sie Alle ausgelöst werden können Sie von überall aus durch Strg + Shift + S.)

Finden Sie die globalen UIElement Ihrer Wahl, zum Beispiel die top-level-Fenster, die die Muttergesellschaft von alle die steuert, wo Sie brauchen diese verbindlich.Aufgrund der "sprudelnden" von WPF-Ereignisse, Ereignisse, die an untergeordneten Elementen bubble ganzen Weg bis zu die Wurzel von der Steuerung Baum.

Nun, zuerst müssen Sie

  1. binden Sie die Schlüssel-Combo mit einem Befehl mit einem InputBinding wie diese
  2. Sie können dann Anschluß der Befehl an Ihren handler (z.B.code, der aufgerufen wird, von SaveAll) über eine CommandBinding.

Für die Windows - Taste, Sie verwenden die richtige Schlüssel aufgezählt Mitglied, Key.LWin oder Key.RWin

    public WindowMain()
    {
       InitializeComponent();
       // Bind Key
       InputBinding ib = new InputBinding(
           MyAppCommands.SaveAll,
           new KeyGesture(Key.S, ModifierKeys.Shift | ModifierKeys.Control));
       this.InputBindings.Add(ib);
       // Bind handler
       CommandBinding cb = new CommandBinding( MyAppCommands.SaveAll);
       cb.Executed += new ExecutedRoutedEventHandler( HandlerThatSavesEverthing );
       this.CommandBindings.Add (cb );
    }

    private void HandlerThatSavesEverthing (object obSender, ExecutedRoutedEventArgs e)
    {
      // Do the Save All thing here.
    }

Andere Tipps

Dies ist eine voll funktionsfähige Lösung, hoffe es hilft...

Verwendung:

_hotKey = new HotKey(Key.F9, KeyModifier.Shift | KeyModifier.Win, OnHotKeyHandler);

...

private void OnHotKeyHandler(HotKey hotKey)
{
    SystemHelper.SetScreenSaverRunning();
}

Klasse:

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
    }

    // ******************************************************************
}

Wenn du gehst zu mischen, Win32-und WPF, hier ist, wie ich es gemacht habe:

using System;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Windows.Media;
using System.Threading;
using System.Windows;
using System.Windows.Input;

namespace GlobalKeyboardHook
{
    public class KeyboardHandler : IDisposable
    {

        public const int WM_HOTKEY = 0x0312;
        public const int VIRTUALKEYCODE_FOR_CAPS_LOCK = 0x14;

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        private readonly Window _mainWindow;
        WindowInteropHelper _host;

        public KeyboardHandler(Window mainWindow)
        {
            _mainWindow = mainWindow;
            _host = new WindowInteropHelper(_mainWindow);

            SetupHotKey(_host.Handle);
            ComponentDispatcher.ThreadPreprocessMessage += ComponentDispatcher_ThreadPreprocessMessage;
        }

        void ComponentDispatcher_ThreadPreprocessMessage(ref MSG msg, ref bool handled)
        {
            if (msg.message == WM_HOTKEY)
            {
                //Handle hot key kere
            }
        }

        private void SetupHotKey(IntPtr handle)
        {
            RegisterHotKey(handle, GetType().GetHashCode(), 0, VIRTUALKEYCODE_FOR_CAPS_LOCK);
        }

        public void Dispose()
        {
            UnregisterHotKey(_host.Handle, GetType().GetHashCode());
        }
    }
}

Sie können den virtual-key code für den hotkey Sie möchten, registrieren Sie sich hier: http://msdn.microsoft.com/en-us/library/ms927178.aspx

Kann es einen besseren Weg, aber das ist, was ich habe, so weit.

Cheers!

Registrieren OS-level-Verknüpfungen ist fast nie eine gute Sache:Benutzer möchten nicht, dass Sie zu Chaos mit Ihren OS.

Das heißt, es gibt eine viel einfachere und benutzerfreundliche Art und Weise dies zu tun, in WPF, wenn Sie sind ok mit der hotkey funktioniert in der Anwendung nur (ich.e so lange, wie Sie Ihre WPF-Anwendung den Fokus hat):

In App.xaml.cs :

protected override void OnStartup(StartupEventArgs e)
{
   EventManager.RegisterClassHandler(typeof(Window), Window.PreviewKeyUpEvent, new KeyEventHandler(OnWindowKeyUp));
}

private void OnWindowKeyUp(object source, KeyEventArgs e))
{
   //Do whatever you like with e.Key and Keyboard.Modifiers
}

So einfach ist das

Dies ist ähnlich zu den bereits gegebenen Antworten, aber ich finde es ein bisschen cleaner:

using System;
using System.Windows.Forms;

namespace GlobalHotkeyExampleForm
{
    public partial class ExampleForm : Form
    {
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        enum KeyModifier
        {
            None = 0,
            Alt = 1,
            Control = 2,
            Shift = 4,
            WinKey = 8
        }

        public ExampleForm()
        {
            InitializeComponent();

            int id = 0;     // The id of the hotkey. 
            RegisterHotKey(this.Handle, id, (int)KeyModifier.Shift, Keys.A.GetHashCode());       // Register Shift + A as global hotkey. 
        }

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

            if (m.Msg == 0x0312)
            {
                /* Note that the three lines below are not needed if you only want to register one hotkey.
                 * The below lines are useful in case you want to register multiple keys, which you can use a switch with the id as argument, or if you want to know which key/modifier was pressed for some particular reason. */

                Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);                  // The key of the hotkey that was pressed.
                KeyModifier modifier = (KeyModifier)((int)m.LParam & 0xFFFF);       // The modifier of the hotkey that was pressed.
                int id = m.WParam.ToInt32();                                        // The id of the hotkey that was pressed.


                MessageBox.Show("Hotkey has been pressed!");
                // do something
            }
        }

        private void ExampleForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            UnregisterHotKey(this.Handle, 0);       // Unregister hotkey with id 0 before closing the form. You might want to call this more than once with different id values if you are planning to register more than one hotkey.
        }
    }
}

Ich habe es gefunden auf fluxbytes.com.

Obwohl RegisterHotKey ist manchmal genau das, was Sie wollen, in den meisten Fällen werden Sie wahrscheinlich nicht verwenden möchten, system-wide hotkeys.Ich landete mit code wie dem folgenden:

using System.Windows;
using System.Windows.Interop;

namespace WpfApp
{
    public partial class MainWindow : Window
    {
        const int WM_KEYUP = 0x0101;

        const int VK_RETURN = 0x0D;
        const int VK_LEFT = 0x25;  

        public MainWindow()
        {
            this.InitializeComponent();

            ComponentDispatcher.ThreadPreprocessMessage += 
                ComponentDispatcher_ThreadPreprocessMessage;
        }

        void ComponentDispatcher_ThreadPreprocessMessage(
            ref MSG msg, ref bool handled)
        {
            if (msg.message == WM_KEYUP)
            {
                if ((int)msg.wParam == VK_RETURN)
                    MessageBox.Show("RETURN was pressed");

                if ((int)msg.wParam == VK_LEFT)
                    MessageBox.Show("LEFT was pressed");
            }
        }
    }
}

Ich bin mir nicht sicher über WPF, aber diese helfen können.Ich benutzte die Lösung beschrieben RegisterHotKey (user32) (geändert, um meine Bedürfnisse natürlich) für eine C# Windows Forms-Anwendung zuweisen STRG-Tastenkombination in Windows, um ein C# - Formular, und es funktionierte wunderbar (sogar unter Windows Vista).Ich hoffe es hilft und viel Glück!

Ich habe das Globale Hotkeys in WPF Projekt auf codeproject.com was macht den job für mich.Es ist relativ neu, nicht müssen einen Verweis auf System.Windows.Formen und Werken "weltweit" in Bezug auf die Reaktion auf die hotkey-Taste gedrückt wird, selbst wenn "Ihre" Anwendung ist nicht das aktive Fenster ist.

RegisterHotKey() vorgeschlagen durch John funktionieren könnte - der einzige Haken ist, dass es erfordert ein HWND (mit PresentationSource.FromVisual(), und Gießen das Ergebnis einer hwndsource verwenden).

Jedoch, Sie müssen auch Antworten auf die WM_HOTKEY Nachricht - und ich bin nicht sicher, ob es ist ein Weg, um Zugang zu den WndProc ein WPF-Fenster oder nicht (was kann getan werden, für Windows Forms windows).

Baboon ' s Lösung funktioniert am besten, da Sie möglicherweise mehrere Fenster.Ich habe zwicken, so verwendet er die PreviewKeyDownEvent statt der PreviewKeyUpEvent, um zu behandeln, Wiederholung in der Tastenanschläge.

Ich würde raten, gegen OS-level-Registrierung, es sei denn, Sie schreiben etwas wie ein snipping-tool oder eine audio-recording-app lässt Sie Zugriff auf Funktionalität, wenn das Fenster wird nicht fokussiert.

Ein Kollege schrieb ein Beispiel, wie zu erstellen Sie eine low-level-Tastatur-hook zu verwendet werden mit WPF.

http://blogs.vertigo.com/personal/ralph/Blog/Lists/Posts/Post.aspx?ID=8

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top