diff --git a/.gitignore b/.gitignore
index d9a98a5..896bfac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,10 +7,12 @@
# or wget:
# wget --no-check-certificate http://gist.githubusercontent.com/kmorcinek/2710267/raw/.gitignore
+RawInput.Sharp/*
+
# User-specific files
-*.suo
-*.user
-*.sln.docstates
+.suo
+.user
+.sln.docstates
# Build results
[Dd]ebug/
diff --git a/App.xaml b/App.xaml
new file mode 100755
index 0000000..7a61778
--- /dev/null
+++ b/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/App.xaml.cs b/App.xaml.cs
new file mode 100755
index 0000000..ca244cc
--- /dev/null
+++ b/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace MacroBoard
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs
new file mode 100755
index 0000000..74087a1
--- /dev/null
+++ b/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/Config.cs b/Config.cs
new file mode 100755
index 0000000..5a63aeb
--- /dev/null
+++ b/Config.cs
@@ -0,0 +1,107 @@
+using Linearstar.Windows.RawInput;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Windows;
+using System.Xml;
+using System.Xml.Serialization;
+using System.Linq;
+
+namespace MacroBoard
+{
+ class Config
+ {
+ public static readonly string ConfigDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configs");
+ public static readonly string AppConfigDir = Path.Combine(ConfigDir, "Application");
+ public static readonly string ModConfigDir = Path.Combine(ConfigDir, "Mods");
+
+ public static readonly string AppConfigDevicesPath = Path.Combine(AppConfigDir, "Devices.cfg");
+
+ ///
+ /// Saves and updates the device config if a new device is found
+ ///
+ /// The DeviceConfig object being stored
+ /// Path where the configuration file will be saved
+ public static void SaveDevices(DeviceConfig deviceConfig, Stream saveStream)
+ {
+ XmlSerializer xs = new XmlSerializer(typeof(DeviceConfig));
+
+ xs.Serialize(saveStream, deviceConfig);
+ }
+
+ public static DeviceConfig ReadDevices(string savePath)
+ {
+ XmlSerializer xs = new XmlSerializer(typeof(DeviceConfig));
+
+ using (TextReader tw = new StreamReader(savePath))
+ {
+ return (DeviceConfig)xs.Deserialize(tw);
+ }
+ }
+
+ //???
+ public static DeviceConfig GetDevices()
+ {
+ return new DeviceConfig(/*new bool(),*/ new List());
+ }
+
+ //???
+ public static bool NewDevicesFound()
+ {
+ return new bool();
+ }
+
+ public static void /*DeviceConfig*/ HandleDeviceConfig(List keyboardList)
+ {
+ if (File.Exists(AppConfigDevicesPath))
+ {
+ DeviceConfig dc = ReadDevices(AppConfigDevicesPath);
+
+ //New Keyboard(s) Found
+ if (dc.Keyboards.Count < keyboardList.Count)
+ {
+ List AddedKeyboardsList = new List();
+
+ AddedKeyboardsList = keyboardList.Where(x => !dc.Keyboards.Any(y => y.KeyboardName == x.KeyboardName)).ToList();
+
+
+ foreach (var keyboard in dc.Keyboards)
+ System.Diagnostics.Debug.WriteLine("dc.Keyboards: " + keyboard.KeyboardName);
+
+ foreach (var keyboard in keyboardList)
+ {
+ System.Diagnostics.Debug.WriteLine("keyboardList: " + keyboard.KeyboardName);
+ }
+
+ string addedKeyboards = "";
+ foreach (var keyboard in AddedKeyboardsList)
+ addedKeyboards += $"\r\n{keyboard.KeyboardName}\r\n";
+
+ MessageBox.Show($"New devices have been found.\r\nPress \"Yes\" if you would like to configure these devices.\r\n\r\nAdded Devices:\r\n{addedKeyboards}", "New Devices Found", MessageBoxButton.YesNo, MessageBoxImage.Question);
+ }
+ //Old Keyboard(s) Removed
+ else if (dc.Keyboards.Count > keyboardList.Count)
+ {
+ List RemovedKeyboardsList = new List();
+
+ RemovedKeyboardsList = dc.Keyboards.Where(x => !keyboardList.Any(y => x.KeyboardName == y.KeyboardName)).ToList();
+
+ string removedKeyboards = "";
+ foreach (var keyboard in RemovedKeyboardsList)
+ removedKeyboards += $"\r\n{keyboard.KeyboardName}\r\n";
+
+ MessageBox.Show($"Old devices have been removed.\r\nRemoved Devices:\r\n{removedKeyboards}", "Old Devices Removed", MessageBoxButton.YesNo, MessageBoxImage.Question);
+ }
+ }
+ else
+ {
+ using (var f = File.Create(AppConfigDevicesPath))
+ {
+ DeviceConfig dc = new DeviceConfig(keyboardList);
+ SaveDevices(dc, f);
+ }
+ }
+ }
+ }
+}
diff --git a/ConfigClasses.cs b/ConfigClasses.cs
new file mode 100755
index 0000000..d14f797
--- /dev/null
+++ b/ConfigClasses.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+
+namespace MacroBoard
+{
+ public class DeviceConfig
+ {
+ public DeviceConfig(List keyboards)
+ {
+ Keyboards = keyboards;
+ }
+
+ //Need a blank constructor to allow for Xml Deserialization
+ private DeviceConfig() { }
+
+
+ public List Keyboards { get; set; }
+ }
+
+ public class KeyboardConfig
+ {
+ public KeyboardConfig(string keyboardAlias, bool isMacroBoard, bool hasAutoNumLock, string keyboardName, string keyboardPath, bool isDefaultMacroBoard)
+ {
+ KeyboardAlias = keyboardAlias;
+ IsMacroBoard = isMacroBoard;
+ HasAutoNumLock = hasAutoNumLock;
+ KeyboardName = keyboardName;
+ KeyboardPath = keyboardPath;
+ IsDefaultMacroBoard = isDefaultMacroBoard;
+ }
+
+ //Need a blank constructor to allow for Xml Deserialization
+ private KeyboardConfig() { }
+
+ public string KeyboardAlias { get; set; }
+ public bool IsMacroBoard { get; set; }
+ public bool HasAutoNumLock { get; set; }
+ public string KeyboardName { get; set; }
+ public string KeyboardPath { get; set; }
+
+ public bool IsDefaultMacroBoard { get; set; }
+ }
+}
diff --git a/DllInject.cs b/DllInject.cs
new file mode 100755
index 0000000..c446074
--- /dev/null
+++ b/DllInject.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace MacroBoard.Inject
+{
+#warning Need to get proper unmangled names in the future.
+ class DllInject
+ {
+ [DllImport("KeyboardHook.dll")]
+ public static extern int InstallHook(IntPtr hwndParent);
+
+ [DllImport("KeyboardHook.dll")]
+ public static extern int UninstallHook();
+ }
+}
diff --git a/Handler.cs b/Handler.cs
new file mode 100755
index 0000000..3162f69
--- /dev/null
+++ b/Handler.cs
@@ -0,0 +1,141 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Text;
+
+namespace MacroBoard
+{
+ class Handler
+ {
+ //Contains list of ModKeyCombination objects accessible by the mod's Type
+ public static Dictionary> ModsKeyCombinations = new Dictionary>();
+
+ ///
+ /// This is a boolean mapping a ModType to a boolean saying whether or not it is allowed to set key combinations determined by the HandlerCommunications.HandleType
+ ///
+ private static Dictionary SupportedByHandler = new Dictionary();
+
+ public static void SetHandlerType(dynamic modType, bool b)
+ {
+ SupportedByHandler.Add(modType, b);
+ }
+
+ public static void HandleCombination(List Keys)
+ {
+
+ var modDataList = ModData.ModDataList;
+
+ for (int i = 0; i < modDataList.Count; i++)
+ {
+ //Contains list of KeyCombinations under a specific mod
+ var modKeyCombinationsList = ModsKeyCombinations[modDataList[i].Type];
+
+ for (int j = 0; j < modKeyCombinationsList.Count; j++)
+ {
+
+ int keysMatching = 0;
+ var ModComboKeys = modKeyCombinationsList[j].Keys;
+
+ for (int k = 0; k < ModComboKeys.Count; k++)
+ {
+
+ for (int l = 0; l < Keys.Count; l++)
+ {
+
+ if (KeyData.CompareToModKeybind(ModComboKeys[k], Keys[l], MainWindow.DefaultKeyboardAlias))
+ {
+ keysMatching++;
+ }
+ }
+
+ }
+
+ if (keysMatching == ModComboKeys.Count)
+ {
+ Debug.WriteLine("Calling Method: " + modKeyCombinationsList[j].CallbackMethod.Method.Name);
+ modKeyCombinationsList[j].CallbackMethod.Invoke();
+ }
+ }
+ }
+ }
+ }
+
+ public class ModKeyCombination
+ {
+ //Convert List<[Mod Name].ModKeyComination> to List Not sure how to cast different types, so copying each invidivual primitive at a time.
+ public static List Convert(dynamic data)
+ {
+ List ComboList = new List();
+ Debug.WriteLine(data.Count as object);
+ for (int i = 0; i < data.Count; i++)
+ {
+ ModKeyCombination Combo = new ModKeyCombination();
+ foreach (PropertyInfo prop in data[i].GetType().GetProperties())
+ {
+ if (prop.Name == "Keys")
+ {
+ List keyListData = new List();
+ var modKeys = prop.GetValue(data[i]);
+ for (int j = 0; j < modKeys.Count; j++)
+ {
+ KeyData keyData = new KeyData();
+
+ foreach (PropertyInfo propKey in modKeys[j].GetType().GetProperties())
+ {
+
+ typeof(KeyData)
+ .GetProperty(propKey.Name, BindingFlags.Instance | BindingFlags.Public)
+ .SetValue(keyData, propKey.GetValue(modKeys[j]));
+ }
+
+ keyListData.Add(keyData);
+ }
+
+ Combo.Keys = keyListData;
+ }
+ else
+ {
+ typeof(ModKeyCombination)
+ .GetProperty(prop.Name, BindingFlags.Instance | BindingFlags.Public)
+ .SetValue(Combo, prop.GetValue(data[i]));
+
+ }
+
+
+ }
+
+ ComboList.Add(Combo);
+ }
+
+ return ComboList;
+ }
+
+ public static void SetModCombinations(dynamic modType, List Combinations)
+ {
+ if (!Handler.ModsKeyCombinations.ContainsKey(modType))
+ {
+ Handler.ModsKeyCombinations.Add(modType, Combinations);
+ }
+ else
+ {
+ Handler.ModsKeyCombinations[modType] = Combinations;
+ }
+ }
+
+ public ModKeyCombination()
+ {
+
+ }
+
+ public ModKeyCombination(List keys, Action callbackMethod)
+ {
+ Keys = keys;
+ CallbackMethod = callbackMethod;
+
+ }
+
+
+ public List Keys { get; set; }
+ public Action CallbackMethod { get; set; }
+ }
diff --git a/HandlerCommunications.cs b/HandlerCommunications.cs
new file mode 100755
index 0000000..6d1ed2a
--- /dev/null
+++ b/HandlerCommunications.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MacroBoard
+{
+ class HandlerCommunications
+ {
+ ///
+ /// Tells the Mod Handler how keys should be handled.
+ ///
+ public enum HandleType
+ {
+ ///
+ /// Have the mod handler (Main Application) handle all of the keys. This means the mod won't recieve "Call" method calls.
+ ///
+ HandlerOnly,
+
+ ///
+ /// Have the mod handle all of the keys. This means the mod handler (Main Application) won't accept any [List<KeyCombination>, delegate] dicts.
+ ///
+ ModOnly,
+
+ ///
+ /// Have both the mod handler (Main Application) and mod handle the keys. This means the mod will recieve "Call" method calls, and can send [List<KeyCombination>, delegate] dicts to the mod handler.
+ ///
+ Both
+ }
+ }
+}
diff --git a/KeyData.cs b/KeyData.cs
new file mode 100755
index 0000000..1f53b6e
--- /dev/null
+++ b/KeyData.cs
@@ -0,0 +1,157 @@
+using Linearstar.Windows.RawInput;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using static MacroBoard.Hook.KeyboardHook;
+
+namespace MacroBoard
+{
+
+
+ public class KeyData
+ {
+ public KeyData() { }
+
+ private static List Keys = new List();
+
+ public static void ProcessKey(KeyData data, uint WindowMessage)
+ {
+ KeyState state = KeyState.Unknown;
+
+ if ((KeyMessages)WindowMessage == KeyMessages.WM_KEYDOWN || (KeyMessages)WindowMessage == KeyMessages.WM_SYSKEYDOWN)
+ {
+ state = KeyState.Down;
+ } else if ((KeyMessages)WindowMessage == KeyMessages.WM_KEYUP || (KeyMessages)WindowMessage == KeyMessages.WM_SYSKEYUP)
+ {
+ state = KeyState.Up;
+ }
+ else
+ {
+ //state is Unknown, this shouldn't happen
+ throw new Exception("KeyState Unknown");
+ }
+
+ if (state == KeyState.Down)
+ {
+ //boolean determining if this key is already down
+ bool keyAlreadyExists = false;
+ for (int i = 0; i < Keys.Count; i++)
+ {
+ KeyData key = Keys[i];
+ if (Compare(data, key))
+ {
+ keyAlreadyExists = true;
+ }
+
+ if (!keyAlreadyExists)
+ Keys.Add(data);
+
+
+
+ }
+
+ Debug.WriteLine("Keys count: " + Keys.Count);
+
+ Keys.ForEach(kbd => Debug.WriteLine(kbd.KeyboardAlias + " : (" + (VKeys)kbd.VirtualKey + ") " + kbd.VirtualKey + " : (" + (RawKeyboardFlags)kbd.Flags + ") " + kbd.Flags + " : " + kbd.ScanCode));
+ Debug.WriteLine("\r\n");
+
+ if (state == KeyState.Up)
+ {
+ for (int i = 0; i < Keys.Count; i++)
+ {
+ KeyData key = Keys[i];
+
+ if (Compare(data, key))
+ {
+ Keys.Remove(key);
+ }
+
+ }
+ }
+ else
+ {
+ //Check all Key Combinations
+ Handler.HandleCombination(Keys);
+ }
+ }
+
+ public static KeyData Format(string KeyboardAlias, RawInputKeyboardData data)
+ {
+
+ return new KeyData(
+ KeyboardAlias,
+ (int)data.Keyboard.Flags,
+ data.Keyboard.ScanCode,
+ data.Keyboard.VirutalKey
+ );
+ }
+
+ public static bool Compare(KeyData key1, KeyData key2)
+ {
+ RawKeyboardFlags key1Flags = (RawKeyboardFlags)key1.Flags;
+ RawKeyboardFlags key2Flags = (RawKeyboardFlags)key2.Flags;
+
+ if (key1.KeyboardAlias == key2.KeyboardAlias &&
+ key1Flags.HasFlag(RawKeyboardFlags.KeyE0) == key2Flags.HasFlag(RawKeyboardFlags.KeyE0) && //could technically just remove the None/KeyUp flag from both and it would solve the problem simpler.
+ key1Flags.HasFlag(RawKeyboardFlags.KeyE1) == key2Flags.HasFlag(RawKeyboardFlags.KeyE1) &&
+ key1.ScanCode == key2.ScanCode &&
+ key1.VirtualKey == key2.VirtualKey)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ //Same as Compare, but is used specifically for comparing Keys and ModKeyCombinations specifically for KeyAlias being [Default]
+ public static bool CompareToModKeybind(KeyData modData, KeyData keyData, string ReplaceDefault)
+ {
+ RawKeyboardFlags key1Flags = (RawKeyboardFlags)modData.Flags;
+ RawKeyboardFlags key2Flags = (RawKeyboardFlags)keyData.Flags;
+
+ if (((modData.KeyboardAlias == keyData.KeyboardAlias) || (modData.KeyboardAlias == "[Default]" && ReplaceDefault == keyData.KeyboardAlias)) &&
+ key1Flags.HasFlag(RawKeyboardFlags.KeyE0) == key2Flags.HasFlag(RawKeyboardFlags.KeyE0) && //could technically just remove the None/KeyUp flag from both and it would solve the problem simpler.
+ key1Flags.HasFlag(RawKeyboardFlags.KeyE1) == key2Flags.HasFlag(RawKeyboardFlags.KeyE1) &&
+ modData.ScanCode == keyData.ScanCode &&
+ modData.VirtualKey == keyData.VirtualKey)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public int Flags { get; set; }
+ public int ScanCode { get; set; }
+ public int VirtualKey { get; set; }
+
+ //Custom made data
+
+ //The string passed when the key is pressed to tell the mod what keyboard it was sent from.
+ public /*readonly*/ string KeyboardAlias { get; set; }
+
+
+ public KeyData(string keyboardAlias, int flags, int scanCode, int virtualKey)
+ {
+ KeyboardAlias = keyboardAlias;
+ Flags = flags;
+ ScanCode = scanCode;
+ VirtualKey = virtualKey;
+ }
+ }
+
+ public enum KeyState
+ {
+ Unknown,
+ Down,
+ Up,
+ }
+
+ [Flags]
+ public enum RawKeyboardFlags : ushort
+ {
+ None = 0,
+ Up = 1 << 0,
+ KeyE0 = 1 << 1,
+ KeyE1 = 1 << 2,
+ }
+}
diff --git a/KeyHandling.cs b/KeyHandling.cs
new file mode 100755
index 0000000..dd403d1
--- /dev/null
+++ b/KeyHandling.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MacroBoard
+{
+ public class KeyHandling
+ {
+ [Flags]
+ public enum KeyModifiers
+ {
+ None = 0,
+ LShift = 1 << 0,
+ RShift = 1 << 1,
+ LControl = 1 << 2,
+ RControl = 1 << 3,
+ LAlt = 1 << 4,
+ RAlt = 1 << 5,
+ LWin = 1 << 6,
+ RWin = 1 << 7
+ }
+
+
+ }
+}
diff --git a/KeyboardData.cs b/KeyboardData.cs
new file mode 100755
index 0000000..6cb0e16
--- /dev/null
+++ b/KeyboardData.cs
@@ -0,0 +1,119 @@
+using Linearstar.Windows.RawInput;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using static MacroBoard.Hook.KeyboardHook;
+
+namespace MacroBoard
+{
+
+
+ class KeyboardData
+ {
+ private static List ActiveData = new List();
+
+ public static void ProcessKey(KeyboardData data)
+ {
+ KeyState state = KeyState.Unknown;
+
+ if ((KeyMessages)data.WindowMessage == KeyMessages.WM_KEYDOWN || (KeyMessages)data.WindowMessage == KeyMessages.WM_SYSKEYDOWN)
+ {
+ state = KeyState.Down;
+ } else if ((KeyMessages)data.WindowMessage == KeyMessages.WM_KEYUP || (KeyMessages)data.WindowMessage == KeyMessages.WM_SYSKEYUP)
+ {
+ state = KeyState.Up;
+ }
+ else
+ {
+ //state is Unknown, this shouldn't happen
+ throw new Exception("KeyState Unknown");
+ }
+
+ if (state == KeyState.Down)
+ {
+ ActiveData.Add(data);
+ }
+
+ ActiveData.ForEach(kbd => Debug.WriteLine(kbd.KeyboardAlias + " : " + (VKeys)kbd.VirtualKey + " : " + kbd.Flags + " : " + kbd.ScanCode));
+ Debug.WriteLine("\r\n");
+
+ if (state == KeyState.Up)
+ {
+ for (int i = 0; i < ActiveData.Count; i++)
+ {
+ KeyboardData kbd = ActiveData[i];
+
+
+ RawKeyboardFlags kbdFlags = (RawKeyboardFlags)kbd.Flags;
+ RawKeyboardFlags dataFlags = (RawKeyboardFlags)data.Flags;
+
+ if (kbd.KeyboardAlias == data.KeyboardAlias &&
+ kbdFlags.HasFlag(RawKeyboardFlags.KeyE0) == dataFlags.HasFlag(RawKeyboardFlags.KeyE0) && //could technically just remove the None/KeyUp flag from both and it would solve the problem simpler.
+ kbdFlags.HasFlag(RawKeyboardFlags.KeyE1) == dataFlags.HasFlag(RawKeyboardFlags.KeyE1) &&
+ kbd.ScanCode == data.ScanCode &&
+ kbd.VirtualKey == data.VirtualKey)
+ {
+ ActiveData.Remove(kbd);
+ }
+ }
+ }
+ }
+
+ public static KeyboardData Format(string KeyboardAlias, RawInputKeyboardData data)
+ {
+ // Using WindowMessage to determine key state
+ return new KeyboardData(
+ KeyboardAlias,
+ data.Keyboard.ExtraInformation,
+ (int)data.Keyboard.Flags,
+ data.Keyboard.ScanCode,
+ data.Keyboard.VirutalKey,
+ data.Keyboard.WindowMessage
+ );
+ }
+
+ //Passed data from "RawInputKeyboardData"
+
+ public readonly uint ExtraInformation;
+ public readonly /*RawKeyboardFlags*/ int Flags;
+ public readonly int ScanCode;
+ public readonly int VirtualKey;
+ public readonly uint WindowMessage;
+
+ //Custom made data
+
+ //The string passed when the key is pressed to tell the mod what keyboard it was sent from.
+ public readonly string KeyboardAlias;
+
+ //Determine if any key modifiers are presed.
+ //public readonly int KeyModifiers;
+
+
+ public KeyboardData(string keyboardAlias, uint extraInformation, int flags, int scanCode, int virtualKey, uint windowMessage)
+ {
+ KeyboardAlias = keyboardAlias;
+ ExtraInformation = extraInformation;
+ Flags = flags;
+ ScanCode = scanCode;
+ VirtualKey = virtualKey;
+ WindowMessage = windowMessage;
+ }
+ }
+
+ public enum KeyState
+ {
+ Unknown,
+ Down,
+ Up,
+ }
+
+ [Flags]
+ public enum RawKeyboardFlags : ushort
+ {
+ None = 0,
+ Up = 1 << 0,
+ KeyE0 = 1 << 1,
+ KeyE1 = 1 << 2,
+ }
+}
diff --git a/KeyboardHook.cs b/KeyboardHook.cs
new file mode 100755
index 0000000..ea5af97
--- /dev/null
+++ b/KeyboardHook.cs
@@ -0,0 +1,448 @@
+using MacroBoard.Native;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Interop;
+
+namespace MacroBoard.Hook
+{
+ ///
+ /// Class for intercepting low level keyboard hooks
+ ///
+ public class KeyboardHook
+ {
+ ///
+ /// Virtual Keys
+ ///
+ public enum VKeys
+ {
+ // Losely based on http://www.pinvoke.net/default.aspx/Enums/VK.html
+
+ LBUTTON = 0x01, // Left mouse button
+ RBUTTON = 0x02, // Right mouse button
+ CANCEL = 0x03, // Control-break processing
+ MBUTTON = 0x04, // Middle mouse button (three-button mouse)
+ XBUTTON1 = 0x05, // Windows 2000/XP: X1 mouse button
+ XBUTTON2 = 0x06, // Windows 2000/XP: X2 mouse button
+ // 0x07 // Undefined
+ BACK = 0x08, // BACKSPACE key
+ TAB = 0x09, // TAB key
+ // 0x0A-0x0B, // Reserved
+ CLEAR = 0x0C, // CLEAR key
+ RETURN = 0x0D, // ENTER key
+ // 0x0E-0x0F, // Undefined
+ SHIFT = 0x10, // SHIFT key
+ CONTROL = 0x11, // CTRL key
+ MENU = 0x12, // ALT key
+ PAUSE = 0x13, // PAUSE key
+ CAPITAL = 0x14, // CAPS LOCK key
+ KANA = 0x15, // Input Method Editor (IME) Kana mode
+ HANGUL = 0x15, // IME Hangul mode
+ // 0x16, // Undefined
+ JUNJA = 0x17, // IME Junja mode
+ FINAL = 0x18, // IME final mode
+ HANJA = 0x19, // IME Hanja mode
+ KANJI = 0x19, // IME Kanji mode
+ // 0x1A, // Undefined
+ ESCAPE = 0x1B, // ESC key
+ CONVERT = 0x1C, // IME convert
+ NONCONVERT = 0x1D, // IME nonconvert
+ ACCEPT = 0x1E, // IME accept
+ MODECHANGE = 0x1F, // IME mode change request
+ SPACE = 0x20, // SPACEBAR
+ PRIOR = 0x21, // PAGE UP key
+ NEXT = 0x22, // PAGE DOWN key
+ END = 0x23, // END key
+ HOME = 0x24, // HOME key
+ LEFT = 0x25, // LEFT ARROW key
+ UP = 0x26, // UP ARROW key
+ RIGHT = 0x27, // RIGHT ARROW key
+ DOWN = 0x28, // DOWN ARROW key
+ SELECT = 0x29, // SELECT key
+ PRINT = 0x2A, // PRINT key
+ EXECUTE = 0x2B, // EXECUTE key
+ SNAPSHOT = 0x2C, // PRINT SCREEN key
+ INSERT = 0x2D, // INS key
+ DELETE = 0x2E, // DEL key
+ HELP = 0x2F, // HELP key
+ KEY_0 = 0x30, // 0 key
+ KEY_1 = 0x31, // 1 key
+ KEY_2 = 0x32, // 2 key
+ KEY_3 = 0x33, // 3 key
+ KEY_4 = 0x34, // 4 key
+ KEY_5 = 0x35, // 5 key
+ KEY_6 = 0x36, // 6 key
+ KEY_7 = 0x37, // 7 key
+ KEY_8 = 0x38, // 8 key
+ KEY_9 = 0x39, // 9 key
+ // 0x3A-0x40, // Undefined
+ KEY_A = 0x41, // A key
+ KEY_B = 0x42, // B key
+ KEY_C = 0x43, // C key
+ KEY_D = 0x44, // D key
+ KEY_E = 0x45, // E key
+ KEY_F = 0x46, // F key
+ KEY_G = 0x47, // G key
+ KEY_H = 0x48, // H key
+ KEY_I = 0x49, // I key
+ KEY_J = 0x4A, // J key
+ KEY_K = 0x4B, // K key
+ KEY_L = 0x4C, // L key
+ KEY_M = 0x4D, // M key
+ KEY_N = 0x4E, // N key
+ KEY_O = 0x4F, // O key
+ KEY_P = 0x50, // P key
+ KEY_Q = 0x51, // Q key
+ KEY_R = 0x52, // R key
+ KEY_S = 0x53, // S key
+ KEY_T = 0x54, // T key
+ KEY_U = 0x55, // U key
+ KEY_V = 0x56, // V key
+ KEY_W = 0x57, // W key
+ KEY_X = 0x58, // X key
+ KEY_Y = 0x59, // Y key
+ KEY_Z = 0x5A, // Z key
+ LWIN = 0x5B, // Left Windows key (Microsoft Natural keyboard)
+ RWIN = 0x5C, // Right Windows key (Natural keyboard)
+ APPS = 0x5D, // Applications key (Natural keyboard)
+ // 0x5E, // Reserved
+ SLEEP = 0x5F, // Computer Sleep key
+ NUMPAD0 = 0x60, // Numeric keypad 0 key
+ NUMPAD1 = 0x61, // Numeric keypad 1 key
+ NUMPAD2 = 0x62, // Numeric keypad 2 key
+ NUMPAD3 = 0x63, // Numeric keypad 3 key
+ NUMPAD4 = 0x64, // Numeric keypad 4 key
+ NUMPAD5 = 0x65, // Numeric keypad 5 key
+ NUMPAD6 = 0x66, // Numeric keypad 6 key
+ NUMPAD7 = 0x67, // Numeric keypad 7 key
+ NUMPAD8 = 0x68, // Numeric keypad 8 key
+ NUMPAD9 = 0x69, // Numeric keypad 9 key
+ MULTIPLY = 0x6A, // Multiply key
+ ADD = 0x6B, // Add key
+ SEPARATOR = 0x6C, // Separator key
+ SUBTRACT = 0x6D, // Subtract key
+ DECIMAL = 0x6E, // Decimal key
+ DIVIDE = 0x6F, // Divide key
+ F1 = 0x70, // F1 key
+ F2 = 0x71, // F2 key
+ F3 = 0x72, // F3 key
+ F4 = 0x73, // F4 key
+ F5 = 0x74, // F5 key
+ F6 = 0x75, // F6 key
+ F7 = 0x76, // F7 key
+ F8 = 0x77, // F8 key
+ F9 = 0x78, // F9 key
+ F10 = 0x79, // F10 key
+ F11 = 0x7A, // F11 key
+ F12 = 0x7B, // F12 key
+ F13 = 0x7C, // F13 key
+ F14 = 0x7D, // F14 key
+ F15 = 0x7E, // F15 key
+ F16 = 0x7F, // F16 key
+ F17 = 0x80, // F17 key
+ F18 = 0x81, // F18 key
+ F19 = 0x82, // F19 key
+ F20 = 0x83, // F20 key
+ F21 = 0x84, // F21 key
+ F22 = 0x85, // F22 key, (PPC only) Key used to lock device.
+ F23 = 0x86, // F23 key
+ F24 = 0x87, // F24 key
+ // 0x88-0X8F, // Unassigned
+ NUMLOCK = 0x90, // NUM LOCK key
+ SCROLL = 0x91, // SCROLL LOCK key
+ // 0x92-0x96, // OEM specific
+ // 0x97-0x9F, // Unassigned
+ LSHIFT = 0xA0, // Left SHIFT key
+ RSHIFT = 0xA1, // Right SHIFT key
+ LCONTROL = 0xA2, // Left CONTROL key
+ RCONTROL = 0xA3, // Right CONTROL key
+ LMENU = 0xA4, // Left MENU key
+ RMENU = 0xA5, // Right MENU key
+ BROWSER_BACK = 0xA6, // Windows 2000/XP: Browser Back key
+ BROWSER_FORWARD = 0xA7, // Windows 2000/XP: Browser Forward key
+ BROWSER_REFRESH = 0xA8, // Windows 2000/XP: Browser Refresh key
+ BROWSER_STOP = 0xA9, // Windows 2000/XP: Browser Stop key
+ BROWSER_SEARCH = 0xAA, // Windows 2000/XP: Browser Search key
+ BROWSER_FAVORITES = 0xAB, // Windows 2000/XP: Browser Favorites key
+ BROWSER_HOME = 0xAC, // Windows 2000/XP: Browser Start and Home key
+ VOLUME_MUTE = 0xAD, // Windows 2000/XP: Volume Mute key
+ VOLUME_DOWN = 0xAE, // Windows 2000/XP: Volume Down key
+ VOLUME_UP = 0xAF, // Windows 2000/XP: Volume Up key
+ MEDIA_NEXT_TRACK = 0xB0,// Windows 2000/XP: Next Track key
+ MEDIA_PREV_TRACK = 0xB1,// Windows 2000/XP: Previous Track key
+ MEDIA_STOP = 0xB2, // Windows 2000/XP: Stop Media key
+ MEDIA_PLAY_PAUSE = 0xB3,// Windows 2000/XP: Play/Pause Media key
+ LAUNCH_MAIL = 0xB4, // Windows 2000/XP: Start Mail key
+ LAUNCH_MEDIA_SELECT = 0xB5, // Windows 2000/XP: Select Media key
+ LAUNCH_APP1 = 0xB6, // Windows 2000/XP: Start Application 1 key
+ LAUNCH_APP2 = 0xB7, // Windows 2000/XP: Start Application 2 key
+ // 0xB8-0xB9, // Reserved
+ OEM_1 = 0xBA, // Used for miscellaneous characters; it can vary by keyboard.
+ // Windows 2000/XP: For the US standard keyboard, the ';:' key
+ OEM_PLUS = 0xBB, // Windows 2000/XP: For any country/region, the '+' key
+ OEM_COMMA = 0xBC, // Windows 2000/XP: For any country/region, the ',' key
+ OEM_MINUS = 0xBD, // Windows 2000/XP: For any country/region, the '-' key
+ OEM_PERIOD = 0xBE, // Windows 2000/XP: For any country/region, the '.' key
+ OEM_2 = 0xBF, // Used for miscellaneous characters; it can vary by keyboard.
+ // Windows 2000/XP: For the US standard keyboard, the '/?' key
+ OEM_3 = 0xC0, // Used for miscellaneous characters; it can vary by keyboard.
+ // Windows 2000/XP: For the US standard keyboard, the '`~' key
+ // 0xC1-0xD7, // Reserved
+ // 0xD8-0xDA, // Unassigned
+ OEM_4 = 0xDB, // Used for miscellaneous characters; it can vary by keyboard.
+ // Windows 2000/XP: For the US standard keyboard, the '[{' key
+ OEM_5 = 0xDC, // Used for miscellaneous characters; it can vary by keyboard.
+ // Windows 2000/XP: For the US standard keyboard, the '\|' key
+ OEM_6 = 0xDD, // Used for miscellaneous characters; it can vary by keyboard.
+ // Windows 2000/XP: For the US standard keyboard, the ']}' key
+ OEM_7 = 0xDE, // Used for miscellaneous characters; it can vary by keyboard.
+ // Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
+ OEM_8 = 0xDF, // Used for miscellaneous characters; it can vary by keyboard.
+ // 0xE0, // Reserved
+ // 0xE1, // OEM specific
+ OEM_102 = 0xE2, // Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
+ // 0xE3-E4, // OEM specific
+ PROCESSKEY = 0xE5, // Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
+ // 0xE6, // OEM specific
+ PACKET = 0xE7, // Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP
+ // 0xE8, // Unassigned
+ // 0xE9-F5, // OEM specific
+ ATTN = 0xF6, // Attn key
+ CRSEL = 0xF7, // CrSel key
+ EXSEL = 0xF8, // ExSel key
+ EREOF = 0xF9, // Erase EOF key
+ PLAY = 0xFA, // Play key
+ ZOOM = 0xFB, // Zoom key
+ NONAME = 0xFC, // Reserved
+ PA1 = 0xFD, // PA1 key
+ OEM_CLEAR = 0xFE // Clear key
+ }
+
+ public enum CustomMessages
+ {
+ WM_APP = 0x8000, //32768
+ WM_HOOK = WM_APP + 1, //32769
+ WM_INPUT_DEVICE_CHANGE = 0x00FE, //254
+ }
+
+
+
+ ///
+ /// Internal callback processing function
+ ///
+ private delegate IntPtr KeyboardHookHandler(int nCode, IntPtr wParam, IntPtr lParam);
+ private KeyboardHookHandler hookHandler;
+
+ ///
+ /// Function that will be called when defined events occur
+ ///
+ /// VKeys
+ public delegate void KeyboardHookCallback(VKeys key);
+
+ #region Events
+ public event KeyboardHookCallback KeyDown;
+ public event KeyboardHookCallback KeyUp;
+ #endregion
+
+ ///
+ /// Hook ID
+ ///
+ private IntPtr hookID = IntPtr.Zero;
+
+ ///
+ /// Window Handle to send message of incoming keys
+ ///
+ private IntPtr hWndServer;
+
+ ///
+ /// Install low level keyboard hook
+ ///
+ public void Install(IntPtr hWndParent, Hooks hookType, params dynamic[] data)
+ {
+ switch (hookType)
+ {
+ case Hooks.WH_KEYBOARD:
+ IntPtr hInstance = data[0];
+ if (hInstance != IntPtr.Zero)
+ {
+ var hProc = Libraries.GetProcAddress(hInstance, "InstallHook");
+ Debug.WriteLine("HPROC: " + hProc);
+ hookID = SetWindowsHookEx((int)Hooks.WH_KEYBOARD, hProc, hInstance, 0);
+ }
+ break;
+
+ case Hooks.WH_KEYBOARD_LL:
+ hookHandler = HookFunc;
+ hookID = SetHook_LL(hookHandler);
+ break;
+ }
+
+ hWndServer = hWndParent;
+
+ }
+
+ ///
+ /// Remove low level keyboard hook
+ ///
+ public void Uninstall()
+ {
+ UnhookWindowsHookEx(hookID);
+ }
+
+ ///
+ /// Registers hook with Windows API
+ ///
+ /// Callback function
+ /// Hook ID
+ //private IntPtr SetHook(Hooks hookType, )
+ //{
+ // using (ProcessModule module = Process.GetCurrentProcess().MainModule)
+ // return SetWindowsHookEx((int)Hooks.WH_KEYBOARD, proc, GetModuleHandle(module.ModuleName), 0);
+
+ //}
+
+
+ ///
+ /// Registers LOW LEVEL hook with Windows API
+ ///
+ /// Callback function
+ /// Hook ID
+ private IntPtr SetHook_LL(KeyboardHookHandler proc)
+ {
+ using (ProcessModule module = Process.GetCurrentProcess().MainModule)
+ return SetWindowsHookEx((int)Hooks.WH_KEYBOARD_LL, proc, GetModuleHandle(module.ModuleName), 0);
+
+ }
+
+
+ ///
+ /// Default hook call, which analyses pressed keys
+ ///
+ private IntPtr HookFunc(int nCode, IntPtr wParam, IntPtr lParam)
+ {
+ //new Thread(x => { MessageBox.Show("HOOK FUNC"); }).Start();
+ if (nCode >= 0)
+ {
+ Debug.WriteLine("WITHOUT SENDMESSAGE");
+
+ //1 means handled, 0 means unhandled
+ bool handled = Messages.SendMessage(hWndServer, (int)CustomMessages.WM_HOOK, wParam, lParam) == (IntPtr)1 ? true : false;
+ Debug.WriteLine("SEND MESSAGE HANDLED? : " + handled);
+
+ if (handled)
+ {
+ return (IntPtr)1;
+ }
+
+ int iwParam = wParam.ToInt32();
+
+ if ((iwParam == (int)KeyMessages.WM_KEYDOWN || iwParam == (int)KeyMessages.WM_SYSKEYDOWN))
+ if (KeyDown != null)
+ KeyDown((VKeys)Marshal.ReadInt32(lParam));
+ if ((iwParam == (int)KeyMessages.WM_KEYUP || iwParam == (int)KeyMessages.WM_SYSKEYUP))
+ if (KeyUp != null)
+ KeyUp((VKeys)Marshal.ReadInt32(lParam));
+ }
+
+ return CallNextHookEx(hookID, nCode, wParam, lParam);
+ }
+
+ ///
+ /// Destructor. Unhook current hook
+ ///
+ ~KeyboardHook()
+ {
+ Uninstall();
+ }
+ public enum Hooks
+ {
+ WH_KEYBOARD = 2,
+ WH_KEYBOARD_LL = 13
+ }
+
+ ///
+ /// Low-Level function declarations
+ ///
+ #region WinAPI
+
+
+ public enum KeyMessages
+ {
+ WM_KEYDOWN = 0x100,
+ WM_SYSKEYDOWN = 0x104,
+ WM_KEYUP = 0x101,
+ WM_SYSKEYUP = 0x105
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookHandler lpfn, IntPtr hMod, uint dwThreadId);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ static extern IntPtr SetWindowsHookEx(int hookType, IntPtr lpfn, IntPtr hMod, uint dwThreadId);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool UnhookWindowsHookEx(IntPtr hhk);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern IntPtr GetModuleHandle(string lpModuleName);
+ #endregion
+ }
+
+ ///
+ /// Doesn't work (only works with WH_KEYBOARD_LL)
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public class KBDLLHOOKSTRUCT
+ {
+ public uint vkCode;
+ public uint scanCode;
+ public KBDLLHOOKSTRUCTFlags flags;
+ public uint time;
+ public UIntPtr dwExtraInfo;
+ }
+
+ ///
+ /// Doesn't work (only works with WH_KEYBOARD_LL)
+ ///
+ [Flags]
+ public enum KBDLLHOOKSTRUCTFlags : uint
+ {
+ LLKHF_EXTENDED = 0x01,
+ LLKHF_INJECTED = 0x10,
+ LLKHF_ALTDOWN = 0x20,
+ LLKHF_UP = 0x80,
+ }
+
+ //[StructLayout(LayoutKind.Sequential)]
+ //public class keymsgflags
+ //{
+
+ // unsigned int repcnt : 16;
+ // unsigned int scancode : 8;
+ // unsigned int extkey : 1;
+ // unsigned int reserved : 4;
+ // unsigned int context : 1;
+ // unsigned int prevstate : 1;
+ // unsigned int transition : 1;
+ //};
+
+ [Flags]
+ public enum KBDHOOKSTRUCTFlags : uint
+ {
+ KHF_EXTENDED = 0x01000000,
+ KHF_INJECTED = 0x10000000,
+ //Not sure if the KHF_LOWER_IL_INJECTED is correct, might have to be 0x00000002? but the others were shown in that form but didn't need to be like that
+ KHF_LOWER_IL_INJECTED = 0x00200000,
+ KHF_ALTDOWN = 0x20000000,
+ KHF_UP = 0x80000000
+ }
+}
diff --git a/MacroBoard.csproj b/MacroBoard.csproj
new file mode 100755
index 0000000..5760379
--- /dev/null
+++ b/MacroBoard.csproj
@@ -0,0 +1,47 @@
+
+
+
+ WinExe
+ netcoreapp3.1
+ true
+ app.manifest
+
+
+
+ true
+
+
+
+ true
+ full
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Windows.Forms.dll
+
+
+
+
diff --git a/MacroBoard.csproj.user b/MacroBoard.csproj.user
new file mode 100755
index 0000000..72081c1
--- /dev/null
+++ b/MacroBoard.csproj.user
@@ -0,0 +1,17 @@
+
+
+
+ true
+
+
+
+ Designer
+
+
+
+
+
+ Designer
+
+
+
\ No newline at end of file
diff --git a/MacroBoard.sln b/MacroBoard.sln
new file mode 100755
index 0000000..42815e6
--- /dev/null
+++ b/MacroBoard.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31112.23
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MacroBoard", "MacroBoard.csproj", "{685525DF-1CE7-4BFA-94DF-60476F201C1A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {685525DF-1CE7-4BFA-94DF-60476F201C1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {685525DF-1CE7-4BFA-94DF-60476F201C1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {685525DF-1CE7-4BFA-94DF-60476F201C1A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {685525DF-1CE7-4BFA-94DF-60476F201C1A}.Debug|x86.Build.0 = Debug|Any CPU
+ {685525DF-1CE7-4BFA-94DF-60476F201C1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {685525DF-1CE7-4BFA-94DF-60476F201C1A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {685525DF-1CE7-4BFA-94DF-60476F201C1A}.Release|x86.ActiveCfg = Release|Any CPU
+ {685525DF-1CE7-4BFA-94DF-60476F201C1A}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {30CBE9E0-E653-446E-821A-7D0FF24CF191}
+ EndGlobalSection
+EndGlobal
diff --git a/MainWindow.xaml b/MainWindow.xaml
new file mode 100755
index 0000000..0b508f8
--- /dev/null
+++ b/MainWindow.xaml
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs
new file mode 100755
index 0000000..9b21416
--- /dev/null
+++ b/MainWindow.xaml.cs
@@ -0,0 +1,686 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using System.Management;
+using System.Windows.Interop;
+//using RawInput_dll;
+using Linearstar.Windows.RawInput;
+using System.Threading;
+using System.ComponentModel;
+using MacroBoard.Native;
+using MacroBoard.Hook;
+using MacroBoard.Inject;
+using System.Runtime.InteropServices;
+
+using System.IO;
+using static MacroBoard.Hook.KeyboardHook;
+using MacroBoard.Volume;
+using System.Reflection;
+using Linearstar.Windows.RawInput.Native;
+using static MacroBoard.KeyHandling;
+using static MacroBoard.HandlerCommunications;
+using AutoMapper;
+//using static MacroBoard.KeyHandling;
+
+
+namespace MacroBoard
+{
+
+
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ //Tunnel between mods and the host process.
+ Tunnel tunnel;
+
+ public MainWindow()
+ {
+ InitializeComponent();
+ Loaded += MainWindow_Loaded;
+ Closing += MainWindow_Closing;
+ }
+
+ protected override void OnSourceInitialized(EventArgs e)
+ {
+ base.OnSourceInitialized(e);
+
+
+ tunnel = new Tunnel();
+ }
+
+ IntPtr hwnd;
+
+ Dictionary NameToRIK = new Dictionary();
+ Dictionary HIDToRIK = new Dictionary();
+ List KeyboardConfig = new List();
+ private void MainWindow_Loaded(object sender, RoutedEventArgs e)
+ {
+
+ GetKeyboardDevices();
+
+ hwnd = new WindowInteropHelper(this).Handle;
+
+ int installed = DllInject.InstallHook(hwnd);
+ Debug.WriteLine("Installed? : " + installed);
+
+
+ RawInputDevice.RegisterDevice(new RawInputDeviceRegistration(HidUsageAndPage.Keyboard, RawInputDeviceFlags.InputSink | RawInputDeviceFlags.DevNotify, hwnd));
+
+ HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
+ source.AddHook(new HwndSourceHook(WndProc));
+
+ LoadConfigs();
+ LoadMods();
+
+ ReloadAllModConfigs.Click += (s, eargs) => ReloadModConfigs();
+ ReloadAllModFiles.Click += (s, eargs) => ReloadModFiles();
+ }
+
+ public void LoadConfigs()
+ {
+ if (!Directory.Exists(Config.AppConfigDir))
+ Directory.CreateDirectory(Config.AppConfigDir);
+
+ if (!Directory.Exists(Config.ModConfigDir))
+ Directory.CreateDirectory(Config.ModConfigDir);
+
+
+
+
+ Config.HandleDeviceConfig(KeyboardConfigs);
+ }
+
+
+ // long must be used to prevent issues when converting to IntPtr
+ public static event Action MacroKeyEvent;
+
+ public List Mods = new List();
+ public void LoadMods()
+ {
+
+
+ string ModsFolder = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Mods");
+ if (!Directory.Exists(ModsFolder))
+ Directory.CreateDirectory(ModsFolder);
+
+ string[] DLLs = Directory.GetFiles(ModsFolder);
+ for (int i = 0; i < DLLs.Length; i++)
+ {
+ Debug.WriteLine(FileVersionInfo.GetVersionInfo(DLLs[i]).FileDescription);
+
+ Assembly asm = Assembly.LoadFile(DLLs[i]);
+ Type type = asm.GetType($"{System.IO.Path.GetFileNameWithoutExtension(DLLs[i])}.Mod");
+
+ dynamic Mod = Activator.CreateInstance(type);
+
+
+
+ //Initialize the Mod, send it the HostProcess to access the Mods
+
+ HandleType handleType = (HandleType)Mod.Init(tunnel);
+
+ Mods.Add(Mod);
+
+ if (handleType == HandleType.HandlerOnly || handleType == HandleType.Both)
+ {
+ Handler.SetHandlerType(type, true);
+
+ //requests combinations so that the mod knows when it is okay to send them and not have conflict with the SetHandlerType restricting it
+
+ List data = ModKeyCombination.Convert(Mod.ReturnKeyCombinations());
+
+ ModKeyCombination.SetModCombinations(type, data);
+
+ ModData modData = new ModData(asm, type, Mod);
+ ModData.ModDataList.Add(modData);
+ MacroKeyEvent += (a, b, c) =>
+ {
+ SendKeyToMod(modData, a, b, c);
+ };
+ }
+ else
+ {
+ Handler.SetHandlerType(type, false);
+ }
+ }
+ }
+
+
+ public void SendKeyToMod(ModData modData, long a, long b, dynamic[] c)
+ {
+ try
+ {
+ modData.Mod.Call(a, b, c);
+ }
+ catch (Exception ex)
+ {
+ if (IgnoreCallExceptions.IsChecked ?? false)
+ return;
+
+
+ int inc = 0;
+ foreach (var debug in new StackTrace(ex).GetFrames())
+ {
+ Debug.WriteLine(inc + ": " + debug.GetMethod().Name);
+ inc++;
+ }
+
+ var s = new StackTrace(ex);
+ var ModMethodNames = s.GetFrames().Select(f => f.GetMethod()).Where(m => m.Module.Assembly == modData.Assembly);
+
+ string StraceTraceMethods = "Stack Trace of Mod Methods:";
+ foreach (var methodBase in ModMethodNames)
+ StraceTraceMethods += "\r\n" + methodBase.Name;
+
+
+ new Thread(() =>
+ MessageBox.Show("Please notify the mod developer of the following error:\r\n\r\nException while or after passing data to \"" + modData.Type.Namespace + "\" (Call Method)\r\n\r\n" + ex.GetType().ToString() + ": " + ex.Message + "\r\n\r\n" + StraceTraceMethods,
+ "MacroBoard - Exception")).Start();
+
+
+
+
+ }
+ }
+
+ // Didn't finish implementing
+ public void UnloadMods()
+ {
+ //foreach (var Mod in Mods)
+ //{
+ // Debug.WriteLine("Output Of Releasal: " + Marshal.ReleaseComObject(Mod));
+ //}
+ }
+
+ public void ReloadModConfigs()
+ {
+ Mods.ForEach(Mod => Mod.Reload());
+ }
+
+ public void NotifyModsOfClosing()
+ {
+ Mods.ForEach(Mod => Mod.Closing());
+ }
+
+ public void ReloadModFiles()
+ {
+ MessageBox.Show("Not possible at the moment.");
+ return;
+ UnloadMods();
+ LoadMods();
+ }
+
+ DeviceConfig LoadedDeviceConfig;
+
+ public static readonly string BlankDeviceName = "None";
+ public void GetKeyboardDevices()
+ {
+ var devices = RawInputDevice.GetDevices();
+ var keyboards = devices.OfType();
+
+ List keyboardList = new List();
+
+
+ Devices.ItemsSource = KeyboardConfigs;
+
+
+ if (File.Exists(Config.AppConfigDevicesPath))
+ {
+ LoadedDeviceConfig = Config.ReadDevices(Config.AppConfigDevicesPath);
+
+ DeviceConfig dc = LoadedDeviceConfig;
+
+ foreach (var keyboard in keyboards)
+ {
+ string keyboardName = keyboard.ProductName;
+
+ int i = 0;
+ while (true)
+ {
+ if (i == 0)
+ {
+ if (!NameToRIK.ContainsKey(keyboardName))
+ {
+ keyboardList.Add(keyboardName);
+ NameToRIK.Add(keyboardName, keyboard);
+ HIDToRIK.Add(keyboard.DevicePath, keyboard);
+
+ foreach (var dcKeyboard in dc.Keyboards)
+ {
+ if (dcKeyboard.KeyboardPath == keyboard.DevicePath)
+ {
+ KeyboardConfigs.Add(new KeyboardConfig(dcKeyboard.KeyboardAlias, dcKeyboard.IsMacroBoard, dcKeyboard.HasAutoNumLock, keyboardName, keyboard.DevicePath, dcKeyboard.IsDefaultMacroBoard));
+ DefaultKeyboardAlias = dcKeyboard.KeyboardAlias;
+ }
+ }
+
+ break;
+ }
+ i++;
+ }
+ else
+ {
+ if (!NameToRIK.ContainsKey($"{keyboardName} ({i})"))
+ {
+ keyboardList.Add($"{keyboardName} ({i})");
+ NameToRIK.Add($"{keyboardName} ({i})", keyboard);
+ HIDToRIK.Add(keyboard.DevicePath, keyboard);
+
+ foreach (var dcKeyboard in dc.Keyboards)
+ {
+ if (dcKeyboard.KeyboardPath == keyboard.DevicePath)
+ {
+ KeyboardConfigs.Add(new KeyboardConfig(dcKeyboard.KeyboardAlias, dcKeyboard.IsMacroBoard, dcKeyboard.HasAutoNumLock, $"{keyboardName} ({i})", keyboard.DevicePath, dcKeyboard.IsDefaultMacroBoard));
+ DefaultKeyboardAlias = dcKeyboard.KeyboardAlias;
+ }
+ }
+ break;
+ }
+ i++;
+ }
+ }
+ }
+ }
+ else
+ {
+ //Set LoadedDeviceConfig.UsingMultipleKeyboards to true by default, can change this later maybe or have an option to change this later
+ if (LoadedDeviceConfig == null)
+ LoadedDeviceConfig = new DeviceConfig(/*true,*/ null);
+
+ foreach (var keyboard in keyboards)
+ {
+ string keyboardName = keyboard.ProductName;
+
+ int i = 0;
+ while (true)
+ {
+ if (i == 0)
+ {
+ if (!NameToRIK.ContainsKey(keyboardName))
+ {
+ keyboardList.Add(keyboardName);
+ NameToRIK.Add(keyboardName, keyboard);
+
+ KeyboardConfigs.Add(new KeyboardConfig("---", false, false, keyboardName, keyboard.DevicePath, false));
+ break;
+ }
+ i++;
+ }
+ else
+ {
+ if (!NameToRIK.ContainsKey($"{keyboardName} ({i})"))
+ {
+ keyboardList.Add($"{keyboardName} ({i})");
+ NameToRIK.Add($"{keyboardName} ({i})", keyboard);
+
+ KeyboardConfigs.Add(new KeyboardConfig("---", false, false, $"{keyboardName} ({i})", keyboard.DevicePath, false));
+ break;
+ }
+ i++;
+ }
+
+ //Just set the first KeyboardConfig's IsDefaultMacroBoard to true
+ DefaultKeyboardAlias = KeyboardConfigs[0].KeyboardAlias;
+ KeyboardConfigs[0].IsDefaultMacroBoard = true;
+
+ }
+
+ }
+ }
+ KeyboardConfigs = KeyboardConfigs.OrderBy(c => c.KeyboardName).ToList();
+
+ NameToRIK.Add(BlankDeviceName, null);
+
+ foreach (var keyboardName in keyboardList.OrderBy(c => c).ToArray())
+ {
+ //DevicesComboBox.Items.Add(keyboardName);
+
+ }
+
+ //Add keys to dictionary for key modifiers
+ foreach (var KeyboardConfig in KeyboardConfig)
+ {
+ KeyModifierDict.Add(KeyboardConfig, (KeyModifiers)0);
+ }
+
+ //Update the selected keyboard highlight
+ try
+ {
+ Devices.Items.Refresh();
+ }
+ catch (Exception ex) { }
+ }
+
+ //Using KeyboardConfig instead of RawInputKeyboard (even though RIK has more information) because we don't want to store all of the information RIK has because it is unnecessary!
+ /*RawInputKeyboard*/ KeyboardConfig macroKeyboard;
+ public void DevicesComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ //Retrieve the KeyboardConfig object instead of getting a string to pass to a dictionary
+ macroKeyboard = (KeyboardConfig)((ComboBox)sender).SelectedValue;
+ //macroKeyboard = NameToRIK[comboBoxText];
+
+ }
+
+
+ private void MainWindow_Closing(object sender, CancelEventArgs e)
+ {
+ DllInject.UninstallHook();
+ RawInputDevice.UnregisterDevice(HidUsageAndPage.Keyboard);
+ //RawInputDevice.UnregisterDevice(HidUsageAndPage.GamePad);
+
+ using (var f = File.Open(Config.AppConfigDevicesPath, FileMode.Create, FileAccess.Write, FileShare.None))
+ {
+ //LoadedDeviceConfig.UsingMultipleKeyboards = true;
+
+ Config.SaveDevices(new DeviceConfig(KeyboardConfig), f);
+ }
+
+ NotifyModsOfClosing();
+
+ }
+
+ private void EnumDevices_Click(object sender, RoutedEventArgs e)
+ {
+ }
+
+ Dictionary HID_DeviceNames = new Dictionary();
+
+ RawInputKeyboardData mostRecentData;
+
+
+ bool blockNextScrollLock;
+ bool receivedBlockNextScrollLock;
+
+ protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
+ {
+
+ switch (msg)
+ {
+
+ case (int)WindowMessage.WM_INPUT:
+ {
+ RawInputData data = null;
+
+ try
+ {
+ // Create an RawInputData from the handle stored in lParam.
+ data = RawInputData.FromHandle(lParam);
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.GetType() + ": " + ex.Message);
+ }
+
+ // You can identify the source device using Header.DeviceHandle or just Device.
+ var sourceDeviceHandle = data?.Header.DeviceHandle;
+ var sourceDevice = data?.Device;
+
+
+ //Complete Product Logic Here
+ if (sourceDevice != null && sourceDevice is RawInputKeyboard) //Null check because not able to retreive device obj when media keys pressed
+ {
+ mostRecentData = (RawInputKeyboardData)data;
+ }
+
+ // The data will be an instance of either RawInputMouseData, RawInputKeyboardData, or RawInputHidData.
+ // They contain the raw input data in their properties.
+
+ switch (data)
+ {
+ case RawInputMouseData mouse:
+ Debug.WriteLine(mouse.Mouse);
+ break;
+ case RawInputKeyboardData keyboard:
+
+ //Need to communicate between WM_HOOK to prevent an infinite loop and pressing the key twice
+ if ((VKeys)keyboard.Keyboard.VirutalKey == VKeys.NUMLOCK && keyboard.Device != null)
+ {
+ foreach (var keybd in KeyboardConfig)
+ {
+ if (keybd.HasAutoNumLock && keybd.KeyboardPath == keyboard.Device.DevicePath)
+ {
+ if (receivedBlockNextScrollLock)
+ {
+ receivedBlockNextScrollLock = false;
+ break;
+ }
+
+ blockNextScrollLock = true;
+ break;
+ }
+ }
+ }
+ break;
+
+ case RawInputHidData hid:
+ break;
+
+ }
+
+ break;
+ Debug.WriteLine(data.Device.DeviceType);
+ }
+
+ case (int)CustomMessages.WM_HOOK:
+ {
+ if ((VKeys)wParam == VKeys.NUMLOCK)
+ {
+ foreach (var keybd in KeyboardConfig)
+ {
+ if (blockNextScrollLock && mostRecentData.Device.DevicePath == keybd.KeyboardPath)
+ {
+ blockNextScrollLock = false;
+ receivedBlockNextScrollLock = true;
+
+ Thread.Sleep(10);
+
+ Keyboards.keybd_event((byte)VKeys.NUMLOCK, 0x45, Keyboards.KEYEVENTF_EXTENDEDKEY | 0, 0);
+
+ Keyboards.keybd_event((byte)VKeys.NUMLOCK, 0x45, Keyboards.KEYEVENTF_EXTENDEDKEY | Keyboards.KEYEVENTF_KEYUP, 0);
+
+ return (IntPtr)1;
+ }
+ }
+ }
+
+ if (HandleKey(wParam, lParam, mostRecentData))
+ {
+ handled = true;
+ return (IntPtr)1;
+ }
+ break;
+ }
+
+ //This message can be used for detecting when a device disconnects and reconnects so it can be reprocessed if it is moved and be reconnected to its keyboard alias
+ case (int)CustomMessages.WM_INPUT_DEVICE_CHANGE: //WindowMessage.WM_DEVICECHANGE is more compatible with XP era
+ {
+#warning this seems to be a race condition between this and HIDToRIK being assigned!
+ string name = User32.GetRawInputDeviceName((RawInputDeviceHandle)lParam);
+
+ //Should Have the user handle it later, setting as it null currently
+ if (!HID_DeviceNames.ContainsKey(lParam))
+ HID_DeviceNames.Add(lParam, name == null ? HID_DeviceNames[lParam] : name);
+ else
+ {
+ HID_DeviceNames[lParam] = name == null ? HID_DeviceNames[lParam] : name;
+
+ }
+
+ // You can identify the source device using Header.DeviceHandle or just Device. //???
+ //var sourceDeviceHandle = data.Header.DeviceHandle;
+ //var sourceDevice = data.Device;
+
+
+ //if (sourceDevice != null)
+ //{
+ // keybdData = (RawInputKeyboardData)data;
+ //}
+
+ if (wParam == (IntPtr)WM_INPUT_DEVICE_CHANGE_WPARAM.GIDC_ARRIVAL)
+ {
+ Debug.WriteLine("Device Arrived: " + name + " : " + lParam);
+
+ Debug.WriteLine("In DeviceNames Dict? : " + HID_DeviceNames.ContainsKey(lParam) + (HID_DeviceNames.ContainsKey(lParam) ? " : DevicePath: " + HID_DeviceNames[lParam] + " : ProductName: " + (HIDToRIK.ContainsKey(HID_DeviceNames[lParam]) ? HIDToRIK[HID_DeviceNames[lParam]].ProductName : "") : ""));
+
+ } else if (wParam == (IntPtr)WM_INPUT_DEVICE_CHANGE_WPARAM.GIDC_REMOVAL)
+ {
+ Debug.WriteLine("Device Removed: " + name + " : " + lParam);
+
+ //Debug.WriteLine("Keyboard Removed: " + HIDToRIK[HID_DeviceNames[lParam]]);
+
+ Debug.WriteLine("In DeviceNames Dict? : " + HID_DeviceNames.ContainsKey(lParam) + (HID_DeviceNames.ContainsKey(lParam) ? " : DevicePath: " + HID_DeviceNames[lParam] + " : ProductName: " + (HIDToRIK.ContainsKey(HID_DeviceNames[lParam]) ? HIDToRIK[HID_DeviceNames[lParam]].ProductName : "") : ""));
+
+ //remove device if disconnected.
+ }
+
+
+
+
+ break;
+ }
+ }
+
+
+ return IntPtr.Zero;
+ }
+
+
+ Dictionary KeyModifierDict = new Dictionary();
+ public bool HandleKey(IntPtr wParam, IntPtr lParam, RawInputKeyboardData keyboardDeviceData)
+ {
+ foreach (var KeyboardConfig in KeyboardConfig)
+ {
+ if (keyboardDeviceData?.Device?.DevicePath == KeyboardConfig.KeyboardPath && KeyboardConfig.IsMacroBoard)
+ {
+ string KeyboardAlias = "";
+ foreach (var KeyBoardConfig in KeyboardConfig)
+ {
+ if (keyboardDeviceData?.Device?.DevicePath == KeyboardConfig.KeyboardPath)
+ {
+ KeyboardAlias = KeyboardConfig.KeyboardAlias;
+ }
+ }
+
+ if (ShowCurrentKeyData.IsChecked != null ? (bool)ShowCurrentKeyData.IsChecked : false)
+ {
+ new Thread(() => MessageBox.Show($"Keyboard Name: {keyboardDeviceData.Device.ProductName}\r\nKeyboardAlias: {KeyboardAlias}\r\nVirtual Key: {(VKeys)keyboardDeviceData.Keyboard.VirutalKey} ({keyboardDeviceData.Keyboard.VirutalKey})\r\nScanCode: {keyboardDeviceData.Keyboard.ScanCode}\r\nFlags: {keyboardDeviceData.Keyboard.Flags} ({(int)keyboardDeviceData.Keyboard.Flags})\r\nWindows Message: {(WindowMessage)keyboardDeviceData.Keyboard.WindowMessage} ({keyboardDeviceData.Keyboard.WindowMessage})")).Start();
+ }
+
+ KeyData.ProcessKey(KeyData.Format(KeyboardAlias, keyboardDeviceData), keyboardDeviceData.Keyboard.WindowMessage);
+
+
+
+
+ MacroKeyEvent?.Invoke((long)wParam, (long)lParam, new dynamic[]
+ {
+ new KeyData(KeyboardAlias, (int)keyboardDeviceData.Keyboard.Flags, keyboardDeviceData.Keyboard.ScanCode, keyboardDeviceData.Keyboard.VirutalKey)
+ });
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static string DefaultKeyboardAlias;
+ private void Devices_MouseDoubleClick(object sender, MouseButtonEventArgs eargs)
+ {
+ for (int i = 0; i < KeyboardConfig.Count; i++)
+ {
+ KeyboardConfig[i].IsDefaultMacroBoard = false;
+ }
+ var kc = ((KeyboardConfig)Devices.SelectedItem);
+ string Alias = kc.KeyboardAlias;
+ kc.IsDefaultMacroBoard = true;
+ DefaultKeyboardAlias = kc.KeyboardAlias;
+
+ Debug.WriteLine(Alias);
+
+ try
+ {
+ Devices.Items.Refresh();
+ }
+ catch (Exception ex) { }
+ }
+
+ }
+
+ #region Redundant
+ class KeyboardInfo
+ {
+ public KeyboardInfo(string caption, string configManagerErrorCode, string installDate, string configManagerUserConfig, string creationClassName,
+ string description, string deviceID, string errorCleared, string errorDescription, string layout, string numberOfFunctionKeys,
+ string lastErrorCode, string name, string pNPDeviceID, string powerManagementSupported,
+ string status, string systemCreationClassName, string systemName)
+ {
+ Caption = caption;
+ ConfigManagerErrorCode = configManagerErrorCode;
+ InstallDate = installDate;
+ ConfigManagerUserConfig = configManagerUserConfig;
+ CreationClassName = creationClassName;
+ Description = description;
+ DeviceID = deviceID;
+ ErrorCleared = errorCleared;
+ ErrorDescription = errorDescription;
+ Layout = layout;
+ NumberOfFunctionKeys = numberOfFunctionKeys;
+ LastErrorCode = lastErrorCode;
+ Name = name;
+ PNPDeviceID = pNPDeviceID;
+ PowerManagementSupported = powerManagementSupported;
+ Status = status;
+ SystemCreationClassName = systemCreationClassName;
+ SystemName = systemName;
+ }
+
+ public string Caption { get; private set; }
+ public string ConfigManagerErrorCode { get; private set; }
+ public string InstallDate { get; private set; }
+ public string ConfigManagerUserConfig { get; private set; }
+ public string CreationClassName { get; private set; }
+ public string Description { get; private set; }
+ public string DeviceID { get; private set; }
+ public string ErrorCleared { get; private set; }
+ public string ErrorDescription { get; private set; }
+ public string Layout { get; private set; }
+ public string NumberOfFunctionKeys { get; private set; }
+ public string LastErrorCode { get; private set; }
+ public string Name { get; private set; }
+ public string PNPDeviceID { get; private set; }
+ public string PowerManagementSupported { get; private set; }
+ public string Status { get; private set; }
+ public string SystemCreationClassName { get; private set; }
+ public string SystemName { get; private set; }
+
+ }
+
+ //class USBDeviceInfo
+ //{
+ // public USBDeviceInfo(string deviceID, string pnpDeviceID, string description)
+ // {
+ // this.DeviceID = deviceID;
+ // this.PnpDeviceID = pnpDeviceID;
+ // this.Description = description;
+ // }
+ // public string DeviceID { get; private set; }
+ // public string PnpDeviceID { get; private set; }
+ // public string Description { get; private set; }
+ //}
+
+ #endregion
+}
diff --git a/Messages.cs b/Messages.cs
new file mode 100755
index 0000000..ab2d3ec
--- /dev/null
+++ b/Messages.cs
@@ -0,0 +1,776 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MacroBoard.Native
+{
+ ///
+ /// From http://wiki.winehq.org/List_Of_Windows_Messages
+ ///
+ [Flags]
+ public enum WindowMessage : uint
+ {
+ WM_NULL = 0x0,
+ WM_CREATE = 0x0001,
+ WM_DESTROY = 0x0002,
+ WM_MOVE = 0x0003,
+ WM_SIZE = 0x0005,
+ WM_ACTIVATE = 0x0006,
+ WM_SETFOCUS = 0x0007,
+ WM_KILLFOCUS = 0x0008,
+ WM_ENABLE = 0x000a,
+ WM_SETREDRAW = 0x000b,
+ WM_SETTEXT = 0x000c,
+ WM_GETTEXT = 0x000d,
+ WM_GETTEXTLENGTH = 0x000e,
+ WM_PAINT = 0x000f,
+ WM_CLOSE = 0x0010,
+ WM_QUERYENDSESSION = 0x0011,
+ WM_QUIT = 0x0012,
+ WM_QUERYOPEN = 0x0013,
+ WM_ERASEBKGND = 0x0014,
+ WM_SYSCOLORCHANGE = 0x0015,
+ WM_ENDSESSION = 0x0016,
+ WM_SHOWWINDOW = 0x0018,
+ WM_CTLCOLOR = 0x0019,
+ WM_WININICHANGE = 0x001a,
+ WM_DEVMODECHANGE = 0x001b,
+ WM_ACTIVATEAPP = 0x001c,
+ WM_FONTCHANGE = 0x001d,
+ WM_TIMECHANGE = 0x001e,
+ WM_CANCELMODE = 0x001f,
+ WM_SETCURSOR = 0x0020,
+ WM_MOUSEACTIVATE = 0x0021,
+ WM_CHILDACTIVATE = 0x0022,
+ WM_QUEUESYNC = 0x0023,
+ WM_GETMINMAXINFO = 0x0024,
+ WM_PAINTICON = 0x0026,
+ WM_ICONERASEBKGND = 0x0027,
+ WM_NEXTDLGCTL = 0x0028,
+ WM_SPOOLERSTATUS = 0x002a,
+ WM_DRAWITEM = 0x002b,
+ WM_MEASUREITEM = 0x002c,
+ WM_DELETEITEM = 0x002d,
+ WM_VKEYTOITEM = 0x002e,
+ WM_CHARTOITEM = 0x002f,
+ WM_SETFONT = 0x0030,
+ WM_GETFONT = 0x0031,
+ WM_SETHOTKEY = 0x0032,
+ WM_GETHOTKEY = 0x0033,
+ WM_QUERYDRAGICON = 0x0037,
+ WM_COMPAREITEM = 0x0039,
+ WM_GETOBJECT = 0x003d,
+ WM_COMPACTING = 0x0041,
+ WM_COMMNOTIFY = 0x0044,
+ WM_WINDOWPOSCHANGING = 0x0046,
+ WM_WINDOWPOSCHANGED = 0x0047,
+ WM_POWER = 0x0048,
+ WM_COPYGLOBALDATA = 0x0049,
+ WM_COPYDATA = 0x004a,
+ WM_CANCELJOURNAL = 0x004b,
+ WM_NOTIFY = 0x004e,
+ WM_INPUTLANGCHANGEREQUEST = 0x0050,
+ WM_INPUTLANGCHANGE = 0x0051,
+ WM_TCARD = 0x0052,
+ WM_HELP = 0x0053,
+ WM_USERCHANGED = 0x0054,
+ WM_NOTIFYFORMAT = 0x0055,
+ WM_CONTEXTMENU = 0x007b,
+ WM_STYLECHANGING = 0x007c,
+ WM_STYLECHANGED = 0x007d,
+ WM_DISPLAYCHANGE = 0x007e,
+ WM_GETICON = 0x007f,
+ WM_SETICON = 0x0080,
+ WM_NCCREATE = 0x0081,
+ WM_NCDESTROY = 0x0082,
+ WM_NCCALCSIZE = 0x0083,
+ WM_NCHITTEST = 0x0084,
+ WM_NCPAINT = 0x0085,
+ WM_NCACTIVATE = 0x0086,
+ WM_GETDLGCODE = 0x0087,
+ WM_SYNCPAINT = 0x0088,
+ WM_NCMOUSEMOVE = 0x00a0,
+ WM_NCLBUTTONDOWN = 0x00a1,
+ WM_NCLBUTTONUP = 0x00a2,
+ WM_NCLBUTTONDBLCLK = 0x00a3,
+ WM_NCRBUTTONDOWN = 0x00a4,
+ WM_NCRBUTTONUP = 0x00a5,
+ WM_NCRBUTTONDBLCLK = 0x00a6,
+ WM_NCMBUTTONDOWN = 0x00a7,
+ WM_NCMBUTTONUP = 0x00a8,
+ WM_NCMBUTTONDBLCLK = 0x00a9,
+ WM_NCXBUTTONDOWN = 0x00ab,
+ WM_NCXBUTTONUP = 0x00ac,
+ WM_NCXBUTTONDBLCLK = 0x00ad,
+ SBM_SETPOS = 0x00e0,
+ SBM_GETPOS = 0x00e1,
+ SBM_SETRANGE = 0x00e2,
+ SBM_GETRANGE = 0x00e3,
+ SBM_ENABLE_ARROWS = 0x00e4,
+ SBM_SETRANGEREDRAW = 0x00e6,
+ SBM_SETSCROLLINFO = 0x00e9,
+ SBM_GETSCROLLINFO = 0x00ea,
+ SBM_GETSCROLLBARINFO = 0x00eb,
+ WM_INPUT = 0x00ff,
+ WM_KEYDOWN = 0x0100,
+ WM_KEYFIRST = 0x0100,
+ WM_KEYUP = 0x0101,
+ WM_CHAR = 0x0102,
+ WM_DEADCHAR = 0x0103,
+ WM_SYSKEYDOWN = 0x0104,
+ WM_SYSKEYUP = 0x0105,
+ WM_SYSCHAR = 0x0106,
+ WM_SYSDEADCHAR = 0x0107,
+ WM_KEYLAST = 0x0108,
+ WM_WNT_CONVERTREQUESTEX = 0x0109,
+ WM_CONVERTREQUEST = 0x010a,
+ WM_CONVERTRESULT = 0x010b,
+ WM_INTERIM = 0x010c,
+ WM_IME_STARTCOMPOSITION = 0x010d,
+ WM_IME_ENDCOMPOSITION = 0x010e,
+ WM_IME_COMPOSITION = 0x010f,
+ WM_IME_KEYLAST = 0x010f,
+ WM_INITDIALOG = 0x0110,
+ WM_COMMAND = 0x0111,
+ WM_SYSCOMMAND = 0x0112,
+ WM_TIMER = 0x0113,
+ WM_HSCROLL = 0x0114,
+ WM_VSCROLL = 0x0115,
+ WM_INITMENU = 0x0116,
+ WM_INITMENUPOPUP = 0x0117,
+ WM_SYSTIMER = 0x0118,
+ WM_MENUSELECT = 0x011f,
+ WM_MENUCHAR = 0x0120,
+ WM_ENTERIDLE = 0x0121,
+ WM_MENURBUTTONUP = 0x0122,
+ WM_MENUDRAG = 0x0123,
+ WM_MENUGETOBJECT = 0x0124,
+ WM_UNINITMENUPOPUP = 0x0125,
+ WM_MENUCOMMAND = 0x0126,
+ WM_CHANGEUISTATE = 0x0127,
+ WM_UPDATEUISTATE = 0x0128,
+ WM_QUERYUISTATE = 0x0129,
+ WM_CTLCOLORMSGBOX = 0x0132,
+ WM_CTLCOLOREDIT = 0x0133,
+ WM_CTLCOLORLISTBOX = 0x0134,
+ WM_CTLCOLORBTN = 0x0135,
+ WM_CTLCOLORDLG = 0x0136,
+ WM_CTLCOLORSCROLLBAR = 0x0137,
+ WM_CTLCOLORSTATIC = 0x0138,
+ WM_MOUSEFIRST = 0x0200,
+ WM_MOUSEMOVE = 0x0200,
+ WM_LBUTTONDOWN = 0x0201,
+ WM_LBUTTONUP = 0x0202,
+ WM_LBUTTONDBLCLK = 0x0203,
+ WM_RBUTTONDOWN = 0x0204,
+ WM_RBUTTONUP = 0x0205,
+ WM_RBUTTONDBLCLK = 0x0206,
+ WM_MBUTTONDOWN = 0x0207,
+ WM_MBUTTONUP = 0x0208,
+ WM_MBUTTONDBLCLK = 0x0209,
+ WM_MOUSELAST = 0x0209,
+ WM_MOUSEWHEEL = 0x020a,
+ WM_XBUTTONDOWN = 0x020b,
+ WM_XBUTTONUP = 0x020c,
+ WM_XBUTTONDBLCLK = 0x020d,
+ WM_PARENTNOTIFY = 0x0210,
+ WM_ENTERMENULOOP = 0x0211,
+ WM_EXITMENULOOP = 0x0212,
+ WM_NEXTMENU = 0x0213,
+ WM_SIZING = 0x0214,
+ WM_CAPTURECHANGED = 0x0215,
+ WM_MOVING = 0x0216,
+ WM_POWERBROADCAST = 0x0218,
+ WM_DEVICECHANGE = 0x0219,
+ WM_MDICREATE = 0x0220,
+ WM_MDIDESTROY = 0x0221,
+ WM_MDIACTIVATE = 0x0222,
+ WM_MDIRESTORE = 0x0223,
+ WM_MDINEXT = 0x0224,
+ WM_MDIMAXIMIZE = 0x0225,
+ WM_MDITILE = 0x0226,
+ WM_MDICASCADE = 0x0227,
+ WM_MDIICONARRANGE = 0x0228,
+ WM_MDIGETACTIVE = 0x0229,
+ WM_MDISETMENU = 0x0230,
+ WM_ENTERSIZEMOVE = 0x0231,
+ WM_EXITSIZEMOVE = 0x0232,
+ WM_DROPFILES = 0x0233,
+ WM_MDIREFRESHMENU = 0x0234,
+ WM_IME_REPORT = 0x0280,
+ WM_IME_SETCONTEXT = 0x0281,
+ WM_IME_NOTIFY = 0x0282,
+ WM_IME_CONTROL = 0x0283,
+ WM_IME_COMPOSITIONFULL = 0x0284,
+ WM_IME_SELECT = 0x0285,
+ WM_IME_CHAR = 0x0286,
+ WM_IME_REQUEST = 0x0288,
+ WM_IMEKEYDOWN = 0x0290,
+ WM_IME_KEYDOWN = 0x0290,
+ WM_IMEKEYUP = 0x0291,
+ WM_IME_KEYUP = 0x0291,
+ WM_NCMOUSEHOVER = 0x02a0,
+ WM_MOUSEHOVER = 0x02a1,
+ WM_NCMOUSELEAVE = 0x02a2,
+ WM_MOUSELEAVE = 0x02a3,
+ WM_CUT = 0x0300,
+ WM_COPY = 0x0301,
+ WM_PASTE = 0x0302,
+ WM_CLEAR = 0x0303,
+ WM_UNDO = 0x0304,
+ WM_RENDERFORMAT = 0x0305,
+ WM_RENDERALLFORMATS = 0x0306,
+ WM_DESTROYCLIPBOARD = 0x0307,
+ WM_DRAWCLIPBOARD = 0x0308,
+ WM_PAINTCLIPBOARD = 0x0309,
+ WM_VSCROLLCLIPBOARD = 0x030a,
+ WM_SIZECLIPBOARD = 0x030b,
+ WM_ASKCBFORMATNAME = 0x030c,
+ WM_CHANGECBCHAIN = 0x030d,
+ WM_HSCROLLCLIPBOARD = 0x030e,
+ WM_QUERYNEWPALETTE = 0x030f,
+ WM_PALETTEISCHANGING = 0x0310,
+ WM_PALETTECHANGED = 0x0311,
+ WM_HOTKEY = 0x0312,
+ WM_PRINT = 0x0317,
+ WM_PRINTCLIENT = 0x0318,
+ WM_APPCOMMAND = 0x0319,
+ WM_HANDHELDFIRST = 0x0358,
+ WM_HANDHELDLAST = 0x035f,
+ WM_AFXFIRST = 0x0360,
+ WM_AFXLAST = 0x037f,
+ WM_PENWINFIRST = 0x0380,
+ WM_RCRESULT = 0x0381,
+ WM_HOOKRCRESULT = 0x0382,
+ WM_GLOBALRCCHANGE = 0x0383,
+ WM_PENMISCINFO = 0x0383,
+ WM_SKB = 0x0384,
+ WM_HEDITCTL = 0x0385,
+ WM_PENCTL = 0x0385,
+ WM_PENMISC = 0x0386,
+ WM_CTLINIT = 0x0387,
+ WM_PENEVENT = 0x0388,
+ WM_PENWINLAST = 0x038f,
+ DDM_SETFMT = 0x0400,
+ DM_GETDEFID = 0x0400,
+ NIN_SELECT = 0x0400,
+ TBM_GETPOS = 0x0400,
+ WM_PSD_PAGESETUPDLG = 0x0400,
+ WM_USER = 0x0400,
+ CBEM_INSERTITEMA = 0x0401,
+ DDM_DRAW = 0x0401,
+ DM_SETDEFID = 0x0401,
+ HKM_SETHOTKEY = 0x0401,
+ PBM_SETRANGE = 0x0401,
+ RB_INSERTBANDA = 0x0401,
+ SB_SETTEXTA = 0x0401,
+ TB_ENABLEBUTTON = 0x0401,
+ TBM_GETRANGEMIN = 0x0401,
+ TTM_ACTIVATE = 0x0401,
+ WM_CHOOSEFONT_GETLOGFONT = 0x0401,
+ WM_PSD_FULLPAGERECT = 0x0401,
+ CBEM_SETIMAGELIST = 0x0402,
+ DDM_CLOSE = 0x0402,
+ DM_REPOSITION = 0x0402,
+ HKM_GETHOTKEY = 0x0402,
+ PBM_SETPOS = 0x0402,
+ RB_DELETEBAND = 0x0402,
+ SB_GETTEXTA = 0x0402,
+ TB_CHECKBUTTON = 0x0402,
+ TBM_GETRANGEMAX = 0x0402,
+ WM_PSD_MINMARGINRECT = 0x0402,
+ CBEM_GETIMAGELIST = 0x0403,
+ DDM_BEGIN = 0x0403,
+ HKM_SETRULES = 0x0403,
+ PBM_DELTAPOS = 0x0403,
+ RB_GETBARINFO = 0x0403,
+ SB_GETTEXTLENGTHA = 0x0403,
+ TBM_GETTIC = 0x0403,
+ TB_PRESSBUTTON = 0x0403,
+ TTM_SETDELAYTIME = 0x0403,
+ WM_PSD_MARGINRECT = 0x0403,
+ CBEM_GETITEMA = 0x0404,
+ DDM_END = 0x0404,
+ PBM_SETSTEP = 0x0404,
+ RB_SETBARINFO = 0x0404,
+ SB_SETPARTS = 0x0404,
+ TB_HIDEBUTTON = 0x0404,
+ TBM_SETTIC = 0x0404,
+ TTM_ADDTOOLA = 0x0404,
+ WM_PSD_GREEKTEXTRECT = 0x0404,
+ CBEM_SETITEMA = 0x0405,
+ PBM_STEPIT = 0x0405,
+ TB_INDETERMINATE = 0x0405,
+ TBM_SETPOS = 0x0405,
+ TTM_DELTOOLA = 0x0405,
+ WM_PSD_ENVSTAMPRECT = 0x0405,
+ CBEM_GETCOMBOCONTROL = 0x0406,
+ PBM_SETRANGE32 = 0x0406,
+ RB_SETBANDINFOA = 0x0406,
+ SB_GETPARTS = 0x0406,
+ TB_MARKBUTTON = 0x0406,
+ TBM_SETRANGE = 0x0406,
+ TTM_NEWTOOLRECTA = 0x0406,
+ WM_PSD_YAFULLPAGERECT = 0x0406,
+ CBEM_GETEDITCONTROL = 0x0407,
+ PBM_GETRANGE = 0x0407,
+ RB_SETPARENT = 0x0407,
+ SB_GETBORDERS = 0x0407,
+ TBM_SETRANGEMIN = 0x0407,
+ TTM_RELAYEVENT = 0x0407,
+ CBEM_SETEXSTYLE = 0x0408,
+ PBM_GETPOS = 0x0408,
+ RB_HITTEST = 0x0408,
+ SB_SETMINHEIGHT = 0x0408,
+ TBM_SETRANGEMAX = 0x0408,
+ TTM_GETTOOLINFOA = 0x0408,
+ CBEM_GETEXSTYLE = 0x0409,
+ CBEM_GETEXTENDEDSTYLE = 0x0409,
+ PBM_SETBARCOLOR = 0x0409,
+ RB_GETRECT = 0x0409,
+ SB_SIMPLE = 0x0409,
+ TB_ISBUTTONENABLED = 0x0409,
+ TBM_CLEARTICS = 0x0409,
+ TTM_SETTOOLINFOA = 0x0409,
+ CBEM_HASEDITCHANGED = 0x040a,
+ RB_INSERTBANDW = 0x040a,
+ SB_GETRECT = 0x040a,
+ TB_ISBUTTONCHECKED = 0x040a,
+ TBM_SETSEL = 0x040a,
+ TTM_HITTESTA = 0x040a,
+ WIZ_QUERYNUMPAGES = 0x040a,
+ CBEM_INSERTITEMW = 0x040b,
+ RB_SETBANDINFOW = 0x040b,
+ SB_SETTEXTW = 0x040b,
+ TB_ISBUTTONPRESSED = 0x040b,
+ TBM_SETSELSTART = 0x040b,
+ TTM_GETTEXTA = 0x040b,
+ WIZ_NEXT = 0x040b,
+ CBEM_SETITEMW = 0x040c,
+ RB_GETBANDCOUNT = 0x040c,
+ SB_GETTEXTLENGTHW = 0x040c,
+ TB_ISBUTTONHIDDEN = 0x040c,
+ TBM_SETSELEND = 0x040c,
+ TTM_UPDATETIPTEXTA = 0x040c,
+ WIZ_PREV = 0x040c,
+ CBEM_GETITEMW = 0x040d,
+ RB_GETROWCOUNT = 0x040d,
+ SB_GETTEXTW = 0x040d,
+ TB_ISBUTTONINDETERMINATE = 0x040d,
+ TTM_GETTOOLCOUNT = 0x040d,
+ CBEM_SETEXTENDEDSTYLE = 0x040e,
+ RB_GETROWHEIGHT = 0x040e,
+ SB_ISSIMPLE = 0x040e,
+ TB_ISBUTTONHIGHLIGHTED = 0x040e,
+ TBM_GETPTICS = 0x040e,
+ TTM_ENUMTOOLSA = 0x040e,
+ SB_SETICON = 0x040f,
+ TBM_GETTICPOS = 0x040f,
+ TTM_GETCURRENTTOOLA = 0x040f,
+ RB_IDTOINDEX = 0x0410,
+ SB_SETTIPTEXTA = 0x0410,
+ TBM_GETNUMTICS = 0x0410,
+ TTM_WINDOWFROMPOINT = 0x0410,
+ RB_GETTOOLTIPS = 0x0411,
+ SB_SETTIPTEXTW = 0x0411,
+ TBM_GETSELSTART = 0x0411,
+ TB_SETSTATE = 0x0411,
+ TTM_TRACKACTIVATE = 0x0411,
+ RB_SETTOOLTIPS = 0x0412,
+ SB_GETTIPTEXTA = 0x0412,
+ TB_GETSTATE = 0x0412,
+ TBM_GETSELEND = 0x0412,
+ TTM_TRACKPOSITION = 0x0412,
+ RB_SETBKCOLOR = 0x0413,
+ SB_GETTIPTEXTW = 0x0413,
+ TB_ADDBITMAP = 0x0413,
+ TBM_CLEARSEL = 0x0413,
+ TTM_SETTIPBKCOLOR = 0x0413,
+ RB_GETBKCOLOR = 0x0414,
+ SB_GETICON = 0x0414,
+ TB_ADDBUTTONSA = 0x0414,
+ TBM_SETTICFREQ = 0x0414,
+ TTM_SETTIPTEXTCOLOR = 0x0414,
+ RB_SETTEXTCOLOR = 0x0415,
+ TB_INSERTBUTTONA = 0x0415,
+ TBM_SETPAGESIZE = 0x0415,
+ TTM_GETDELAYTIME = 0x0415,
+ RB_GETTEXTCOLOR = 0x0416,
+ TB_DELETEBUTTON = 0x0416,
+ TBM_GETPAGESIZE = 0x0416,
+ TTM_GETTIPBKCOLOR = 0x0416,
+ RB_SIZETORECT = 0x0417,
+ TB_GETBUTTON = 0x0417,
+ TBM_SETLINESIZE = 0x0417,
+ TTM_GETTIPTEXTCOLOR = 0x0417,
+ RB_BEGINDRAG = 0x0418,
+ TB_BUTTONCOUNT = 0x0418,
+ TBM_GETLINESIZE = 0x0418,
+ TTM_SETMAXTIPWIDTH = 0x0418,
+ RB_ENDDRAG = 0x0419,
+ TB_COMMANDTOINDEX = 0x0419,
+ TBM_GETTHUMBRECT = 0x0419,
+ TTM_GETMAXTIPWIDTH = 0x0419,
+ RB_DRAGMOVE = 0x041a,
+ TBM_GETCHANNELRECT = 0x041a,
+ TB_SAVERESTOREA = 0x041a,
+ TTM_SETMARGIN = 0x041a,
+ RB_GETBARHEIGHT = 0x041b,
+ TB_CUSTOMIZE = 0x041b,
+ TBM_SETTHUMBLENGTH = 0x041b,
+ TTM_GETMARGIN = 0x041b,
+ RB_GETBANDINFOW = 0x041c,
+ TB_ADDSTRINGA = 0x041c,
+ TBM_GETTHUMBLENGTH = 0x041c,
+ TTM_POP = 0x041c,
+ RB_GETBANDINFOA = 0x041d,
+ TB_GETITEMRECT = 0x041d,
+ TBM_SETTOOLTIPS = 0x041d,
+ TTM_UPDATE = 0x041d,
+ RB_MINIMIZEBAND = 0x041e,
+ TB_BUTTONSTRUCTSIZE = 0x041e,
+ TBM_GETTOOLTIPS = 0x041e,
+ TTM_GETBUBBLESIZE = 0x041e,
+ RB_MAXIMIZEBAND = 0x041f,
+ TBM_SETTIPSIDE = 0x041f,
+ TB_SETBUTTONSIZE = 0x041f,
+ TTM_ADJUSTRECT = 0x041f,
+ TBM_SETBUDDY = 0x0420,
+ TB_SETBITMAPSIZE = 0x0420,
+ TTM_SETTITLEA = 0x0420,
+ MSG_FTS_JUMP_VA = 0x0421,
+ TB_AUTOSIZE = 0x0421,
+ TBM_GETBUDDY = 0x0421,
+ TTM_SETTITLEW = 0x0421,
+ RB_GETBANDBORDERS = 0x0422,
+ MSG_FTS_JUMP_QWORD = 0x0423,
+ RB_SHOWBAND = 0x0423,
+ TB_GETTOOLTIPS = 0x0423,
+ MSG_REINDEX_REQUEST = 0x0424,
+ TB_SETTOOLTIPS = 0x0424,
+ MSG_FTS_WHERE_IS_IT = 0x0425,
+ RB_SETPALETTE = 0x0425,
+ TB_SETPARENT = 0x0425,
+ RB_GETPALETTE = 0x0426,
+ RB_MOVEBAND = 0x0427,
+ TB_SETROWS = 0x0427,
+ TB_GETROWS = 0x0428,
+ TB_GETBITMAPFLAGS = 0x0429,
+ TB_SETCMDID = 0x042a,
+ RB_PUSHCHEVRON = 0x042b,
+ TB_CHANGEBITMAP = 0x042b,
+ TB_GETBITMAP = 0x042c,
+ MSG_GET_DEFFONT = 0x042d,
+ TB_GETBUTTONTEXTA = 0x042d,
+ TB_REPLACEBITMAP = 0x042e,
+ TB_SETINDENT = 0x042f,
+ TB_SETIMAGELIST = 0x0430,
+ TB_GETIMAGELIST = 0x0431,
+ TB_LOADIMAGES = 0x0432,
+ TTM_ADDTOOLW = 0x0432,
+ TB_GETRECT = 0x0433,
+ TTM_DELTOOLW = 0x0433,
+ TB_SETHOTIMAGELIST = 0x0434,
+ TTM_NEWTOOLRECTW = 0x0434,
+ TB_GETHOTIMAGELIST = 0x0435,
+ TTM_GETTOOLINFOW = 0x0435,
+ TB_SETDISABLEDIMAGELIST = 0x0436,
+ TTM_SETTOOLINFOW = 0x0436,
+ TB_GETDISABLEDIMAGELIST = 0x0437,
+ TTM_HITTESTW = 0x0437,
+ TB_SETSTYLE = 0x0438,
+ TTM_GETTEXTW = 0x0438,
+ TB_GETSTYLE = 0x0439,
+ TTM_UPDATETIPTEXTW = 0x0439,
+ TB_GETBUTTONSIZE = 0x043a,
+ TTM_ENUMTOOLSW = 0x043a,
+ TB_SETBUTTONWIDTH = 0x043b,
+ TTM_GETCURRENTTOOLW = 0x043b,
+ TB_SETMAXTEXTROWS = 0x043c,
+ TB_GETTEXTROWS = 0x043d,
+ TB_GETOBJECT = 0x043e,
+ TB_GETBUTTONINFOW = 0x043f,
+ TB_SETBUTTONINFOW = 0x0440,
+ TB_GETBUTTONINFOA = 0x0441,
+ TB_SETBUTTONINFOA = 0x0442,
+ TB_INSERTBUTTONW = 0x0443,
+ TB_ADDBUTTONSW = 0x0444,
+ TB_HITTEST = 0x0445,
+ TB_SETDRAWTEXTFLAGS = 0x0446,
+ TB_GETHOTITEM = 0x0447,
+ TB_SETHOTITEM = 0x0448,
+ TB_SETANCHORHIGHLIGHT = 0x0449,
+ TB_GETANCHORHIGHLIGHT = 0x044a,
+ TB_GETBUTTONTEXTW = 0x044b,
+ TB_SAVERESTOREW = 0x044c,
+ TB_ADDSTRINGW = 0x044d,
+ TB_MAPACCELERATORA = 0x044e,
+ TB_GETINSERTMARK = 0x044f,
+ TB_SETINSERTMARK = 0x0450,
+ TB_INSERTMARKHITTEST = 0x0451,
+ TB_MOVEBUTTON = 0x0452,
+ TB_GETMAXSIZE = 0x0453,
+ TB_SETEXTENDEDSTYLE = 0x0454,
+ TB_GETEXTENDEDSTYLE = 0x0455,
+ TB_GETPADDING = 0x0456,
+ TB_SETPADDING = 0x0457,
+ TB_SETINSERTMARKCOLOR = 0x0458,
+ TB_GETINSERTMARKCOLOR = 0x0459,
+ TB_MAPACCELERATORW = 0x045a,
+ TB_GETSTRINGW = 0x045b,
+ TB_GETSTRINGA = 0x045c,
+ TAPI_REPLY = 0x0463,
+ ACM_OPENA = 0x0464,
+ BFFM_SETSTATUSTEXTA = 0x0464,
+ CDM_FIRST = 0x0464,
+ CDM_GETSPEC = 0x0464,
+ IPM_CLEARADDRESS = 0x0464,
+ WM_CAP_UNICODE_START = 0x0464,
+ ACM_PLAY = 0x0465,
+ BFFM_ENABLEOK = 0x0465,
+ CDM_GETFILEPATH = 0x0465,
+ IPM_SETADDRESS = 0x0465,
+ PSM_SETCURSEL = 0x0465,
+ UDM_SETRANGE = 0x0465,
+ WM_CHOOSEFONT_SETLOGFONT = 0x0465,
+ ACM_STOP = 0x0466,
+ BFFM_SETSELECTIONA = 0x0466,
+ CDM_GETFOLDERPATH = 0x0466,
+ IPM_GETADDRESS = 0x0466,
+ PSM_REMOVEPAGE = 0x0466,
+ UDM_GETRANGE = 0x0466,
+ WM_CAP_SET_CALLBACK_ERRORW = 0x0466,
+ WM_CHOOSEFONT_SETFLAGS = 0x0466,
+ ACM_OPENW = 0x0467,
+ BFFM_SETSELECTIONW = 0x0467,
+ CDM_GETFOLDERIDLIST = 0x0467,
+ IPM_SETRANGE = 0x0467,
+ PSM_ADDPAGE = 0x0467,
+ UDM_SETPOS = 0x0467,
+ WM_CAP_SET_CALLBACK_STATUSW = 0x0467,
+ BFFM_SETSTATUSTEXTW = 0x0468,
+ CDM_SETCONTROLTEXT = 0x0468,
+ IPM_SETFOCUS = 0x0468,
+ PSM_CHANGED = 0x0468,
+ UDM_GETPOS = 0x0468,
+ CDM_HIDECONTROL = 0x0469,
+ IPM_ISBLANK = 0x0469,
+ PSM_RESTARTWINDOWS = 0x0469,
+ UDM_SETBUDDY = 0x0469,
+ CDM_SETDEFEXT = 0x046a,
+ PSM_REBOOTSYSTEM = 0x046a,
+ UDM_GETBUDDY = 0x046a,
+ PSM_CANCELTOCLOSE = 0x046b,
+ UDM_SETACCEL = 0x046b,
+ EM_CONVPOSITION = 0x046c,
+ PSM_QUERYSIBLINGS = 0x046c,
+ UDM_GETACCEL = 0x046c,
+ MCIWNDM_GETZOOM = 0x046d,
+ PSM_UNCHANGED = 0x046d,
+ UDM_SETBASE = 0x046d,
+ PSM_APPLY = 0x046e,
+ UDM_GETBASE = 0x046e,
+ PSM_SETTITLEA = 0x046f,
+ UDM_SETRANGE32 = 0x046f,
+ PSM_SETWIZBUTTONS = 0x0470,
+ UDM_GETRANGE32 = 0x0470,
+ WM_CAP_DRIVER_GET_NAMEW = 0x0470,
+ PSM_PRESSBUTTON = 0x0471,
+ UDM_SETPOS32 = 0x0471,
+ WM_CAP_DRIVER_GET_VERSIONW = 0x0471,
+ PSM_SETCURSELID = 0x0472,
+ UDM_GETPOS32 = 0x0472,
+ PSM_SETFINISHTEXTA = 0x0473,
+ PSM_GETTABCONTROL = 0x0474,
+ PSM_ISDIALOGMESSAGE = 0x0475,
+ MCIWNDM_REALIZE = 0x0476,
+ PSM_GETCURRENTPAGEHWND = 0x0476,
+ MCIWNDM_SETTIMEFORMATA = 0x0477,
+ PSM_INSERTPAGE = 0x0477,
+ MCIWNDM_GETTIMEFORMATA = 0x0478,
+ PSM_SETTITLEW = 0x0478,
+ WM_CAP_FILE_SET_CAPTURE_FILEW = 0x0478,
+ MCIWNDM_VALIDATEMEDIA = 0x0479,
+ PSM_SETFINISHTEXTW = 0x0479,
+ WM_CAP_FILE_GET_CAPTURE_FILEW = 0x0479,
+ MCIWNDM_PLAYTO = 0x047b,
+ WM_CAP_FILE_SAVEASW = 0x047b,
+ MCIWNDM_GETFILENAMEA = 0x047c,
+ MCIWNDM_GETDEVICEA = 0x047d,
+ PSM_SETHEADERTITLEA = 0x047d,
+ WM_CAP_FILE_SAVEDIBW = 0x047d,
+ MCIWNDM_GETPALETTE = 0x047e,
+ PSM_SETHEADERTITLEW = 0x047e,
+ MCIWNDM_SETPALETTE = 0x047f,
+ PSM_SETHEADERSUBTITLEA = 0x047f,
+ MCIWNDM_GETERRORA = 0x0480,
+ PSM_SETHEADERSUBTITLEW = 0x0480,
+ PSM_HWNDTOINDEX = 0x0481,
+ PSM_INDEXTOHWND = 0x0482,
+ MCIWNDM_SETINACTIVETIMER = 0x0483,
+ PSM_PAGETOINDEX = 0x0483,
+ PSM_INDEXTOPAGE = 0x0484,
+ DL_BEGINDRAG = 0x0485,
+ MCIWNDM_GETINACTIVETIMER = 0x0485,
+ PSM_IDTOINDEX = 0x0485,
+ DL_DRAGGING = 0x0486,
+ PSM_INDEXTOID = 0x0486,
+ DL_DROPPED = 0x0487,
+ PSM_GETRESULT = 0x0487,
+ DL_CANCELDRAG = 0x0488,
+ PSM_RECALCPAGESIZES = 0x0488,
+ MCIWNDM_GET_SOURCE = 0x048c,
+ MCIWNDM_PUT_SOURCE = 0x048d,
+ MCIWNDM_GET_DEST = 0x048e,
+ MCIWNDM_PUT_DEST = 0x048f,
+ MCIWNDM_CAN_PLAY = 0x0490,
+ MCIWNDM_CAN_WINDOW = 0x0491,
+ MCIWNDM_CAN_RECORD = 0x0492,
+ MCIWNDM_CAN_SAVE = 0x0493,
+ MCIWNDM_CAN_EJECT = 0x0494,
+ MCIWNDM_CAN_CONFIG = 0x0495,
+ IE_GETINK = 0x0496,
+ IE_MSGFIRST = 0x0496,
+ MCIWNDM_PALETTEKICK = 0x0496,
+ IE_SETINK = 0x0497,
+ IE_GETPENTIP = 0x0498,
+ IE_SETPENTIP = 0x0499,
+ IE_GETERASERTIP = 0x049a,
+ IE_SETERASERTIP = 0x049b,
+ IE_GETBKGND = 0x049c,
+ IE_SETBKGND = 0x049d,
+ IE_GETGRIDORIGIN = 0x049e,
+ IE_SETGRIDORIGIN = 0x049f,
+ IE_GETGRIDPEN = 0x04a0,
+ IE_SETGRIDPEN = 0x04a1,
+ IE_GETGRIDSIZE = 0x04a2,
+ IE_SETGRIDSIZE = 0x04a3,
+ IE_GETMODE = 0x04a4,
+ IE_SETMODE = 0x04a5,
+ IE_GETINKRECT = 0x04a6,
+ WM_CAP_SET_MCI_DEVICEW = 0x04a6,
+ WM_CAP_GET_MCI_DEVICEW = 0x04a7,
+ WM_CAP_PAL_OPENW = 0x04b4,
+ WM_CAP_PAL_SAVEW = 0x04b5,
+ IE_GETAPPDATA = 0x04b8,
+ IE_SETAPPDATA = 0x04b9,
+ IE_GETDRAWOPTS = 0x04ba,
+ IE_SETDRAWOPTS = 0x04bb,
+ IE_GETFORMAT = 0x04bc,
+ IE_SETFORMAT = 0x04bd,
+ IE_GETINKINPUT = 0x04be,
+ IE_SETINKINPUT = 0x04bf,
+ IE_GETNOTIFY = 0x04c0,
+ IE_SETNOTIFY = 0x04c1,
+ IE_GETRECOG = 0x04c2,
+ IE_SETRECOG = 0x04c3,
+ IE_GETSECURITY = 0x04c4,
+ IE_SETSECURITY = 0x04c5,
+ IE_GETSEL = 0x04c6,
+ IE_SETSEL = 0x04c7,
+ CDM_LAST = 0x04c8,
+ IE_DOCOMMAND = 0x04c8,
+ MCIWNDM_NOTIFYMODE = 0x04c8,
+ IE_GETCOMMAND = 0x04c9,
+ IE_GETCOUNT = 0x04ca,
+ IE_GETGESTURE = 0x04cb,
+ MCIWNDM_NOTIFYMEDIA = 0x04cb,
+ IE_GETMENU = 0x04cc,
+ IE_GETPAINTDC = 0x04cd,
+ MCIWNDM_NOTIFYERROR = 0x04cd,
+ IE_GETPDEVENT = 0x04ce,
+ IE_GETSELCOUNT = 0x04cf,
+ IE_GETSELITEMS = 0x04d0,
+ IE_GETSTYLE = 0x04d1,
+ MCIWNDM_SETTIMEFORMATW = 0x04db,
+ EM_OUTLINE = 0x04dc,
+ MCIWNDM_GETTIMEFORMATW = 0x04dc,
+ EM_GETSCROLLPOS = 0x04dd,
+ EM_SETSCROLLPOS = 0x04de,
+ EM_SETFONTSIZE = 0x04df,
+ MCIWNDM_GETFILENAMEW = 0x04e0,
+ MCIWNDM_GETDEVICEW = 0x04e1,
+ MCIWNDM_GETERRORW = 0x04e4,
+ FM_GETFOCUS = 0x0600,
+ FM_GETDRIVEINFOA = 0x0601,
+ FM_GETSELCOUNT = 0x0602,
+ FM_GETSELCOUNTLFN = 0x0603,
+ FM_GETFILESELA = 0x0604,
+ FM_GETFILESELLFNA = 0x0605,
+ FM_REFRESH_WINDOWS = 0x0606,
+ FM_RELOAD_EXTENSIONS = 0x0607,
+ FM_GETDRIVEINFOW = 0x0611,
+ FM_GETFILESELW = 0x0614,
+ FM_GETFILESELLFNW = 0x0615,
+ WLX_WM_SAS = 0x0659,
+ SM_GETSELCOUNT = 0x07e8,
+ UM_GETSELCOUNT = 0x07e8,
+ WM_CPL_LAUNCH = 0x07e8,
+ SM_GETSERVERSELA = 0x07e9,
+ UM_GETUSERSELA = 0x07e9,
+ WM_CPL_LAUNCHED = 0x07e9,
+ SM_GETSERVERSELW = 0x07ea,
+ UM_GETUSERSELW = 0x07ea,
+ SM_GETCURFOCUSA = 0x07eb,
+ UM_GETGROUPSELA = 0x07eb,
+ SM_GETCURFOCUSW = 0x07ec,
+ UM_GETGROUPSELW = 0x07ec,
+ SM_GETOPTIONS = 0x07ed,
+ UM_GETCURFOCUSA = 0x07ed,
+ UM_GETCURFOCUSW = 0x07ee,
+ UM_GETOPTIONS = 0x07ef,
+ UM_GETOPTIONS2 = 0x07f0,
+ OCMBASE = 0x2000,
+ OCM_CTLCOLOR = 0x2019,
+ OCM_DRAWITEM = 0x202b,
+ OCM_MEASUREITEM = 0x202c,
+ OCM_DELETEITEM = 0x202d,
+ OCM_VKEYTOITEM = 0x202e,
+ OCM_CHARTOITEM = 0x202f,
+ OCM_COMPAREITEM = 0x2039,
+ OCM_NOTIFY = 0x204e,
+ OCM_COMMAND = 0x2111,
+ OCM_HSCROLL = 0x2114,
+ OCM_VSCROLL = 0x2115,
+ OCM_CTLCOLORMSGBOX = 0x2132,
+ OCM_CTLCOLOREDIT = 0x2133,
+ OCM_CTLCOLORLISTBOX = 0x2134,
+ OCM_CTLCOLORBTN = 0x2135,
+ OCM_CTLCOLORDLG = 0x2136,
+ OCM_CTLCOLORSCROLLBAR = 0x2137,
+ OCM_CTLCOLORSTATIC = 0x2138,
+ OCM_PARENTNOTIFY = 0x2210,
+ WM_APP = 0x8000,
+ WM_RASDIALEVENT = 0xcccd
+ }
+
+ ///
+ /// From https://msdn.microsoft.com/en-us/library/windows/desktop/aa372716(v=vs.85).aspx
+ ///
+ [Flags]
+ public enum WindowMessageParameter : uint
+ {
+ PBT_APMQUERYSUSPEND = 0x0,
+ PBT_APMBATTERYLOW = 0x9, // Notifies applications that the battery power is low.
+ PBT_APMOEMEVENT = 0xb, // Notifies applications that the APM BIOS has signalled an APM OEM event.
+ PBT_APMQUERYSTANDBY = 0x0001, //
+ PBT_APMPOWERSTATUSCHANGE = 0xa, // Notifies applications of a change in the power status of the computer, such as a switch from battery power to A/C. The system also broadcasts this event when remaining battery power slipsbelowthethresholdspecified by the user or if the battery power changes by a specified percentage.
+ PBT_APMQUERYSUSPENDFAILED = 0x218, // Notifies applications that permission to suspend the computer was denied.
+ PBT_APMRESUMEAUTOMATIC = 0x12, // Notifies applications that the system is resuming from sleep or hibernation. If the system detects any user activity after broadcasting PBT_APMRESUMEAUTOMATIC, it will broadcast aPBT_APMRESUMESUSPENDeventt let applications know they can resume full interaction with the user.
+ PBT_APMRESUMECRITICAL = 0x6, // Notifies applications that the system has resumed operation.
+ PBT_APMRESUMESUSPEND = 0x7, // Notifies applications that the system has resumed operation after being suspended.
+ PBT_APMSUSPEND = 0x4, // Notifies applications that the computer is about to enter a suspended state.
+ PBT_POWERSETTINGCHANGE = 0x8013, // Notifies applications that a power setting change event occurred.
+ WM_POWER = 0x48, // Notifies applications that the system, typically a battery-powered personal computer, is about to enter a suspended mode.
+ WM_POWERBROADCAST = 0x218, // Notifies applications that a power-management event has occurred.
+ BROADCAST_QUERY_DENY = 0x424D5144 //
+ }
+
+
+
+ public enum WM_INPUT_DEVICE_CHANGE_WPARAM
+ {
+ GIDC_ARRIVAL = 1,
+ GIDC_REMOVAL = 2
+ }
+}
diff --git a/ModData.cs b/ModData.cs
new file mode 100755
index 0000000..c5c929b
--- /dev/null
+++ b/ModData.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+
+namespace MacroBoard
+{
+ public class ModData
+ {
+ public static List ModDataList = new List();
+ //Type is kinda unnecessary as you can get the type through other methods, but this makes it easier
+ public ModData(Assembly asm, Type type, dynamic mod)
+ {
+ Assembly = asm;
+ Type = type;
+ Mod = mod;
+ }
+
+ public Assembly Assembly;
+ public Type Type;
+ public dynamic Mod;
+ }
+}
diff --git a/NativeMethods.cs b/NativeMethods.cs
new file mode 100755
index 0000000..9b40002
--- /dev/null
+++ b/NativeMethods.cs
@@ -0,0 +1,172 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace MacroBoard.Native
+{
+ public static class Messages
+ {
+ [DllImport("user32.dll")]
+ public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
+
+ [return: MarshalAs(UnmanagedType.Bool)]
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
+
+
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern bool PeekMessage(
+ out NativeMessage lpMsg,
+ IntPtr hwnd,
+ uint wMsgFilterMin,
+ uint wMsgFilterMax,
+ uint wRemoveMsg);
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct NativeMessage
+ {
+ public IntPtr handle;
+ public uint msg;
+ public IntPtr wParam;
+ public IntPtr lParam;
+ public uint time;
+ public System.Drawing.Point p;
+ }
+
+ [Flags]
+ public enum PeekMessageParams : uint
+ {
+ PM_NOREMOVE = 0x0000,
+ PM_REMOVE = 0x0001,
+ PM_NOYIELD = 0x0002,
+ PM_QS_INPUT = QueueStatusFlags.QS_INPUT << 16,
+ PM_QS_POSTMESSAGE = (QueueStatusFlags.QS_POSTMESSAGE | QueueStatusFlags.QS_HOTKEY | QueueStatusFlags.QS_TIMER) << 16,
+ PM_QS_PAINT = QueueStatusFlags.QS_PAINT << 16,
+ PM_QS_SENDMESSAGE = QueueStatusFlags.QS_SENDMESSAGE << 16
+ }
+
+ [Flags]
+ public enum QueueStatusFlags : uint
+ {
+ QS_KEY = 0x1,
+ QS_MOUSEMOVE = 0x2,
+ QS_MOUSEBUTTON = 0x4,
+ QS_MOUSE = (QS_MOUSEMOVE | QS_MOUSEBUTTON),
+ QS_INPUT = (QS_MOUSE | QS_KEY),
+ QS_POSTMESSAGE = 0x8,
+ QS_TIMER = 0x10,
+ QS_PAINT = 0x20,
+ QS_SENDMESSAGE = 0x40,
+ QS_HOTKEY = 0x80,
+ QS_REFRESH = (QS_HOTKEY | QS_KEY | QS_MOUSEBUTTON | QS_PAINT),
+ QS_ALLEVENTS = (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY),
+ QS_ALLINPUT = (QS_SENDMESSAGE | QS_PAINT | QS_TIMER | QS_POSTMESSAGE | QS_MOUSEBUTTON | QS_MOUSEMOVE | QS_HOTKEY | QS_KEY),
+ QS_ALLPOSTMESSAGE = 0x100,
+ QS_RAWINPUT = 0x400
+ }
+
+
+ public enum AppComandCode : uint
+ {
+ BASS_BOOST = 20,
+ BASS_DOWN = 19,
+ BASS_UP = 21,
+ BROWSER_BACKWARD = 1,
+ BROWSER_FAVORITES = 6,
+ BROWSER_FORWARD = 2,
+ BROWSER_HOME = 7,
+ BROWSER_REFRESH = 3,
+ BROWSER_SEARCH = 5,
+ BROWSER_STOP = 4,
+ LAUNCH_APP1 = 17,
+ LAUNCH_APP2 = 18,
+ LAUNCH_MAIL = 15,
+ LAUNCH_MEDIA_SELECT = 16,
+ MEDIA_NEXTTRACK = 11,
+ MEDIA_PLAY_PAUSE = 14,
+ MEDIA_PREVIOUSTRACK = 12,
+ MEDIA_STOP = 13,
+ TREBLE_DOWN = 22,
+ TREBLE_UP = 23,
+ VOLUME_DOWN = 9,
+ VOLUME_MUTE = 8,
+ VOLUME_UP = 10,
+ MICROPHONE_VOLUME_MUTE = 24,
+ MICROPHONE_VOLUME_DOWN = 25,
+ MICROPHONE_VOLUME_UP = 26,
+ CLOSE = 31,
+ COPY = 36,
+ CORRECTION_LIST = 45,
+ CUT = 37,
+ DICTATE_OR_COMMAND_CONTROL_TOGGLE = 43,
+ FIND = 28,
+ FORWARD_MAIL = 40,
+ HELP = 27,
+ MEDIA_CHANNEL_DOWN = 52,
+ MEDIA_CHANNEL_UP = 51,
+ MEDIA_FASTFORWARD = 49,
+ MEDIA_PAUSE = 47,
+ MEDIA_PLAY = 46,
+ MEDIA_RECORD = 48,
+ MEDIA_REWIND = 50,
+ MIC_ON_OFF_TOGGLE = 44,
+ NEW = 29,
+ OPEN = 30,
+ PASTE = 38,
+ PRINT = 33,
+ REDO = 35,
+ REPLY_TO_MAIL = 39,
+ SAVE = 32,
+ SEND_MAIL = 41,
+ SPELL_CHECK = 42,
+ UNDO = 34,
+ DELETE = 53,
+ DWM_FLIP3D = 54
+ }
+ }
+
+ public static class Libraries
+ {
+ [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
+ public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
+
+ [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
+ public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
+ }
+
+ public static class Windows
+ {
+ [DllImport("user32.dll")]
+ public static extern IntPtr FindWindow(string strClassName, string strWindowName);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
+ }
+
+ public static class Keyboards
+ {
+ public const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
+ public const uint KEYEVENTF_KEYUP = 0x0002;
+
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
+ public static extern short GetKeyState(int keyCode);
+
+ public static bool IsNumLockEnabled() => (((ushort)GetKeyState(0x90)) & 0xFFFF) != 0;
+
+ public enum KeyState
+ {
+ Down,
+ Up
+ }
+
+ //There is a built in System.Windows.Input version of this that has a Toggled version, but I am using my own.
+ public static KeyState GetKeyState(IntPtr lParam) => (((ulong)lParam & 0x80000000) == 0 ? KeyState.Down : KeyState.Up);
+
+ [DllImport("user32.dll")]
+ public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
+ }
+}
\ No newline at end of file
diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json
new file mode 100755
index 0000000..60ce808
--- /dev/null
+++ b/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "MacroBoard": {
+ "commandName": "Project",
+ "nativeDebugging": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/Tunnel.cs b/Tunnel.cs
new file mode 100755
index 0000000..74b2e97
--- /dev/null
+++ b/Tunnel.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using System.Threading;
+using System.Windows;
+
+namespace MacroBoard
+{
+ public class Tunnel
+ {
+
+ public Tunnel()
+ {
+
+ }
+
+
+ public void UpdateKeyCombinations(dynamic modType, dynamic modKeyCombinations)
+ {
+ ModKeyCombination.SetModCombinations(modType, (List)modKeyCombinations);
+ }
+
+
+ public readonly MainWindow HostWindow;
+
+ public void WriteDebugLine(string str)
+ {
+ Debug.WriteLine(str);
+ }
+
+ public void ShowMessageBox(string messageBoxText, string caption, int button, int icon)
+ {
+ new Thread(() => MessageBox.Show(messageBoxText, caption, (MessageBoxButton)button, (MessageBoxImage)icon)).Start();
+ }
+ }
+}
diff --git a/VolumeControl.cs b/VolumeControl.cs
new file mode 100755
index 0000000..0e913ae
--- /dev/null
+++ b/VolumeControl.cs
@@ -0,0 +1,231 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MacroBoard.Volume
+{
+ public class VolumeMixer
+ {
+ public static float? GetApplicationVolume(int pid)
+ {
+ ISimpleAudioVolume volume = GetVolumeObject(pid);
+ if (volume == null)
+ return null;
+
+ float level;
+ volume.GetMasterVolume(out level);
+ Marshal.ReleaseComObject(volume);
+ return level * 100;
+ }
+
+ public static bool? GetApplicationMute(int pid)
+ {
+ ISimpleAudioVolume volume = GetVolumeObject(pid);
+ if (volume == null)
+ return null;
+
+ bool mute;
+ volume.GetMute(out mute);
+ Marshal.ReleaseComObject(volume);
+ return mute;
+ }
+
+ public static void SetApplicationVolume(int pid, float level)
+ {
+ ISimpleAudioVolume volume = GetVolumeObject(pid);
+ if (volume == null)
+ return;
+
+ Guid guid = Guid.Empty;
+ volume.SetMasterVolume(level / 100, ref guid);
+ Marshal.ReleaseComObject(volume);
+ }
+
+ public static void SetApplicationMute(int pid, bool mute)
+ {
+ ISimpleAudioVolume volume = GetVolumeObject(pid);
+ if (volume == null)
+ return;
+
+ Guid guid = Guid.Empty;
+ volume.SetMute(mute, ref guid);
+ Marshal.ReleaseComObject(volume);
+ }
+
+ private static ISimpleAudioVolume GetVolumeObject(int pid)
+ {
+ // get the speakers (1st render + multimedia) device
+ IMMDeviceEnumerator deviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
+ IMMDevice speakers;
+ deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers);
+
+ // activate the session manager. we need the enumerator
+ Guid IID_IAudioSessionManager2 = typeof(IAudioSessionManager2).GUID;
+ object o;
+ speakers.Activate(ref IID_IAudioSessionManager2, 0, IntPtr.Zero, out o);
+ IAudioSessionManager2 mgr = (IAudioSessionManager2)o;
+
+ // enumerate sessions for on this device
+ IAudioSessionEnumerator sessionEnumerator;
+ mgr.GetSessionEnumerator(out sessionEnumerator);
+ int count;
+ sessionEnumerator.GetCount(out count);
+
+ // search for an audio session with the required name
+ // NOTE: we could also use the process id instead of the app name (with IAudioSessionControl2)
+ ISimpleAudioVolume volumeControl = null;
+ for (int i = 0; i < count; i++)
+ {
+ IAudioSessionControl2 ctl;
+ sessionEnumerator.GetSession(i, out ctl);
+ int cpid;
+ ctl.GetProcessId(out cpid);
+
+ if (cpid == pid)
+ {
+ volumeControl = ctl as ISimpleAudioVolume;
+ break;
+ }
+ Marshal.ReleaseComObject(ctl);
+ }
+ Marshal.ReleaseComObject(sessionEnumerator);
+ Marshal.ReleaseComObject(mgr);
+ Marshal.ReleaseComObject(speakers);
+ Marshal.ReleaseComObject(deviceEnumerator);
+ return volumeControl;
+ }
+ }
+
+ [ComImport]
+ [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
+ internal class MMDeviceEnumerator
+ {
+ }
+
+ internal enum EDataFlow
+ {
+ eRender,
+ eCapture,
+ eAll,
+ EDataFlow_enum_count
+ }
+
+ internal enum ERole
+ {
+ eConsole,
+ eMultimedia,
+ eCommunications,
+ ERole_enum_count
+ }
+
+ [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IMMDeviceEnumerator
+ {
+ int NotImpl1();
+
+ [PreserveSig]
+ int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice);
+
+ // the rest is not implemented
+ }
+
+ [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IMMDevice
+ {
+ [PreserveSig]
+ int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
+
+ // the rest is not implemented
+ }
+
+ [Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IAudioSessionManager2
+ {
+ int NotImpl1();
+ int NotImpl2();
+
+ [PreserveSig]
+ int GetSessionEnumerator(out IAudioSessionEnumerator SessionEnum);
+
+ // the rest is not implemented
+ }
+
+ [Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IAudioSessionEnumerator
+ {
+ [PreserveSig]
+ int GetCount(out int SessionCount);
+
+ [PreserveSig]
+ int GetSession(int SessionCount, out IAudioSessionControl2 Session);
+ }
+
+ [Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface ISimpleAudioVolume
+ {
+ [PreserveSig]
+ int SetMasterVolume(float fLevel, ref Guid EventContext);
+
+ [PreserveSig]
+ int GetMasterVolume(out float pfLevel);
+
+ [PreserveSig]
+ int SetMute(bool bMute, ref Guid EventContext);
+
+ [PreserveSig]
+ int GetMute(out bool pbMute);
+ }
+
+ [Guid("bfb7ff88-7239-4fc9-8fa2-07c950be9c6d"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IAudioSessionControl2
+ {
+ // IAudioSessionControl
+ [PreserveSig]
+ int NotImpl0();
+
+ [PreserveSig]
+ int GetDisplayName([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal);
+
+ [PreserveSig]
+ int SetDisplayName([MarshalAs(UnmanagedType.LPWStr)] string Value, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext);
+
+ [PreserveSig]
+ int GetIconPath([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal);
+
+ [PreserveSig]
+ int SetIconPath([MarshalAs(UnmanagedType.LPWStr)] string Value, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext);
+
+ [PreserveSig]
+ int GetGroupingParam(out Guid pRetVal);
+
+ [PreserveSig]
+ int SetGroupingParam([MarshalAs(UnmanagedType.LPStruct)] Guid Override, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext);
+
+ [PreserveSig]
+ int NotImpl1();
+
+ [PreserveSig]
+ int NotImpl2();
+
+ // IAudioSessionControl2
+ [PreserveSig]
+ int GetSessionIdentifier([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal);
+
+ [PreserveSig]
+ int GetSessionInstanceIdentifier([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal);
+
+ [PreserveSig]
+ int GetProcessId(out int pRetVal);
+
+ [PreserveSig]
+ int IsSystemSoundsSession();
+
+ [PreserveSig]
+ int SetDuckingPreference(bool optOut);
+ }
+}
+
diff --git a/app.manifest b/app.manifest
new file mode 100755
index 0000000..4392813
--- /dev/null
+++ b/app.manifest
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+