├── .gitignore
├── LICENSE
├── README.md
├── Silence.Hooking
├── GlobalKeyEventHandler.cs
├── GlobalKeyEventHandlerArgs.cs
├── GlobalMouseEventHandler.cs
├── GlobalMouseEventHandlerArgs.cs
├── HandleableEventArgs.cs
├── Properties
│ └── AssemblyInfo.cs
├── Silence.Hooking.csproj
└── Windows
│ ├── HookManager.Callbacks.Keyboard.cs
│ ├── HookManager.Callbacks.Mouse.cs
│ ├── HookManager.Callbacks.cs
│ ├── HookManager.Interop.cs
│ ├── HookManager.Structures.cs
│ ├── HookManager.cs
│ └── Native
│ └── User32.cs
├── Silence.Macro
├── Macro.cs
├── MacroDelayEvent.cs
├── MacroEvent.cs
├── MacroKeyDownEvent.cs
├── MacroKeyEvent.cs
├── MacroKeyUpEvent.cs
├── MacroMouseDownEvent.cs
├── MacroMouseEvent.cs
├── MacroMouseMoveEvent.cs
├── MacroMouseUpEvent.cs
├── MacroMouseWheelEvent.cs
├── MacroPlayer.cs
├── MacroRecorder.cs
├── Properties
│ └── AssemblyInfo.cs
└── Silence.Macro.csproj
├── Silence.Simulation
├── IInputDeviceStateAdaptor.cs
├── IInputMessageDispatcher.cs
├── IInputSimulator.cs
├── IKeyboardSimulator.cs
├── IMouseSimulator.cs
├── InputBuilder.cs
├── InputSimulator.cs
├── KeyboardSimulator.cs
├── MouseButton.cs
├── MouseSimulator.cs
├── Native
│ ├── HARDWAREINPUT.cs
│ ├── INPUT.cs
│ ├── InputType.cs
│ ├── KEYBDINPUT.cs
│ ├── KeyboardFlag.cs
│ ├── MOUSEINPUT.cs
│ ├── MOUSEKEYBDHARDWAREINPUT.cs
│ ├── MouseFlag.cs
│ ├── NativeMethods.cs
│ ├── VirtualKeyCode.cs
│ └── XButton.cs
├── Properties
│ └── AssemblyInfo.cs
├── Silence.Simulation.csproj
├── WindowsInputDeviceStateAdaptor.cs
└── WindowsInputMessageDispatcher.cs
├── Silence.sln
└── Silence
├── ConfigurationFile.cs
├── ControlButton.cs
├── FormMain.Designer.cs
├── FormMain.cs
├── FormMain.resx
├── JsonSerializable.cs
├── Localization
├── Language.cs
└── LanguagePack.cs
├── Program.cs
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
└── Settings.settings
├── RepetitionsDialog.Designer.cs
├── RepetitionsDialog.cs
├── RepetitionsDialog.resx
├── Resources
├── clear.png
├── loop.png
├── menu_closed.png
├── menu_open.png
├── open.png
├── pause.png
├── play.png
├── record.png
├── save.png
└── stop.png
├── Silence.csproj
├── ThemeColor.cs
├── app.manifest
├── lang
├── lang_en.json
└── lang_zh.json
├── packages.config
└── silence.ico
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | *.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.pfx
193 | *.publishsettings
194 | node_modules/
195 | orleans.codegen.cs
196 |
197 | # Since there are multiple workflows, uncomment next line to ignore bower_components
198 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
199 | #bower_components/
200 |
201 | # RIA/Silverlight projects
202 | Generated_Code/
203 |
204 | # Backup & report files from converting an old project file
205 | # to a newer Visual Studio version. Backup files are not needed,
206 | # because we have git ;-)
207 | _UpgradeReport_Files/
208 | Backup*/
209 | UpgradeLog*.XML
210 | UpgradeLog*.htm
211 |
212 | # SQL Server files
213 | *.mdf
214 | *.ldf
215 |
216 | # Business Intelligence projects
217 | *.rdl.data
218 | *.bim.layout
219 | *.bim_*.settings
220 |
221 | # Microsoft Fakes
222 | FakesAssemblies/
223 |
224 | # GhostDoc plugin setting file
225 | *.GhostDoc.xml
226 |
227 | # Node.js Tools for Visual Studio
228 | .ntvs_analysis.dat
229 |
230 | # Visual Studio 6 build log
231 | *.plg
232 |
233 | # Visual Studio 6 workspace options file
234 | *.opt
235 |
236 | # Visual Studio LightSwitch build output
237 | **/*.HTMLClient/GeneratedArtifacts
238 | **/*.DesktopClient/GeneratedArtifacts
239 | **/*.DesktopClient/ModelManifest.xml
240 | **/*.Server/GeneratedArtifacts
241 | **/*.Server/ModelManifest.xml
242 | _Pvt_Extensions
243 |
244 | # Paket dependency manager
245 | .paket/paket.exe
246 | paket-files/
247 |
248 | # FAKE - F# Make
249 | .fake/
250 |
251 | # JetBrains Rider
252 | .idea/
253 | *.sln.iml
254 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Saul Johnson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Silence
2 | A simple, clean macro recorder written in C#. Windows 10 compatible.
3 |
4 | ## Acknowledgements
5 | It's been a while since I re-created this repo and managed to lose the readme in the process (completely forgot about it), so if make any mistakes/ommissions with attribution/copyright notices for anyone, please do not hesitate to contact me and I'll put it right.
6 |
7 | * The original [HookLib](https://github.com/codelogic/HookLib) by [Paul Rhode](https://github.com/codelogic).
8 | * The original [Input Simulator](https://github.com/michaelnoonan/inputsimulator/) by [Michael Noonan](https://github.com/michaelnoonan/).
9 |
--------------------------------------------------------------------------------
/Silence.Hooking/GlobalKeyEventHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Hooking
4 | {
5 | public delegate void GlobalKeyEventHandler(object sender, GlobalKeyEventHandlerArgs args);
6 | }
7 |
--------------------------------------------------------------------------------
/Silence.Hooking/GlobalKeyEventHandlerArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Hooking
4 | {
5 | ///
6 | /// Represents a set of event arguments passed into the handler for a global key event.
7 | ///
8 | public class GlobalKeyEventHandlerArgs : HandleableEventArgs
9 | {
10 | ///
11 | /// A virtual-key code. The code must be a value in the range 1 to 254.
12 | ///
13 | public int VirtualKeyCode { get; private set; }
14 |
15 | ///
16 | /// A hardware scan code for the key.
17 | ///
18 | public int ScanCode { get; private set; }
19 |
20 | ///
21 | /// The extended-key flag, event-injected flag, context code, and transition-state flag.
22 | ///
23 | public int Flags { get; private set; }
24 |
25 | ///
26 | /// The time stamp for this message.
27 | ///
28 | public int Time { get; private set; }
29 |
30 | ///
31 | /// Additional information associated with the message.
32 | ///
33 | public int ExtraInfo { get; private set; }
34 |
35 | ///
36 | /// Initialises a new instance of a set of global key event handler arguments.
37 | ///
38 | /// A virtual-key code. The code must be a value in the range 1 to 254.
39 | /// A hardware scan code for the key.
40 | /// The extended-key flag, event-injected flag, context code, and transition-state flag.
41 | /// The time stamp for this message.
42 | /// Additional information associated with the message.
43 | public GlobalKeyEventHandlerArgs(int virtualKeyCode, int scanCode, int flags, int time, int extraInfo)
44 | {
45 | VirtualKeyCode = virtualKeyCode;
46 | ScanCode = scanCode;
47 | Flags = flags;
48 | Time = time;
49 | ExtraInfo = extraInfo;
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Silence.Hooking/GlobalMouseEventHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Hooking
4 | {
5 | public delegate void GlobalMouseEventHandler(object sender, GlobalMouseEventHandlerArgs args);
6 | }
7 |
--------------------------------------------------------------------------------
/Silence.Hooking/GlobalMouseEventHandlerArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 | using System.Windows.Input;
4 |
5 | namespace Silence.Hooking
6 | {
7 | ///
8 | /// Represents a set of event arguments passed into the handler for a global mouse event.
9 | ///
10 | public class GlobalMouseEventHandlerArgs : HandleableEventArgs
11 | {
12 | ///
13 | /// The x- and y-coordinates of the cursor, in screen coordinates.
14 | ///
15 | public Point Point { get; private set; }
16 |
17 | ///
18 | /// The mouse button associated with the message.
19 | ///
20 | public MouseButton Button { get; private set; }
21 |
22 | ///
23 | /// Contains information about mouse X buttons or the mouse wheel if relevant.
24 | ///
25 | public int MouseData { get; private set; }
26 |
27 | ///
28 | /// The event-injected flag.
29 | ///
30 | public int Flags { get; private set; }
31 |
32 | ///
33 | /// The time stamp for this message.
34 | ///
35 | public int Time { get; private set; }
36 |
37 | ///
38 | /// Additional information associated with the message.
39 | ///
40 | public int ExtraInfo { get; private set; }
41 |
42 | ///
43 | /// The mouse scroll wheel delta value if relevant.
44 | ///
45 | public int Delta { get; private set; }
46 |
47 | ///
48 | /// Initialises a new instance of a set of global mouse event handler arguments.
49 | ///
50 | /// The x- and y-coordinates of the cursor, in screen coordinates.
51 | /// Contains information about mouse X buttons or the mouse wheel if relevant.
52 | /// Contains information about mouse X buttons or the mouse wheel if relevant.
53 | /// The event-injected flag.
54 | /// The time stamp for this message.
55 | /// Additional information associated with the message.
56 | /// The mouse scroll wheel delta value if relevant.
57 | public GlobalMouseEventHandlerArgs(Point point, MouseButton button, int mouseData, int flags, int time, int extraInfo, int delta)
58 | {
59 | Point = point;
60 | Button = button;
61 | MouseData = mouseData;
62 | Flags = flags;
63 | Time = time;
64 | ExtraInfo = extraInfo;
65 | Delta = delta;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Silence.Hooking/HandleableEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Hooking
4 | {
5 | ///
6 | /// Represents a set of event arguments handleable by a global hook.
7 | ///
8 | public abstract class HandleableEventArgs : EventArgs
9 | {
10 | ///
11 | /// A value indicating whether or not the event was handled.
12 | ///
13 | public bool Handled { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Silence.Hooking/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Silence.Hooking")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Silence.Hooking")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("8897b3b9-fafe-4dd7-81b5-611008cb6437")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Silence.Hooking/Silence.Hooking.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {8897B3B9-FAFE-4DD7-81B5-611008CB6437}
8 | Library
9 | Properties
10 | Silence.Hooking
11 | Silence.Hooking
12 | v4.8
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
70 |
--------------------------------------------------------------------------------
/Silence.Hooking/Windows/HookManager.Callbacks.Keyboard.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Reflection;
4 | using System.Runtime.InteropServices;
5 | using System.Windows.Input;
6 |
7 | namespace Silence.Hooking.Windows
8 | {
9 | public partial class HookManager
10 | {
11 | ///
12 | /// This field is not objectively needed but we need to keep a reference to a delegate which will be
13 | /// passed to unmanaged code to prevent the GC from cleaning it up.
14 | ///
15 | private HookProc windowsKeyboardDelegate;
16 |
17 | ///
18 | /// Stores the handle to the keyboard hook procedure.
19 | ///
20 | private int windowsKeyboardHookHandle;
21 |
22 | ///
23 | /// A callback function which will be called every time a keyboard activity is detected.
24 | ///
25 | /// Specifies whether the hook procedure must process the message.
26 | /// Specifies whether the message was sent by the current thread.
27 | /// A pointer to a CWPSTRUCT structure that contains details about the message.
28 | ///
29 | private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
30 | {
31 | // Indicates if any underlying events handled the action.
32 | bool handled = false;
33 |
34 | if (nCode >= 0)
35 | {
36 | // Marshal the data from callback.
37 | KBDLLHOOKSTRUCT keyStruct = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
38 |
39 | // Key was pressed down.
40 | if (GlobalKeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
41 | {
42 | GlobalKeyEventHandlerArgs keyEventArgs = new GlobalKeyEventHandlerArgs(
43 | keyStruct.vkCode,
44 | keyStruct.scanCode,
45 | keyStruct.flags,
46 | keyStruct.time,
47 | keyStruct.dwExtraInfo);
48 |
49 | GlobalKeyDown.Invoke(null, keyEventArgs);
50 | handled = keyEventArgs.Handled;
51 | }
52 |
53 | // Key was released.
54 | if (GlobalKeyUp != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
55 | {
56 | GlobalKeyEventHandlerArgs keyEventArgs = new GlobalKeyEventHandlerArgs(
57 | keyStruct.vkCode,
58 | keyStruct.scanCode,
59 | keyStruct.flags,
60 | keyStruct.time,
61 | keyStruct.dwExtraInfo);
62 |
63 | GlobalKeyUp.Invoke(null, keyEventArgs);
64 | handled = handled || keyEventArgs.Handled;
65 | }
66 | }
67 |
68 | // Exit method here without calling next hook if is event was handled.
69 | if (handled)
70 | {
71 | return -1;
72 | }
73 |
74 | // Call next hook.
75 | return CallNextHookEx(windowsKeyboardHookHandle, nCode, wParam, lParam);
76 | }
77 |
78 | ///
79 | /// Installs a keyboard hook if one is not installed already.
80 | ///
81 | private void EnsureSubscribedToGlobalKeyboardEvents()
82 | {
83 | // Install keyboard hook only if it is not installed and must be installed.
84 | if (windowsKeyboardHookHandle == 0)
85 | {
86 | // Keep a reference to avoid collection by the GC.
87 | windowsKeyboardDelegate = KeyboardHookProc;
88 |
89 | // Install hook.
90 | windowsKeyboardHookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, windowsKeyboardDelegate, IntPtr.Zero, 0);
91 |
92 | // If failed.
93 | if (windowsKeyboardHookHandle == 0)
94 | {
95 | // Do cleanup.
96 | ForceUnsunscribeFromGlobalKeyboardEvents();
97 |
98 | // Initializes and throws a new instance of the Win32Exception class with the specified error.
99 | throw new Win32Exception(Marshal.GetLastWin32Error());
100 | }
101 | }
102 | }
103 |
104 | ///
105 | /// Unsubscribes from the keyboard hook if no subscribers are registered.
106 | ///
107 | private void TryUnsubscribeFromGlobalKeyboardEvents()
108 | {
109 | // If no subsribers are registered unsubscribe from hook.
110 | if (GlobalKeyDown == null &&
111 | GlobalKeyUp == null)
112 | {
113 | ForceUnsunscribeFromGlobalKeyboardEvents();
114 | }
115 | }
116 |
117 | ///
118 | /// Uninstalls the keyboard hook.
119 | ///
120 | private void ForceUnsunscribeFromGlobalKeyboardEvents()
121 | {
122 | // Don't try to uninstall a null hook.
123 | if (windowsKeyboardHookHandle != 0)
124 | {
125 | // Uninstall hook.
126 | var result = UnhookWindowsHookEx(windowsKeyboardHookHandle);
127 |
128 | // Reset invalid handle.
129 | windowsKeyboardHookHandle = 0;
130 |
131 | // Free up for GC.
132 | windowsKeyboardDelegate = null;
133 |
134 | // If failed, an exception must be thrown.
135 | if (result == 0)
136 | {
137 | //Initializes and throws a new instance of the Win32Exception class with the specified error.
138 | throw new Win32Exception(Marshal.GetLastWin32Error());
139 | }
140 | }
141 | }
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/Silence.Hooking/Windows/HookManager.Callbacks.Mouse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Reflection;
4 | using System.Runtime.InteropServices;
5 | using System.Windows.Input;
6 |
7 | using Silence.Hooking.Windows.Native;
8 |
9 | namespace Silence.Hooking.Windows
10 | {
11 | public partial class HookManager
12 | {
13 | ///
14 | /// This field is not objectively needed but we need to keep a reference to a delegate which will be
15 | /// passed to unmanaged code to prevent the GC from cleaning it up.
16 | ///
17 | private HookProc windowsMouseDelegate;
18 |
19 | ///
20 | /// Stores the handle to the mouse hook procedure.
21 | ///
22 | private int windowsMouseHookHandle;
23 |
24 | ///
25 | /// Retrieves the high-order word from a 32-bit integer.
26 | ///
27 | /// The integer from which to retrieve the high-order word.
28 | ///
29 | private static short GetHighOrderWord(int num)
30 | {
31 | return (short)((num >> 16) & 0xffff);
32 | }
33 |
34 | ///
35 | /// A callback function which will be called every time a mouse activity is detected.
36 | ///
37 | /// Specifies whether the hook procedure must process the message.
38 | /// Specifies whether the message was sent by the current thread.
39 | /// A pointer to a CWPSTRUCT structure that contains details about the message.
40 | ///
41 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644975(v=vs.85).aspx
42 | private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
43 | {
44 | if (nCode >= 0)
45 | {
46 | // Marshal the data from callback.
47 | MSLLHOOKSTRUCT mouseHookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
48 |
49 | // Detect mouse button used.
50 | MouseButton button = MouseButton.Middle;
51 | if (wParam == WM_RBUTTONDBLCLK || wParam == WM_RBUTTONDOWN || wParam == WM_RBUTTONUP)
52 | {
53 | button = MouseButton.Right;
54 | }
55 | else if (wParam == WM_LBUTTONDBLCLK || wParam == WM_LBUTTONDOWN || wParam == WM_LBUTTONUP)
56 | {
57 | button = MouseButton.Left;
58 | }
59 |
60 | // Generate event.
61 | var mouseEventArgs = new GlobalMouseEventHandlerArgs(
62 | new System.Windows.Point(mouseHookStruct.pt.x, mouseHookStruct.pt.y),
63 | button,
64 | mouseHookStruct.mouseData,
65 | mouseHookStruct.flags,
66 | mouseHookStruct.time,
67 | mouseHookStruct.dwExtraInfo,
68 | GetHighOrderWord(mouseHookStruct.mouseData));
69 |
70 | // Mouse button up.
71 | if (GlobalMouseUp != null && (wParam == WM_RBUTTONUP || wParam == WM_LBUTTONUP))
72 | {
73 | GlobalMouseUp.Invoke(null, mouseEventArgs);
74 | }
75 |
76 | // Mouse button down.
77 | if (GlobalMouseDown != null && (wParam == WM_RBUTTONDOWN || wParam == WM_LBUTTONDOWN))
78 | {
79 | GlobalMouseDown.Invoke(null, mouseEventArgs);
80 | }
81 |
82 | // The mouse wheel was moved.
83 | if (GlobalMouseWheel != null && wParam == WM_MOUSEWHEEL)
84 | {
85 | GlobalMouseWheel.Invoke(null, mouseEventArgs);
86 | }
87 |
88 | // If there is a listener for mouse movement and a mouse movement occured.
89 | if ((GlobalMouseMove != null) && wParam == WM_MOUSEMOVE)
90 | {
91 | GlobalMouseMove.Invoke(null, mouseEventArgs);
92 | }
93 |
94 | // Exit method here without calling next hook if is event was handled.
95 | if (mouseEventArgs.Handled)
96 | {
97 | return -1;
98 | }
99 | }
100 |
101 | // Call next hook.
102 | return CallNextHookEx(windowsMouseHookHandle, nCode, wParam, lParam);
103 | }
104 |
105 | ///
106 | /// Installs a mouse hook if one is not installed already.
107 | ///
108 | private void EnsureSubscribedToGlobalMouseEvents()
109 | {
110 | // Install mouse hook only if it is not installed already.
111 | if (windowsMouseHookHandle == 0)
112 | {
113 | // Keep a reference to avoid collection by the GC.
114 | windowsMouseDelegate = MouseHookProc;
115 |
116 | // Install hook.
117 | windowsMouseHookHandle = SetWindowsHookEx(WH_MOUSE_LL, windowsMouseDelegate, IntPtr.Zero, 0);
118 |
119 | // If failed.
120 | if (windowsMouseHookHandle == 0)
121 | {
122 | // Do cleanup.
123 | ForceUnsunscribeFromGlobalMouseEvents();
124 |
125 | // Initializes and throws a new instance of the Win32Exception class with the specified error.
126 | throw new Win32Exception(Marshal.GetLastWin32Error());
127 | }
128 | }
129 | }
130 |
131 | ///
132 | /// Unsubscribes from the mouse hook if no subscribers are registered.
133 | ///
134 | private void TryUnsubscribeFromGlobalMouseEvents()
135 | {
136 | // If no subsribers are registered unsubscribe from hook.
137 | if (GlobalMouseDown == null &&
138 | GlobalMouseMove == null &&
139 | GlobalMouseUp == null &&
140 | GlobalMouseWheel == null)
141 | {
142 | ForceUnsunscribeFromGlobalMouseEvents();
143 | }
144 | }
145 |
146 | ///
147 | /// Uninstalls the mouse hook.
148 | ///
149 | private void ForceUnsunscribeFromGlobalMouseEvents()
150 | {
151 | // Don't try to uninstall a null hook.
152 | if (windowsMouseHookHandle != 0)
153 | {
154 | // Uninstall hook
155 | var result = UnhookWindowsHookEx(windowsMouseHookHandle);
156 |
157 | // Reset invalid handle.
158 | windowsMouseHookHandle = 0;
159 |
160 | // Free up for GC.
161 | windowsMouseDelegate = null;
162 |
163 | // If failed, an exception must be thrown.
164 | if (result == 0)
165 | {
166 | // Initializes and throws a new instance of the Win32Exception class with the specified error.
167 | throw new Win32Exception(Marshal.GetLastWin32Error());
168 | }
169 | }
170 | }
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/Silence.Hooking/Windows/HookManager.Callbacks.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Hooking.Windows
4 | {
5 | partial class HookManager
6 | {
7 | ///
8 | /// An application-defined or library-defined callback function used with the SetWindowsHookEx function.
9 | ///
10 | /// Specifies whether the hook procedure must process the message.
11 | /// Specifies whether the message was sent by the current thread.
12 | /// A pointer to a CWPSTRUCT structure that contains details about the message.
13 | ///
14 | ///
15 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644975(v=vs.85).aspx
16 | ///
17 | private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Silence.Hooking/Windows/HookManager.Structures.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 | using System;
3 |
4 | namespace Silence.Hooking.Windows
5 | {
6 | public partial class HookManager
7 | {
8 | ///
9 | /// The POINT structure defines the x- and y- coordinates of a point.
10 | ///
11 | ///
12 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx
13 | ///
14 | [StructLayout(LayoutKind.Sequential)]
15 | private struct Point
16 | {
17 | ///
18 | /// The x-coordinate of the point.
19 | ///
20 | public int x;
21 |
22 | ///
23 | /// The y-coordinate of the point.
24 | ///
25 | public int y;
26 | }
27 |
28 | ///
29 | /// Contains information about a low-level mouse input event.
30 | ///
31 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644970(v=vs.85).aspx
32 | ///
33 | ///
34 | [StructLayout(LayoutKind.Sequential)]
35 | private struct MSLLHOOKSTRUCT
36 | {
37 | ///
38 | /// The x- and y-coordinates of the cursor, in screen coordinates.
39 | ///
40 | public Point pt;
41 |
42 | ///
43 | /// Contains information about mouse X buttons or the mouse wheel if relevant.
44 | ///
45 | public int mouseData;
46 |
47 | ///
48 | /// The event-injected flag.
49 | ///
50 | public int flags;
51 |
52 | ///
53 | /// The time stamp for this message.
54 | ///
55 | public int time;
56 |
57 | ///
58 | /// Additional information associated with the message.
59 | ///
60 | public int dwExtraInfo;
61 | }
62 |
63 | ///
64 | /// Contains information about a low-level keyboard input event.
65 | ///
66 | ///
67 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644967(v=vs.85).aspx
68 | ///
69 | [StructLayout(LayoutKind.Sequential)]
70 | private struct KBDLLHOOKSTRUCT
71 | {
72 | ///
73 | /// A virtual-key code. The code must be a value in the range 1 to 254.
74 | ///
75 | public int vkCode;
76 |
77 | ///
78 | /// A hardware scan code for the key.
79 | ///
80 | public int scanCode;
81 |
82 | ///
83 | /// The extended-key flag, event-injected flag, context code, and transition-state flag.
84 | ///
85 | public int flags;
86 |
87 | ///
88 | /// The time stamp for this message.
89 | ///
90 | public int time;
91 |
92 | ///
93 | /// Additional information associated with the message.
94 | ///
95 | public int dwExtraInfo;
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/Silence.Hooking/Windows/HookManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Input;
3 | using System.Collections.Generic;
4 |
5 | namespace Silence.Hooking.Windows
6 | {
7 | ///
8 | /// Provides events and methods for easily managing global input events regardless of application focus.
9 | ///
10 | public partial class HookManager : IDisposable
11 | {
12 | ///
13 | /// Raised whenever the global mouse hook detects a mouse move action.
14 | ///
15 | private event GlobalMouseEventHandler GlobalMouseMove;
16 |
17 | ///
18 | /// Raised whenever the global mouse hook detects a mouse down action.
19 | ///
20 | private event GlobalMouseEventHandler GlobalMouseDown;
21 |
22 | ///
23 | /// Raised whenever the global mouse hook detects a mouse up action.
24 | ///
25 | private event GlobalMouseEventHandler GlobalMouseUp;
26 |
27 | ///
28 | /// Raised whenever the global mouse hook detects a mouse wheel action.
29 | ///
30 | private event GlobalMouseEventHandler GlobalMouseWheel;
31 |
32 | ///
33 | /// Raised whenever the global keyboard hook detects a key up action.
34 | ///
35 | private event GlobalKeyEventHandler GlobalKeyUp;
36 |
37 | ///
38 | /// Raised whenever the global keyboard hook detects a key down action.
39 | ///
40 | private event GlobalKeyEventHandler GlobalKeyDown;
41 |
42 | ///
43 | /// Raised whenever the global mouse hook detects a mouse move action.
44 | ///
45 | public event GlobalMouseEventHandler MouseMove
46 | {
47 | add
48 | {
49 | EnsureSubscribedToGlobalMouseEvents();
50 | GlobalMouseMove += value;
51 | }
52 | remove
53 | {
54 | GlobalMouseMove -= value;
55 | TryUnsubscribeFromGlobalMouseEvents();
56 | }
57 | }
58 |
59 | ///
60 | /// Raised whenever the global mouse hook detects a mouse down action.
61 | ///
62 | public event GlobalMouseEventHandler MouseDown
63 | {
64 | add
65 | {
66 | EnsureSubscribedToGlobalMouseEvents();
67 | GlobalMouseDown += value;
68 | }
69 | remove
70 | {
71 | GlobalMouseDown -= value;
72 | TryUnsubscribeFromGlobalMouseEvents();
73 | }
74 | }
75 |
76 | ///
77 | /// Raised whenever the global mouse hook detects a mouse up action.
78 | ///
79 | public event GlobalMouseEventHandler MouseUp
80 | {
81 | add
82 | {
83 | EnsureSubscribedToGlobalMouseEvents();
84 | GlobalMouseUp += value;
85 | }
86 | remove
87 | {
88 | GlobalMouseUp -= value;
89 | TryUnsubscribeFromGlobalMouseEvents();
90 | }
91 | }
92 |
93 | ///
94 | /// Raised whenever the global mouse hook detects a mouse wheel action.
95 | ///
96 | public event GlobalMouseEventHandler MouseWheel
97 | {
98 | add
99 | {
100 | EnsureSubscribedToGlobalMouseEvents();
101 | GlobalMouseWheel += value;
102 | }
103 | remove
104 | {
105 | GlobalMouseWheel -= value;
106 | TryUnsubscribeFromGlobalMouseEvents();
107 | }
108 | }
109 |
110 | ///
111 | /// Raised whenever the global keyboard hook detects a key up action.
112 | ///
113 | public event GlobalKeyEventHandler KeyUp
114 | {
115 | add
116 | {
117 | EnsureSubscribedToGlobalKeyboardEvents();
118 | GlobalKeyUp += value;
119 | }
120 | remove
121 | {
122 | GlobalKeyUp -= value;
123 | TryUnsubscribeFromGlobalKeyboardEvents();
124 | }
125 | }
126 |
127 | ///
128 | /// Raised whenever the global keyboard hook detects a key down action.
129 | ///
130 | public event GlobalKeyEventHandler KeyDown
131 | {
132 | add
133 | {
134 | EnsureSubscribedToGlobalKeyboardEvents();
135 | GlobalKeyDown += value;
136 | }
137 | remove
138 | {
139 | GlobalKeyDown -= value;
140 | TryUnsubscribeFromGlobalKeyboardEvents();
141 | }
142 | }
143 |
144 | ///
145 | /// Unsubscribes from all hooks and releases all resources associated with this object.
146 | ///
147 | public void Dispose()
148 | {
149 |
150 | // Force unsubscription from all hooks.
151 | ForceUnsunscribeFromGlobalKeyboardEvents();
152 | ForceUnsunscribeFromGlobalMouseEvents();
153 |
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/Silence.Hooking/Windows/Native/User32.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using System.Security;
4 | using System.Windows.Interop;
5 |
6 | namespace Silence.Hooking.Windows.Native
7 | {
8 | ///
9 | /// Provides access to User32 library methods from managed code.
10 | ///
11 | public static class User32
12 | {
13 | ///
14 | /// Translates virtual-key messages into character messages.
15 | ///
16 | /// A pointer to an MSG structure that contains message information retrieved from the calling thread's message queue by using the GetMessage or PeekMessage function.
17 | ///
18 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644955(v=vs.85).aspx
19 | [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
20 | public static extern bool TranslateMessage([In, Out] ref MSG msg);
21 |
22 | ///
23 | /// Dispatches a message to a window procedure.
24 | ///
25 | /// A pointer to a structure that contains the message.
26 | ///
27 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644934(v=vs.85).aspx
28 | [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("user32.dll", CharSet = CharSet.Auto)]
29 | public static extern IntPtr DispatchMessage([In] ref MSG msg);
30 |
31 | ///
32 | /// Retrieves a message from the calling thread's message queue.
33 | ///
34 | /// A pointer to an MSG structure that receives message information from the thread's message queue.
35 | /// A handle to the window whose messages are to be retrieved. The window must belong to the current thread.
36 | /// The integer value of the lowest message value to be retrieved.
37 | /// The integer value of the highest message value to be retrieved.
38 | ///
39 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx
40 | [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
41 | public static extern bool GetMessage(ref MSG lpMsg, Int32 hwnd, Int32 wMsgFilterMin, Int32 wMsgFilterMax);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Silence.Macro/Macro.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Xml;
6 |
7 | namespace Silence.Macro
8 | {
9 |
10 | ///
11 | /// Represents a recorded sequence of mouse and keyboard events.
12 | ///
13 | public class Macro
14 | {
15 |
16 | ///
17 | /// Holds the list of events that comprise this macro.
18 | ///
19 | private List events;
20 |
21 | ///
22 | /// Gets the list of events that comprise this macro as an array.
23 | ///
24 | public MacroEvent[] Events {
25 | get
26 | {
27 | return (events == null ? null : events.ToArray());
28 | }
29 | }
30 |
31 | ///
32 | /// Initialises a new instance of a macro.
33 | ///
34 | public Macro()
35 | {
36 | events = new List();
37 | }
38 |
39 | ///
40 | /// Appends an event to the end of this macro.
41 | ///
42 | /// The event to append.
43 | public void AddEvent(MacroEvent newEvent)
44 | {
45 | events.Add(newEvent);
46 | }
47 |
48 | ///
49 | /// Removes all events from this macro.
50 | ///
51 | public void ClearEvents()
52 | {
53 | events.Clear();
54 | }
55 |
56 | ///
57 | /// Serialises this object to an XML string for saving.
58 | ///
59 | ///
60 | public string ToXml()
61 | {
62 | StringBuilder str = new StringBuilder();
63 | str.AppendLine("");
64 | foreach (MacroEvent current in events)
65 | {
66 | str.AppendLine(current.ToXml());
67 | }
68 | str.AppendLine("");
69 |
70 | return str.ToString();
71 | }
72 |
73 | ///
74 | /// Saves this macro to a file at the specified path.
75 | ///
76 | /// The path to save to.
77 | public void Save(string path)
78 | {
79 | XmlDocument xmlDoc = new XmlDocument();
80 | xmlDoc.LoadXml(ToXml());
81 |
82 | xmlDoc.Save(path);
83 | }
84 |
85 | ///
86 | /// Loads the macro file at the specifed path into this object.
87 | ///
88 | /// The path to load the macro from.
89 | public void Load(string path)
90 | {
91 | ClearEvents();
92 |
93 | XmlDocument xmlDoc = new XmlDocument();
94 | xmlDoc.Load(path);
95 |
96 | foreach (XmlElement current in xmlDoc.DocumentElement)
97 | {
98 | switch (current.Name)
99 | {
100 | case "MacroKeyDownEvent" :
101 | AddEvent(new MacroKeyDownEvent(current));
102 | break;
103 | case "MacroKeyUpEvent":
104 | AddEvent(new MacroKeyUpEvent(current));
105 | break;
106 | case "MacroMouseDownEvent":
107 | AddEvent(new MacroMouseDownEvent(current));
108 | break;
109 | case "MacroMouseUpEvent":
110 | AddEvent(new MacroMouseUpEvent(current));
111 | break;
112 | case "MacroMouseMoveEvent":
113 | AddEvent(new MacroMouseMoveEvent(current));
114 | break;
115 | case "MacroMouseWheelEvent":
116 | AddEvent(new MacroMouseWheelEvent(current));
117 | break;
118 | case "MacroDelayEvent":
119 | AddEvent(new MacroDelayEvent(current));
120 | break;
121 | }
122 | }
123 | }
124 |
125 | }
126 |
127 | }
128 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroDelayEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Xml;
6 |
7 | namespace Silence.Macro
8 | {
9 |
10 | ///
11 | /// Represents a delay that occurs between user actions during recording of a macro.
12 | ///
13 | class MacroDelayEvent : MacroEvent
14 | {
15 |
16 | ///
17 | /// Gets or sets the delay in ticks.
18 | ///
19 | public long Delay { get; set; }
20 |
21 | ///
22 | /// Initialises a new instance of a macro delay event.
23 | ///
24 | /// The delay in ticks.
25 | public MacroDelayEvent(long delay)
26 | {
27 | Delay = delay;
28 | }
29 |
30 | ///
31 | /// Initialises a new instance of a macro delay event.
32 | ///
33 | /// The serialised XML element to initialise from.
34 | public MacroDelayEvent(XmlElement element)
35 | {
36 | foreach(XmlElement current in element) {
37 | switch(current.Name) {
38 | case "Delay" :
39 | Delay = int.Parse(current.InnerText);
40 | break;
41 | }
42 | }
43 | }
44 |
45 | ///
46 | /// Serialises this object to an XML string for saving.
47 | ///
48 | ///
49 | public override string ToXml()
50 | {
51 | StringBuilder str = new StringBuilder();
52 | str.AppendLine("");
53 | str.AppendLine("" + Delay.ToString() + "");
54 | str.AppendLine("");
55 |
56 | return str.ToString();
57 | }
58 |
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Silence.Macro
7 | {
8 |
9 | ///
10 | /// Represents an event that occurs during macro recording.
11 | ///
12 | public abstract class MacroEvent
13 | {
14 |
15 | ///
16 | /// Returns a representation of this object as an XML string.
17 | ///
18 | ///
19 | public abstract string ToXml();
20 |
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroKeyDownEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Xml;
6 |
7 | namespace Silence.Macro
8 | {
9 |
10 | ///
11 | /// Represents a key down event that occurs during macro recording.
12 | ///
13 | public class MacroKeyDownEvent : MacroKeyEvent
14 | {
15 |
16 | ///
17 | /// Initialises a new instance of a macro key down event.
18 | ///
19 | /// The virtual key code associated with the event.
20 | public MacroKeyDownEvent(int virtualKeyCode)
21 | : base(virtualKeyCode)
22 | {
23 | // Straight to superclass constructor.
24 | }
25 |
26 | ///
27 | /// Initialises a new instance of a macro key down event.
28 | ///
29 | /// The serialised XML element to initialise from.
30 | public MacroKeyDownEvent(XmlElement element)
31 | : base(0)
32 | {
33 | foreach (XmlElement current in element)
34 | {
35 | switch (current.Name)
36 | {
37 | case "VirtualKeyCode" :
38 | VirtualKeyCode = int.Parse(current.InnerText);
39 | break;
40 | }
41 | }
42 | }
43 |
44 | ///
45 | /// Serialises this object to an XML string for saving.
46 | ///
47 | ///
48 | public override string ToXml()
49 | {
50 | StringBuilder str = new StringBuilder();
51 | str.AppendLine("");
52 | str.AppendLine("" + VirtualKeyCode.ToString() + "");
53 | str.AppendLine("");
54 |
55 | return str.ToString();
56 | }
57 |
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroKeyEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Silence.Macro
7 | {
8 | ///
9 | /// Represents a keyboard event that occurs during macro recording.
10 | ///
11 | public abstract class MacroKeyEvent : MacroEvent
12 | {
13 | ///
14 | /// Gets or sets the virtual key code associated with the event.
15 | ///
16 | public int VirtualKeyCode { get; set; }
17 |
18 | ///
19 | /// Initialises a new instance of a macro key event.
20 | ///
21 | /// The virtual key code associated with the event.
22 | protected MacroKeyEvent(int virtualKeyCode)
23 | {
24 | VirtualKeyCode = virtualKeyCode;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroKeyUpEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Xml;
6 |
7 | namespace Silence.Macro
8 | {
9 |
10 | ///
11 | /// Represents a key up event that occurs during macro recording.
12 | ///
13 | public class MacroKeyUpEvent : MacroKeyEvent
14 | {
15 |
16 | ///
17 | /// Initialises a new instance of a macro key up event.
18 | ///
19 | /// The virtual key code associated with the event.
20 | public MacroKeyUpEvent(int virtualKeyCode)
21 | : base(virtualKeyCode)
22 | {
23 | // Straight to superclass constructor.
24 | }
25 |
26 | ///
27 | /// Initialises a new instance of a macro key up event.
28 | ///
29 | /// The serialised XML element to initialise from.
30 | public MacroKeyUpEvent(XmlElement element)
31 | : base(0)
32 | {
33 | foreach (XmlElement current in element)
34 | {
35 | switch (current.Name)
36 | {
37 | case "VirtualKeyCode":
38 | VirtualKeyCode = int.Parse(current.InnerText);
39 | break;
40 | }
41 | }
42 | }
43 |
44 | ///
45 | /// Serialises this object to an XML string for saving.
46 | ///
47 | ///
48 | public override string ToXml()
49 | {
50 | StringBuilder str = new StringBuilder();
51 | str.AppendLine("");
52 | str.AppendLine("" + VirtualKeyCode.ToString() + "");
53 | str.AppendLine("");
54 |
55 | return str.ToString();
56 | }
57 |
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroMouseDownEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Windows.Input;
7 | using System.Xml;
8 |
9 | namespace Silence.Macro
10 | {
11 |
12 | ///
13 | /// Represents a mouse button down event that occurs during macro recording.
14 | ///
15 | class MacroMouseDownEvent : MacroMouseEvent
16 | {
17 |
18 | ///
19 | /// Gets or sets the mouse button associated with the event.
20 | ///
21 | public MouseButton Button { get; set; }
22 |
23 | ///
24 | /// Initialises a new instance of a macro mouse down event.
25 | ///
26 | /// The screen coordinates at which this event occurred.
27 | /// The mouse button associated with the event.
28 | public MacroMouseDownEvent(Point location, MouseButton button)
29 | : base(location)
30 | {
31 | Button = button;
32 | }
33 |
34 | ///
35 | /// Initialises a new instance of a macro mouse down event.
36 | ///
37 | /// The serialised XML element to initialise from.
38 | public MacroMouseDownEvent(XmlElement element)
39 | : base(new Point(0, 0))
40 | {
41 | foreach (XmlElement current in element)
42 | {
43 | switch (current.Name)
44 | {
45 | case "Location":
46 | Location = Point.Parse(current.InnerText);
47 | break;
48 | case "Button":
49 | Button = (MouseButton)Enum.Parse(typeof(MouseButton), current.InnerText);
50 | break;
51 | }
52 | }
53 | }
54 |
55 | ///
56 | /// Serialises this object to an XML string for saving.
57 | ///
58 | ///
59 | public override string ToXml()
60 | {
61 | StringBuilder str = new StringBuilder();
62 | str.AppendLine("");
63 | str.AppendLine("" + Location.ToString() + "");
64 | str.AppendLine("");
65 | str.AppendLine("");
66 |
67 | return str.ToString();
68 | }
69 |
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroMouseEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 |
7 | namespace Silence.Macro
8 | {
9 |
10 | ///
11 | /// Represents a mouse event that occurs during recording of a macro.
12 | ///
13 | public abstract class MacroMouseEvent : MacroEvent
14 | {
15 |
16 | ///
17 | /// Gets or sets the screen coordinates at which this event occurred.
18 | ///
19 | public Point Location { get; set; }
20 |
21 | ///
22 | /// Initialises a new instance of a macro mouse event.
23 | ///
24 | /// The screen coordinates at which the event occured.
25 | public MacroMouseEvent(Point location)
26 | {
27 | Location = location;
28 | }
29 |
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroMouseMoveEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Xml;
7 |
8 | namespace Silence.Macro
9 | {
10 |
11 | ///
12 | /// Represents a mouse move event that occurs during macro recording.
13 | ///
14 | class MacroMouseMoveEvent : MacroMouseEvent
15 | {
16 |
17 | ///
18 | /// Initialises a new instance of a mouse move event.
19 | ///
20 | /// The screen coordinates at which this event occurred.
21 | public MacroMouseMoveEvent(Point location) : base(location)
22 | {
23 | // Straight to superclass constructor.
24 | }
25 |
26 | ///
27 | /// Initialises a new instance of a macro mouse move event.
28 | ///
29 | /// The serialised XML element to initialise from.
30 | public MacroMouseMoveEvent(XmlElement element)
31 | : base(new Point(0, 0))
32 | {
33 | foreach (XmlElement current in element)
34 | {
35 | switch (current.Name)
36 | {
37 | case "Location" :
38 | Location = Point.Parse(current.InnerText);
39 | break;
40 | }
41 | }
42 | }
43 |
44 | ///
45 | /// Serialises this object to an XML string for saving.
46 | ///
47 | ///
48 | public override string ToXml()
49 | {
50 | StringBuilder str = new StringBuilder();
51 | str.AppendLine("");
52 | str.AppendLine("" + Location.ToString() + "");
53 | str.AppendLine("");
54 |
55 | return str.ToString();
56 | }
57 |
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroMouseUpEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Windows.Input;
7 | using System.Xml;
8 |
9 | namespace Silence.Macro
10 | {
11 |
12 | ///
13 | /// Represents a mouse button up event that occurs during macro recording.
14 | ///
15 | class MacroMouseUpEvent : MacroMouseEvent
16 | {
17 |
18 | ///
19 | /// Gets or sets the mouse button associated with the event.
20 | ///
21 | public MouseButton Button { get; set; }
22 |
23 | ///
24 | /// Initialises a new instance of a macro mouse up event.
25 | ///
26 | /// The screen coordinates at which this event occurred.
27 | /// The mouse button associated with the event.
28 | public MacroMouseUpEvent(Point location, MouseButton button)
29 | : base(location)
30 | {
31 | Button = button;
32 | }
33 |
34 | ///
35 | /// Initialises a new instance of a macro mouse up event.
36 | ///
37 | /// The serialised XML element to initialise from.
38 | public MacroMouseUpEvent(XmlElement element)
39 | : base(new Point(0, 0))
40 | {
41 | foreach (XmlElement current in element)
42 | {
43 | switch (current.Name)
44 | {
45 | case "Location" :
46 | Location = Point.Parse(current.InnerText);
47 | break;
48 | case "Button" :
49 | Button = (MouseButton) Enum.Parse(typeof(MouseButton), current.InnerText);
50 | break;
51 | }
52 | }
53 | }
54 |
55 | ///
56 | /// Serialises this object to an XML string for saving.
57 | ///
58 | ///
59 | public override string ToXml()
60 | {
61 | StringBuilder str = new StringBuilder();
62 | str.AppendLine("");
63 | str.AppendLine("" + Location.ToString() + "");
64 | str.AppendLine("");
65 | str.AppendLine("");
66 |
67 | return str.ToString();
68 | }
69 |
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroMouseWheelEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Xml;
7 |
8 | namespace Silence.Macro
9 | {
10 |
11 | ///
12 | /// Represents a mouse wheel event that occurs during macro recording.
13 | ///
14 | class MacroMouseWheelEvent : MacroMouseEvent
15 | {
16 |
17 | ///
18 | /// Gets or sets the delta value of the wheel rotation.
19 | ///
20 | public int Delta { get; set; }
21 |
22 | ///
23 | /// Initialises a new instance of a mouse wheel event.
24 | ///
25 | /// The screen coordinates at which this event occurred.
26 | /// The delta value of the wheel rotation.
27 | public MacroMouseWheelEvent(Point location, int delta) : base(location)
28 | {
29 | Delta = delta;
30 | }
31 |
32 | ///
33 | /// Initialises a new instance of a mouse wheel event.
34 | ///
35 | /// The serialised XML element to initialise from.
36 | public MacroMouseWheelEvent(XmlElement element)
37 | : base(new Point(0, 0))
38 | {
39 | foreach(XmlElement current in element)
40 | {
41 | switch (current.Name)
42 | {
43 | case "Location" :
44 | Location = Point.Parse(current.InnerText);
45 | break;
46 | case "Delta" :
47 | Delta = int.Parse(current.InnerText);
48 | break;
49 | }
50 | }
51 | }
52 |
53 | ///
54 | /// Serialises this object to an XML string for saving.
55 | ///
56 | ///
57 | public override string ToXml()
58 | {
59 | StringBuilder str = new StringBuilder();
60 | str.AppendLine("");
61 | str.AppendLine("" + Location.ToString() + "");
62 | str.AppendLine("" + Delta.ToString() + "");
63 | str.AppendLine("");
64 |
65 | return str.ToString();
66 | }
67 |
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroPlayer.cs:
--------------------------------------------------------------------------------
1 | using Silence.Simulation;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Windows;
8 | using System.Windows.Forms;
9 |
10 | namespace Silence.Macro
11 | {
12 |
13 | ///
14 | /// Provides support for playback of recorded macros.
15 | ///
16 | public class MacroPlayer
17 | {
18 |
19 | ///
20 | /// Holds the mouse simulator that underlies this object.
21 | ///
22 | private MouseSimulator underlyingMouseSimulator;
23 |
24 | ///
25 | /// Holds the keyboard simulator that underlies this object.
26 | ///
27 | private KeyboardSimulator underlyingKeyboardSimulator;
28 |
29 | ///
30 | /// Holds the thread that the macro is currently executing on.
31 | ///
32 | private Thread macroThread;
33 |
34 | ///
35 | /// Holds whether or not the macro has been cancelled.
36 | ///
37 | private bool cancelled;
38 |
39 | ///
40 | /// Holds the number of times the macro should repeat before ending.
41 | ///
42 | private int repetitions;
43 |
44 | ///
45 | /// Gets the macro currently loaded into the player.
46 | ///
47 | public Macro CurrentMacro { get; private set; }
48 |
49 | ///
50 | /// Gets or sets the number of times the macro should repeat before ending.
51 | ///
52 | public int Repetitions {
53 | get
54 | {
55 | return repetitions;
56 | }
57 | set
58 | {
59 | repetitions = (value == 0 ? 1 : value);
60 | }
61 | }
62 |
63 | ///
64 | /// Gets whether or not a macro is currently being played.
65 | ///
66 | public bool IsPlaying { get; private set; }
67 |
68 | ///
69 | /// Initialies a new instance of a macro player.
70 | ///
71 | public MacroPlayer()
72 | {
73 | underlyingMouseSimulator = new MouseSimulator(new InputSimulator());
74 | underlyingKeyboardSimulator = new KeyboardSimulator(new InputSimulator());
75 | repetitions = 1;
76 | cancelled = false;
77 | }
78 |
79 | ///
80 | /// Cancels playback of the current macro.
81 | ///
82 | public void CancelPlayback()
83 | {
84 | cancelled = IsPlaying;
85 | }
86 |
87 | ///
88 | /// Loads a macro into the player.
89 | ///
90 | /// The macro to load into the player.
91 | public void LoadMacro(Macro macro)
92 | {
93 | CurrentMacro = macro;
94 | }
95 |
96 | ///
97 | /// Converts a point to absolute screen coordinates.
98 | ///
99 | /// The point to convert.
100 | ///
101 | private Point ConvertPointToAbsolute(Point point)
102 | {
103 | return new Point((Convert.ToDouble(65535) * point.X) / Convert.ToDouble(Screen.PrimaryScreen.Bounds.Width),
104 | (Convert.ToDouble(65535) * point.Y) / Convert.ToDouble(Screen.PrimaryScreen.Bounds.Height));
105 | }
106 |
107 | ///
108 | /// Plays the macro on the current thread.
109 | ///
110 | private void PlayMacro()
111 | {
112 | IsPlaying = true;
113 |
114 | // Repeat macro as required.
115 | for (int i = 0; i < Repetitions; i++)
116 | {
117 | // Loop through each macro event.
118 | foreach (MacroEvent current in CurrentMacro.Events)
119 | {
120 | // Cancel playback.
121 | if (cancelled)
122 | {
123 | cancelled = false;
124 | i = Repetitions;
125 | break;
126 | }
127 |
128 | // Cast event to appropriate type.
129 | if(current is MacroDelayEvent)
130 | {
131 | // Delay event.
132 | MacroDelayEvent castEvent = (MacroDelayEvent)current;
133 | Thread.Sleep(new TimeSpan(castEvent.Delay));
134 | }
135 | else if (current is MacroMouseMoveEvent)
136 | {
137 | // Mouse move event.
138 | MacroMouseMoveEvent castEvent = (MacroMouseMoveEvent)current;
139 | Point absolutePoint = ConvertPointToAbsolute(castEvent.Location);
140 | underlyingMouseSimulator.MoveMouseTo(absolutePoint.X, absolutePoint.Y);
141 | }
142 | else if (current is MacroMouseDownEvent)
143 | {
144 | // Mouse down event.
145 | MacroMouseDownEvent castEvent = (MacroMouseDownEvent)current;
146 | Point absolutePoint = ConvertPointToAbsolute(castEvent.Location);
147 | underlyingMouseSimulator.MoveMouseTo(absolutePoint.X, absolutePoint.Y);
148 | if (castEvent.Button == System.Windows.Input.MouseButton.Left)
149 | {
150 | underlyingMouseSimulator.LeftButtonDown();
151 | }
152 | else if (castEvent.Button == System.Windows.Input.MouseButton.Right)
153 | {
154 | underlyingMouseSimulator.RightButtonDown();
155 | }
156 | }
157 | else if (current is MacroMouseUpEvent)
158 | {
159 | // Mouse up event.
160 | MacroMouseUpEvent castEvent = (MacroMouseUpEvent)current;
161 | Point absolutePoint = ConvertPointToAbsolute(castEvent.Location);
162 | underlyingMouseSimulator.MoveMouseTo(absolutePoint.X, absolutePoint.Y);
163 | if (castEvent.Button == System.Windows.Input.MouseButton.Left)
164 | {
165 | underlyingMouseSimulator.LeftButtonUp();
166 | }
167 | else if (castEvent.Button == System.Windows.Input.MouseButton.Right)
168 | {
169 | underlyingMouseSimulator.RightButtonUp();
170 | }
171 | }
172 | else if (current is MacroKeyDownEvent)
173 | {
174 | // Key down event.
175 | MacroKeyDownEvent castEvent = (MacroKeyDownEvent)current;
176 | underlyingKeyboardSimulator.KeyDown((Simulation.Native.VirtualKeyCode)castEvent.VirtualKeyCode);
177 | }
178 | else if (current is MacroKeyUpEvent)
179 | {
180 | // Key up event.
181 | MacroKeyUpEvent castEvent = (MacroKeyUpEvent)current;
182 | underlyingKeyboardSimulator.KeyUp((Simulation.Native.VirtualKeyCode)castEvent.VirtualKeyCode);
183 | }
184 | else if (current is MacroMouseWheelEvent)
185 | {
186 | // Mouse wheel event.
187 | MacroMouseWheelEvent castEvent = (MacroMouseWheelEvent)current;
188 | Point absolutePoint = ConvertPointToAbsolute(castEvent.Location);
189 | underlyingMouseSimulator.MoveMouseTo(absolutePoint.X, absolutePoint.Y);
190 | underlyingMouseSimulator.VerticalScroll(castEvent.Delta / 120);
191 | }
192 |
193 | }
194 | }
195 |
196 | IsPlaying = false;
197 | }
198 |
199 | ///
200 | /// Plays the macro on a seperate background thread.
201 | ///
202 | public void PlayMacroAsync()
203 | {
204 | macroThread = new Thread(PlayMacro);
205 | macroThread.Start();
206 | }
207 |
208 | }
209 |
210 | }
211 |
--------------------------------------------------------------------------------
/Silence.Macro/MacroRecorder.cs:
--------------------------------------------------------------------------------
1 | using Silence.Hooking.Windows;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace Silence.Macro
8 | {
9 |
10 | ///
11 | /// Allows recording sequences of mouse and keyboard events using global input hooks.
12 | ///
13 | public class MacroRecorder : IDisposable
14 | {
15 |
16 | ///
17 | /// Holds the underlying mouse/keyboard hook.
18 | ///
19 | private HookManager underlyingHook;
20 |
21 | ///
22 | /// Holds the time in ticks that the last event occurred.
23 | ///
24 | private long lastEventTime;
25 |
26 | ///
27 | /// Gets the macro currently being recorded.
28 | ///
29 | public Macro CurrentMacro { get; private set; }
30 |
31 | ///
32 | /// Gets whether or not the macro recorder is currently running.
33 | ///
34 | public bool IsRunning { get; private set; }
35 |
36 | ///
37 | /// Initialises a new instance of a macro recorder.
38 | ///
39 | public MacroRecorder()
40 | {
41 | underlyingHook = new HookManager();
42 |
43 | underlyingHook.KeyDown += underlyingHook_KeyDown;
44 | underlyingHook.KeyUp += underlyingHook_KeyUp;
45 | underlyingHook.MouseDown += underlyingHook_MouseDown;
46 | underlyingHook.MouseUp += underlyingHook_MouseUp;
47 | underlyingHook.MouseMove += underlyingHook_MouseMove;
48 | underlyingHook.MouseWheel += underlyingHook_MouseWheel;
49 | }
50 |
51 | ///
52 | /// Releases all resources associated with this object.
53 | ///
54 | public void Dispose()
55 | {
56 | underlyingHook.Dispose();
57 | }
58 |
59 | ///
60 | /// Adds a delay event to the current macro representing the time in ticks since this method was last called.
61 | ///
62 | private void AddDelayEvent()
63 | {
64 | long timeNow = DateTime.Now.Ticks;
65 | CurrentMacro.AddEvent(new MacroDelayEvent(timeNow - lastEventTime));
66 | lastEventTime = timeNow;
67 | }
68 |
69 | ///
70 | /// Loads a macro into the macro recorder.
71 | ///
72 | /// The macro to load.
73 | public void LoadMacro(Macro macro)
74 | {
75 | CurrentMacro = macro;
76 | }
77 |
78 | ///
79 | /// Clears the current macro from the macro recorder.
80 | ///
81 | public void Clear()
82 | {
83 | CurrentMacro = new Macro();
84 | }
85 |
86 | ///
87 | /// Starts recording mouse and keyboard events.
88 | ///
89 | public void StartRecording()
90 | {
91 | if (CurrentMacro == null)
92 | {
93 | Clear();
94 | }
95 | lastEventTime = DateTime.Now.Ticks;
96 | IsRunning = true;
97 | }
98 |
99 | ///
100 | /// Stops recording mouse and keyboard events.
101 | ///
102 | public void StopRecording()
103 | {
104 | IsRunning = false;
105 | }
106 |
107 | private void underlyingHook_KeyDown(object sender, Silence.Hooking.GlobalKeyEventHandlerArgs e)
108 | {
109 |
110 | if (IsRunning)
111 | {
112 | AddDelayEvent();
113 | CurrentMacro.AddEvent(new MacroKeyDownEvent(e.VirtualKeyCode));
114 | }
115 | }
116 |
117 | private void underlyingHook_KeyUp(object sender, Silence.Hooking.GlobalKeyEventHandlerArgs e)
118 | {
119 | if (IsRunning)
120 | {
121 | AddDelayEvent();
122 | CurrentMacro.AddEvent(new MacroKeyUpEvent(e.VirtualKeyCode));
123 | }
124 | }
125 |
126 | private void underlyingHook_MouseDown(object sender, Silence.Hooking.GlobalMouseEventHandlerArgs e)
127 | {
128 | if (IsRunning)
129 | {
130 | AddDelayEvent();
131 | CurrentMacro.AddEvent(new MacroMouseDownEvent(e.Point, e.Button));
132 | }
133 | }
134 |
135 | private void underlyingHook_MouseUp(object sender, Silence.Hooking.GlobalMouseEventHandlerArgs e)
136 | {
137 | if (IsRunning)
138 | {
139 | AddDelayEvent();
140 | CurrentMacro.AddEvent(new MacroMouseUpEvent(e.Point, e.Button));
141 | }
142 | }
143 |
144 | private void underlyingHook_MouseMove(object sender, Silence.Hooking.GlobalMouseEventHandlerArgs e)
145 | {
146 | if (IsRunning)
147 | {
148 | AddDelayEvent();
149 | CurrentMacro.AddEvent(new MacroMouseMoveEvent(e.Point));
150 | }
151 | }
152 |
153 | private void underlyingHook_MouseWheel(object sender, Silence.Hooking.GlobalMouseEventHandlerArgs e)
154 | {
155 | if (IsRunning)
156 | {
157 | AddDelayEvent();
158 | CurrentMacro.AddEvent(new MacroMouseWheelEvent(e.Point, e.Delta));
159 | }
160 | }
161 |
162 | }
163 |
164 | }
165 |
--------------------------------------------------------------------------------
/Silence.Macro/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Silence.Macro")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Silence.Macro")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("63b186aa-962c-4a5f-90ee-268bbb5377f2")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Silence.Macro/Silence.Macro.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {63B186AA-962C-4A5F-90EE-268BBB5377F2}
8 | Library
9 | Properties
10 | Silence.Macro
11 | Silence.Macro
12 | v4.8
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | {8897b3b9-fafe-4dd7-81b5-611008cb6437}
66 | Silence.Hooking
67 |
68 |
69 | {ce200217-b899-4ca8-833a-7dcad1b6f7d9}
70 | Silence.Simulation
71 |
72 |
73 |
74 |
81 |
--------------------------------------------------------------------------------
/Silence.Simulation/IInputDeviceStateAdaptor.cs:
--------------------------------------------------------------------------------
1 | using Silence.Simulation.Native;
2 |
3 | namespace Silence.Simulation
4 | {
5 | ///
6 | /// The contract for a service that interprets the state of input devices.
7 | ///
8 | public interface IInputDeviceStateAdaptor
9 | {
10 | ///
11 | /// Determines whether the specified key is up or down.
12 | ///
13 | /// The for the key.
14 | ///
15 | /// true if the key is down; otherwise, false.
16 | ///
17 | bool IsKeyDown(VirtualKeyCode keyCode);
18 |
19 | ///
20 | /// Determines whether the specified key is up or down.
21 | ///
22 | /// The for the key.
23 | ///
24 | /// true if the key is up; otherwise, false.
25 | ///
26 | bool IsKeyUp(VirtualKeyCode keyCode);
27 |
28 | ///
29 | /// Determines whether the physical key is up or down at the time the function is called regardless of whether the application thread has read the keyboard event from the message pump.
30 | ///
31 | /// The for the key.
32 | ///
33 | /// true if the key is down; otherwise, false.
34 | ///
35 | bool IsHardwareKeyDown(VirtualKeyCode keyCode);
36 |
37 | ///
38 | /// Determines whether the physical key is up or down at the time the function is called regardless of whether the application thread has read the keyboard event from the message pump.
39 | ///
40 | /// The for the key.
41 | ///
42 | /// true if the key is up; otherwise, false.
43 | ///
44 | bool IsHardwareKeyUp(VirtualKeyCode keyCode);
45 |
46 | ///
47 | /// Determines whether the toggling key is toggled on (in-effect) or not.
48 | ///
49 | /// The for the key.
50 | ///
51 | /// true if the toggling key is toggled on (in-effect); otherwise, false.
52 | ///
53 | bool IsTogglingKeyInEffect(VirtualKeyCode keyCode);
54 | }
55 | }
--------------------------------------------------------------------------------
/Silence.Simulation/IInputMessageDispatcher.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Silence.Simulation.Native;
3 |
4 | namespace Silence.Simulation
5 | {
6 | ///
7 | /// The contract for a service that dispatches messages to the appropriate destination.
8 | ///
9 | internal interface IInputMessageDispatcher
10 | {
11 | ///
12 | /// Dispatches the specified list of messages in their specified order.
13 | ///
14 | /// The list of messages to be dispatched.
15 | /// If the array is empty.
16 | /// If the array is null.
17 | /// If the any of the commands in the array could not be sent successfully.
18 | void DispatchInput(INPUT[] inputs);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Silence.Simulation/IInputSimulator.cs:
--------------------------------------------------------------------------------
1 | namespace Silence.Simulation
2 | {
3 | ///
4 | /// The contract for a service that simulates Keyboard and Mouse input and Hardware Input Device state detection for the Windows Platform.
5 | ///
6 | public interface IInputSimulator
7 | {
8 | ///
9 | /// Gets the instance for simulating Keyboard input.
10 | ///
11 | /// The instance.
12 | IKeyboardSimulator Keyboard { get; }
13 |
14 | ///
15 | /// Gets the instance for simulating Mouse input.
16 | ///
17 | /// The instance.
18 | IMouseSimulator Mouse { get; }
19 |
20 | ///
21 | /// Gets the instance for determining the state of the various input devices.
22 | ///
23 | /// The instance.
24 | IInputDeviceStateAdaptor InputDeviceState { get; }
25 | }
26 | }
--------------------------------------------------------------------------------
/Silence.Simulation/IKeyboardSimulator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Silence.Simulation.Native;
4 |
5 | namespace Silence.Simulation
6 | {
7 | ///
8 | /// The service contract for a keyboard simulator for the Windows platform.
9 | ///
10 | public interface IKeyboardSimulator
11 | {
12 | ///
13 | /// Gets the instance for simulating Mouse input.
14 | ///
15 | /// The instance.
16 | IMouseSimulator Mouse { get; }
17 |
18 | ///
19 | /// Simulates the key down gesture for the specified key.
20 | ///
21 | /// The for the key.
22 | IKeyboardSimulator KeyDown(VirtualKeyCode keyCode);
23 |
24 | ///
25 | /// Simulates the key press gesture for the specified key.
26 | ///
27 | /// The for the key.
28 | IKeyboardSimulator KeyPress(VirtualKeyCode keyCode);
29 |
30 | ///
31 | /// Simulates a key press for each of the specified key codes in the order they are specified.
32 | ///
33 | ///
34 | IKeyboardSimulator KeyPress(params VirtualKeyCode[] keyCodes);
35 |
36 | ///
37 | /// Simulates the key up gesture for the specified key.
38 | ///
39 | /// The for the key.
40 | IKeyboardSimulator KeyUp(VirtualKeyCode keyCode);
41 |
42 | ///
43 | /// Simulates a modified keystroke where there are multiple modifiers and multiple keys like CTRL-ALT-K-C where CTRL and ALT are the modifierKeys and K and C are the keys.
44 | /// The flow is Modifiers KeyDown in order, Keys Press in order, Modifiers KeyUp in reverse order.
45 | ///
46 | /// The list of s for the modifier keys.
47 | /// The list of s for the keys to simulate.
48 | IKeyboardSimulator ModifiedKeyStroke(IEnumerable modifierKeyCodes, IEnumerable keyCodes);
49 |
50 | ///
51 | /// Simulates a modified keystroke where there are multiple modifiers and one key like CTRL-ALT-C where CTRL and ALT are the modifierKeys and C is the key.
52 | /// The flow is Modifiers KeyDown in order, Key Press, Modifiers KeyUp in reverse order.
53 | ///
54 | /// The list of s for the modifier keys.
55 | /// The for the key.
56 | IKeyboardSimulator ModifiedKeyStroke(IEnumerable modifierKeyCodes, VirtualKeyCode keyCode);
57 |
58 | ///
59 | /// Simulates a modified keystroke where there is one modifier and multiple keys like CTRL-K-C where CTRL is the modifierKey and K and C are the keys.
60 | /// The flow is Modifier KeyDown, Keys Press in order, Modifier KeyUp.
61 | ///
62 | /// The for the modifier key.
63 | /// The list of s for the keys to simulate.
64 | IKeyboardSimulator ModifiedKeyStroke(VirtualKeyCode modifierKey, IEnumerable keyCodes);
65 |
66 | ///
67 | /// Simulates a simple modified keystroke like CTRL-C where CTRL is the modifierKey and C is the key.
68 | /// The flow is Modifier KeyDown, Key Press, Modifier KeyUp.
69 | ///
70 | /// The for the modifier key.
71 | /// The for the key.
72 | IKeyboardSimulator ModifiedKeyStroke(VirtualKeyCode modifierKeyCode, VirtualKeyCode keyCode);
73 |
74 | ///
75 | /// Simulates uninterrupted text entry via the keyboard.
76 | ///
77 | /// The text to be simulated.
78 | IKeyboardSimulator TextEntry(string text);
79 |
80 | ///
81 | /// Simulates a single character text entry via the keyboard.
82 | ///
83 | /// The unicode character to be simulated.
84 | IKeyboardSimulator TextEntry(char character);
85 |
86 | ///
87 | /// Sleeps the executing thread to create a pause between simulated inputs.
88 | ///
89 | /// The number of milliseconds to wait.
90 | IKeyboardSimulator Sleep(int millsecondsTimeout);
91 |
92 | ///
93 | /// Sleeps the executing thread to create a pause between simulated inputs.
94 | ///
95 | /// The time to wait.
96 | IKeyboardSimulator Sleep(TimeSpan timeout);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/Silence.Simulation/IMouseSimulator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Simulation
4 | {
5 | ///
6 | /// The service contract for a mouse simulator for the Windows platform.
7 | ///
8 | public interface IMouseSimulator
9 | {
10 | ///
11 | /// Gets the instance for simulating Keyboard input.
12 | ///
13 | /// The instance.
14 | IKeyboardSimulator Keyboard { get; }
15 |
16 | ///
17 | /// Simulates mouse movement by the specified distance measured as a delta from the current mouse location in pixels.
18 | ///
19 | /// The distance in pixels to move the mouse horizontally.
20 | /// The distance in pixels to move the mouse vertically.
21 | IMouseSimulator MoveMouseBy(int pixelDeltaX, int pixelDeltaY);
22 |
23 | ///
24 | /// Simulates mouse movement to the specified location on the primary display device.
25 | ///
26 | /// The destination's absolute X-coordinate on the primary display device where 0 is the extreme left hand side of the display device and 65535 is the extreme right hand side of the display device.
27 | /// The destination's absolute Y-coordinate on the primary display device where 0 is the top of the display device and 65535 is the bottom of the display device.
28 | IMouseSimulator MoveMouseTo(double absoluteX, double absoluteY);
29 |
30 | ///
31 | /// Simulates mouse movement to the specified location on the Virtual Desktop which includes all active displays.
32 | ///
33 | /// The destination's absolute X-coordinate on the virtual desktop where 0 is the left hand side of the virtual desktop and 65535 is the extreme right hand side of the virtual desktop.
34 | /// The destination's absolute Y-coordinate on the virtual desktop where 0 is the top of the virtual desktop and 65535 is the bottom of the virtual desktop.
35 | IMouseSimulator MoveMouseToPositionOnVirtualDesktop(double absoluteX, double absoluteY);
36 |
37 | ///
38 | /// Simulates a mouse left button down gesture.
39 | ///
40 | IMouseSimulator LeftButtonDown();
41 |
42 | ///
43 | /// Simulates a mouse left button up gesture.
44 | ///
45 | IMouseSimulator LeftButtonUp();
46 |
47 | ///
48 | /// Simulates a mouse left button click gesture.
49 | ///
50 | IMouseSimulator LeftButtonClick();
51 |
52 | ///
53 | /// Simulates a mouse left button double-click gesture.
54 | ///
55 | IMouseSimulator LeftButtonDoubleClick();
56 |
57 | ///
58 | /// Simulates a mouse right button down gesture.
59 | ///
60 | IMouseSimulator RightButtonDown();
61 |
62 | ///
63 | /// Simulates a mouse right button up gesture.
64 | ///
65 | IMouseSimulator RightButtonUp();
66 |
67 | ///
68 | /// Simulates a mouse right button click gesture.
69 | ///
70 | IMouseSimulator RightButtonClick();
71 |
72 | ///
73 | /// Simulates a mouse right button double-click gesture.
74 | ///
75 | IMouseSimulator RightButtonDoubleClick();
76 |
77 | ///
78 | /// Simulates a mouse X button down gesture.
79 | ///
80 | /// The button id.
81 | IMouseSimulator XButtonDown(int buttonId);
82 |
83 | ///
84 | /// Simulates a mouse X button up gesture.
85 | ///
86 | /// The button id.
87 | IMouseSimulator XButtonUp(int buttonId);
88 |
89 | ///
90 | /// Simulates a mouse X button click gesture.
91 | ///
92 | /// The button id.
93 | IMouseSimulator XButtonClick(int buttonId);
94 |
95 | ///
96 | /// Simulates a mouse X button double-click gesture.
97 | ///
98 | /// The button id.
99 | IMouseSimulator XButtonDoubleClick(int buttonId);
100 |
101 | ///
102 | /// Simulates mouse vertical wheel scroll gesture.
103 | ///
104 | /// The amount to scroll in clicks. A positive value indicates that the wheel was rotated forward, away from the user; a negative value indicates that the wheel was rotated backward, toward the user.
105 | IMouseSimulator VerticalScroll(int scrollAmountInClicks);
106 |
107 | ///
108 | /// Simulates a mouse horizontal wheel scroll gesture. Supported by Windows Vista and later.
109 | ///
110 | /// The amount to scroll in clicks. A positive value indicates that the wheel was rotated to the right; a negative value indicates that the wheel was rotated to the left.
111 | IMouseSimulator HorizontalScroll(int scrollAmountInClicks);
112 |
113 | ///
114 | /// Sleeps the executing thread to create a pause between simulated inputs.
115 | ///
116 | /// The number of milliseconds to wait.
117 | IMouseSimulator Sleep(int millsecondsTimeout);
118 |
119 | ///
120 | /// Sleeps the executing thread to create a pause between simulated inputs.
121 | ///
122 | /// The time to wait.
123 | IMouseSimulator Sleep(TimeSpan timeout);
124 | }
125 | }
--------------------------------------------------------------------------------
/Silence.Simulation/InputSimulator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Simulation
4 | {
5 | ///
6 | /// Implements the interface to simulate Keyboard and Mouse input and provide the state of those input devices.
7 | ///
8 | public class InputSimulator : IInputSimulator
9 | {
10 | ///
11 | /// The instance to use for simulating keyboard input.
12 | ///
13 | private readonly IKeyboardSimulator _keyboardSimulator;
14 |
15 | ///
16 | /// The instance to use for simulating mouse input.
17 | ///
18 | private readonly IMouseSimulator _mouseSimulator;
19 |
20 | ///
21 | /// The instance to use for interpreting the state of the input devices.
22 | ///
23 | private readonly IInputDeviceStateAdaptor _inputDeviceState;
24 |
25 | ///
26 | /// Initializes a new instance of the class using the specified , and instances.
27 | ///
28 | /// The instance to use for simulating keyboard input.
29 | /// The instance to use for simulating mouse input.
30 | /// The instance to use for interpreting the state of input devices.
31 | public InputSimulator(IKeyboardSimulator keyboardSimulator, IMouseSimulator mouseSimulator, IInputDeviceStateAdaptor inputDeviceStateAdaptor)
32 | {
33 | _keyboardSimulator = keyboardSimulator;
34 | _mouseSimulator = mouseSimulator;
35 | _inputDeviceState = inputDeviceStateAdaptor;
36 | }
37 |
38 | ///
39 | /// Initializes a new instance of the class using the default , and instances.
40 | ///
41 | public InputSimulator()
42 | {
43 | _keyboardSimulator = new KeyboardSimulator(this);
44 | _mouseSimulator = new MouseSimulator(this);
45 | _inputDeviceState = new WindowsInputDeviceStateAdaptor();
46 | }
47 |
48 | ///
49 | /// Gets the instance for simulating Keyboard input.
50 | ///
51 | /// The instance.
52 | public IKeyboardSimulator Keyboard
53 | {
54 | get { return _keyboardSimulator; }
55 | }
56 |
57 | ///
58 | /// Gets the instance for simulating Mouse input.
59 | ///
60 | /// The instance.
61 | public IMouseSimulator Mouse
62 | {
63 | get { return _mouseSimulator; }
64 | }
65 |
66 | ///
67 | /// Gets the instance for determining the state of the various input devices.
68 | ///
69 | /// The instance.
70 | public IInputDeviceStateAdaptor InputDeviceState
71 | {
72 | get { return _inputDeviceState; }
73 | }
74 | }
75 | }
--------------------------------------------------------------------------------
/Silence.Simulation/KeyboardSimulator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using Silence.Simulation.Native;
5 |
6 | namespace Silence.Simulation
7 | {
8 | ///
9 | /// Implements the interface by calling the an to simulate Keyboard gestures.
10 | ///
11 | public class KeyboardSimulator : IKeyboardSimulator
12 | {
13 | private readonly IInputSimulator _inputSimulator;
14 |
15 | ///
16 | /// The instance of the to use for dispatching messages.
17 | ///
18 | private readonly IInputMessageDispatcher _messageDispatcher;
19 |
20 | ///
21 | /// Initializes a new instance of the class using an instance of a for dispatching messages.
22 | ///
23 | /// The that owns this instance.
24 | public KeyboardSimulator(IInputSimulator inputSimulator)
25 | {
26 | if (inputSimulator == null) throw new ArgumentNullException("inputSimulator");
27 |
28 | _inputSimulator = inputSimulator;
29 | _messageDispatcher = new WindowsInputMessageDispatcher();
30 | }
31 |
32 | ///
33 | /// Initializes a new instance of the class using the specified for dispatching messages.
34 | ///
35 | /// The that owns this instance.
36 | /// The to use for dispatching messages.
37 | /// If null is passed as the .
38 | internal KeyboardSimulator(IInputSimulator inputSimulator, IInputMessageDispatcher messageDispatcher)
39 | {
40 | if (inputSimulator == null) throw new ArgumentNullException("inputSimulator");
41 |
42 | if (messageDispatcher == null)
43 | throw new InvalidOperationException(
44 | string.Format("The {0} cannot operate with a null {1}. Please provide a valid {1} instance to use for dispatching {2} messages.",
45 | typeof(KeyboardSimulator).Name, typeof(IInputMessageDispatcher).Name, typeof(INPUT).Name));
46 |
47 | _inputSimulator = inputSimulator;
48 | _messageDispatcher = messageDispatcher;
49 | }
50 |
51 | ///
52 | /// Gets the instance for simulating Mouse input.
53 | ///
54 | /// The instance.
55 | public IMouseSimulator Mouse { get { return _inputSimulator.Mouse; } }
56 |
57 | private void ModifiersDown(InputBuilder builder, IEnumerable modifierKeyCodes)
58 | {
59 | if (modifierKeyCodes == null) return;
60 | foreach (var key in modifierKeyCodes) builder.AddKeyDown(key);
61 | }
62 |
63 | private void ModifiersUp(InputBuilder builder, IEnumerable modifierKeyCodes)
64 | {
65 | if (modifierKeyCodes == null) return;
66 |
67 | // Key up in reverse (I miss LINQ)
68 | var stack = new Stack(modifierKeyCodes);
69 | while (stack.Count > 0) builder.AddKeyUp(stack.Pop());
70 | }
71 |
72 | private void KeysPress(InputBuilder builder, IEnumerable keyCodes)
73 | {
74 | if (keyCodes == null) return;
75 | foreach (var key in keyCodes) builder.AddKeyPress(key);
76 | }
77 |
78 | ///
79 | /// Sends the list of messages using the instance.
80 | ///
81 | /// The of messages to send.
82 | private void SendSimulatedInput(INPUT[] inputList)
83 | {
84 | _messageDispatcher.DispatchInput(inputList);
85 | }
86 |
87 | ///
88 | /// Calls the Win32 SendInput method to simulate a KeyDown.
89 | ///
90 | /// The to press
91 | public IKeyboardSimulator KeyDown(VirtualKeyCode keyCode)
92 | {
93 | var inputList = new InputBuilder().AddKeyDown(keyCode).ToArray();
94 | SendSimulatedInput(inputList);
95 | return this;
96 | }
97 |
98 | ///
99 | /// Calls the Win32 SendInput method to simulate a KeyUp.
100 | ///
101 | /// The to lift up
102 | public IKeyboardSimulator KeyUp(VirtualKeyCode keyCode)
103 | {
104 | var inputList = new InputBuilder().AddKeyUp(keyCode).ToArray();
105 | SendSimulatedInput(inputList);
106 | return this;
107 | }
108 |
109 | ///
110 | /// Calls the Win32 SendInput method with a KeyDown and KeyUp message in the same input sequence in order to simulate a Key PRESS.
111 | ///
112 | /// The to press
113 | public IKeyboardSimulator KeyPress(VirtualKeyCode keyCode)
114 | {
115 | var inputList = new InputBuilder().AddKeyPress(keyCode).ToArray();
116 | SendSimulatedInput(inputList);
117 | return this;
118 | }
119 |
120 | ///
121 | /// Simulates a key press for each of the specified key codes in the order they are specified.
122 | ///
123 | ///
124 | public IKeyboardSimulator KeyPress(params VirtualKeyCode[] keyCodes)
125 | {
126 | var builder = new InputBuilder();
127 | KeysPress(builder, keyCodes);
128 | SendSimulatedInput(builder.ToArray());
129 | return this;
130 | }
131 |
132 | ///
133 | /// Simulates a simple modified keystroke like CTRL-C where CTRL is the modifierKey and C is the key.
134 | /// The flow is Modifier KeyDown, Key Press, Modifier KeyUp.
135 | ///
136 | /// The modifier key
137 | /// The key to simulate
138 | public IKeyboardSimulator ModifiedKeyStroke(VirtualKeyCode modifierKeyCode, VirtualKeyCode keyCode)
139 | {
140 | ModifiedKeyStroke(new[] { modifierKeyCode }, new[] { keyCode });
141 | return this;
142 | }
143 |
144 | ///
145 | /// Simulates a modified keystroke where there are multiple modifiers and one key like CTRL-ALT-C where CTRL and ALT are the modifierKeys and C is the key.
146 | /// The flow is Modifiers KeyDown in order, Key Press, Modifiers KeyUp in reverse order.
147 | ///
148 | /// The list of modifier keys
149 | /// The key to simulate
150 | public IKeyboardSimulator ModifiedKeyStroke(IEnumerable modifierKeyCodes, VirtualKeyCode keyCode)
151 | {
152 | ModifiedKeyStroke(modifierKeyCodes, new[] {keyCode});
153 | return this;
154 | }
155 |
156 | ///
157 | /// Simulates a modified keystroke where there is one modifier and multiple keys like CTRL-K-C where CTRL is the modifierKey and K and C are the keys.
158 | /// The flow is Modifier KeyDown, Keys Press in order, Modifier KeyUp.
159 | ///
160 | /// The modifier key
161 | /// The list of keys to simulate
162 | public IKeyboardSimulator ModifiedKeyStroke(VirtualKeyCode modifierKey, IEnumerable keyCodes)
163 | {
164 | ModifiedKeyStroke(new [] {modifierKey}, keyCodes);
165 | return this;
166 | }
167 |
168 | ///
169 | /// Simulates a modified keystroke where there are multiple modifiers and multiple keys like CTRL-ALT-K-C where CTRL and ALT are the modifierKeys and K and C are the keys.
170 | /// The flow is Modifiers KeyDown in order, Keys Press in order, Modifiers KeyUp in reverse order.
171 | ///
172 | /// The list of modifier keys
173 | /// The list of keys to simulate
174 | public IKeyboardSimulator ModifiedKeyStroke(IEnumerable modifierKeyCodes, IEnumerable keyCodes)
175 | {
176 | var builder = new InputBuilder();
177 | ModifiersDown(builder, modifierKeyCodes);
178 | KeysPress(builder, keyCodes);
179 | ModifiersUp(builder, modifierKeyCodes);
180 |
181 | SendSimulatedInput(builder.ToArray());
182 | return this;
183 | }
184 |
185 | ///
186 | /// Calls the Win32 SendInput method with a stream of KeyDown and KeyUp messages in order to simulate uninterrupted text entry via the keyboard.
187 | ///
188 | /// The text to be simulated.
189 | public IKeyboardSimulator TextEntry(string text)
190 | {
191 | if (text.Length > UInt32.MaxValue / 2) throw new ArgumentException(string.Format("The text parameter is too long. It must be less than {0} characters.", UInt32.MaxValue / 2), "text");
192 | var inputList = new InputBuilder().AddCharacters(text).ToArray();
193 | SendSimulatedInput(inputList);
194 | return this;
195 | }
196 |
197 | ///
198 | /// Simulates a single character text entry via the keyboard.
199 | ///
200 | /// The unicode character to be simulated.
201 | public IKeyboardSimulator TextEntry(char character)
202 | {
203 | var inputList = new InputBuilder().AddCharacter(character).ToArray();
204 | SendSimulatedInput(inputList);
205 | return this;
206 | }
207 |
208 | ///
209 | /// Sleeps the executing thread to create a pause between simulated inputs.
210 | ///
211 | /// The number of milliseconds to wait.
212 | public IKeyboardSimulator Sleep(int millsecondsTimeout)
213 | {
214 | Thread.Sleep(millsecondsTimeout);
215 | return this;
216 | }
217 |
218 | ///
219 | /// Sleeps the executing thread to create a pause between simulated inputs.
220 | ///
221 | /// The time to wait.
222 | public IKeyboardSimulator Sleep(TimeSpan timeout)
223 | {
224 | Thread.Sleep(timeout);
225 | return this;
226 | }
227 | }
228 | }
--------------------------------------------------------------------------------
/Silence.Simulation/MouseButton.cs:
--------------------------------------------------------------------------------
1 | namespace Silence.Simulation
2 | {
3 | ///
4 | /// The mouse button
5 | ///
6 | public enum MouseButton
7 | {
8 | ///
9 | /// Left mouse button
10 | ///
11 | LeftButton,
12 |
13 | ///
14 | /// Middle mouse button
15 | ///
16 | MiddleButton,
17 |
18 | ///
19 | /// Right moust button
20 | ///
21 | RightButton,
22 | }
23 | }
--------------------------------------------------------------------------------
/Silence.Simulation/Native/HARDWAREINPUT.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Simulation.Native
4 | {
5 | #pragma warning disable 649
6 | ///
7 | /// The HARDWAREINPUT structure contains information about a simulated message generated by an input device other than a keyboard or mouse. (see: http://msdn.microsoft.com/en-us/library/ms646269(VS.85).aspx)
8 | /// Declared in Winuser.h, include Windows.h
9 | ///
10 | internal struct HARDWAREINPUT
11 | {
12 | ///
13 | /// Value specifying the message generated by the input hardware.
14 | ///
15 | public UInt32 Msg;
16 |
17 | ///
18 | /// Specifies the low-order word of the lParam parameter for uMsg.
19 | ///
20 | public UInt16 ParamL;
21 |
22 | ///
23 | /// Specifies the high-order word of the lParam parameter for uMsg.
24 | ///
25 | public UInt16 ParamH;
26 | }
27 | #pragma warning restore 649
28 | }
29 |
--------------------------------------------------------------------------------
/Silence.Simulation/Native/INPUT.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Simulation.Native
4 | {
5 | #pragma warning disable 649
6 | ///
7 | /// The INPUT structure is used by SendInput to store information for synthesizing input events such as keystrokes, mouse movement, and mouse clicks. (see: http://msdn.microsoft.com/en-us/library/ms646270(VS.85).aspx)
8 | /// Declared in Winuser.h, include Windows.h
9 | ///
10 | ///
11 | /// This structure contains information identical to that used in the parameter list of the keybd_event or mouse_event function.
12 | /// Windows 2000/XP: INPUT_KEYBOARD supports nonkeyboard input methods, such as handwriting recognition or voice recognition, as if it were text input by using the KEYEVENTF_UNICODE flag. For more information, see the remarks section of KEYBDINPUT.
13 | ///
14 | internal struct INPUT
15 | {
16 | ///
17 | /// Specifies the type of the input event. This member can be one of the following values.
18 | /// - The event is a mouse event. Use the mi structure of the union.
19 | /// - The event is a keyboard event. Use the ki structure of the union.
20 | /// - Windows 95/98/Me: The event is from input hardware other than a keyboard or mouse. Use the hi structure of the union.
21 | ///
22 | public UInt32 Type;
23 |
24 | ///
25 | /// The data structure that contains information about the simulated Mouse, Keyboard or Hardware event.
26 | ///
27 | public MOUSEKEYBDHARDWAREINPUT Data;
28 | }
29 | #pragma warning restore 649
30 | }
31 |
--------------------------------------------------------------------------------
/Silence.Simulation/Native/InputType.cs:
--------------------------------------------------------------------------------
1 | namespace Silence.Simulation.Native
2 | {
3 | ///
4 | /// Specifies the type of the input event. This member can be one of the following values.
5 | ///
6 | internal enum InputType : uint // UInt32
7 | {
8 | ///
9 | /// INPUT_MOUSE = 0x00 (The event is a mouse event. Use the mi structure of the union.)
10 | ///
11 | Mouse = 0,
12 |
13 | ///
14 | /// INPUT_KEYBOARD = 0x01 (The event is a keyboard event. Use the ki structure of the union.)
15 | ///
16 | Keyboard = 1,
17 |
18 | ///
19 | /// INPUT_HARDWARE = 0x02 (Windows 95/98/Me: The event is from input hardware other than a keyboard or mouse. Use the hi structure of the union.)
20 | ///
21 | Hardware = 2,
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Silence.Simulation/Native/KEYBDINPUT.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Simulation.Native
4 | {
5 | #pragma warning disable 649
6 | ///
7 | /// The KEYBDINPUT structure contains information about a simulated keyboard event. (see: http://msdn.microsoft.com/en-us/library/ms646271(VS.85).aspx)
8 | /// Declared in Winuser.h, include Windows.h
9 | ///
10 | ///
11 | /// Windows 2000/XP: INPUT_KEYBOARD supports nonkeyboard-input methodssuch as handwriting recognition or voice recognitionas if it were text input by using the KEYEVENTF_UNICODE flag. If KEYEVENTF_UNICODE is specified, SendInput sends a WM_KEYDOWN or WM_KEYUP message to the foreground thread's message queue with wParam equal to VK_PACKET. Once GetMessage or PeekMessage obtains this message, passing the message to TranslateMessage posts a WM_CHAR message with the Unicode character originally specified by wScan. This Unicode character will automatically be converted to the appropriate ANSI value if it is posted to an ANSI window.
12 | /// Windows 2000/XP: Set the KEYEVENTF_SCANCODE flag to define keyboard input in terms of the scan code. This is useful to simulate a physical keystroke regardless of which keyboard is currently being used. The virtual key value of a key may alter depending on the current keyboard layout or what other keys were pressed, but the scan code will always be the same.
13 | ///
14 | internal struct KEYBDINPUT
15 | {
16 | ///
17 | /// Specifies a virtual-key code. The code must be a value in the range 1 to 254. The Winuser.h header file provides macro definitions (VK_*) for each value. If the dwFlags member specifies KEYEVENTF_UNICODE, wVk must be 0.
18 | ///
19 | public UInt16 KeyCode;
20 |
21 | ///
22 | /// Specifies a hardware scan code for the key. If dwFlags specifies KEYEVENTF_UNICODE, wScan specifies a Unicode character which is to be sent to the foreground application.
23 | ///
24 | public UInt16 Scan;
25 |
26 | ///
27 | /// Specifies various aspects of a keystroke. This member can be certain combinations of the following values.
28 | /// KEYEVENTF_EXTENDEDKEY - If specified, the scan code was preceded by a prefix byte that has the value 0xE0 (224).
29 | /// KEYEVENTF_KEYUP - If specified, the key is being released. If not specified, the key is being pressed.
30 | /// KEYEVENTF_SCANCODE - If specified, wScan identifies the key and wVk is ignored.
31 | /// KEYEVENTF_UNICODE - Windows 2000/XP: If specified, the system synthesizes a VK_PACKET keystroke. The wVk parameter must be zero. This flag can only be combined with the KEYEVENTF_KEYUP flag. For more information, see the Remarks section.
32 | ///
33 | public UInt32 Flags;
34 |
35 | ///
36 | /// Time stamp for the event, in milliseconds. If this parameter is zero, the system will provide its own time stamp.
37 | ///
38 | public UInt32 Time;
39 |
40 | ///
41 | /// Specifies an additional value associated with the keystroke. Use the GetMessageExtraInfo function to obtain this information.
42 | ///
43 | public IntPtr ExtraInfo;
44 | }
45 | #pragma warning restore 649
46 | }
47 |
--------------------------------------------------------------------------------
/Silence.Simulation/Native/KeyboardFlag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Simulation.Native
4 | {
5 | ///
6 | /// Specifies various aspects of a keystroke. This member can be certain combinations of the following values.
7 | ///
8 | [Flags]
9 | internal enum KeyboardFlag : uint // UInt32
10 | {
11 | ///
12 | /// KEYEVENTF_EXTENDEDKEY = 0x0001 (If specified, the scan code was preceded by a prefix byte that has the value 0xE0 (224).)
13 | ///
14 | ExtendedKey = 0x0001,
15 |
16 | ///
17 | /// KEYEVENTF_KEYUP = 0x0002 (If specified, the key is being released. If not specified, the key is being pressed.)
18 | ///
19 | KeyUp = 0x0002,
20 |
21 | ///
22 | /// KEYEVENTF_UNICODE = 0x0004 (If specified, wScan identifies the key and wVk is ignored.)
23 | ///
24 | Unicode = 0x0004,
25 |
26 | ///
27 | /// KEYEVENTF_SCANCODE = 0x0008 (Windows 2000/XP: If specified, the system synthesizes a VK_PACKET keystroke. The wVk parameter must be zero. This flag can only be combined with the KEYEVENTF_KEYUP flag. For more information, see the Remarks section.)
28 | ///
29 | ScanCode = 0x0008,
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Silence.Simulation/Native/MOUSEINPUT.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Simulation.Native
4 | {
5 | #pragma warning disable 649
6 | ///
7 | /// The MOUSEINPUT structure contains information about a simulated mouse event. (see: http://msdn.microsoft.com/en-us/library/ms646273(VS.85).aspx)
8 | /// Declared in Winuser.h, include Windows.h
9 | ///
10 | ///
11 | /// If the mouse has moved, indicated by MOUSEEVENTF_MOVE, dx and dy specify information about that movement. The information is specified as absolute or relative integer values.
12 | /// If MOUSEEVENTF_ABSOLUTE value is specified, dx and dy contain normalized absolute coordinates between 0 and 65,535. The event procedure maps these coordinates onto the display surface. Coordinate (0,0) maps onto the upper-left corner of the display surface; coordinate (65535,65535) maps onto the lower-right corner. In a multimonitor system, the coordinates map to the primary monitor.
13 | /// Windows 2000/XP: If MOUSEEVENTF_VIRTUALDESK is specified, the coordinates map to the entire virtual desktop.
14 | /// If the MOUSEEVENTF_ABSOLUTE value is not specified, dx and dy specify movement relative to the previous mouse event (the last reported position). Positive values mean the mouse moved right (or down); negative values mean the mouse moved left (or up).
15 | /// Relative mouse motion is subject to the effects of the mouse speed and the two-mouse threshold values. A user sets these three values with the Pointer Speed slider of the Control Panel's Mouse Properties sheet. You can obtain and set these values using the SystemParametersInfo function.
16 | /// The system applies two tests to the specified relative mouse movement. If the specified distance along either the x or y axis is greater than the first mouse threshold value, and the mouse speed is not zero, the system doubles the distance. If the specified distance along either the x or y axis is greater than the second mouse threshold value, and the mouse speed is equal to two, the system doubles the distance that resulted from applying the first threshold test. It is thus possible for the system to multiply specified relative mouse movement along the x or y axis by up to four times.
17 | ///
18 | internal struct MOUSEINPUT
19 | {
20 | ///
21 | /// Specifies the absolute position of the mouse, or the amount of motion since the last mouse event was generated, depending on the value of the dwFlags member. Absolute data is specified as the x coordinate of the mouse; relative data is specified as the number of pixels moved.
22 | ///
23 | public Int32 X;
24 |
25 | ///
26 | /// Specifies the absolute position of the mouse, or the amount of motion since the last mouse event was generated, depending on the value of the dwFlags member. Absolute data is specified as the y coordinate of the mouse; relative data is specified as the number of pixels moved.
27 | ///
28 | public Int32 Y;
29 |
30 | ///
31 | /// If dwFlags contains MOUSEEVENTF_WHEEL, then mouseData specifies the amount of wheel movement. A positive value indicates that the wheel was rotated forward, away from the user; a negative value indicates that the wheel was rotated backward, toward the user. One wheel click is defined as WHEEL_DELTA, which is 120.
32 | /// Windows Vista: If dwFlags contains MOUSEEVENTF_HWHEEL, then dwData specifies the amount of wheel movement. A positive value indicates that the wheel was rotated to the right; a negative value indicates that the wheel was rotated to the left. One wheel click is defined as WHEEL_DELTA, which is 120.
33 | /// Windows 2000/XP: IfdwFlags does not contain MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, or MOUSEEVENTF_XUP, then mouseData should be zero.
34 | /// If dwFlags contains MOUSEEVENTF_XDOWN or MOUSEEVENTF_XUP, then mouseData specifies which X buttons were pressed or released. This value may be any combination of the following flags.
35 | ///
36 | public UInt32 MouseData;
37 |
38 | ///
39 | /// A set of bit flags that specify various aspects of mouse motion and button clicks. The bits in this member can be any reasonable combination of the following values.
40 | /// The bit flags that specify mouse button status are set to indicate changes in status, not ongoing conditions. For example, if the left mouse button is pressed and held down, MOUSEEVENTF_LEFTDOWN is set when the left button is first pressed, but not for subsequent motions. Similarly, MOUSEEVENTF_LEFTUP is set only when the button is first released.
41 | /// You cannot specify both the MOUSEEVENTF_WHEEL flag and either MOUSEEVENTF_XDOWN or MOUSEEVENTF_XUP flags simultaneously in the dwFlags parameter, because they both require use of the mouseData field.
42 | ///
43 | public UInt32 Flags;
44 |
45 | ///
46 | /// Time stamp for the event, in milliseconds. If this parameter is 0, the system will provide its own time stamp.
47 | ///
48 | public UInt32 Time;
49 |
50 | ///
51 | /// Specifies an additional value associated with the mouse event. An application calls GetMessageExtraInfo to obtain this extra information.
52 | ///
53 | public IntPtr ExtraInfo;
54 | }
55 | #pragma warning restore 649
56 | }
--------------------------------------------------------------------------------
/Silence.Simulation/Native/MOUSEKEYBDHARDWAREINPUT.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | namespace Silence.Simulation.Native
4 | {
5 | #pragma warning disable 649
6 | ///
7 | /// The combined/overlayed structure that includes Mouse, Keyboard and Hardware Input message data (see: http://msdn.microsoft.com/en-us/library/ms646270(VS.85).aspx)
8 | ///
9 | [StructLayout(LayoutKind.Explicit)]
10 | internal struct MOUSEKEYBDHARDWAREINPUT
11 | {
12 | ///
13 | /// The definition.
14 | ///
15 | [FieldOffset(0)]
16 | public MOUSEINPUT Mouse;
17 |
18 | ///
19 | /// The definition.
20 | ///
21 | [FieldOffset(0)]
22 | public KEYBDINPUT Keyboard;
23 |
24 | ///
25 | /// The definition.
26 | ///
27 | [FieldOffset(0)]
28 | public HARDWAREINPUT Hardware;
29 | }
30 | #pragma warning restore 649
31 | }
32 |
--------------------------------------------------------------------------------
/Silence.Simulation/Native/MouseFlag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Silence.Simulation.Native
4 | {
5 | ///
6 | /// The set of MouseFlags for use in the Flags property of the structure. (See: http://msdn.microsoft.com/en-us/library/ms646273(VS.85).aspx)
7 | ///
8 | [Flags]
9 | internal enum MouseFlag : uint // UInt32
10 | {
11 | ///
12 | /// Specifies that movement occurred.
13 | ///
14 | Move = 0x0001,
15 |
16 | ///
17 | /// Specifies that the left button was pressed.
18 | ///
19 | LeftDown = 0x0002,
20 |
21 | ///
22 | /// Specifies that the left button was released.
23 | ///
24 | LeftUp = 0x0004,
25 |
26 | ///
27 | /// Specifies that the right button was pressed.
28 | ///
29 | RightDown = 0x0008,
30 |
31 | ///
32 | /// Specifies that the right button was released.
33 | ///
34 | RightUp = 0x0010,
35 |
36 | ///
37 | /// Specifies that the middle button was pressed.
38 | ///
39 | MiddleDown = 0x0020,
40 |
41 | ///
42 | /// Specifies that the middle button was released.
43 | ///
44 | MiddleUp = 0x0040,
45 |
46 | ///
47 | /// Windows 2000/XP: Specifies that an X button was pressed.
48 | ///
49 | XDown = 0x0080,
50 |
51 | ///
52 | /// Windows 2000/XP: Specifies that an X button was released.
53 | ///
54 | XUp = 0x0100,
55 |
56 | ///
57 | /// Windows NT/2000/XP: Specifies that the wheel was moved, if the mouse has a wheel. The amount of movement is specified in mouseData.
58 | ///
59 | VerticalWheel = 0x0800,
60 |
61 | ///
62 | /// Specifies that the wheel was moved horizontally, if the mouse has a wheel. The amount of movement is specified in mouseData. Windows 2000/XP: Not supported.
63 | ///
64 | HorizontalWheel = 0x1000,
65 |
66 | ///
67 | /// Windows 2000/XP: Maps coordinates to the entire desktop. Must be used with MOUSEEVENTF_ABSOLUTE.
68 | ///
69 | VirtualDesk = 0x4000,
70 |
71 | ///
72 | /// Specifies that the dx and dy members contain normalized absolute coordinates. If the flag is not set, dxand dy contain relative data (the change in position since the last reported position). This flag can be set, or not set, regardless of what kind of mouse or other pointing device, if any, is connected to the system. For further information about relative mouse motion, see the following Remarks section.
73 | ///
74 | Absolute = 0x8000,
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Silence.Simulation/Native/NativeMethods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace Silence.Simulation.Native
5 | {
6 | ///
7 | /// References all of the Native Windows API methods for the WindowsInput functionality.
8 | ///
9 | internal static class NativeMethods
10 | {
11 | ///
12 | /// The GetAsyncKeyState function determines whether a key is up or down at the time the function is called, and whether the key was pressed after a previous call to GetAsyncKeyState. (See: http://msdn.microsoft.com/en-us/library/ms646293(VS.85).aspx)
13 | ///
14 | /// Specifies one of 256 possible virtual-key codes. For more information, see Virtual Key Codes. Windows NT/2000/XP: You can use left- and right-distinguishing constants to specify certain keys. See the Remarks section for further information.
15 | ///
16 | /// If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState. However, you should not rely on this last behavior; for more information, see the Remarks.
17 | ///
18 | /// Windows NT/2000/XP: The return value is zero for the following cases:
19 | /// - The current desktop is not the active desktop
20 | /// - The foreground thread belongs to another process and the desktop does not allow the hook or the journal record.
21 | ///
22 | /// Windows 95/98/Me: The return value is the global asynchronous key state for each virtual key. The system does not check which thread has the keyboard focus.
23 | ///
24 | /// Windows 95/98/Me: Windows 95 does not support the left- and right-distinguishing constants. If you call GetAsyncKeyState with these constants, the return value is zero.
25 | ///
26 | ///
27 | /// The GetAsyncKeyState function works with mouse buttons. However, it checks on the state of the physical mouse buttons, not on the logical mouse buttons that the physical buttons are mapped to. For example, the call GetAsyncKeyState(VK_LBUTTON) always returns the state of the left physical mouse button, regardless of whether it is mapped to the left or right logical mouse button. You can determine the system's current mapping of physical mouse buttons to logical mouse buttons by calling
28 | /// Copy CodeGetSystemMetrics(SM_SWAPBUTTON) which returns TRUE if the mouse buttons have been swapped.
29 | ///
30 | /// Although the least significant bit of the return value indicates whether the key has been pressed since the last query, due to the pre-emptive multitasking nature of Windows, another application can call GetAsyncKeyState and receive the "recently pressed" bit instead of your application. The behavior of the least significant bit of the return value is retained strictly for compatibility with 16-bit Windows applications (which are non-preemptive) and should not be relied upon.
31 | ///
32 | /// You can use the virtual-key code constants VK_SHIFT, VK_CONTROL, and VK_MENU as values for the vKey parameter. This gives the state of the SHIFT, CTRL, or ALT keys without distinguishing between left and right.
33 | ///
34 | /// Windows NT/2000/XP: You can use the following virtual-key code constants as values for vKey to distinguish between the left and right instances of those keys.
35 | ///
36 | /// Code Meaning
37 | /// VK_LSHIFT Left-shift key.
38 | /// VK_RSHIFT Right-shift key.
39 | /// VK_LCONTROL Left-control key.
40 | /// VK_RCONTROL Right-control key.
41 | /// VK_LMENU Left-menu key.
42 | /// VK_RMENU Right-menu key.
43 | ///
44 | /// These left- and right-distinguishing constants are only available when you call the GetKeyboardState, SetKeyboardState, GetAsyncKeyState, GetKeyState, and MapVirtualKey functions.
45 | ///
46 | [DllImport("user32.dll", SetLastError = true)]
47 | public static extern Int16 GetAsyncKeyState(UInt16 virtualKeyCode);
48 |
49 | ///
50 | /// The GetKeyState function retrieves the status of the specified virtual key. The status specifies whether the key is up, down, or toggled (on, off alternating each time the key is pressed). (See: http://msdn.microsoft.com/en-us/library/ms646301(VS.85).aspx)
51 | ///
52 | ///
53 | /// Specifies a virtual key. If the desired virtual key is a letter or digit (A through Z, a through z, or 0 through 9), nVirtKey must be set to the ASCII value of that character. For other keys, it must be a virtual-key code.
54 | /// If a non-English keyboard layout is used, virtual keys with values in the range ASCII A through Z and 0 through 9 are used to specify most of the character keys. For example, for the German keyboard layout, the virtual key of value ASCII O (0x4F) refers to the "o" key, whereas VK_OEM_1 refers to the "o with umlaut" key.
55 | ///
56 | ///
57 | /// The return value specifies the status of the specified virtual key, as follows:
58 | /// If the high-order bit is 1, the key is down; otherwise, it is up.
59 | /// If the low-order bit is 1, the key is toggled. A key, such as the CAPS LOCK key, is toggled if it is turned on. The key is off and untoggled if the low-order bit is 0. A toggle key's indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled.
60 | ///
61 | ///
62 | /// The key status returned from this function changes as a thread reads key messages from its message queue. The status does not reflect the interrupt-level state associated with the hardware. Use the GetAsyncKeyState function to retrieve that information.
63 | /// An application calls GetKeyState in response to a keyboard-input message. This function retrieves the state of the key when the input message was generated.
64 | /// To retrieve state information for all the virtual keys, use the GetKeyboardState function.
65 | /// An application can use the virtual-key code constants VK_SHIFT, VK_CONTROL, and VK_MENU as values for the nVirtKey parameter. This gives the status of the SHIFT, CTRL, or ALT keys without distinguishing between left and right. An application can also use the following virtual-key code constants as values for nVirtKey to distinguish between the left and right instances of those keys.
66 | /// VK_LSHIFT
67 | /// VK_RSHIFT
68 | /// VK_LCONTROL
69 | /// VK_RCONTROL
70 | /// VK_LMENU
71 | /// VK_RMENU
72 | ///
73 | /// These left- and right-distinguishing constants are available to an application only through the GetKeyboardState, SetKeyboardState, GetAsyncKeyState, GetKeyState, and MapVirtualKey functions.
74 | ///
75 | [DllImport("user32.dll", SetLastError = true)]
76 | public static extern Int16 GetKeyState(UInt16 virtualKeyCode);
77 |
78 | ///
79 | /// The SendInput function synthesizes keystrokes, mouse motions, and button clicks.
80 | ///
81 | /// Number of structures in the Inputs array.
82 | /// Pointer to an array of INPUT structures. Each structure represents an event to be inserted into the keyboard or mouse input stream.
83 | /// Specifies the size, in bytes, of an INPUT structure. If cbSize is not the size of an INPUT structure, the function fails.
84 | /// The function returns the number of events that it successfully inserted into the keyboard or mouse input stream. If the function returns zero, the input was already blocked by another thread. To get extended error information, call GetLastError.Microsoft Windows Vista. This function fails when it is blocked by User Interface Privilege Isolation (UIPI). Note that neither GetLastError nor the return value will indicate the failure was caused by UIPI blocking.
85 | ///
86 | /// Microsoft Windows Vista. This function is subject to UIPI. Applications are permitted to inject input only into applications that are at an equal or lesser integrity level.
87 | /// The SendInput function inserts the events in the INPUT structures serially into the keyboard or mouse input stream. These events are not interspersed with other keyboard or mouse input events inserted either by the user (with the keyboard or mouse) or by calls to keybd_event, mouse_event, or other calls to SendInput.
88 | /// This function does not reset the keyboard's current state. Any keys that are already pressed when the function is called might interfere with the events that this function generates. To avoid this problem, check the keyboard's state with the GetAsyncKeyState function and correct as necessary.
89 | ///
90 | [DllImport("user32.dll", SetLastError = true)]
91 | public static extern UInt32 SendInput(UInt32 numberOfInputs, INPUT[] inputs, Int32 sizeOfInputStructure);
92 |
93 | ///
94 | /// The GetMessageExtraInfo function retrieves the extra message information for the current thread. Extra message information is an application- or driver-defined value associated with the current thread's message queue.
95 | ///
96 | ///
97 | /// To set a thread's extra message information, use the SetMessageExtraInfo function.
98 | [DllImport("user32.dll")]
99 | public static extern IntPtr GetMessageExtraInfo();
100 | }
101 | }
--------------------------------------------------------------------------------
/Silence.Simulation/Native/XButton.cs:
--------------------------------------------------------------------------------
1 | namespace Silence.Simulation.Native
2 | {
3 | ///
4 | /// XButton definitions for use in the MouseData property of the structure. (See: http://msdn.microsoft.com/en-us/library/ms646273(VS.85).aspx)
5 | ///
6 | internal enum XButton : uint
7 | {
8 | ///
9 | /// Set if the first X button is pressed or released.
10 | ///
11 | XButton1 = 0x0001,
12 |
13 | ///
14 | /// Set if the second X button is pressed or released.
15 | ///
16 | XButton2 = 0x0002,
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Silence.Simulation/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Silence.Simulation")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Silence.Simulation")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("ce200217-b899-4ca8-833a-7dcad1b6f7d9")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Silence.Simulation/Silence.Simulation.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {CE200217-B899-4CA8-833A-7DCAD1B6F7D9}
8 | Library
9 | Properties
10 | Silence.Simulation
11 | Silence.Simulation
12 | v4.8
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
77 |
--------------------------------------------------------------------------------
/Silence.Simulation/WindowsInputMessageDispatcher.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using Silence.Simulation.Native;
4 |
5 | namespace Silence.Simulation
6 | {
7 | ///
8 | /// Implements the by calling .
9 | ///
10 | internal class WindowsInputMessageDispatcher : IInputMessageDispatcher
11 | {
12 | ///
13 | /// Dispatches the specified list of messages in their specified order by issuing a single called to .
14 | ///
15 | /// The list of messages to be dispatched.
16 | /// If the array is empty.
17 | /// If the array is null.
18 | /// If the any of the commands in the array could not be sent successfully.
19 | public void DispatchInput(INPUT[] inputs)
20 | {
21 | if (inputs == null) throw new ArgumentNullException("inputs");
22 | if (inputs.Length == 0) throw new ArgumentException("The input array was empty", "inputs");
23 | var successful = NativeMethods.SendInput((UInt32)inputs.Length, inputs, Marshal.SizeOf(typeof (INPUT)));
24 | if (successful != inputs.Length)
25 | throw new Exception("Some simulated input commands were not sent successfully. The most common reason for this happening are the security features of Windows including User Interface Privacy Isolation (UIPI). Your application can only send commands to applications of the same or lower elevation. Similarly certain commands are restricted to Accessibility/UIAutomation applications. Refer to the project home page and the code samples for more information.");
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/Silence.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.24720.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Silence", "Silence\Silence.csproj", "{1CBBC97A-D669-48FA-81D3-E5CBD5E55C7B}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Silence.Hooking", "Silence.Hooking\Silence.Hooking.csproj", "{8897B3B9-FAFE-4DD7-81B5-611008CB6437}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Silence.Macro", "Silence.Macro\Silence.Macro.csproj", "{63B186AA-962C-4A5F-90EE-268BBB5377F2}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Silence.Simulation", "Silence.Simulation\Silence.Simulation.csproj", "{CE200217-B899-4CA8-833A-7DCAD1B6F7D9}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {1CBBC97A-D669-48FA-81D3-E5CBD5E55C7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {1CBBC97A-D669-48FA-81D3-E5CBD5E55C7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {1CBBC97A-D669-48FA-81D3-E5CBD5E55C7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {1CBBC97A-D669-48FA-81D3-E5CBD5E55C7B}.Release|Any CPU.Build.0 = Release|Any CPU
24 | {8897B3B9-FAFE-4DD7-81B5-611008CB6437}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {8897B3B9-FAFE-4DD7-81B5-611008CB6437}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {8897B3B9-FAFE-4DD7-81B5-611008CB6437}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {8897B3B9-FAFE-4DD7-81B5-611008CB6437}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {63B186AA-962C-4A5F-90EE-268BBB5377F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {63B186AA-962C-4A5F-90EE-268BBB5377F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {63B186AA-962C-4A5F-90EE-268BBB5377F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {63B186AA-962C-4A5F-90EE-268BBB5377F2}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {CE200217-B899-4CA8-833A-7DCAD1B6F7D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {CE200217-B899-4CA8-833A-7DCAD1B6F7D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {CE200217-B899-4CA8-833A-7DCAD1B6F7D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {CE200217-B899-4CA8-833A-7DCAD1B6F7D9}.Release|Any CPU.Build.0 = Release|Any CPU
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/Silence/ConfigurationFile.cs:
--------------------------------------------------------------------------------
1 | namespace Silence
2 | {
3 | ///
4 | /// Represents the application configuration file.
5 | ///
6 | internal class ConfigurationFile : JsonSerializable
7 | {
8 | ///
9 | /// The code for the language the application is configured to use.
10 | ///
11 | public string LanguageCode { get; set; }
12 |
13 | ///
14 | /// The application's base theme color.
15 | ///
16 | public ThemeColor ThemeColor { get; set; }
17 |
18 | ///
19 | /// Initializes a new instance of the application configuration file.
20 | ///
21 | public ConfigurationFile()
22 | {
23 | LanguageCode = "en";
24 | ThemeColor = new ThemeColor
25 | {
26 | R = 37,
27 | G = 0,
28 | B = 64
29 | };
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Silence/ControlButton.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows.Forms;
7 |
8 | namespace Silence
9 | {
10 |
11 | public class ControlButton : PictureBox
12 | {
13 |
14 | private Color _mouseOutBackgroundColor = Color.FromArgb(255, 37, 0, 64);
15 |
16 | private Color _mouseOverBackgroundColor = Color.FromArgb(255, 65, 33, 89);
17 |
18 | private Color _mouseDownBackgroundColor = Color.FromArgb(255, 44, 23, 61);
19 |
20 | private Color _shapeColor = Color.White;
21 |
22 | private Bitmap _shapeImage = null;
23 |
24 | private Bitmap _mouseOverImage = null;
25 |
26 | private Bitmap _mouseOutImage = null;
27 |
28 | private Bitmap _mouseDownImage = null;
29 |
30 | private MouseState _currentMouseState = MouseState.Out;
31 |
32 | private enum MouseState : int
33 | {
34 |
35 | Out = 0,
36 |
37 | Over = 1,
38 |
39 | Down = 2,
40 | }
41 |
42 | private MouseState CurrentMouseState
43 | {
44 | get
45 | {
46 | return _currentMouseState;
47 | }
48 | set
49 | {
50 | _currentMouseState = value;
51 | DisplayStateImage();
52 | DisplayStateImage();
53 | }
54 | }
55 |
56 | public Color MouseOverBackgroundColor
57 | {
58 | get
59 | {
60 | return _mouseOverBackgroundColor;
61 | }
62 | set
63 | {
64 | _mouseOverBackgroundColor = value;
65 | RenderImages();
66 | DisplayStateImage();
67 | }
68 | }
69 |
70 | public Color MouseOutBackgroundColor
71 | {
72 | get
73 | {
74 | return _mouseOutBackgroundColor;
75 | }
76 | set
77 | {
78 | _mouseOutBackgroundColor = value;
79 | RenderImages();
80 | DisplayStateImage();
81 | }
82 | }
83 |
84 | public Color MouseDownBackgroundColor
85 | {
86 | get
87 | {
88 | return _mouseDownBackgroundColor;
89 | }
90 | set
91 | {
92 | _mouseDownBackgroundColor = value;
93 | RenderImages();
94 | DisplayStateImage();
95 | }
96 | }
97 |
98 | public Bitmap ShapeImage
99 | {
100 | get
101 | {
102 | return _shapeImage;
103 | }
104 | set
105 | {
106 | _shapeImage = value;
107 | RenderImages();
108 | DisplayStateImage();
109 | }
110 | }
111 |
112 | public Color ShapeColor
113 | {
114 | get
115 | {
116 | return _shapeColor;
117 | }
118 | set
119 | {
120 | _shapeColor = value;
121 | RenderImages();
122 | DisplayStateImage();
123 | }
124 | }
125 |
126 | private void DisplayStateImage()
127 | {
128 | switch (_currentMouseState)
129 | {
130 | case MouseState.Out:
131 | this.Image = _mouseOutImage;
132 | break;
133 | case MouseState.Over:
134 | this.Image = _mouseOverImage;
135 | break;
136 | case MouseState.Down:
137 | this.Image = _mouseDownImage;
138 | break;
139 | }
140 | }
141 |
142 | private void RenderImages()
143 | {
144 | Bitmap bmp = new Bitmap(this.Width, this.Height);
145 | Graphics g = Graphics.FromImage(bmp);
146 | g.Clear(MouseOutBackgroundColor);
147 | if (!(ShapeImage == null))
148 | {
149 | for (int y = 0; (y
150 | <= (ShapeImage.Height - 1)); y++)
151 | {
152 | for (int x = 0; (x
153 | <= (ShapeImage.Width - 1)); x++)
154 | {
155 | Color pixelColor = Color.FromArgb(ShapeImage.GetPixel(x, y).A, ShapeColor);
156 | g.FillRectangle(new SolidBrush(pixelColor), new Rectangle(x, y, 1, 1));
157 | }
158 | }
159 | }
160 | _mouseOutImage = new Bitmap(bmp);
161 | g.Clear(MouseOverBackgroundColor);
162 | if (!(ShapeImage == null))
163 | {
164 | for (int y = 0; (y
165 | <= (ShapeImage.Height - 1)); y++)
166 | {
167 | for (int x = 0; (x
168 | <= (ShapeImage.Width - 1)); x++)
169 | {
170 | Color pixelColor = Color.FromArgb(ShapeImage.GetPixel(x, y).A, ShapeColor);
171 | g.FillRectangle(new SolidBrush(pixelColor), new Rectangle(x, y, 1, 1));
172 | }
173 | }
174 | }
175 | _mouseOverImage = new Bitmap(bmp);
176 | g.Clear(MouseDownBackgroundColor);
177 | if (!(ShapeImage == null))
178 | {
179 | for (int y = 0; (y
180 | <= (ShapeImage.Height - 1)); y++)
181 | {
182 | for (int x = 0; (x
183 | <= (ShapeImage.Width - 1)); x++)
184 | {
185 | Color pixelColor = Color.FromArgb(ShapeImage.GetPixel(x, y).A, ShapeColor);
186 | g.FillRectangle(new SolidBrush(pixelColor), new Rectangle(x, y, 1, 1));
187 | }
188 | }
189 | }
190 | _mouseDownImage = new Bitmap(bmp);
191 | g.Dispose();
192 | bmp.Dispose();
193 | }
194 |
195 | private void ControlButton_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
196 | {
197 | CurrentMouseState = MouseState.Down;
198 | }
199 |
200 | private void ControlButton_MouseEnter(object sender, System.EventArgs e)
201 | {
202 | CurrentMouseState = MouseState.Over;
203 | }
204 |
205 | private void ControlButton_MouseLeave(object sender, System.EventArgs e)
206 | {
207 | CurrentMouseState = MouseState.Out;
208 | }
209 |
210 | private void ControlButton_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
211 | {
212 | CurrentMouseState = MouseState.Over;
213 | }
214 |
215 | private void ControlButton_SizeChanged(object sender, System.EventArgs e)
216 | {
217 | RenderImages();
218 | DisplayStateImage();
219 | }
220 |
221 | public ControlButton()
222 | : base()
223 | {
224 | RenderImages();
225 | DisplayStateImage();
226 |
227 | this.MouseEnter += ControlButton_MouseEnter;
228 | this.MouseLeave += ControlButton_MouseLeave;
229 | this.MouseDown += ControlButton_MouseDown;
230 | this.MouseUp += ControlButton_MouseUp;
231 | this.SizeChanged += ControlButton_SizeChanged;
232 | }
233 |
234 | }
235 | }
236 |
--------------------------------------------------------------------------------
/Silence/FormMain.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using Silence.Localization;
3 | using Silence.Macro;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Data;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Windows.Forms;
12 |
13 | namespace Silence
14 | {
15 | public partial class FormMain : Form
16 | {
17 | private const string ConfigurationFilePath = "config.json";
18 |
19 | private readonly MacroRecorder _recorder = new MacroRecorder();
20 | private readonly MacroPlayer _player = new MacroPlayer();
21 |
22 | private readonly ConfigurationFile _config;
23 | private readonly LanguagePack _languages;
24 |
25 | public FormMain()
26 | {
27 | InitializeComponent();
28 |
29 | if (!File.Exists(ConfigurationFilePath))
30 | new ConfigurationFile().Save(ConfigurationFilePath);
31 | _config = ConfigurationFile.FromFile(ConfigurationFilePath);
32 |
33 | _languages = new LanguagePack(@"lang");
34 | _languages.SelectLanguage(_config.LanguageCode);
35 | }
36 |
37 | private void recordControlButton_Click(object sender, EventArgs e)
38 | {
39 | // Confirm action.
40 | if (_recorder.CurrentMacro != null && _recorder.CurrentMacro.Events.Length > 0)
41 | {
42 | var result = MessageBox.Show(_languages.GetLocalizedString("confirm_append_message"),
43 | _languages.GetLocalizedString("confirm_append_title"), MessageBoxButtons.YesNoCancel,
44 | MessageBoxIcon.Warning);
45 | if (result == DialogResult.Yes)
46 | _recorder.Clear();
47 | else if (result == DialogResult.Cancel)
48 | return;
49 | }
50 |
51 | // Begin recording.
52 | _recorder.StartRecording();
53 | }
54 |
55 | private void stopControlButton_Click(object sender, EventArgs e)
56 | {
57 | // Stop recording.
58 | _recorder.StopRecording();
59 | }
60 |
61 | private void playControlButton_Click(object sender, EventArgs e)
62 | {
63 | // Load and play macro.
64 | _player.LoadMacro(_recorder.CurrentMacro);
65 | _player.PlayMacroAsync();
66 | }
67 |
68 | private void clearControlButton_Click(object sender, EventArgs e)
69 | {
70 | // Confirm action.
71 | if (_recorder.CurrentMacro != null && _recorder.CurrentMacro.Events.Length > 0)
72 | {
73 | var result = MessageBox.Show(_languages.GetLocalizedString("confirm_clear_message"),
74 | _languages.GetLocalizedString("confirm_clear_title"), MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
75 | if (result == DialogResult.Yes)
76 | _recorder.Clear();
77 | }
78 | }
79 |
80 | private void openControlButton_Click(object sender, EventArgs e)
81 | {
82 | // Confirm action.
83 | if (_recorder.CurrentMacro != null && _recorder.CurrentMacro.Events.Length > 0)
84 | {
85 | var result = MessageBox.Show(_languages.GetLocalizedString("confirm_open_message"),
86 | _languages.GetLocalizedString("confirm_clear_title"), MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
87 | if (result == DialogResult.No)
88 | return;
89 | }
90 |
91 | // Browse for file
92 | var dialog = new OpenFileDialog
93 | {
94 | Title = _languages.GetLocalizedString("dialog_open_macro_title"),
95 | Filter = _languages.GetLocalizedString("dialog_open_macro_filter")
96 | };
97 |
98 | // Load macro into recorder.
99 | if (dialog.ShowDialog() == DialogResult.OK)
100 | {
101 | var loadedMacro = new Macro.Macro();
102 | loadedMacro.Load(dialog.FileName);
103 | _recorder.LoadMacro(loadedMacro);
104 | }
105 | }
106 |
107 | private void saveControlButton_Click(object sender, EventArgs e)
108 | {
109 | // Check there is a macro to save.
110 | if (_recorder.CurrentMacro == null || _recorder.CurrentMacro.Events.Length == 0)
111 | {
112 | MessageBox.Show(_languages.GetLocalizedString("error_save_nomacro_message"),
113 | _languages.GetLocalizedString("error_save_nomacro_title"), MessageBoxButtons.OK, MessageBoxIcon.Error);
114 | return;
115 | }
116 |
117 | // Choose file to save to.
118 | var dialog = new SaveFileDialog
119 | {
120 | Title = _languages.GetLocalizedString("dialog_save_macro_title"),
121 | Filter = _languages.GetLocalizedString("dialog_save_macro_filter")
122 | };
123 |
124 | // Save file.
125 | if (dialog.ShowDialog() == DialogResult.OK)
126 | _recorder.CurrentMacro.Save(dialog.FileName);
127 | }
128 |
129 | private void loopControlButton_Click(object sender, EventArgs e)
130 | {
131 | // Set number of repetitions on player.
132 | var dialog = new RepetitionsDialog { Repetitions = _player.Repetitions };
133 | if (dialog.ShowDialog() == DialogResult.OK)
134 | _player.Repetitions = dialog.Repetitions;
135 | }
136 |
137 | private void FormMain_Load(object sender, EventArgs e)
138 | {
139 | // Load theme color for buttons.
140 | foreach (var control in panel1.Controls)
141 | {
142 | var button = (ControlButton)control;
143 | button.MouseOutBackgroundColor = _config.ThemeColor.ToColor();
144 | button.MouseOverBackgroundColor = _config.ThemeColor.ToColor(32);
145 | button.MouseDownBackgroundColor = _config.ThemeColor.ToColor(-32);
146 | }
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/Silence/JsonSerializable.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using Newtonsoft.Json;
3 |
4 | namespace Silence
5 | {
6 | ///
7 | /// Represents an object that can be written to and read from a file as JSON.
8 | ///
9 | /// The object type.
10 | public abstract class JsonSerializable
11 | {
12 | ///
13 | /// Saves this object to a file as JSON.
14 | ///
15 | /// The filename to write to.
16 | public void Save(string filename)
17 | {
18 | var writer = new StreamWriter(filename);
19 | writer.Write(JsonConvert.SerializeObject(this, Formatting.Indented));
20 | writer.Flush();
21 | writer.Close();
22 | }
23 |
24 | ///
25 | /// Reads an object of this type from a JSON file.
26 | ///
27 | /// The filename to read from.
28 | ///
29 | public static T FromFile(string filename)
30 | {
31 | var reader = new StreamReader(filename);
32 | var obj = JsonConvert.DeserializeObject(reader.ReadToEnd());
33 | reader.Close();
34 | return obj;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Silence/Localization/Language.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Silence.Localization
7 | {
8 | public class Language : JsonSerializable
9 | {
10 | public string Code { get; set; }
11 |
12 | public string Name { get; set; }
13 |
14 | public Dictionary LocalizedStrings { get; set; }
15 |
16 | public Language()
17 | {
18 | LocalizedStrings = new Dictionary();
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Silence/Localization/LanguagePack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 |
8 | namespace Silence.Localization
9 | {
10 | public class LanguagePack
11 | {
12 | private readonly Dictionary _languages;
13 |
14 | public string SelectedLanguageCode { get; private set; }
15 |
16 | public string GetLocalizedString(string key)
17 | {
18 | return _languages[SelectedLanguageCode].LocalizedStrings[key];
19 | }
20 |
21 | public void SelectLanguage(string code)
22 | {
23 | if (!_languages.ContainsKey(code))
24 | {
25 | throw new ArgumentException("No language with this code was found in the language pack.");
26 | }
27 | SelectedLanguageCode = code;
28 | }
29 |
30 | public LanguagePack(string directory, string pattern = "lang_*.json")
31 | {
32 | if (!Directory.Exists(directory))
33 | {
34 | throw new DirectoryNotFoundException("The language pack directory could not be found.");
35 | }
36 |
37 | _languages = new Dictionary();
38 | var files = new DirectoryInfo(directory).GetFiles(pattern);
39 | foreach (var file in files)
40 | {
41 | var lang = Language.FromFile(file.FullName);
42 | _languages.Add(lang.Code, lang);
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Silence/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | namespace Silence
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// The main entry point for the application.
13 | ///
14 | [STAThread]
15 | static void Main()
16 | {
17 | Application.EnableVisualStyles();
18 | Application.SetCompatibleTextRenderingDefault(false);
19 | Application.Run(new FormMain());
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Silence/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Silence")]
9 | [assembly: AssemblyDescription("A simple, clean macro recorder written in C#. Windows 10 compatible.")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Saul Johnson")]
12 | [assembly: AssemblyProduct("Silence")]
13 | [assembly: AssemblyCopyright("Copyright © Saul Johnson 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("1cbbc97a-d669-48fa-81d3-e5cbd5e55c7b")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Silence/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Silence.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Silence.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Drawing.Bitmap.
65 | ///
66 | internal static System.Drawing.Bitmap clear {
67 | get {
68 | object obj = ResourceManager.GetObject("clear", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 |
73 | ///
74 | /// Looks up a localized resource of type System.Drawing.Bitmap.
75 | ///
76 | internal static System.Drawing.Bitmap loop {
77 | get {
78 | object obj = ResourceManager.GetObject("loop", resourceCulture);
79 | return ((System.Drawing.Bitmap)(obj));
80 | }
81 | }
82 |
83 | ///
84 | /// Looks up a localized resource of type System.Drawing.Bitmap.
85 | ///
86 | internal static System.Drawing.Bitmap menu_closed {
87 | get {
88 | object obj = ResourceManager.GetObject("menu_closed", resourceCulture);
89 | return ((System.Drawing.Bitmap)(obj));
90 | }
91 | }
92 |
93 | ///
94 | /// Looks up a localized resource of type System.Drawing.Bitmap.
95 | ///
96 | internal static System.Drawing.Bitmap menu_open {
97 | get {
98 | object obj = ResourceManager.GetObject("menu_open", resourceCulture);
99 | return ((System.Drawing.Bitmap)(obj));
100 | }
101 | }
102 |
103 | ///
104 | /// Looks up a localized resource of type System.Drawing.Bitmap.
105 | ///
106 | internal static System.Drawing.Bitmap open {
107 | get {
108 | object obj = ResourceManager.GetObject("open", resourceCulture);
109 | return ((System.Drawing.Bitmap)(obj));
110 | }
111 | }
112 |
113 | ///
114 | /// Looks up a localized resource of type System.Drawing.Bitmap.
115 | ///
116 | internal static System.Drawing.Bitmap pause {
117 | get {
118 | object obj = ResourceManager.GetObject("pause", resourceCulture);
119 | return ((System.Drawing.Bitmap)(obj));
120 | }
121 | }
122 |
123 | ///
124 | /// Looks up a localized resource of type System.Drawing.Bitmap.
125 | ///
126 | internal static System.Drawing.Bitmap play {
127 | get {
128 | object obj = ResourceManager.GetObject("play", resourceCulture);
129 | return ((System.Drawing.Bitmap)(obj));
130 | }
131 | }
132 |
133 | ///
134 | /// Looks up a localized resource of type System.Drawing.Bitmap.
135 | ///
136 | internal static System.Drawing.Bitmap record {
137 | get {
138 | object obj = ResourceManager.GetObject("record", resourceCulture);
139 | return ((System.Drawing.Bitmap)(obj));
140 | }
141 | }
142 |
143 | ///
144 | /// Looks up a localized resource of type System.Drawing.Bitmap.
145 | ///
146 | internal static System.Drawing.Bitmap save {
147 | get {
148 | object obj = ResourceManager.GetObject("save", resourceCulture);
149 | return ((System.Drawing.Bitmap)(obj));
150 | }
151 | }
152 |
153 | ///
154 | /// Looks up a localized resource of type System.Drawing.Bitmap.
155 | ///
156 | internal static System.Drawing.Bitmap stop {
157 | get {
158 | object obj = ResourceManager.GetObject("stop", resourceCulture);
159 | return ((System.Drawing.Bitmap)(obj));
160 | }
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/Silence/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\clear.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
125 | ..\Resources\loop.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
126 |
127 |
128 | ..\Resources\menu_closed.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
129 |
130 |
131 | ..\Resources\menu_open.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
132 |
133 |
134 | ..\Resources\open.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
135 |
136 |
137 | ..\Resources\pause.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
138 |
139 |
140 | ..\Resources\play.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
141 |
142 |
143 | ..\Resources\record.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
144 |
145 |
146 | ..\Resources\save.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
147 |
148 |
149 | ..\Resources\stop.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
150 |
151 |
--------------------------------------------------------------------------------
/Silence/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Silence.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Silence/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Silence/RepetitionsDialog.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Silence
2 | {
3 | partial class RepetitionsDialog
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RepetitionsDialog));
32 | this.cancelButton = new System.Windows.Forms.Button();
33 | this.buttonPanel = new System.Windows.Forms.Panel();
34 | this.okButton = new System.Windows.Forms.Button();
35 | this.panel2 = new System.Windows.Forms.Panel();
36 | this.repetitionsLabel = new System.Windows.Forms.Label();
37 | this.repetitionsSelector = new System.Windows.Forms.NumericUpDown();
38 | this.buttonPanel.SuspendLayout();
39 | ((System.ComponentModel.ISupportInitialize)(this.repetitionsSelector)).BeginInit();
40 | this.SuspendLayout();
41 | //
42 | // cancelButton
43 | //
44 | this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
45 | this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
46 | this.cancelButton.Location = new System.Drawing.Point(163, 13);
47 | this.cancelButton.Name = "cancelButton";
48 | this.cancelButton.Size = new System.Drawing.Size(75, 23);
49 | this.cancelButton.TabIndex = 0;
50 | this.cancelButton.Text = "Cancel";
51 | this.cancelButton.UseVisualStyleBackColor = true;
52 | this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
53 | //
54 | // buttonPanel
55 | //
56 | this.buttonPanel.BackColor = System.Drawing.Color.White;
57 | this.buttonPanel.Controls.Add(this.okButton);
58 | this.buttonPanel.Controls.Add(this.cancelButton);
59 | this.buttonPanel.Dock = System.Windows.Forms.DockStyle.Bottom;
60 | this.buttonPanel.Location = new System.Drawing.Point(0, 51);
61 | this.buttonPanel.Name = "buttonPanel";
62 | this.buttonPanel.Size = new System.Drawing.Size(250, 48);
63 | this.buttonPanel.TabIndex = 1;
64 | //
65 | // okButton
66 | //
67 | this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
68 | this.okButton.Location = new System.Drawing.Point(82, 13);
69 | this.okButton.Name = "okButton";
70 | this.okButton.Size = new System.Drawing.Size(75, 23);
71 | this.okButton.TabIndex = 1;
72 | this.okButton.Text = "OK";
73 | this.okButton.UseVisualStyleBackColor = true;
74 | this.okButton.Click += new System.EventHandler(this.okButton_Click);
75 | //
76 | // panel2
77 | //
78 | this.panel2.BackColor = System.Drawing.Color.Silver;
79 | this.panel2.Dock = System.Windows.Forms.DockStyle.Bottom;
80 | this.panel2.Location = new System.Drawing.Point(0, 50);
81 | this.panel2.Name = "panel2";
82 | this.panel2.Size = new System.Drawing.Size(250, 1);
83 | this.panel2.TabIndex = 2;
84 | //
85 | // repetitionsLabel
86 | //
87 | this.repetitionsLabel.AutoSize = true;
88 | this.repetitionsLabel.Location = new System.Drawing.Point(13, 18);
89 | this.repetitionsLabel.Name = "repetitionsLabel";
90 | this.repetitionsLabel.Size = new System.Drawing.Size(63, 13);
91 | this.repetitionsLabel.TabIndex = 3;
92 | this.repetitionsLabel.Text = "Repetitions:";
93 | //
94 | // repetitionsSelector
95 | //
96 | this.repetitionsSelector.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
97 | | System.Windows.Forms.AnchorStyles.Right)));
98 | this.repetitionsSelector.Location = new System.Drawing.Point(83, 14);
99 | this.repetitionsSelector.Maximum = new decimal(new int[] {
100 | 1000000,
101 | 0,
102 | 0,
103 | 0});
104 | this.repetitionsSelector.Minimum = new decimal(new int[] {
105 | 1,
106 | 0,
107 | 0,
108 | 0});
109 | this.repetitionsSelector.Name = "repetitionsSelector";
110 | this.repetitionsSelector.Size = new System.Drawing.Size(155, 20);
111 | this.repetitionsSelector.TabIndex = 4;
112 | this.repetitionsSelector.Value = new decimal(new int[] {
113 | 1,
114 | 0,
115 | 0,
116 | 0});
117 | //
118 | // RepetitionsDialog
119 | //
120 | this.AcceptButton = this.okButton;
121 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
122 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
123 | this.CancelButton = this.cancelButton;
124 | this.ClientSize = new System.Drawing.Size(250, 99);
125 | this.Controls.Add(this.repetitionsSelector);
126 | this.Controls.Add(this.repetitionsLabel);
127 | this.Controls.Add(this.panel2);
128 | this.Controls.Add(this.buttonPanel);
129 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
130 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
131 | this.MaximizeBox = false;
132 | this.MinimizeBox = false;
133 | this.Name = "RepetitionsDialog";
134 | this.ShowIcon = false;
135 | this.ShowInTaskbar = false;
136 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
137 | this.Text = "Repetitions";
138 | this.buttonPanel.ResumeLayout(false);
139 | ((System.ComponentModel.ISupportInitialize)(this.repetitionsSelector)).EndInit();
140 | this.ResumeLayout(false);
141 | this.PerformLayout();
142 |
143 | }
144 |
145 | #endregion
146 |
147 | private System.Windows.Forms.Button cancelButton;
148 | private System.Windows.Forms.Panel buttonPanel;
149 | private System.Windows.Forms.Button okButton;
150 | private System.Windows.Forms.Panel panel2;
151 | private System.Windows.Forms.Label repetitionsLabel;
152 | private System.Windows.Forms.NumericUpDown repetitionsSelector;
153 | }
154 | }
--------------------------------------------------------------------------------
/Silence/RepetitionsDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 |
10 | namespace Silence
11 | {
12 | public partial class RepetitionsDialog : Form
13 | {
14 | public int Repetitions
15 | {
16 | get { return (int)repetitionsSelector.Value; }
17 | set { repetitionsSelector.Value = value; }
18 | }
19 |
20 | public RepetitionsDialog()
21 | {
22 | InitializeComponent();
23 | }
24 |
25 | private void okButton_Click(object sender, EventArgs e)
26 | {
27 | this.DialogResult = DialogResult.OK;
28 | this.Close();
29 | }
30 |
31 | private void cancelButton_Click(object sender, EventArgs e)
32 | {
33 | this.DialogResult = DialogResult.Cancel;
34 | this.Close();
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Silence/Resources/clear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lambdacasserole/silence/9df98f5542252c3780ffe7c7afe31a83fe04526d/Silence/Resources/clear.png
--------------------------------------------------------------------------------
/Silence/Resources/loop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lambdacasserole/silence/9df98f5542252c3780ffe7c7afe31a83fe04526d/Silence/Resources/loop.png
--------------------------------------------------------------------------------
/Silence/Resources/menu_closed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lambdacasserole/silence/9df98f5542252c3780ffe7c7afe31a83fe04526d/Silence/Resources/menu_closed.png
--------------------------------------------------------------------------------
/Silence/Resources/menu_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lambdacasserole/silence/9df98f5542252c3780ffe7c7afe31a83fe04526d/Silence/Resources/menu_open.png
--------------------------------------------------------------------------------
/Silence/Resources/open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lambdacasserole/silence/9df98f5542252c3780ffe7c7afe31a83fe04526d/Silence/Resources/open.png
--------------------------------------------------------------------------------
/Silence/Resources/pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lambdacasserole/silence/9df98f5542252c3780ffe7c7afe31a83fe04526d/Silence/Resources/pause.png
--------------------------------------------------------------------------------
/Silence/Resources/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lambdacasserole/silence/9df98f5542252c3780ffe7c7afe31a83fe04526d/Silence/Resources/play.png
--------------------------------------------------------------------------------
/Silence/Resources/record.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lambdacasserole/silence/9df98f5542252c3780ffe7c7afe31a83fe04526d/Silence/Resources/record.png
--------------------------------------------------------------------------------
/Silence/Resources/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lambdacasserole/silence/9df98f5542252c3780ffe7c7afe31a83fe04526d/Silence/Resources/save.png
--------------------------------------------------------------------------------
/Silence/Resources/stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lambdacasserole/silence/9df98f5542252c3780ffe7c7afe31a83fe04526d/Silence/Resources/stop.png
--------------------------------------------------------------------------------
/Silence/Silence.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {1CBBC97A-D669-48FA-81D3-E5CBD5E55C7B}
8 | WinExe
9 | Properties
10 | Silence
11 | Silence
12 | v4.8
13 | 512
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 | silence.ico
37 |
38 |
39 | app.manifest
40 |
41 |
42 |
43 | ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
44 | True
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | Component
62 |
63 |
64 | Form
65 |
66 |
67 | FormMain.cs
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Form
76 |
77 |
78 | RepetitionsDialog.cs
79 |
80 |
81 |
82 | FormMain.cs
83 |
84 |
85 | ResXFileCodeGenerator
86 | Resources.Designer.cs
87 | Designer
88 |
89 |
90 | True
91 | Resources.resx
92 | True
93 |
94 |
95 | RepetitionsDialog.cs
96 |
97 |
98 |
99 | PreserveNewest
100 |
101 |
102 | PreserveNewest
103 |
104 |
105 |
106 | SettingsSingleFileGenerator
107 | Settings.Designer.cs
108 |
109 |
110 | True
111 | Settings.settings
112 | True
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 | {63b186aa-962c-4a5f-90ee-268bbb5377f2}
148 | Silence.Macro
149 |
150 |
151 |
152 |
153 |
154 |
155 |
162 |
--------------------------------------------------------------------------------
/Silence/ThemeColor.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 |
3 | namespace Silence
4 | {
5 | ///
6 | /// Represents a base theme color for the application.
7 | ///
8 | internal class ThemeColor
9 | {
10 | ///
11 | /// The color's red component.
12 | ///
13 | public int R { get; set; }
14 |
15 | ///
16 | /// The color's green component.
17 | ///
18 | public int G { get; set; }
19 |
20 | ///
21 | /// The color's blue component.
22 | ///
23 | public int B { get; set; }
24 |
25 | ///
26 | /// Initialises a new instance of a theme color.
27 | ///
28 | /// The red component.
29 | /// The green component.
30 | /// The blue component.
31 | public ThemeColor(int r, int g, int b)
32 | {
33 | R = r;
34 | G = g;
35 | B = b;
36 | }
37 |
38 | ///
39 | /// Initialises a new instance of a theme color.
40 | ///
41 | public ThemeColor() : this(0, 0, 0)
42 | {
43 | }
44 |
45 | ///
46 | /// Returns this theme color as a Color object.
47 | ///
48 | /// The brightness modifier to apply to the returned Color object.
49 | ///
50 | public Color ToColor(int brightness = 0)
51 | {
52 | // Add brightness modifier, limit to valid range.
53 | var r = R + brightness;
54 | r = r > 255 ? 255 : (r < 0 ? 0 : r);
55 | var g = G + brightness;
56 | g = g > 255 ? 255 : (g < 0 ? 0 : g);
57 | var b = B + brightness;
58 | b = b > 255 ? 255 : (b < 0 ? 0 : b);
59 |
60 | return Color.FromArgb(255, r, g, b);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Silence/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
54 |
55 |
56 |
57 | true
58 | true
59 |
60 |
61 |
62 |
63 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/Silence/lang/lang_en.json:
--------------------------------------------------------------------------------
1 | {
2 | "Code": "en",
3 | "Name": "English",
4 | "LocalizedStrings": {
5 | "confirm_append_message": "This will continue appending to your current macro, would you like to start over and clear the current macro?",
6 | "confirm_append_title": "Clear Macro?",
7 | "confirm_clear_message": "Are you sure you want to clear the current macro?",
8 | "confirm_clear_title": "Clear Macro?",
9 | "confirm_open_message": "Are you sure you want to load this file and overwrite the currently recorded macro?",
10 | "confirm_open_title": "Clear Macro?",
11 | "error_save_nomacro_message": "There is no macro currently recorded.",
12 | "error_save_nomacro_title": "Cannot Save Macro",
13 | "dialog_save_macro_title": "Save Macro",
14 | "dialog_save_macro_filter": "Silence Macro Files (*.hush)|*.hush|All Files (*.*)|*.*",
15 | "dialog_open_macro_title": "Open Macro",
16 | "dialog_open_macro_filter": "Silence Macro Files (*.hush)|*.hush|All Files (*.*)|*.*"
17 | }
18 | }
--------------------------------------------------------------------------------
/Silence/lang/lang_zh.json:
--------------------------------------------------------------------------------
1 | {
2 | "Code": "zh",
3 | "Name": "Chinese",
4 | "LocalizedStrings": {
5 | "confirm_append_message": "您想要追加到您的现有宏或重新开始?",
6 | "confirm_append_title": "继续或重新开始?",
7 | "confirm_clear_message": "您真的想要删除您的现有宏?",
8 | "confirm_clear_title": "删除现有宏?",
9 | "confirm_open_message": "您真的想要打开这个宏文件和删除您的现有宏?",
10 | "confirm_open_title": "删除现有宏?",
11 | "error_save_nomacro_message": "不可能保存文件因为没有现有宏。",
12 | "error_save_nomacro_title": "不可能保存宏",
13 | "dialog_save_macro_title": "保存宏文件",
14 | "dialog_save_macro_filter": "Silence的宏文件 (*.hush)|*.hush|所有文件 (*.*)|*.*",
15 | "dialog_open_macro_title": "打开宏文件",
16 | "dialog_open_macro_filter": "Silence的宏文件 (*.hush)|*.hush|所有文件 (*.*)|*.*"
17 | }
18 | }
--------------------------------------------------------------------------------
/Silence/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Silence/silence.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lambdacasserole/silence/9df98f5542252c3780ffe7c7afe31a83fe04526d/Silence/silence.ico
--------------------------------------------------------------------------------