[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / SendKeys.cs
blob6a5c10367bf08fa5266d5a23b11033011bab9857
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
22 // Authors:
23 // Peter Bartok (pbartok@novell.com)
24 // Andreia Gaita (avidigal@novell.com)
28 using System.Collections;
29 using System.Runtime.InteropServices;
30 using System.Text;
32 namespace System.Windows.Forms {
35 public class SendKeys {
36 private struct Keyword {
37 public Keyword(string keyword, int vk) {
38 this.keyword = keyword;
39 this.vk = vk;
41 internal string keyword;
42 internal int vk;
45 #region Local variables
46 private static Queue keys = new Queue();
47 private static Hashtable keywords;
48 #endregion
50 static SendKeys() {
51 SendKeys.keywords = new Hashtable();
53 keywords.Add("BACKSPACE", (int)Keys.Back);
54 keywords.Add("BS", (int)Keys.Back);
55 keywords.Add("BKSP", (int)Keys.Back);
56 keywords.Add("BREAK", (int)Keys.Cancel);
57 keywords.Add("CAPSLOCK", (int)Keys.CapsLock);
58 keywords.Add("DELETE", (int)Keys.Delete);
59 keywords.Add("DEL", (int)Keys.Delete);
60 keywords.Add("DOWN", (int)Keys.Down);
61 keywords.Add("END", (int)Keys.End);
62 keywords.Add("ENTER", (int)Keys.Enter);
63 keywords.Add("~", (int)Keys.Enter);
64 keywords.Add("ESC", (int)Keys.Escape);
65 keywords.Add("HELP", (int)Keys.Help);
66 keywords.Add("HOME", (int)Keys.Home);
67 keywords.Add("INSERT", (int)Keys.Insert);
68 keywords.Add("INS", (int)Keys.Insert);
69 keywords.Add("LEFT", (int)Keys.Left);
70 keywords.Add("NUMLOCK", (int)Keys.NumLock);
71 keywords.Add("PGDN", (int)Keys.PageDown);
72 keywords.Add("PGUP", (int)Keys.PageUp);
73 keywords.Add("PRTSC", (int)Keys.PrintScreen);
74 keywords.Add("RIGHT", (int)Keys.Right);
75 keywords.Add("SCROLLLOCK", (int)Keys.Scroll);
76 keywords.Add("TAB", (int)Keys.Tab);
77 keywords.Add("UP", (int)Keys.Up);
78 keywords.Add("F1", (int)Keys.F1);
79 keywords.Add("F2", (int)Keys.F2);
80 keywords.Add("F3", (int)Keys.F3);
81 keywords.Add("F4", (int)Keys.F4);
82 keywords.Add("F5", (int)Keys.F5);
83 keywords.Add("F6", (int)Keys.F6);
84 keywords.Add("F7", (int)Keys.F7);
85 keywords.Add("F8", (int)Keys.F8);
86 keywords.Add("F9", (int)Keys.F9);
87 keywords.Add("F10", (int)Keys.F10);
88 keywords.Add("F11", (int)Keys.F11);
89 keywords.Add("F12", (int)Keys.F12);
90 keywords.Add("F13", (int)Keys.F13);
91 keywords.Add("F14", (int)Keys.F14);
92 keywords.Add("F15", (int)Keys.F15);
93 keywords.Add("F16", (int)Keys.F16);
94 keywords.Add("ADD", (int)Keys.Add);
95 keywords.Add("SUBTRACT", (int)Keys.Subtract);
96 keywords.Add("MULTIPLY", (int)Keys.Multiply);
97 keywords.Add("DIVIDE", (int)Keys.Divide);
98 keywords.Add("+", (int)Keys.ShiftKey);
99 keywords.Add("^", (int)Keys.ControlKey);
100 keywords.Add("%", (int)Keys.Menu);
103 #region Private methods
105 private SendKeys() {
109 private static void AddVKey(int vk, bool down)
111 MSG msg = new MSG();
112 msg.message = down ? Msg.WM_KEYDOWN : Msg.WM_KEYUP;
113 msg.wParam = new IntPtr(vk);
114 msg.lParam = IntPtr.Zero;
115 keys.Enqueue(msg);
118 private static void AddVKey(int vk, int repeat_count)
120 MSG msg;
122 for (int i = 0; i < repeat_count; i++ ) {
123 msg = new MSG();
124 msg.message = Msg.WM_KEYDOWN;
125 msg.wParam = new IntPtr(vk);
126 msg.lParam = (IntPtr)1;
127 keys.Enqueue(msg);
129 msg = new MSG();
130 msg.message = Msg.WM_KEYUP;
131 msg.wParam = new IntPtr(vk);
132 msg.lParam = IntPtr.Zero;
133 keys.Enqueue(msg);
138 private static void AddKey(char key, int repeat_count) {
139 MSG msg;
141 for (int i = 0; i < repeat_count; i++ ) {
142 msg = new MSG();
143 msg.message = Msg.WM_KEYDOWN;
144 msg.wParam = new IntPtr(key);
145 msg.lParam = IntPtr.Zero;
146 keys.Enqueue(msg);
148 msg = new MSG();
149 msg.message = Msg.WM_KEYUP;
150 msg.wParam = new IntPtr(key);
151 msg.lParam = IntPtr.Zero;
152 keys.Enqueue(msg);
156 private static void Parse(string key_string) {
157 bool isBlock = false;
158 bool isVkey = false;
159 bool isRepeat = false;
160 bool isShift = false;
161 bool isCtrl = false;
162 bool isAlt = false;
164 StringBuilder repeats = new StringBuilder();
165 StringBuilder group_string = new StringBuilder();
167 int key_len = key_string.Length;
168 for (int i = 0; i < key_len; i++) {
169 switch(key_string[i]) {
170 case '{':
172 group_string.Remove(0, group_string.Length);
173 repeats.Remove(0, repeats.Length);
174 int start = i+1;
175 for (; start < key_len && key_string[start] != '}'; start++) {
176 if (Char.IsWhiteSpace(key_string[start])) {
177 if (isRepeat)
178 throw new ArgumentException("SendKeys string {0} is not valid.", key_string);
180 isRepeat = true;
181 continue;
183 if (isRepeat) {
184 if (!Char.IsDigit(key_string[start]))
185 throw new ArgumentException("SendKeys string {0} is not valid.", key_string);
187 repeats.Append(key_string[start]);
189 continue;
192 group_string.Append(key_string[start]);
194 if (start == key_len || start == i+1)
195 throw new ArgumentException("SendKeys string {0} is not valid.", key_string);
197 else if (SendKeys.keywords.Contains(group_string.ToString().ToUpper())) {
198 isVkey = true;
200 else {
201 throw new ArgumentException("SendKeys string {0} is not valid.", key_string);
204 int repeat = 1;
205 if (repeats.Length > 0)
206 repeat = Int32.Parse(repeats.ToString());
207 if (isVkey)
208 AddVKey((int)keywords[group_string.ToString().ToUpper()], repeats.Length == 0 ? 1 : repeat);
209 else {
210 if (Char.IsUpper(Char.Parse(group_string.ToString()))) {
211 if (!isShift)
212 AddVKey((int)keywords["+"], true);
213 AddKey(Char.Parse(group_string.ToString()), 1);
214 if (!isShift)
215 AddVKey((int)keywords["+"], false);
217 else
218 AddKey(Char.Parse(group_string.ToString().ToUpper()), repeats.Length == 0 ? 1 : repeat);
221 i = start;
222 isRepeat = isVkey = false;
223 if (isShift)
224 AddVKey((int)keywords["+"], false);
225 if (isCtrl)
226 AddVKey((int)keywords["^"], false);
227 if (isAlt)
228 AddVKey((int)keywords["%"], false);
229 isShift = isCtrl = isAlt = false;
230 break;
232 case '+': {
233 AddVKey((int)keywords["+"], true);
234 isShift = true;;
235 break;
238 case '^': {
239 AddVKey((int)keywords["^"], true);
240 isCtrl = true;
241 break;
244 case '%': {
245 AddVKey((int)keywords["%"], true);
246 isAlt = true;
247 break;
250 case '~': {
251 AddVKey((int)keywords["ENTER"], 1);
252 break;
255 case '(':
256 isBlock = true;
257 break;
259 case ')': {
260 if (isShift)
261 AddVKey((int)keywords["+"], false);
262 if (isCtrl)
263 AddVKey((int)keywords["^"], false);
264 if (isAlt)
265 AddVKey((int)keywords["%"], false);
266 isShift = isCtrl = isAlt = isBlock = false;
267 break;
270 default: {
271 if (Char.IsUpper(key_string[i])) {
272 if (!isShift)
273 AddVKey((int)keywords["+"], true);
274 AddKey(key_string[i], 1);
275 if (!isShift)
276 AddVKey((int)keywords["+"], false);
278 else
279 AddKey(Char.Parse(key_string[i].ToString().ToUpper()), 1);
281 if (!isBlock) {
282 if (isShift)
283 AddVKey((int)keywords["+"], false);
284 if (isCtrl)
285 AddVKey((int)keywords["^"], false);
286 if (isAlt)
287 AddVKey((int)keywords["%"], false);
288 isShift = isCtrl = isAlt = isBlock = false;
290 break;
295 if (isBlock)
296 throw new ArgumentException("SendKeys string {0} is not valid.", key_string);
298 if (isShift)
299 AddVKey((int)keywords["+"], false);
300 if (isCtrl)
301 AddVKey((int)keywords["^"], false);
302 if (isAlt)
303 AddVKey((int)keywords["%"], false);
307 private static void SendInput() {
308 IntPtr hwnd = XplatUI.GetActive ();
310 if (hwnd != IntPtr.Zero) {
311 Form active = ((Form) Control.FromHandle (hwnd));
312 if (active != null && active.ActiveControl != null)
313 hwnd = active.ActiveControl.Handle;
314 else if (active != null)
315 hwnd = active.Handle;
317 XplatUI.SendInput(hwnd, keys);
318 keys.Clear();
321 #endregion // Private Methods
323 #region Public Static Methods
324 public static void Flush() {
325 Application.DoEvents();
328 public static void Send(string keys) {
329 Parse(keys);
330 SendInput();
333 private static object lockobj = new object();
334 public static void SendWait(string keys) {
335 lock(lockobj) {
336 Send(keys);
338 Flush();
341 #endregion // Public Static Methods