C#WinForms和WPF中的全局快捷方式

介绍
有时,您的窗体或窗口(取决于您是否正在构建WinForm或WPF应用程序)可能需要响应热键或快捷方式(本文中可互换使用),无论应用程序是否集中或在后台运行。

此外,如果你想注册多个热键,在应用程序内或外,它有点困难。在本文中,我们将创建一个库,允许应用程序过程的热键和执行其他键盘操作。

术语
HotKeys:这些是用户在键盘上按下的键,可能需要由您的应用程序处理。
LocalHotKeys:一个在应用程序中管理常规热键的类;他们有一个键和或修饰符(修饰符是LocalHotkey的可选),它们只在应用程序集中时才工作。一个例子是Control + C(在大多数情况下用于复制)
GlobalHotKeys:在应用程序之外管理热键的类,无论窗体或窗口是否具有焦点或正在后台运行。它们是具有键AND修改器的常规热键,只要应用程序正在运行(无论是在后台聚焦,最小化还是运行),都会对其进行处理。一个例子是Window + L(用于锁定计算机)
ChordHotKeys:一类高级的LocalHotKeys,更像是两个LocalHotKeys; BASE和CHORD。基地必须有一个BaseKey AND一个BaseModifier,当它们被按下时,它们会启动Chord,Chord有一个键和一个可选的Modifier。一个例子是Control + K,Control + D(用于Visual Studio IDE中的缩进代码),在这种情况下,Control + K是基础,而Control + D是和弦的热键。像LocalHotKeys,他们只有当应用程序的重点工作。
HotKeyManager:这个类管理上面的类;它跟踪其更改,并在键盘上按下与其关联的热键时引发事件。此外,HotKeyManager类可以从键盘侦听所有键按下,报告给我们的应用程序,也可以模拟按键。
*注册热键意味着将Hotkey订阅到HotKeyManager。
HotKeyControl:允许用户通过输入设置热键的UserControl。
这里写图片描述
* HotKeyControl不会将Windows键视为修饰符,而是将其视为与Key(s)枚举中完全相同的键。

背景
在我开始使用.Net之前,我想禁用键盘上的一些键,特别是对于我创建的基于计算机的测试应用程序的Control + Alt + Delete,我研究了编程方式,但发现没有,直到我导致使用ScanCodeMap ,(现在不要太激动了,HotKeyManager不能这样做)只有警告是我不得不重新启动Windows,当我要启用或禁用这些键。我也有麻烦的.Net实现全局快捷键和使键可变。创建这个库是为了加快速度,允许您轻松地在键盘上执行操作,并在同一时间管理多个动态热键,如在VLC播放器和其他应用程序。

源文件
WPF的HotKeyManager类具有大多数WinForm等效项的功能,尽管它可能更容易在同一项目中为两个平台创建类,但是,如果您在WinForm中创建一个程序,并希望引用dll,你还需要导入:

PresentationCore
演示框架和
WindowsBase
这是WPF的核心库,并且如果你在WPF中创建一个程序,你将需要导入:

