/// <summary> /// Create a list of key actions from all the menu items in a particular menu. Each menu item with a name and Click event handler will be added to this list. /// </summary> /// <param name="m">The menu to load from.</param> /// <remarks>No exceptions are thrown from this method; a blank list is returned if no menu items could be added. Each menu item should have a name (via the <c>Name</c> or <c>x:Name</c> properties). /// If multiple menu items do not have a name, then only the first one encountered will be added to the list.</remarks> /// <returns>A list of key actions created from the menu passed in.</returns> public static KeyActionList CreateListFromMenu(Menu m) { KeyActionList rekya = new KeyActionList(); #if NETCOREAPP foreach (object?element in m.Items) #else foreach (object element in m.Items) #endif { if (element is MenuItem mi && element != null) { if (mi.Items.Count > 0) { rekya.AddRange(CreateListFromMenuItem(mi)); } else { // if this a top-level MenuItem that has a click event of its own, then okay try { rekya.Add(CreateFromMenuItem(mi)); } catch (MissingMemberException) { } catch (InvalidOperationException) { } } } } return(rekya); }
/// <summary> /// Load in and register keyboard shortcuts from a file. A KeyActionList is needed to map the shortcuts to their actions. /// </summary> /// <param name="file">The file to load from.</param> /// <param name="methodList">The list of actions available for keyboard shortcuts, to use for mapping.</param> /// <exception cref="System.IO.FileNotFoundException">Thrown if the file cannot be found.</exception> /// <remarks> /// If there is a shortcut in the file that references an action not in the <paramref name="methodList"/>, that shortcut is skipped. /// Also, if a shortcut in the file has the same keyboard combination and key as a shortcut already registed, that shortcut is skipped. /// </remarks> public void LoadShortcutsFromFile(string file, KeyActionList methodList) { var list = KeyboardShortcutsIo.LoadFromFile(file, methodList); foreach (KeyboardShortcut item in list) { try { KeyRegistry.RegisterKeyShortcut(item); } catch (ArgumentException) { // thrown if there's already a shortcut registered with this particular keyboard combination and key // skip the particular shortcut } } }
/// <summary> /// Load a list of keyboard shortcuts from a file. The list of available actions is also needed to map the shortcuts to these actions. /// </summary> /// <param name="file">The file to load from.</param> /// <param name="list">A list of actions available to be accessed via keyboard shortcuts.</param> /// <returns>A list of keyboard shortcuts, which can be loaded into a KeyRegistry.</returns> /// <exception cref="FileNotFoundException">Thrown if the file does not exist.</exception> /// <remarks>If there is a shortcut in this file that reference an action ID that isn't on the <paramref name="list"/>, then that shortcut is skipped.</remarks> public static List <KeyboardShortcut> LoadFromFile(string file, KeyActionList list) { if (!File.Exists(file)) { throw new FileNotFoundException("The specified file does not exist. Keyboard shortcuts cannot be loaded.", file); } List <KeyboardShortcut> entries = new List <KeyboardShortcut>(); XmlReader xr = XmlReader.Create(file); xr.MoveToContent(); while (xr.Read()) { if (xr.NodeType == XmlNodeType.Element) { //xr.ReadStartElement("ks"); #if NETCOREAPP string?c = xr.GetAttribute("comb"); string?k = xr.GetAttribute("keyid"); string?m = xr.GetAttribute("action"); #else string c = xr.GetAttribute("comb"); string k = xr.GetAttribute("keyid"); string m = xr.GetAttribute("action"); #endif if (string.IsNullOrEmpty(m)) { m = xr.GetAttribute("methodid"); } if (string.IsNullOrEmpty(c) || string.IsNullOrEmpty(k) || string.IsNullOrEmpty(m)) { // skip item } else if (Enum.TryParse(c, out KeyboardCombination kc)) { // try to load keys by their internal integer value // from https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.key?view=net-5.0 (the middle column) if (int.TryParse(k, out int kv)) { #if NETCOREAPP IKeyAction?a = null; #else IKeyAction a = null; #endif if (list != null) { // checks the key action list for "Xxx", "mnuXxx", and "btnXxx" // this is a carryover from internal usage, but I figure it should still be helpful // if desired, I can remove this or make a toggle for it in a future release if (list.ContainsId(m)) { a = list[m]; } else if (list.ContainsId("mnu" + m)) { m = "mnu" + m; a = list[m]; } else if (list.ContainsId("btn" + m)) { m = "btn" + m; a = list[m]; } } if (a != null) { KeyboardShortcut ke = new KeyboardShortcut(kc, (Key)kv, a); entries.Add(ke); } } else { // if the integer-based value doesn't work, try to parse based upon the name of the Key in the enum // again from https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.key?view=net-5.0 (the left column) if (Enum.TryParse(k, out Key kz)) { #if NETCOREAPP IKeyAction?a = null; #else IKeyAction a = null; #endif if (list != null) { // checks the key action list for "Xxx", "mnuXxx", and "btnXxx" // this is a carryover from internal usage, but I figure it should still be helpful // if desired, I can remove this or make a toggle for it in a future release if (list.ContainsId(m)) { a = list[m]; } else if (list.ContainsId("mnu" + m)) { m = "mnu" + m; a = list[m]; } else if (list.ContainsId("btn" + m)) { m = "btn" + m; a = list[m]; } } if (a != null) { KeyboardShortcut ke = new KeyboardShortcut(kc, kz, a); entries.Add(ke); } } } } //xr.ReadEndElement(); } } xr.Close(); return(entries); }