|
| 1 | +using System; |
| 2 | +using System.Collections.Generic; |
| 3 | +using System.Globalization; |
| 4 | +using System.Runtime.InteropServices; |
| 5 | +using System.Text; |
| 6 | + |
| 7 | +namespace Rubberduck.VBEditor.Native |
| 8 | +{ |
| 9 | + public static class WinEvents |
| 10 | + { |
| 11 | + #region Debugging symbol lookups |
| 12 | + public static readonly Dictionary<uint, string> EventNameLookup = new Dictionary<uint, string> |
| 13 | + { |
| 14 | + {0x1, "EVENT_SYSTEM_SOUND"}, |
| 15 | + {0x2, "EVENT_SYSTEM_ALERT"}, |
| 16 | + {0x3, "EVENT_SYSTEM_FOREGROUND"}, |
| 17 | + {0x4, "EVENT_SYSTEM_MENUSTART"}, |
| 18 | + {0x5, "EVENT_SYSTEM_MENUEND"}, |
| 19 | + {0x6, "EVENT_SYSTEM_MENUPOPUPSTART"}, |
| 20 | + {0x7, "EVENT_SYSTEM_MENUPOPUPEND"}, |
| 21 | + {0x8, "EVENT_SYSTEM_CAPTURESTART"}, |
| 22 | + {0x9, "EVENT_SYSTEM_CAPTUREEND"}, |
| 23 | + {0xa, "EVENT_SYSTEM_MOVESIZESTART"}, |
| 24 | + {0xb, "EVENT_SYSTEM_MOVESIZEEND"}, |
| 25 | + {0xc, "EVENT_SYSTEM_CONTEXTHELPSTART"}, |
| 26 | + {0xd, "EVENT_SYSTEM_CONTEXTHELPEND"}, |
| 27 | + {0xe, "EVENT_SYSTEM_DRAGDROPSTART"}, |
| 28 | + {0xf, "EVENT_SYSTEM_DRAGDROPEND"}, |
| 29 | + {0x10, "EVENT_SYSTEM_DIALOGSTART"}, |
| 30 | + {0x11, "EVENT_SYSTEM_DIALOGEND"}, |
| 31 | + {0x12, "EVENT_SYSTEM_SCROLLINGSTART"}, |
| 32 | + {0x13, "EVENT_SYSTEM_SCROLLINGEND"}, |
| 33 | + {0x14, "EVENT_SYSTEM_SWITCHSTART"}, |
| 34 | + {0x15, "EVENT_SYSTEM_SWITCHEND"}, |
| 35 | + {0x16, "EVENT_SYSTEM_MINIMIZESTART"}, |
| 36 | + {0x17, "EVENT_SYSTEM_MINIMIZEEND"}, |
| 37 | + {0x8000, "EVENT_OBJECT_CREATE"}, |
| 38 | + {0x8001, "EVENT_OBJECT_DESTROY"}, |
| 39 | + {0x8002, "EVENT_OBJECT_SHOW"}, |
| 40 | + {0x8003, "EVENT_OBJECT_HIDE"}, |
| 41 | + {0x8004, "EVENT_OBJECT_REORDER"}, |
| 42 | + {0x8005, "EVENT_OBJECT_FOCUS"}, |
| 43 | + {0x8006, "EVENT_OBJECT_SELECTION"}, |
| 44 | + {0x8007, "EVENT_OBJECT_SELECTIONADD"}, |
| 45 | + {0x8008, "EVENT_OBJECT_SELECTIONREMOVE"}, |
| 46 | + {0x8009, "EVENT_OBJECT_SELECTIONWITHIN"}, |
| 47 | + {0x800A, "EVENT_OBJECT_STATECHANGE"}, |
| 48 | + {0x800B, "EVENT_OBJECT_LOCATIONCHANGE"}, |
| 49 | + {0x800C, "EVENT_OBJECT_NAMECHANGE"}, |
| 50 | + {0x800D, "EVENT_OBJECT_DESCRIPTIONCHANGE"}, |
| 51 | + {0x800E, "EVENT_OBJECT_VALUECHANGE"}, |
| 52 | + {0x800F, "EVENT_OBJECT_PARENTCHANGE"}, |
| 53 | + {0x8010, "EVENT_OBJECT_HELPCHANGE"}, |
| 54 | + {0x8011, "EVENT_OBJECT_DEFACTIONCHANGE"}, |
| 55 | + {0x8012, "EVENT_OBJECT_ACCELERATORCHANGE"}, |
| 56 | + }; |
| 57 | + |
| 58 | + public static readonly Dictionary<uint, string> ObjectIdNameLookup = new Dictionary<uint, string> |
| 59 | + { |
| 60 | + { 0x00000000, "OBJID_WINDOW" }, |
| 61 | + { 0xFFFFFFFF, "OBJID_SYSMENU" }, |
| 62 | + { 0xFFFFFFFE, "OBJID_TITLEBAR" }, |
| 63 | + { 0xFFFFFFFD, "OBJID_MENU" }, |
| 64 | + { 0xFFFFFFFC, "OBJID_CLIENT" }, |
| 65 | + { 0xFFFFFFFB, "OBJID_VSCROLL" }, |
| 66 | + { 0xFFFFFFFA, "OBJID_HSCROLL" }, |
| 67 | + { 0xFFFFFFF9, "OBJID_SIZEGRIP" }, |
| 68 | + { 0xFFFFFFF8, "OBJID_CARET" }, |
| 69 | + { 0xFFFFFFF7, "OBJID_CURSOR" }, |
| 70 | + { 0xFFFFFFF6, "OBJID_ALERT" }, |
| 71 | + { 0xFFFFFFF5, "OBJID_SOUND" }, |
| 72 | + { 0xFFFFFFF4, "OBJID_QUERYCLASSNAMEIDX" }, |
| 73 | + { 0xFFFFFFF0, "OBJID_NATIVEOM" }, |
| 74 | + }; |
| 75 | + #endregion |
| 76 | + |
| 77 | + #region System enumerations |
| 78 | + // ReSharper disable InconsistentNaming |
| 79 | + //See https://msdn.microsoft.com/en-us/library/windows/desktop/dd318066(v=vs.85).aspx |
| 80 | + public enum EventConstant : uint |
| 81 | + { |
| 82 | + EVENT_MIN = 0x1, |
| 83 | + EVENT_SYSTEM_SOUND = 0x1, |
| 84 | + EVENT_SYSTEM_ALERT = 0x2, |
| 85 | + EVENT_SYSTEM_FOREGROUND = 0x3, |
| 86 | + EVENT_SYSTEM_MENUSTART = 0x4, |
| 87 | + EVENT_SYSTEM_MENUEND = 0x5, |
| 88 | + EVENT_SYSTEM_MENUPOPUPSTART = 0x6, |
| 89 | + EVENT_SYSTEM_MENUPOPUPEND = 0x7, |
| 90 | + EVENT_SYSTEM_CAPTURESTART = 0x8, |
| 91 | + EVENT_SYSTEM_CAPTUREEND = 0x9, |
| 92 | + EVENT_SYSTEM_MOVESIZESTART = 0xa, |
| 93 | + EVENT_SYSTEM_MOVESIZEEND = 0xb, |
| 94 | + EVENT_SYSTEM_CONTEXTHELPSTART = 0xc, |
| 95 | + EVENT_SYSTEM_CONTEXTHELPEND = 0xd, |
| 96 | + EVENT_SYSTEM_DRAGDROPSTART = 0xe, |
| 97 | + EVENT_SYSTEM_DRAGDROPEND = 0xf, |
| 98 | + EVENT_SYSTEM_DIALOGSTART = 0x10, |
| 99 | + EVENT_SYSTEM_DIALOGEND = 0x11, |
| 100 | + EVENT_SYSTEM_SCROLLINGSTART = 0x12, |
| 101 | + EVENT_SYSTEM_SCROLLINGEND = 0x13, |
| 102 | + EVENT_SYSTEM_SWITCHSTART = 0x14, |
| 103 | + EVENT_SYSTEM_SWITCHEND = 0x15, |
| 104 | + EVENT_SYSTEM_MINIMIZESTART = 0x16, |
| 105 | + EVENT_SYSTEM_MINIMIZEEND = 0x17, |
| 106 | + EVENT_OEM_DEFINED_START = 0x0101, |
| 107 | + EVENT_OEM_DEFINED_END = 0x01FF, |
| 108 | + EVENT_AIA_START = 0xA000, |
| 109 | + EVENT_AIA_END = 0xAFFF, |
| 110 | + EVENT_UIA_EVENTID_START = 0x4E00, |
| 111 | + EVENT_UIA_EVENTID_END = 0x4EFF, |
| 112 | + EVENT_UIA_PROPID_START = 0x7500, |
| 113 | + EVENT_UIA_PROPID_END = 0x75FF, |
| 114 | + EVENT_OBJECT_START = 0x8000, |
| 115 | + EVENT_OBJECT_CREATE = 0x8000, |
| 116 | + EVENT_OBJECT_DESTROY = 0x8001, |
| 117 | + EVENT_OBJECT_SHOW = 0x8002, |
| 118 | + EVENT_OBJECT_HIDE = 0x8003, |
| 119 | + EVENT_OBJECT_REORDER = 0x8004, |
| 120 | + EVENT_OBJECT_FOCUS = 0x8005, |
| 121 | + EVENT_OBJECT_SELECTION = 0x8006, |
| 122 | + EVENT_OBJECT_SELECTIONADD = 0x8007, |
| 123 | + EVENT_OBJECT_SELECTIONREMOVE = 0x8008, |
| 124 | + EVENT_OBJECT_SELECTIONWITHIN = 0x8009, |
| 125 | + EVENT_OBJECT_STATECHANGE = 0x800A, |
| 126 | + EVENT_OBJECT_LOCATIONCHANGE = 0x800B, |
| 127 | + EVENT_OBJECT_NAMECHANGE = 0x800C, |
| 128 | + EVENT_OBJECT_DESCRIPTIONCHANGE = 0x800D, |
| 129 | + EVENT_OBJECT_VALUECHANGE = 0x800E, |
| 130 | + EVENT_OBJECT_PARENTCHANGE = 0x800F, |
| 131 | + EVENT_OBJECT_HELPCHANGE = 0x8010, |
| 132 | + EVENT_OBJECT_DEFACTIONCHANGE = 0x8011, |
| 133 | + EVENT_OBJECT_ACCELERATORCHANGE = 0x8012, |
| 134 | + EVENT_OBJECT_INVOKED = 0x8013, |
| 135 | + EVENT_OBJECT_CONTENTSCROLLED = 0x8015, |
| 136 | + EVENT_SYSTEM_ARRANGMENTPREVIEW = 0x8016, |
| 137 | + EVENT_OBJECT_LIVEREGIONCHANGED = 0x8019, |
| 138 | + EVENT_OBJECT_HOSTEDOBJECTSINVALIDATED = 0x8020, |
| 139 | + EVENT_OBJECT_DRAGSTART = 0x8021, |
| 140 | + EVENT_OBJECT_DRAGCANCEL = 0x8022, |
| 141 | + EVENT_OBJECT_DRAGCOMPLETE = 0x8023, |
| 142 | + EVENT_OBJECT_DRAGENTER = 0x8024, |
| 143 | + EVENT_OBJECT_DRAGLEAVE = 0x8025, |
| 144 | + EVENT_OBJECT_DRAGDROPPED = 0x8026, |
| 145 | + EVENT_OBJECT_IME_SHOW = 0x8027, |
| 146 | + EVENT_OBJECT_IME_HIDE = 0x8028, |
| 147 | + EVENT_OBJECT_IME_CHANGE = 0x8029, |
| 148 | + EVENT_OBJECT_TEXTEDIT_CONVERSIONTARGETCHANGED = 0x8030, |
| 149 | + EVENT_OBJECT_TEXTSELECTIONCHANGED = 0x8014, |
| 150 | + EVENT_OBJECT_END = 0x80FF, |
| 151 | + EVENT_MAX = 0x7FFFFFFF |
| 152 | + } |
| 153 | + // possible marshaling unmanaged type conflict/problem between 32/64 bit |
| 154 | + |
| 155 | + public enum ObjId : uint |
| 156 | + { |
| 157 | + OBJID_WINDOW = 0x00000000, |
| 158 | + OBJID_SYSMENU = 0xFFFFFFFF, |
| 159 | + OBJID_TITLEBAR = 0xFFFFFFFE, |
| 160 | + OBJID_MENU = 0xFFFFFFFD, |
| 161 | + OBJID_CLIENT = 0xFFFFFFFC, |
| 162 | + OBJID_VSCROLL = 0xFFFFFFFB, |
| 163 | + OBJID_HSCROLL = 0xFFFFFFFA, |
| 164 | + OBJID_SIZEGRIP = 0xFFFFFFF9, |
| 165 | + OBJID_CARET = 0xFFFFFFF8, |
| 166 | + OBJID_CURSOR = 0xFFFFFFF7, |
| 167 | + OBJID_ALERT = 0xFFFFFFF6, |
| 168 | + OBJID_SOUND = 0xFFFFFFF5, |
| 169 | + OBJID_QUERYCLASSNAMEIDX = 0xFFFFFFF4, |
| 170 | + OBJID_NATIVEOM = 0xFFFFFFF0 |
| 171 | + } |
| 172 | + |
| 173 | + public enum WinEventFlags : uint |
| 174 | + { |
| 175 | + WINEVENT_OUTOFCONTEXT = 0x0000, |
| 176 | + WINEVENT_SKIPOWNTHREAD = 0x0001, |
| 177 | + WINEVENT_SKIPOWNPROCESS = 0x0002, |
| 178 | + WINEVENT_INCONTEXT = 0x0004 |
| 179 | + } |
| 180 | + // ReSharper restore InconsistentNaming |
| 181 | + #endregion |
| 182 | + |
| 183 | + #region API declarations |
| 184 | + |
| 185 | + public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, uint idObject, uint idChild, uint dwEventThread, uint dwmsEventTime); |
| 186 | + |
| 187 | + [DllImport("user32.dll")] |
| 188 | + public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, IntPtr lpfnWinEventProc, uint idProcess, |
| 189 | + uint idThread, uint dwFlags); |
| 190 | + |
| 191 | + [DllImport("user32.dll")] |
| 192 | + public static extern int GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); |
| 193 | + |
| 194 | + [DllImport("user32.dll")] |
| 195 | + public static extern bool UnhookWinEvent(IntPtr hWinEventHook); |
| 196 | + |
| 197 | + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] |
| 198 | + public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); |
| 199 | + |
| 200 | + #endregion |
| 201 | + |
| 202 | + #region Extension methods |
| 203 | + |
| 204 | + public static string ToObjectIdString(this uint objectId) |
| 205 | + { |
| 206 | + return ObjectIdNameLookup.ContainsKey(objectId) ? ObjectIdNameLookup[objectId] : objectId.ToString(CultureInfo.InvariantCulture); |
| 207 | + } |
| 208 | + |
| 209 | + public static string ToEventIdString(this uint eventId) |
| 210 | + { |
| 211 | + return EventNameLookup.ContainsKey(eventId) ? EventNameLookup[eventId] : eventId.ToString(CultureInfo.InvariantCulture); |
| 212 | + } |
| 213 | + |
| 214 | + public static string ToClassName(this IntPtr hwnd) |
| 215 | + { |
| 216 | + var buffer = new StringBuilder(256); |
| 217 | + if (hwnd != IntPtr.Zero) |
| 218 | + { |
| 219 | + return GetClassName(hwnd, buffer, buffer.Capacity) != 0 ? buffer.ToString() : string.Empty; |
| 220 | + } |
| 221 | + return string.Empty; |
| 222 | + } |
| 223 | + |
| 224 | + #endregion |
| 225 | + } |
| 226 | +} |
0 commit comments