System.Windows.Forms和
System.Drawing。
版本取决于在编写项目时使用的版本,这将使您的项目被不必要的引用阻塞,这就是为什么我在两个单独的项目中编写库,保持代码使用完全相同。源文件(在C#中但与VB兼容)包含5个项目:C#2.0中的WinForm库,C#3.0和4.0中的WPF库(这只是因为我想为WPF创建一个更好的控件)项目一个为WinForm和WPF。

*我正在为WinForm创建另一个库,将类转换为组件,以便可以在设计时添加和验证,而不是在代码中编写它们。

上班。
快捷方式包含修饰符(可以是一个或多个)和单个键。修饰符键是:Shift键,Alt键,控制键和窗口键(这不完全是一个修饰符,应该只在创建GlobalShortcuts时使用),请注意,这是无论是左还是右键,WinForm中的右Alt键发送“Control + Alt”,WPF发送LeftCtrl,但是有一些调整发送与WinForm相同的键。

一个引用被添加到Microsoft.VisualBasic,我们将使用它来执行一些字符串操作和获得一些键盘键状态。

我们定义一个修饰符枚举,并用flags属性标记它,该属性指定枚举可以被视为一个位字段,第二个枚举定义了当我们想要我们的本地热键事件时。

//首先,我们要定义GlobalHotkeys和LocalHotKeys的修饰符。

#region **修饰符和常量。
    /// <summary>定义用作“修改器”的键。
    /// </summary>
    [Flags]
    public enum Modifiers
    {
        /// <summary>指定键应被视为是,不带任何修饰符。
        /// </summary>

        NoModifier = 0x0000,

        /// <summary>指定用键按下加速键(ALT)。
        /// </summary>
        Alt = 0x0001,
        /// <summary>指定用键按下控制键。
        /// </summary>
        Ctrl = 0x0002,
        /// <summary>指定使用相关键按下Shift键。
        /// </summary>
        Shift = 0x0004,
        /// <summary>指定使用相关键按下Window键。
        /// </summary>
        Win = 0x0008
    }

    public enum RaiseLocalEvent
    {
        OnKeyDown = 0x100, //也是256.和WM_KEYDOWN相同。
        OnKeyUp = 0x101 //另外257,与WM_KEYUP相同。
    }
#endregion 

WPF已经在命名空间System.Windows.Input中有自己的修饰符键作为ModifierKeys,并且还设置了flags属性,因此这不是必需的。

flags属性允许修饰符通过XOR组合,所以可以在WinForm中写一个语句:

**In C#**
Modifiers modifier = Modifiers.Control | Modifiers.Shift; 
**In VB**
Dim modifier as Modifiers = Modifiers.Control Xor Modifiers.Shift
**And in WPF,**
ModifierKeys modifier = ModifierKeys.Control | ModifierKeys.Shift;
**In VB**
Dim modifier as ModifierKeys = ModifierKeys.Control Xor ModifierKeys.Shift

意思是修饰符是“Control + Shift”

RaiseLocalEvent枚举将确定何时应该引发LocalHotKey事件,当键被关闭(OnKeyDown)或当它被释放(OnKeyUp)时。

public class HotKeyAlreadyRegisteredException : Exception
public class HotKeyUnregistrationFailedException : Exception
public class HotKeyRegistrationFailedException : Exception
public class HotKeyInvalidNameException : Exception

HotKeyAlreadyRegisteredException:顾名思义,当尝试使用HotKeyManager重新注册热键(具有相同的名称,键和或修饰符)时,将抛出此异常。对于GlobalHotKeys,当全局热键的键和修饰符正被另一个应用程序使用时,会抛出此异常。例如,尝试注册Window + L会引发此异常。当使用库时,尝试用LocalHotKey正在使用的基本键和基本修饰符注册ChordHotKey会引发HotKeyAlreadyRegisteredException,同时尝试注册具有已注册为基本键和修饰符的键和修饰符的LocalHotKey的ChordHotKey会引发相同的异常。优先级给予首次注册的HotKey。

HotKeyUnregistrationFailedException:当HotKey无法注销时抛出此异常。 HotKeyRegistrationFailedException相同,当HotKey无法注册时抛出,也会在您试图注册HotKeys(如Control + Escape)时发生。

HotKeyInvalidNameException:当您尝试注册具有无效名称的HotKey时抛出此异常;此库中的热键更像控件,您需要为每个热键分配一个名称,与Visual Studio中相同,有效的HotKey名称不以数字开头或包含空格。在函数中检查名称。

public static bool IsValidHotkeyName(string text)
{
    //If the name starts with a number, contains space or is null, return false.
    if (string.IsNullOrEmpty(text)) return false;

    if (text.Contains(" ") || char.IsDigit((char)text.ToCharArray().GetValue(0)))
        return false;

    return true;
}

当然,如果你喜欢,你可以改变这个。

HotKey共享类
这是一个静态类,有助于执行一些功能,如检查前面讨论的HotKey控件的名称,将字符串拆分为其相应的键和修饰符(对我们的HotKeyControl有用)和逆转过程。 它还包含一个枚举修饰符的结构。 HotKeyControl将把热键作为一个字符串,这不是非常有用的,除非我们将其分割为各自的键和修饰符,ParseShortcut函数允许我们实现这一点。

类具有静态函数ParseShortcut和CombineShortcut。 前者允许你剥离一个快捷方式,说“Control + Alt + T”到它各自的修饰符(Control,Alt)和键(T),而后者做相反。

ParseShortcut函数是一个对象数组,返回其下限中的热键字符串的修饰符,以及上限中的键。

函数public static object [] ParseShortcut(string text)有一个重载。

public static object[] ParseShortcut(string text, string separator)
{
    bool HasAlt = false; bool HasControl = false; bool HasShift = false; bool HasWin = false;

    Modifiers Modifier = Modifiers.None;        //变量包含修饰符。
    Keys key = 0;           //注册的键。

    string[] result;
    string[] separators = new string[] { separator };
    result = text.Split(separators, StringSplitOptions.RemoveEmptyEntries);

    //迭代通过键,找到修饰符。
    foreach (string entry in result)
    {
        //Find the Control Key.
        if (entry.Trim() == Keys.Control.ToString())
        {
            HasControl = true;
        }
        //Find the Alt key.
        if (entry.Trim() == Keys.Alt.ToString())
        {
            HasAlt = true;
        }
        //Find the Shift key.
        if (entry.Trim() == Keys.Shift.ToString())
        {
            HasShift = true;
        }
        //Find the Window key.
        if (entry.Trim() == Keys.LWin.ToString())
        {
            HasWin = true;
        }
    }

    if (HasControl) { Modifier |= Modifiers.Control; }
    if (HasAlt) { Modifier |= Modifiers.Alt; }
    if (HasShift) { Modifier |= Modifiers.Shift; }
    if (HasWin) { Modifier |= Modifiers.Win; }

    KeysConverter keyconverter = new KeysConverter();
    key = (Keys)keyconverter.ConvertFrom(result.GetValue(result.Length - 1));

    return new object[] { Modifier, key };
}

请注意,该函数使用KeysConverter类,System.Windows.Forms.Keys枚举的TypeConverter将字符串转换为其Key枚举表示形式。

用法:

**In C#**
object[] Result = ParseShortcut(“Control + Shift + A”, “ + ”);
Modifiers modifier = (Modifiers)Result[0];                          //Control | Shift
Keys key = (Keys)Result[1];                                        //Keys.A
**In VB**
Dim Result() as Object = ParseShortcut(“Control + Shift + A”, “ + “)
Dim modifier as Modifiers = CType(Result(0), Modifiers)           'Control Xor Shift
Dim key as Keys = CType(Result(0), Keys)                          'Keys.A
And to reverse this process, we use the CombineShortcut function

public static string CombineShortcut(Modifiers mod, Keys key)
{
    string hotkey = "";
    foreach (Modifiers a in new HotKeyShared.ParseModifier((int)mod))
    {
        hotkey += a.ToString() + " + ";
    }

    if (hotkey.Contains(Modifiers.None.ToString())) hotkey = "";
    hotkey += key.ToString();
    return hotkey;
}
**Usage:**

Modifiers modifier = Modifiers.Control | Modifiers.Shift;
CombineShortcut(modifier, Keys.A);                         //Control + Shift + A
Dim modifier as Modifiers = Modifiers.Control Xor Modifiers.Shift
CombineShortcut(modifier, Keys.A)                          'Control + Shift + A

热键控制
HotKeyControl是一个UserControl,它扩展了TextBox控件以捕捉用户在活动时按下的键。 它添加了当用户设置HotKey时引发的事件HotKeyIsSet,并且还添加了属性UserKey和UserModifer(在设计视图中不可见),它返回键和修改用户集和属性ForceModifiers(在设计视图中可见) ),其指定当设置热键时用户应该被强制输入修改,如果为真,则接受所有热键。

