2 * This file is part of the libCEC(R) library.
4 * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
5 * libCEC(R) is an original work, containing original code.
7 * libCEC(R) is a trademark of Pulse-Eight Limited.
9 * This program is dual-licensed; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * Alternatively, you can license this library under a commercial license,
25 * please contact Pulse-Eight Licensing for more information.
27 * For more information contact:
28 * Pulse-Eight Licensing <license@pulse-eight.com>
29 * http://www.pulse-eight.com/
30 * http://www.pulse-eight.net/
34 using System.Runtime.InteropServices;
35 using System.Diagnostics;
36 using System.Reflection;
37 using LibCECTray.Properties;
39 namespace LibCECTray.controller.applications
42 /// Windows API methods and types
44 internal class WindowsAPI
47 public enum VirtualKeyCode : ushort
179 VK_BROWSER_BACK = 0xA6,
180 VK_BROWSER_FORWARD = 0xA7,
181 VK_BROWSER_REFRESH = 0xA8,
182 VK_BROWSER_STOP = 0xA9,
183 VK_BROWSER_SEARCH = 0xAA,
184 VK_BROWSER_FAVORITES = 0xAB,
185 VK_BROWSER_HOME = 0xAC,
186 VK_VOLUME_MUTE = 0xAD,
187 VK_VOLUME_DOWN = 0xAE,
189 VK_MEDIA_NEXT_TRACK = 0xB0,
190 VK_MEDIA_PREV_TRACK = 0xB1,
191 VK_MEDIA_STOP = 0xB2,
192 VK_MEDIA_PLAY_PAUSE = 0xB3,
193 VK_LAUNCH_MAIL = 0xB4,
194 VK_LAUNCH_MEDIA_SELECT = 0xB5,
195 VK_LAUNCH_APP1 = 0xB6,
196 VK_LAUNCH_APP2 = 0xB7,
201 VK_OEM_PERIOD = 0xBE,
210 VK_PROCESSKEY = 0xE5,
223 public static string GetVirtualKeyName(VirtualKeyCode key)
225 var keyName = Enum.GetName(typeof(VirtualKeyCode), key).ToUpper();
226 var friendlyName = Resources.ResourceManager.GetString(keyName, Resources.Culture);
227 return friendlyName ?? keyName.ToLower().Substring(3).Replace('_', ' ');
230 public enum InputType : uint
237 public enum KeyEvent : uint
239 ExtendedKey = 0x0001,
245 public enum XButton : uint
251 public enum MouseEvent : uint
263 VirtualDesk = 0x4000,
272 #pragma warning disable 649
273 public struct MouseInput
277 public UInt32 MouseData;
280 public IntPtr ExtraInfo;
282 public struct KeyboardInput
284 public UInt16 KeyCode;
288 public IntPtr ExtraInfo;
290 public struct HardwareInput
293 public UInt16 ParamL;
294 public UInt16 ParamH;
297 [StructLayout(LayoutKind.Explicit)]
298 public struct CombinedInput
301 public MouseInput Mouse;
303 public KeyboardInput Keyboard;
305 public HardwareInput Hardware;
310 public InputType Type;
311 public CombinedInput Data;
313 #pragma warning restore 649
317 [DllImport("kernel32.dll")]
318 public static extern uint GetCurrentThreadId();
320 [DllImport("kernel32.dll", SetLastError = true)]
321 public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer,
322 int dwSize, out int lpNumberOfBytesRead);
324 [DllImport("user32.dll")]
325 public static extern IntPtr GetForegroundWindow();
327 [DllImport("user32.dll", SetLastError = true)]
328 public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
330 [DllImport("user32.dll")]
331 public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
333 [DllImport("user32.dll", SetLastError = true)]
334 public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass,
337 [DllImport("user32.Dll", EntryPoint = "PostMessageA")]
338 public static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
340 [DllImport("user32.dll")]
341 public static extern byte VkKeyScan(char ch);
343 [DllImport("user32.dll")]
344 public static extern uint MapVirtualKey(uint uCode, uint uMapType);
346 [DllImport("user32.dll")]
347 public static extern IntPtr SetFocus(IntPtr hWnd);
349 [DllImport("user32.dll", CharSet = CharSet.Unicode)]
350 [return: MarshalAs(UnmanagedType.Bool)]
351 public static extern bool SetForegroundWindow(IntPtr hWnd);
353 [DllImport("user32.dll", CharSet = CharSet.Unicode)]
354 [return: MarshalAs(UnmanagedType.Bool)]
355 public static extern bool AllowSetForegroundWindow(int dwProcessId);
357 [DllImport("user32.dll")]
358 public static extern uint SendInput(uint numberOfInputs,
359 [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] Input[] input, int structSize);
361 [DllImport("user32.dll")]
362 public static extern IntPtr GetMessageExtraInfo();
364 [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
365 public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
367 [DllImport("user32.dll", CharSet = CharSet.Unicode)]
368 public static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
370 [DllImport("user32.dll", CharSet = CharSet.Unicode)]
371 public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
375 /// Forces a window to the foreground
377 /// <param name="windowHandle">Window that becomes the foreground window</param>
378 /// <returns>True when succeeded, false otherwise</returns>
379 public static bool ForceForeground(IntPtr windowHandle)
381 // get current foreground
382 var currentForeground = GetForegroundWindow();
384 // window already foreground window
385 if (currentForeground == windowHandle)
390 var windowThreadId = GetWindowThreadProcessId(windowHandle, out temp);
392 // attach thread input
393 if (currentForeground != IntPtr.Zero && !AttachThreadInput(GetCurrentThreadId(), windowThreadId, true))
397 SetForegroundWindow(windowHandle);
398 while (GetForegroundWindow() != windowHandle){}
401 if (currentForeground != IntPtr.Zero)
402 AttachThreadInput(GetCurrentThreadId(), windowThreadId, false);
404 return (GetForegroundWindow() == windowHandle);
408 /// Makes an application the foreground window and send input to it
410 /// <param name="windowHandle">The window to send the input to</param>
411 /// <param name="numberOfInputs">Number of inputs in the input parameter</param>
412 /// <param name="input">The input to send</param>
413 /// <param name="structSize">The size of an input struct</param>
414 /// <returns>True when sent false otherwise</returns>
415 public static bool SendInputTo(IntPtr windowHandle, uint numberOfInputs, Input[] input, int structSize)
417 return ShowWindowAsync(windowHandle, (int)ShowType.ShowNormal) &&
418 ForceForeground(windowHandle) &&
419 SendInput(numberOfInputs, input, structSize) == 0;
423 /// Find a window handle given it's name
425 /// <param name="name">The name of the window</param>
426 /// <returns>The requested handle, or IntPtr.Zero when not found</returns>
427 public static IntPtr FindWindow(string name)
429 foreach (var proc in Process.GetProcesses())
431 if (proc.MainWindowTitle == name)
432 return proc.MainWindowHandle;
439 /// Check whether there's another instance of this program running, and return the process when found
441 /// <returns>The running process, or null when not found</returns>
442 public static Process RunningInstance()
444 var current = Process.GetCurrentProcess();
445 foreach (var process in Process.GetProcessesByName(current.ProcessName))
447 if (process.Id != current.Id && Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)