StephaneLenclud@125: using System; StephaneLenclud@126: using System.IO; StephaneLenclud@125: using System.Collections.Generic; StephaneLenclud@125: using System.Linq; StephaneLenclud@125: using System.Text; StephaneLenclud@125: using System.Threading.Tasks; StephaneLenclud@125: using System.Diagnostics; StephaneLenclud@125: using System.Runtime.InteropServices; StephaneLenclud@125: using System.Windows.Forms; StephaneLenclud@125: // StephaneLenclud@125: using Hid = SharpLib.Hid; StephaneLenclud@125: using SharpLib.Win32; StephaneLenclud@125: StephaneLenclud@125: namespace SharpDisplayManager StephaneLenclud@125: { StephaneLenclud@138: /// StephaneLenclud@138: /// Implement handling of HID input reports notably to be able to launch an application using the Green Start button from IR remotes. StephaneLenclud@138: /// StephaneLenclud@131: [System.ComponentModel.DesignerCategory("Code")] StephaneLenclud@131: public class MainFormHid : Form StephaneLenclud@131: { StephaneLenclud@131: [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "SwitchToThisWindow")] StephaneLenclud@131: public static extern void SwitchToThisWindow([System.Runtime.InteropServices.InAttribute()] System.IntPtr hwnd, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)] bool fUnknown); StephaneLenclud@131: // StephaneLenclud@131: public delegate void OnHidEventDelegate(object aSender, Hid.Event aHidEvent); StephaneLenclud@126: StephaneLenclud@131: /// StephaneLenclud@131: /// Use notably to handle green start key from IR remote control StephaneLenclud@131: /// StephaneLenclud@131: private Hid.Handler iHidHandler; StephaneLenclud@126: StephaneLenclud@131: /// StephaneLenclud@131: /// Register HID devices so that we receive corresponding WM_INPUT messages. StephaneLenclud@131: /// StephaneLenclud@131: protected void RegisterHidDevices() StephaneLenclud@131: { StephaneLenclud@131: // Register the input device to receive the commands from the StephaneLenclud@131: // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp StephaneLenclud@131: // for the vendor defined usage page. StephaneLenclud@128: StephaneLenclud@131: RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[5]; StephaneLenclud@128: StephaneLenclud@131: int i = 0; StephaneLenclud@131: rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.WindowsMediaCenterRemoteControl; StephaneLenclud@131: rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.WindowsMediaCenter.WindowsMediaCenterRemoteControl; StephaneLenclud@131: rid[i].dwFlags = Const.RIDEV_INPUTSINK; StephaneLenclud@131: rid[i].hwndTarget = Handle; StephaneLenclud@128: StephaneLenclud@131: i++; StephaneLenclud@131: rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.Consumer; StephaneLenclud@131: rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.Consumer.ConsumerControl; StephaneLenclud@131: rid[i].dwFlags = Const.RIDEV_INPUTSINK; StephaneLenclud@131: rid[i].hwndTarget = Handle; StephaneLenclud@126: StephaneLenclud@131: i++; StephaneLenclud@131: rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.Consumer; StephaneLenclud@131: rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.Consumer.Selection; StephaneLenclud@131: rid[i].dwFlags = Const.RIDEV_INPUTSINK; StephaneLenclud@131: rid[i].hwndTarget = Handle; StephaneLenclud@125: StephaneLenclud@131: i++; StephaneLenclud@131: rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.GenericDesktopControls; StephaneLenclud@131: rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.GenericDesktop.SystemControl; StephaneLenclud@131: rid[i].dwFlags = Const.RIDEV_INPUTSINK; StephaneLenclud@131: rid[i].hwndTarget = Handle; StephaneLenclud@125: StephaneLenclud@131: i++; StephaneLenclud@131: rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.GenericDesktopControls; StephaneLenclud@131: rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.GenericDesktop.GamePad; StephaneLenclud@131: rid[i].dwFlags = Const.RIDEV_INPUTSINK; StephaneLenclud@131: rid[i].hwndTarget = Handle; StephaneLenclud@125: StephaneLenclud@131: //i++; StephaneLenclud@131: //rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.GenericDesktopControls; StephaneLenclud@131: //rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.GenericDesktop.Keyboard; StephaneLenclud@131: //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK; StephaneLenclud@131: //rid[i].hwndTarget = Handle; StephaneLenclud@125: StephaneLenclud@131: //i++; StephaneLenclud@131: //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls; StephaneLenclud@131: //rid[i].usUsage = (ushort)Hid.UsageCollection.GenericDesktop.Mouse; StephaneLenclud@131: //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK; StephaneLenclud@131: //rid[i].hwndTarget = aHWND; StephaneLenclud@125: StephaneLenclud@125: StephaneLenclud@131: iHidHandler = new SharpLib.Hid.Handler(rid); StephaneLenclud@131: if (!iHidHandler.IsRegistered) StephaneLenclud@131: { StephaneLenclud@131: Debug.WriteLine("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString()); StephaneLenclud@131: } StephaneLenclud@131: iHidHandler.OnHidEvent += HandleHidEventThreadSafe; StephaneLenclud@131: } StephaneLenclud@125: StephaneLenclud@131: /// StephaneLenclud@131: /// Here we receive HID events from our HID library. StephaneLenclud@131: /// StephaneLenclud@131: /// StephaneLenclud@131: /// StephaneLenclud@131: public void HandleHidEventThreadSafe(object aSender, SharpLib.Hid.Event aHidEvent) StephaneLenclud@131: { StephaneLenclud@131: if (aHidEvent.IsStray) StephaneLenclud@131: { StephaneLenclud@131: //Stray event just ignore it StephaneLenclud@131: return; StephaneLenclud@131: } StephaneLenclud@125: StephaneLenclud@131: if (this.InvokeRequired) StephaneLenclud@131: { StephaneLenclud@131: //Not in the proper thread, invoke ourselves StephaneLenclud@131: OnHidEventDelegate d = new OnHidEventDelegate(HandleHidEventThreadSafe); StephaneLenclud@131: this.Invoke(d, new object[] { aSender, aHidEvent }); StephaneLenclud@131: } StephaneLenclud@131: else StephaneLenclud@131: { StephaneLenclud@131: //We are in the proper thread StephaneLenclud@131: if (aHidEvent.Usages.Count > 0 StephaneLenclud@131: && aHidEvent.UsagePage == (ushort)Hid.UsagePage.WindowsMediaCenterRemoteControl StephaneLenclud@131: && aHidEvent.Usages[0] == (ushort)Hid.Usage.WindowsMediaCenterRemoteControl.GreenStart) StephaneLenclud@131: //&& aHidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer StephaneLenclud@131: //&& aHidEvent.Usages[0] == (ushort)Hid.Usage.ConsumerControl.ThinkPadFullscreenMagnifier) StephaneLenclud@131: { StephaneLenclud@131: //First check if the process we want to launch already exists StephaneLenclud@131: string procName = Path.GetFileNameWithoutExtension(Properties.Settings.Default.StartFileName); StephaneLenclud@131: Process[] existingProcesses = Process.GetProcessesByName(procName); StephaneLenclud@131: if (existingProcesses == null || existingProcesses.Length == 0) StephaneLenclud@131: { StephaneLenclud@131: // Process do not exists just try to launch it StephaneLenclud@131: ProcessStartInfo start = new ProcessStartInfo(); StephaneLenclud@131: // Enter in the command line arguments, everything you would enter after the executable name itself StephaneLenclud@131: //start.Arguments = arguments; StephaneLenclud@131: // Enter the executable to run, including the complete path StephaneLenclud@131: start.FileName = Properties.Settings.Default.StartFileName; StephaneLenclud@131: start.WindowStyle = ProcessWindowStyle.Normal; StephaneLenclud@131: start.CreateNoWindow = true; StephaneLenclud@131: start.UseShellExecute = true; StephaneLenclud@131: // Run the external process & wait for it to finish StephaneLenclud@131: Process proc = Process.Start(start); StephaneLenclud@125: StephaneLenclud@131: //SL: We could have used that too StephaneLenclud@131: //Shell32.Shell shell = new Shell32.Shell(); StephaneLenclud@131: //shell.ShellExecute(Properties.Settings.Default.StartFileName); StephaneLenclud@131: } StephaneLenclud@131: else StephaneLenclud@131: { StephaneLenclud@131: //This won't work properly until we have a manifest that enables uiAccess. StephaneLenclud@131: //However uiAccess just won't work with ClickOnce so we will have to use a different deployment system. StephaneLenclud@131: SwitchToThisWindow(existingProcesses[0].MainWindowHandle, true); StephaneLenclud@131: } StephaneLenclud@131: } StephaneLenclud@131: } StephaneLenclud@131: } StephaneLenclud@125: StephaneLenclud@131: /// StephaneLenclud@131: /// We need to handle WM_INPUT. StephaneLenclud@131: /// StephaneLenclud@131: /// StephaneLenclud@131: protected override void WndProc(ref Message message) StephaneLenclud@131: { StephaneLenclud@131: switch (message.Msg) StephaneLenclud@131: { StephaneLenclud@131: case Const.WM_INPUT: StephaneLenclud@131: //Returning zero means we processed that message. StephaneLenclud@131: message.Result = new IntPtr(0); StephaneLenclud@131: iHidHandler.ProcessInput(ref message); StephaneLenclud@131: break; StephaneLenclud@131: } StephaneLenclud@131: //Is that needed? Check the docs. StephaneLenclud@131: base.WndProc(ref message); StephaneLenclud@131: } StephaneLenclud@131: } StephaneLenclud@125: }