对于WinForm

HotKey控件利用文本框的KeyDown和KeyUp事件来获得用户按下的键。 并使用复位按钮清除输入的HotKey。

void HotKeyControl_KeyDown(object sender, KeyEventArgs e)
{
    e.SuppressKeyPress = true;  //禁止键由底层控件处理。
    this.Text = string.Empty;  //清空文本框的内容
    KeyisSet = false; //此时用户尚未指定快捷方式。

    //使用户指定修饰符。 控制,Alt或Shift。
    //如果不存在修饰符,请清除文本框。
    if (e.Modifiers == Keys.None && forcemodifier)
    {
        MessageBox.Show("You have to specify a modifier like 'Control', 'Alt' or 'Shift'");
        this.Text = Keys.None.ToString();
        return;
    }

    //A modifier is present. Process each modifier.存在改性剂。 处理每个修饰符。
    //修饰符由“,”分隔。 所以我们将它们分开,并将每一个写入文本框。
    foreach (string modifier in e.Modifiers.ToString().Split(new Char[] { ',' }))
    {
        if (modifier != Keys.None.ToString())
            this.Text += modifier + " + ";
    }

    //KEYCODE包含用户按下的最后一个键。
    //如果KEYCODE包含修饰符,则用户没有输入快捷方式。 因此,KeyisSet为假
    //But if not, KeyisSet is true.但如果不是,KeyisSet是真的。
    if (e.KeyCode == Keys.ShiftKey | e.KeyCode == Keys.ControlKey | e.KeyCode == Keys.Menu)
    {
        KeyisSet = false;
    }
    else
    {
        this.Text += e.KeyCode.ToString();
        KeyisSet = true;
    }
}

