Skip to content

Commit f2dee70

Browse files
committed
Rearrange extension methods and other small utilities to be more self-contained as single files, without depending on code from other files
1 parent 81b1601 commit f2dee70

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed

Src/WinForms.cs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Runtime.InteropServices;
5+
using System.Windows.Forms;
6+
7+
namespace RT.Util
8+
{
9+
public static partial class Ut
10+
{
11+
/// <summary>
12+
/// Sends the specified sequence of key strokes to the active application. See remarks for details.</summary>
13+
/// <param name="keys">
14+
/// A collection of objects of type <see cref="Keys"/>, <see cref="char"/>, or <c>System.Tuple&lt;Keys,
15+
/// bool&gt;</c>.</param>
16+
/// <exception cref="ArgumentNullException">
17+
/// <paramref name="keys"/> was null.</exception>
18+
/// <exception cref="ArgumentException">
19+
/// <paramref name="keys"/> contains an object which is of an unexpected type. Only <see cref="Keys"/>, <see
20+
/// cref="char"/> and <c>System.Tuple&lt;System.Windows.Forms.Keys, bool&gt;</c> are accepted.</exception>
21+
/// <remarks>
22+
/// <list type="bullet">
23+
/// <item><description>
24+
/// For objects of type <see cref="Keys"/>, the relevant key is pressed and released.</description></item>
25+
/// <item><description>
26+
/// For objects of type <see cref="char"/>, the specified Unicode character is simulated as a keypress and
27+
/// release.</description></item>
28+
/// <item><description>
29+
/// For objects of type <c>Tuple&lt;Keys, bool&gt;</c> or <c>ValueType&lt;Keys, bool&gt;</c>, the bool
30+
/// specifies whether to simulate only a key-down (false) or only a key-up (true).</description></item></list></remarks>
31+
/// <example>
32+
/// <para>
33+
/// The following example demonstrates how to use this method to send the key combination Win+R:</para>
34+
/// <code>
35+
/// Ut.SendKeystrokes(Ut.NewArray&lt;object&gt;(
36+
/// (Keys.LWin, false),
37+
/// Keys.R,
38+
/// (Keys.LWin, true)
39+
/// ));</code></example>
40+
public static void SendKeystrokes(IEnumerable<object> keys)
41+
{
42+
if (keys == null)
43+
throw new ArgumentNullException(nameof(keys));
44+
45+
var input = new List<WinAPI.INPUT>();
46+
foreach (var elem in keys)
47+
{
48+
void sendTuple(Keys key, bool isUp)
49+
{
50+
var keyEvent = new WinAPI.INPUT
51+
{
52+
Type = WinAPI.INPUT_KEYBOARD,
53+
SpecificInput = new WinAPI.MOUSEKEYBDHARDWAREINPUT
54+
{
55+
Keyboard = new WinAPI.KEYBDINPUT { wVk = (ushort) key }
56+
}
57+
};
58+
if (isUp)
59+
keyEvent.SpecificInput.Keyboard.dwFlags |= WinAPI.KEYEVENTF_KEYUP;
60+
input.Add(keyEvent);
61+
}
62+
63+
if (elem is Tuple<Keys, bool> t)
64+
sendTuple(t.Item1, t.Item2);
65+
else if (elem is ValueTuple<Keys, bool> vt)
66+
sendTuple(vt.Item1, vt.Item2);
67+
else
68+
{
69+
if (!(elem is Keys || elem is char))
70+
throw new ArgumentException(@"The input collection is expected to contain only objects of type Keys, char, Tuple<Keys, bool> or ValueTuple<Keys, bool>.", nameof(keys));
71+
var keyDown = new WinAPI.INPUT
72+
{
73+
Type = WinAPI.INPUT_KEYBOARD,
74+
SpecificInput = new WinAPI.MOUSEKEYBDHARDWAREINPUT
75+
{
76+
Keyboard = (elem is Keys)
77+
? new WinAPI.KEYBDINPUT { wVk = (ushort) (Keys) elem }
78+
: new WinAPI.KEYBDINPUT { wScan = (char) elem, dwFlags = WinAPI.KEYEVENTF_UNICODE }
79+
}
80+
};
81+
var keyUp = keyDown;
82+
keyUp.SpecificInput.Keyboard.dwFlags |= WinAPI.KEYEVENTF_KEYUP;
83+
input.Add(keyDown);
84+
input.Add(keyUp);
85+
}
86+
}
87+
var inputArr = input.ToArray();
88+
WinAPI.SendInput((uint) inputArr.Length, inputArr, Marshal.SizeOf(input[0]));
89+
}
90+
91+
/// <summary>
92+
/// Sends the specified key the specified number of times.</summary>
93+
/// <param name="key">
94+
/// Key stroke to send.</param>
95+
/// <param name="times">
96+
/// Number of times to send the <paramref name="key"/>.</param>
97+
public static void SendKeystrokes(Keys key, int times)
98+
{
99+
if (times > 0)
100+
SendKeystrokes(Enumerable.Repeat((object) key, times));
101+
}
102+
103+
/// <summary>Sends key strokes equivalent to typing the specified text.</summary>
104+
public static void SendKeystrokesForText(string text)
105+
{
106+
if (!string.IsNullOrEmpty(text))
107+
SendKeystrokes(text.Cast<object>());
108+
}
109+
110+
/// <summary>Determines whether the Ctrl key is pressed.</summary>
111+
public static bool Ctrl { get { return Control.ModifierKeys.HasFlag(Keys.Control); } }
112+
/// <summary>Determines whether the Alt key is pressed.</summary>
113+
public static bool Alt { get { return Control.ModifierKeys.HasFlag(Keys.Alt); } }
114+
/// <summary>Determines whether the Shift key is pressed.</summary>
115+
public static bool Shift { get { return Control.ModifierKeys.HasFlag(Keys.Shift); } }
116+
}
117+
}

0 commit comments

Comments
 (0)