CODE: Encapsulating The Key Bindings menu

User Tag List

Results 1 to 2 of 2
  1. #1
    EmilyStrange's Avatar Active Member
    Reputation
    34
    Join Date
    Jul 2009
    Posts
    125
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    CODE: Encapsulating The Key Bindings

    I encapsulated the key bindings of the game client into a reusable class that can be used for converting the key combinations stored as strings in the game client into .NET Keys values and associate the keys with the action bindings. These are the same key combination strings you would find in the WTF folder.

    You will need to change the references to the memory reader/writer library to whatever flavour you use.
    Code:
    using System;
    using System.Collections.Generic;
    using Voodoo;
    using WarcraftVoodoo.Version41014333;
    using System.Windows.Forms;
    
    namespace WarcraftVoodoo
    {
        public class KeyBindings
        {
            // brute-force dictionary to quickly lookup key combinations stored as
            // strings and convert the string to a .NET Keys value
            private Dictionary<string, Keys> m_allPossibleKeys;
    
            // The raw key bindings stored in the game client.
            private CachedValue<Dictionary<string, string>> m_rawKeyBindgs;
    
            // The game client that this set of key bindings refers to.
            private GameClient m_gameClient;
    
            /// <summary>
            /// Construct a new key bindings instance for a game client.
            /// </summary>
            /// <param name="gc">The game client that this set of key bindings refers to.</param>
            public KeyBindings(GameClient gc)
            {
                m_gameClient = gc;
                CreateKeyCombinations();
    
                // set up the reader delegate to read the raw key bindings from the game client
                m_rawKeyBindgs = new CachedValue<Dictionary<string, string>>(() =>
                {
                    return GetRawKeyBindings();
                });
    
                // key bindings don't change all that often, no point updating them 20 times a second
                m_rawKeyBindgs.UpdateInterval = TimeSpan.FromSeconds(30);
            }
    
            /// <summary>
            /// This function returns a dictionary of raw key combinations as strings
            /// as they are stored in the game client memory. The action binding is
            /// used as the dictionary key.
            /// </summary>
            public Dictionary<string, string> RawKeyBindings
            {
                get
                {
                    return m_rawKeyBindgs.Value;
                }
    
            }
    
            /// <summary>
            /// This function returns a dictionary of key combinations in .NET Keys format
            /// along with the action binding that would be performed if that key combination
            /// were pressed by the user. The action binding is used as the dictionary key.
            ///
            /// Note that not all raw key bindings will be converted to interpreted key bindings,
            /// e.g. MOUSEBUTTON3 is not converted, nor is NUMLOCK. This is done for a number of
            /// technical reasons.
            /// </summary>
            public Dictionary<string, Keys> InterpretedKeyBindings
            {
                get
                {
                    // convert the raw key bindings to interpreted key bindings.
                    // TODO cache the interpreted key bindings rather than convert them on each request
                    // TODO convert this loop to a cleaner LINQ version
                    Dictionary<string, Keys> interpretedBindings = new Dictionary<string, Keys>();
                    foreach (KeyValuePair<string, string> rawBinding in m_rawKeyBindgs.Value)
                    {
                        if (m_allPossibleKeys.ContainsKey(rawBinding.Value) == true)
                        {
                            interpretedBindings[rawBinding.Key] = m_allPossibleKeys[rawBinding.Value];
                        }
                    }
    
                    return interpretedBindings;
                }
    
            }
    
    
            /// <summary>
            /// This function creates a dictionary of all possible valid keys
            /// with the three modifier keys applied to each key in the permissible
            /// combinations.
            /// This function is a brute-force method of looking up a key with modifiers
            /// string in the dictionary as it is extracted from the game client and
            /// converting it directly in to its .NET equivalent.
            /// This could also be done with a regular expression but this is a small
            /// speed optimisation at the expense of a little memory.
            /// </summary>
            private void CreateKeyCombinations()
            {
                Dictionary<string, System.Windows.Forms.Keys> dotNetKeys = new Dictionary<string, System.Windows.Forms.Keys>();
    #region key mappings
                // This is fugly but gets the job done when needing to pre-populate the dictionary simply
                // Credit to amadmonk for typing out the original table.
                // Errors fixed by Emily Dearheart Stranger.
                dotNetKeys["0"] = Keys.D0;
                dotNetKeys["1"] = Keys.D1;
                dotNetKeys["2"] = Keys.D2;
                dotNetKeys["3"] = Keys.D3;
                dotNetKeys["4"] = Keys.D4;
                dotNetKeys["5"] = Keys.D5;
                dotNetKeys["6"] = Keys.D6;
                dotNetKeys["7"] = Keys.D7;
                dotNetKeys["8"] = Keys.D8;
                dotNetKeys["9"] = Keys.D9;
                dotNetKeys["-"] = Keys.OemMinus;
                dotNetKeys["="] = Keys.Oemplus;
                dotNetKeys["A"] = Keys.A;
                dotNetKeys["B"] = Keys.B;
                dotNetKeys["C"] = Keys.C;
                dotNetKeys["D"] = Keys.D;
                dotNetKeys["E"] = Keys.E;
                dotNetKeys["F"] = Keys.F;
                dotNetKeys["G"] = Keys.G;
                dotNetKeys["H"] = Keys.H;
                dotNetKeys["I"] = Keys.I;
                dotNetKeys["J"] = Keys.J;
                dotNetKeys["K"] = Keys.K;
                dotNetKeys["L"] = Keys.L;
                dotNetKeys["M"] = Keys.M;
                dotNetKeys["N"] = Keys.N;
                dotNetKeys["O"] = Keys.O;
                dotNetKeys["P"] = Keys.P;
                dotNetKeys["Q"] = Keys.Q;
                dotNetKeys["R"] = Keys.R;
                dotNetKeys["S"] = Keys.S;
                dotNetKeys["T"] = Keys.T;
                dotNetKeys["U"] = Keys.U;
                dotNetKeys["V"] = Keys.V;
                dotNetKeys["W"] = Keys.W;
                dotNetKeys["X"] = Keys.X;
                dotNetKeys["Y"] = Keys.Y;
                dotNetKeys["Z"] = Keys.Z;
                dotNetKeys["UP"] = Keys.Up;
                dotNetKeys["DOWN"] = Keys.Down;
                dotNetKeys["LEFT"] = Keys.Left;
                dotNetKeys["RIGHT"] = Keys.Right;
                dotNetKeys["SPACE"] = Keys.Space;
                //dotNetKeys["NUMLOCK"] = Keys.NumLock; // doesn't work w/PostMessage
                dotNetKeys["ESCAPE"] = Keys.Escape;
                dotNetKeys["F1"] = Keys.F1;
                dotNetKeys["F2"] = Keys.F2;
                dotNetKeys["F3"] = Keys.F3;
                dotNetKeys["F4"] = Keys.F4;
                dotNetKeys["F5"] = Keys.F5;
                dotNetKeys["F6"] = Keys.F6;
                dotNetKeys["F7"] = Keys.F7;
                dotNetKeys["F8"] = Keys.F8;
                dotNetKeys["F9"] = Keys.F9;
                dotNetKeys["F10"] = Keys.F10;
                dotNetKeys["F11"] = Keys.F11;
                dotNetKeys["F12"] = Keys.F12;
                dotNetKeys["F13"] = Keys.F13;
                dotNetKeys["F14"] = Keys.F14;
                dotNetKeys["F15"] = Keys.F15;
                dotNetKeys["F16"] = Keys.F16;
                dotNetKeys["F17"] = Keys.F17;
                dotNetKeys["F18"] = Keys.F18;
                dotNetKeys["F19"] = Keys.F19;
                dotNetKeys["F20"] = Keys.F20;
                dotNetKeys["F21"] = Keys.F21;
                dotNetKeys["F22"] = Keys.F22;
                dotNetKeys["F23"] = Keys.F23;
                dotNetKeys["F24"] = Keys.F24;
                dotNetKeys["PAGEUP"] = Keys.PageUp;
                dotNetKeys["PAGEDOWN"] = Keys.PageDown;
                dotNetKeys["ENTER"] = Keys.Return;
                dotNetKeys["INSERT"] = Keys.Insert;
                dotNetKeys["DELETE"] = Keys.Delete;
                dotNetKeys["HOME"] = Keys.Home;
                dotNetKeys["END"] = Keys.End;
                dotNetKeys["/"] = Keys.OemQuestion;
                dotNetKeys["'"] = Keys.Oem7;
                dotNetKeys["["] = Keys.OemOpenBrackets;
                dotNetKeys["]"] = Keys.OemCloseBrackets;
                dotNetKeys["TAB"] = Keys.Tab;
                dotNetKeys["NUMPAD0"] = Keys.NumPad0;
                dotNetKeys["NUMPAD1"] = Keys.NumPad1;
                dotNetKeys["NUMPAD2"] = Keys.NumPad2;
                dotNetKeys["NUMPAD3"] = Keys.NumPad3;
                dotNetKeys["NUMPAD4"] = Keys.NumPad4;
                dotNetKeys["NUMPAD5"] = Keys.NumPad5;
                dotNetKeys["NUMPAD6"] = Keys.NumPad6;
                dotNetKeys["NUMPAD7"] = Keys.NumPad7;
                dotNetKeys["NUMPAD8"] = Keys.NumPad8;
                dotNetKeys["NUMPAD9"] = Keys.NumPad9;
                dotNetKeys["NUMPADMULTIPLY"] = Keys.Multiply;
                dotNetKeys["NUMPADMINUS"] = Keys.Subtract;
                dotNetKeys["NUMPADPLUS"] = Keys.Add;
                dotNetKeys["NUMPADDIVIDE"] = Keys.Divide;
                #endregion
    
                m_allPossibleKeys = new Dictionary<string, Keys>();
    
                // The magic value 8 is derived from the fact that there are three possible modifier
                // keys, Alt, Ctrl and Shift. Each modifier key can be either depressed or released.
                // With those details in mind, three modifier keys provides for eight possible
                // combinations of modifiers, or 2 ^ 3 possible combinations, whereby 2
                // is a binary value indicating whether the key is pressed or released,
                // and 3 represents the three possible modifier keys.
                // (Yeah, clear as mud, there are 8 possible combinations given 3 distinct modifier keys.)
                const int ModifierCombinations = 8;
                for (int modifiers = 0; modifiers < ModifierCombinations; modifiers++)
                {
    
                    // Assemble the key string with modifiers applied and the .NET Keys value with modifiers OR'ed in.
                    // Note: Not using a string builder as the set up time is longer than the copying operation of
                    // an immutable object.
                    string modifierString = String.Empty;
                    Keys modifierKeys = Keys.None;
                    // apply the ALT key modifier
                    if ((modifiers & 1) == 1)
                    {
                        modifierString = "ALT-";
                        modifierKeys |= Keys.Alt;
                    }
    
                    // apply the CTRL key modifier
                    if ((modifiers & 2) == 2)
                    {
                        modifierString += "CTRL-";
                        modifierKeys |= Keys.Control;
                    }
    
                    // apply the SHIFT key modifier
                    if ((modifiers & 4) == 4)
                    {
                        modifierString += "SHIFT-";
                        modifierKeys |= Keys.Shift;
                    }
    
                    // apply the assembled modifier to each of the possible valid keys
                    foreach (KeyValuePair<string, Keys> keyKeys in dotNetKeys)
                    {
                        string baseKeyString = keyKeys.Key;
                        Keys baseKey = keyKeys.Value;
                        string finalKeyString = modifierString + baseKeyString;
                        Keys finalKey = modifierKeys | baseKey;
                        // store the .NET Keys value in the dictionary with the key string as the dictionary key
                        m_allPossibleKeys[finalKeyString] = finalKey;
    
                    }
    
                }
    
            }
    
            // TODO deprecated function on 11/03/01, delete after 11/09/01 if no longer needed
            //public Dictionary<string, Keys> GetInterpretedKeyBindings()
            //{
            //    Dictionary<string, System.Windows.Forms.Keys> remappedBindings = new Dictionary<string, System.Windows.Forms.Keys>();
            //    Dictionary<string, string> rawKeyBindings = GetRawKeyBindings();
            //    foreach (KeyValuePair<string, string> binding in rawKeyBindings)
            //    {
            //        Regex keysUsed = new Regex(@"(ALT-)?(CTRL-)?(SHIFT-)?([A-Z0-9-\][='`,\./*+;\\]*)");
            //        Match match = keysUsed.Match(binding.Value);
            //        if (match.Success == false)
            //        {
            //            Log.LogError("I found a key, but I couldn't interpret it.");
            //        }
            //        else if (match.Groups.Count == 0)
            //        {
            //            Log.LogError("I found a key, but I couldn't interpret it.");
            //        }
            //        else
            //        {
            //            Keys remappedKeys = Keys.None;
            //            if (match.Groups[1].Value.Equals("ALT-") == true)
            //            {
            //                remappedKeys |= Keys.Alt;
            //            }
    
            //            if (match.Groups[2].Value.Equals("CTRL-") == true)
            //            {
            //                remappedKeys |= Keys.Control;
            //            }
    
            //            if (match.Groups[3].Value.Equals("SHIFT-") == true)
            //            {
            //                remappedKeys |= Keys.Shift;
            //            }
    
            //            Keys key;
            //            string keyString = match.Groups[4].Value.ToString();
            //            bool keyFound = keyToKeys.TryGetValue(keyString, out key);
            //            if (keyFound)
            //            {
            //                remappedKeys |= key;
            //                Log.LogDebug(String.Format("Interpreted {0} as {1} ({2})", binding.Key, remappedKeys, binding.Value));
            //                remappedBindings[binding.Key] = remappedKeys;
            //            }
            //            else
            //            {
            //                Log.LogInfo(String.Format(@"Found a key \"{0}\" but cannot interpret it", binding.Value));
            //            }
    
            //        }
    
            //    }
    
            //    return remappedBindings;
            //}
    
            /// <summary>
            /// This function is an enumerator that iterates over the linked list of key bindings
            /// </summary>
            /// <returns>A pointer to the next key binding in the linked list</returns>
            private IEnumerable<uint> BindingsList()
            {
                // locate the key bindings linked list in game client memory and read the first binding in the list
                uint bindingsManager = m_gameClient.MemoryEditor.ReadUInt(m_gameClient.ToAbsoluteAddress(LocalPlayerAddress.KeyBindings));
                uint currentAddress = m_gameClient.MemoryEditor.ReadUInt(bindingsManager + KeyBindingsOffset.First);
                while ((currentAddress != 0) && ((currentAddress & 1) == 0))
                {
                    yield return currentAddress;
                    // read the next key binding in the linked list
                    uint nextAddress = m_gameClient.MemoryEditor.ReadUInt(bindingsManager + KeyBindingsOffset.Next);
                    currentAddress = m_gameClient.MemoryEditor.ReadUInt(currentAddress + nextAddress + sizeof(uint));
                }
    
            }
    
            /// <summary>
            /// This function scans the linked list of key bindings in memory and returns
            /// a dictionary containing the key combination and the action binding that
            /// is performed when that particular key combination is pressed by the user.
            /// </summary>
            /// <returns>Dictionar of key combinations and action bindings. The action bindings are the dictionary keys.</returns>
            private Dictionary<string, string> GetRawKeyBindings()
            {
                // the maximum permissible string length to read
                const int MaxStringLength = 255;
    
                // for each key binding in the key bindings linked list
                //      read the string that represents the key to be pressed
                //      read the action binding that would occur if the key is pressed
                //      store the key string in a dictionary with the action binding as the dictionary key
                Dictionary<string, string> keys = new Dictionary<string, string>();
                foreach (uint addr in BindingsList())
                {
                    uint keyPtr = m_gameClient.MemoryEditor.ReadUInt(addr + KeyBindingsOffset.KeyString);
                    string keyString = m_gameClient.MemoryEditor.ReadASCIIString(keyPtr, MaxStringLength);
                    uint actionPtr = m_gameClient.MemoryEditor.ReadUInt(addr + KeyBindingsOffset.ActionString);
                    string actionString = m_gameClient.MemoryEditor.ReadASCIIString(actionPtr, MaxStringLength);
                    if (keyString.Length > 0 && actionString.Length > 0)
                    {
                        if (keys.ContainsKey(actionString) == false)
                        {
                            keys[actionString] = keyString;
                        }
    
                    }
    
                }
    
                return keys;
            }
    
        }
    
    }
    And this is how I dump all of the key bindings for a particular game client:
    Code:
            private void Debug_DumpLeadersKeyBindings()
            {
                PlayerCharacter leadPlayerCharacter = PartyManager.LeadPlayerCharacter;
                if (leadPlayerCharacter == null)
                {
                    return;
                }
    
                WowLocalPlayer localPlayer = leadPlayerCharacter.LocalPlayer;
                if (localPlayer == null)
                {
                    return;
                }
    
                Log.LogDebug(String.Format("These are all of the key bindings that {0} has.", localPlayer.Name));
                Dictionary<string, Keys> bindings = localPlayer.KeyBindings.InterpretedKeyBindings;
                foreach (KeyValuePair<string, Keys> binding in bindings)
                {
                    Log.LogDebug(String.Format("{0}\t\t{1}", binding.Key, binding.Value));
                }
    
            }
    Last edited by EmilyStrange; 06-29-2011 at 04:42 PM. Reason: Fixed a typo

    CODE: Encapsulating The Key Bindings
  2. #2
    erix920's Avatar Private
    Reputation
    4
    Join Date
    Mar 2011
    Posts
    11
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's a whole list of keys in case special ones are used:

    Code:
        Public Shared keyTable As New Hashtable
        Public Shared Sub compileKeyTable()
            keyTable.Clear()
            keyTable.Add("BUTTON1", &H1)
            keyTable.Add("BUTTON2", &H2)
            keyTable.Add("CANCEL", &H3)
            keyTable.Add("BUTTON3", &H4)
            keyTable.Add("BACK", &H8)
            keyTable.Add("TAB", &H9)
            keyTable.Add("CLEAR", &HC)
            keyTable.Add("RETURN", &HD)
            keyTable.Add("SHIFT", &H10)
            keyTable.Add("CTRL", &H11)
            keyTable.Add("ALT", &H12)
            keyTable.Add("PAUSE", &H13)
            keyTable.Add("CAPITAL", &H14)
            keyTable.Add("ESCAPE", &H1B)
            keyTable.Add("SPACE", &H20)
            keyTable.Add("PAGEUP", &H21)
            keyTable.Add("PAGEDOWN", &H22)
            keyTable.Add("END", &H23)
            keyTable.Add("HOME", &H24)
            keyTable.Add("LEFT", &H25)
            keyTable.Add("UP", &H26)
            keyTable.Add("RIGHT", &H27)
            keyTable.Add("DOWN", &H28)
            keyTable.Add("SELECT", &H29)
            keyTable.Add("PRINT", &H2A)
            keyTable.Add("EXECUTE", &H2B)
            keyTable.Add("PRINTSCREEN", &H2C) ' Print screen key
            keyTable.Add("INSERT", &H2D)
            keyTable.Add("DELETE", &H2E)
            keyTable.Add("HELP", &H2F)
            keyTable.Add("0", &H30)
            keyTable.Add("1", &H31)
            keyTable.Add("2", &H32)
            keyTable.Add("3", &H33)
            keyTable.Add("4", &H34)
            keyTable.Add("5", &H35)
            keyTable.Add("6", &H36)
            keyTable.Add("7", &H37)
            keyTable.Add("8", &H38)
            keyTable.Add("9", &H39)
            keyTable.Add("A", &H41)
            keyTable.Add("B", &H42)
            keyTable.Add("C", &H43)
            keyTable.Add("D", &H44)
            keyTable.Add("E", &H45)
            keyTable.Add("F", &H46)
            keyTable.Add("G", &H47)
            keyTable.Add("H", &H48)
            keyTable.Add("I", &H49)
            keyTable.Add("J", &H4A)
            keyTable.Add("K", &H4B)
            keyTable.Add("L", &H4C)
            keyTable.Add("M", &H4D)
            keyTable.Add("N", &H4E)
            keyTable.Add("O", &H4F)
            keyTable.Add("P", &H50)
            keyTable.Add("Q", &H51)
            keyTable.Add("R", &H52)
            keyTable.Add("S", &H53)
            keyTable.Add("T", &H54)
            keyTable.Add("U", &H55)
            keyTable.Add("V", &H56)
            keyTable.Add("W", &H57)
            keyTable.Add("X", &H58)
            keyTable.Add("Y", &H59)
            keyTable.Add("Z", &H5A)
            keyTable.Add("NUMPAD0", &H60)
            keyTable.Add("NUMPAD1", &H4C)
            keyTable.Add("NUMPAD2", &H4D)
            keyTable.Add("NUMPAD3", &H4E)
            keyTable.Add("NUMPAD4", &H4F)
            keyTable.Add("NUMPAD5", &H50)
            keyTable.Add("NUMPAD6", &H51)
            keyTable.Add("NUMPAD7", &H52)
            keyTable.Add("NUMPAD8", &H53)
            keyTable.Add("NUMPAD9", &H54)
            keyTable.Add("SEPARATOR", &H6C) ' No idea what this is 
            keyTable.Add("-", &H6D) ' Subtract key
            keyTable.Add(".", &H6E) ' Decimal key
            keyTable.Add("/", &H6F) ' Divide key
            keyTable.Add("F1", &H70)
            keyTable.Add("F2", &H71)
            keyTable.Add("F3", &H72)
            keyTable.Add("F4", &H73)
            keyTable.Add("F5", &H74)
            keyTable.Add("F6", &H75)
            keyTable.Add("F7", &H76)
            keyTable.Add("F8", &H77)
            keyTable.Add("F9", &H78)
            keyTable.Add("F10", &H79)
            keyTable.Add("F11", &H7A)
            keyTable.Add("F12", &H7B)
            keyTable.Add("F13", &H7C)
            keyTable.Add("F14", &H7D)
            keyTable.Add("F15", &H7E)
            keyTable.Add("F16", &H7F)
            keyTable.Add("F17", 128)
            keyTable.Add("F18", 129)
            keyTable.Add("F19", 130)
            keyTable.Add("F20", 131)
            keyTable.Add("F21", 132)
            keyTable.Add("F22", 133)
            keyTable.Add("F23", 134)
            keyTable.Add("F24", 135)
            keyTable.Add("NUMLOCK", &H90)
            keyTable.Add("SCROLL", &H91)
            keyTable.Add("LSHIFT", &HA0)
            keyTable.Add("RSHIFT", &HA1)
            keyTable.Add("LCONTROL", &HA2)
            keyTable.Add("RCONTROL", &HA3)
            keyTable.Add("LMENU", &HA4)
            keyTable.Add("RMENU", &HA5)
            keyTable.Add("PLAY", &HFA)
            keyTable.Add("ZOOM", &HFB)
        End Sub

Similar Threads

  1. CODE: Encapsulating The Spell Book
    By EmilyStrange in forum WoW Memory Editing
    Replies: 0
    Last Post: 06-29-2011, 03:34 PM
  2. Best Mage Key Bindings
    By The Phenom2 in forum World of Warcraft General
    Replies: 5
    Last Post: 03-03-2008, 03:43 PM
  3. 19 rogue Key Bindings?
    By ihatelag in forum WoW PvP & Battlegrounds
    Replies: 8
    Last Post: 01-10-2008, 10:24 AM
  4. Rogue key bindings (problem)
    By Spazzoid in forum Community Chat
    Replies: 3
    Last Post: 05-12-2007, 07:16 PM
All times are GMT -5. The time now is 04:01 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search