KeyUp事件通过检查变量KeyisSet来确定HotKey是否已经设置,如果true提高HotKeyIsSet事件或清除控件。

void HotKeyControl_KeyUp(object sender, KeyEventArgs e)
{
    //在KeyUp如果KeyisSet为False然后清除文本框。
    if (KeyisSet == false)
    {
        this.Text = Keys.None.ToString();
    }
    else
    {
        if (HotKeyIsSet != null)
        {
            var ex = new HotKeyIsSetEventArgs(UserKey, UserModifier);
            HotKeyIsSet(this, ex);
            if (ex.Cancel)
            {
                KeyisSet = false;
                this.Text = Keys.None.ToString();
            }
        }
    }
}

对于WPF

源文件包含两个HotKey控件,一个构建在.Net Framework 3.0中,另一个构建在.Net Framework 4.0中。

HotKeyControl使用PreviewKeyDown事件和一个钩子来获取用户按下的键。

public HotKeyControl()
{
    this.GotFocus += new RoutedEventHandler(HotKeyControl_GotFocus); //在这里挂钩。
    this.hook = new HwndSourceHook(WndProc); //接到Windows消息。
    this.LostFocus += new RoutedEventHandler(HotKeyControl_LostFocus); //这里取下挂钩。
    this.ContextMenu = null; //禁用快捷方式。
    Text = Keys.None.ToString();
    this.IsReadOnly = true;
    this.PreviewKeyDown += new KeyEventHandler(HotKeyControl_PreviewKeyDown);
}
  • HotKey必须在HotKeyManager中注册,然后才能工作(引发事件)

HotKeyManager
在WinForm中的HotKeyManager类将管理GlobalHotKey,LocalHotKey和ChordHotKey类,实现:

IMessageFilter:将允许类接收Windows消息回调。
IDisposable:将释放所有资源,并注销所有HotKeys。
该类将通过添加接收Windows消息

Application.AddMessageFilter(this);

在构造函数中,将通过添加停止接收Windows消息

Application.RemoveMessageFilter(this);

在析构函数中。
然后类将通过添加函数接收消息,这是实现IMessageFilter的结果。

public bool PreFilterMessage(ref Message m) { }

对于WPF,一个Hook被添加到类,以允许它接收Windows消息。

我将Key枚举从WinForm复制到WPF类,以允许Local和ChordHotKeys,因为Windows仍然向WinForm发送与WPF应用程序相同的密钥消息。

this.hook = new HwndSourceHook(WndProc); //接到Windows消息。
this.hwndSource = (HwndSource)HwndSource.FromVisual(window); // new WindowInteropHelper(window).Handle // 如果需要InPtr。
this.hwndSource.AddHook(hook);

然后类将从函数接收Windows消息。

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { }

在源文件中,HotKeyManager没有空导航,这是因为我想要您提供一个窗体或窗口,视情况而定,因为GlobalHotKeys注册的窗体或窗口的句柄是必需的Windows注册或取消注册。如果你想在服务中使用这个库,或者你不打算使用GlobalHotKeys,你可以添加一个空的构造函数并进行必要的修改,库仍然可以正常工作。

HotKeyManager在注册的窗体或窗口正在关闭时自动处理,您不需要在您的应用程序中重新构建,并且如果您这样做,则不会抛出异常。它也可以被禁用,它仍然接收消息,它只是不做任何事情与他们和在WinForm中,你可以设置HotKeyManager临时禁用自己,当另一个表单,可能是一个对话框,因为它仍然引发事件,设置DisableOnManagerFormInactive到真实。

现在,当您的应用程序中按下一个键时,Windows会发送一条消息,其中包含有关按下的键和状态(无论是按住还是已发布)的信息到我们的类,因为我们已订阅它们。

但是,为了在按下按键时按下Modifiers,我引用了Microsoft.VisualBasic来加快速度。你可以随时在键盘上得到修改器,如下所示:

Microsoft.VisualBasic.Devices.Keyboard UserKeyBoard = new Microsoft.VisualBasic.Devices.Keyboard();
bool AltPressed = UserKeyBoard.AltKeyDown;
bool ControlPressed = UserKeyBoard.CtrlKeyDown;
bool ShiftPressed = UserKeyBoard.ShiftKeyDown;

您可以看到Window键不作为修饰符而是作为Key,要获得Window键的状态,可以使用:

  short ret = Win32.GetKeyState(0x5b); //Get the state of the Window key.
            if ((ret & 0x8000) == 0x8000) LocalModifier |= Modifiers.Window;

当在键盘上按任何键时,HotKeyManager遍历所有注册的LocalHotKeys和ChordHotKeys,并为发现的事件引发事件。

查找LocalHotKeys

Using delegates

Keys keydownCode = (Keys)(int)m.WParam & Keys.KeyCode; //获取被按下的键。
 LocalHotKey KeyDownHotkey = LocalHotKeyContainer.Find
 (
     delegate(LocalHotKey d)
     {
      return ((d.Key == keydownCode) && (d.Modifier == LocalModifier)
             && (d.WhenToRaise == RaiseLocalEvent.OnKeyDown));
     }
 );

using Linq,

LocalHotKey KeyDownHotkey = (from items in LocalHotKeyContainer
                where items.Key == keydownCode && items.Modifier == LocalModifier
                where items.WhenToRaise == RaiseLocalEvent.OnKeyDown
                select items).FirstOrDefault();

*当没有找到任何内容时,此搜索返回null。

查找ChordHotKeys
当无法找到LocalHotKey时,Manager会检查任何注册的ChordHotKey的基本键和修饰符是否与按下的键匹配,这就是为什么您不能为任何其他localhotkey设置相同的基本键和修饰符。 如果找到一个,则它转到ChordMode,并等待另一个键被丢弃修改符,如果被按下的第二个键匹配任何和弦的chordkey和修改符,则它提出该和弦的事件,否则叶子ChordMode并给出 听起来像Visual Studio。

查找GlobalHotKeys
要注册GlobalHotKeys,没有内置的功能允许这种功能,但它是内置在Win32 API和.Net提供了一种方法来调用非本地库。 我们感兴趣的方法在User32.dll,RegisterHotKey和UnRegisterHotKey中定义。

RegisterHotKey和UnregisterHotKey。

现在,定义重要的方法:允许我们注册快捷方式的静态函数。

[DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int RegisterHotKey(IntPtr hwnd, int id, int modifiers, int key);

[DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int UnregisterHotKey(IntPtr hwnd, int id);

请注意,我们不提供方法体。 该方法在user32.dll中定义,我们只是为我们的应用程序添加一种方法来直接调用该方法。

1.hWnd是指窗体或窗口句柄,
2.id是热键的唯一标识符。
3.修饰符是要用您的键按下的修饰键(shift / alt / ctrl / win)的整数表示,
4.而key是热键的虚拟键代码。
当按下GlobalHotKey时,Windows会在发送注册到wParam时分配给它的GlobalHotKey的ID,然后该ID可用于搜索所有GlobalHotKey,就像我们对LocalHotKeys所做的那样。

其他功能
HotKeyManager也支持枚举,可以迭代一个特定的热键; 全局,本地或和弦这样:

string message = "Global HotKeys.\n";

foreach (GlobalHotKey gh in MyHotKeyManager.EnumerateGlobalHotKeys)
{
     message += string.Format("{0}{1}", Environment.NewLine, gh.FullInfo());
}

message += "\n\nLocal HotKeys.\n";

foreach (LocalHotKey lh in MyHotKeyManager.EnumerateLocalHotKeys)
{
     message += string.Format("{0}{1}", Environment.NewLine, lh.FullInfo());
}

message += "\n\nChord HotKeys.\n";

foreach (ChordHotKey ch in MyHotKeyManager.EnumerateChordHotKeys)
{
      message += string.Format("{0}{1}", Environment.NewLine, ch.FullInfo());
}

MessageBox.Show(message, "All HotKeys registered by this app.", MessageBoxButtons.OK, MessageBoxIcon.Information);

这里写图片描述

这将允许迭代更容易,因为我们可以直接遍历所有ChordHotKeys像这样

而不是像这样实现IEnumerable 和迭代,这将需要使用命名空间System.Collections.Generic

foreach (ChordHotKey ch in (IEnumerable<ChordHotKey>)MyHotKeyManager)
{
      message += string.Format("{0}{1}", Environment.NewLine, gh.FullInfo());
}

HotKeyManager还利用Win32 API获取所有键盘按下,即使您的应用程序不专注,可以禁用它们。

KeyboardHookEventHandler keyboardhandler = (sender, handler) =>
        {
            if (handler.Modifier == KeyboardHookEventArgs.modifiers.Shift)
                { handler.Handled = true; }
            switch (handler.Key)
            {
                case Keys.A:
                case Keys.E:
                case Keys.I:
                case Keys.O:
                case Keys.U:
                    handler.Handled = true;
                    return;
            }
        };

上面的代码禁用键盘上的元音键,但按下Shift键时会禁用所有键。

HotKeyManager,使用Win32API也可以模拟一个Key按,在这里,我们模拟按Control + A。

MyHotKeyManager.SimulateKeyDown(Keys.Control);           //按住控制键
MyHotKeyManager.SimulateKeyPress(Keys.A);                //按住 A 键
MyHotKeyManager.SimulateKeyUp(Keys.Control);             //释放控制键

HotKey管理器是通过取消注册所有注册的GlobalHotKeys注册的类,从所有键盘消息从方法中挂钩类,HotKeyManager.Dispose

for (int i = GlobalHotKeyContainer.Count - 1; i >= 0; i--)
{
     RemoveGlobalHotKey(GlobalHotKeyContainer[i]);
}

LocalHotKeyContainer.Clear();
ChordHotKeyContainer.Clear();
KeyBoardUnHook();

使用代码
现在,我们将HotKeys添加到HotKeyManager中,如下所示:

**In C#**
GlobalHotKey ghkNotepad = new GlobalHotKey("ghkNotepad", Keys.N, Modifiers.Control | Modifiers.Shift);
LocalHotKey lhkNewHotkey = new LocalHotKey("lhkNewHotKey", Keys.A);
ChordHotKey chotCmd = new ChordHotKey("chotCmd", Keys.C, Modifiers.Alt, Keys.P, Modifiers.Alt);

MyHotKeyManager.AddGlobalHotKey(ghkNotepad);
MyHotKeyManager.AddLocalHotKey(lhkNewHotkey);
MyHotKeyManager.AddChordHotKey(chotCmd);
**In VB**
Dim ghkNotepad as new GlobalHotKey("ghkNotepad", Keys.N, Modifiers.Control Xor Modifiers.Shift)
Dim lhkNewHotkey as new LocalHotKey("lhkNewHotKey", Keys.A)
Dim chotCmd as new ChordHotKey("chotCmd", Keys.C, Modifiers.Alt, Keys.P, Modifiers.Alt)

MyHotKeyManager.AddGlobalHotKey(ghkNotepad)
MyHotKeyManager.AddLocalHotKey(lhkNewHotKey)
MyHotKeyManager.AddChordHotKey(chotCmd)

对于HotKeyControl,用户可以使用控件设置快捷方式,然后可以从HotKeyControl.UserKey和HotKeyControl.UserModifier获取关联的键和修饰符。

HotKeyManager还可以模拟按键并向键盘添加一个挂钩。

您可以通过将键的Handled属性设置为true来禁用键盘键,似乎被忽略的键的唯一组合是Control + Alt + Delete。

当你尝试创建一个新的HotKeyManager,在InitializeComponent方法中使用WPF,它可能会导致你的窗口崩溃,你最好这样做时,窗口已经加载。

库还可以扩展到组件中,以便可以在设计时和运行时添加和验证HotKey,它将为您节省大量代码。

源文件中的示例如下所示。
这里写图片描述

翻译来源:https://www.codeproject.com/articles/442285/global-shortcuts-in-winforms-and-wpf

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C知道:C# WinFormsWPF是两种不同的用户界面(UI)开发框架。它们都是用于构建Windows应用程序的技术,但在设计和功能上有一些区别。 1. 设计风格:WinForms使用传统的窗体和控件的设计风格,类似于传统的Windows桌面应用程序。而WPF则提供了更现代化、灵活和可定制的设计风格,通过XAML语言和矢量图形实现高度可视化的用户界面。 2. 数据绑定:WPF对数据绑定提供了更强大和灵活的支持。它使用绑定表达式语言(Binding Expression Language)来实现数据和界面元素之间的双向绑定,使开发者能够更轻松地处理数据更新和UI反馈。 3. UI布局:WPF提供了一种称为布局系统(Layout System)的机制,它可以自动调整和重新排列界面元素,以适应不同尺寸和分辨率的屏幕。这使得在不同设备上呈现一致的用户界面变得更加容易。 4. 图形和动画效果:WPF支持强大的矢量图形和动画效果,包括渐变、旋转、缩放、透明度等。这使得开发者能够创建更具吸引力和交互性的用户界面。 5. 性能:由于WPF使用硬件加速和矢量图形,它在图形渲染和动画方面可能比WinForms更高效。然而,在某些情况下,特别是当应用程序包含大量控件和复杂布局时,WPF可能比WinForms消耗更多的系统资源。 选择使用WinForms还是WPF,取决于你的项目需求和个人偏好。如果你喜欢传统的Windows桌面应用程序设计风格,并且不需要复杂的图形和动画效果,那么WinForms可能更适合你。如果你想要一个现代化、灵活和具有吸引力的用户界面,并且对数据绑定和UI布局有更高的要求,那么WPF可能更适合你。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值