Server/MainForm.Hid.cs
author StephaneLenclud
Tue, 26 May 2015 12:23:55 +0200
changeset 138 426cc984fd18
parent 131 9262041d1320
child 150 728fe28168e2
permissions -rw-r--r--
Documentation and minor clean-up.
StephaneLenclud@125
     1
using System;
StephaneLenclud@126
     2
using System.IO;
StephaneLenclud@125
     3
using System.Collections.Generic;
StephaneLenclud@125
     4
using System.Linq;
StephaneLenclud@125
     5
using System.Text;
StephaneLenclud@125
     6
using System.Threading.Tasks;
StephaneLenclud@125
     7
using System.Diagnostics;
StephaneLenclud@125
     8
using System.Runtime.InteropServices;
StephaneLenclud@125
     9
using System.Windows.Forms;
StephaneLenclud@125
    10
//
StephaneLenclud@125
    11
using Hid = SharpLib.Hid;
StephaneLenclud@125
    12
using SharpLib.Win32;
StephaneLenclud@125
    13
StephaneLenclud@125
    14
namespace SharpDisplayManager
StephaneLenclud@125
    15
{
StephaneLenclud@138
    16
    /// <summary>
StephaneLenclud@138
    17
    /// Implement handling of HID input reports notably to be able to launch an application using the Green Start button from IR remotes.
StephaneLenclud@138
    18
    /// </summary>
StephaneLenclud@131
    19
    [System.ComponentModel.DesignerCategory("Code")]
StephaneLenclud@131
    20
    public class MainFormHid : Form
StephaneLenclud@131
    21
    {
StephaneLenclud@131
    22
        [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "SwitchToThisWindow")]
StephaneLenclud@131
    23
        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
    24
        //
StephaneLenclud@131
    25
        public delegate void OnHidEventDelegate(object aSender, Hid.Event aHidEvent);
StephaneLenclud@126
    26
StephaneLenclud@131
    27
        /// <summary>
StephaneLenclud@131
    28
        /// Use notably to handle green start key from IR remote control
StephaneLenclud@131
    29
        /// </summary>
StephaneLenclud@131
    30
        private Hid.Handler iHidHandler;
StephaneLenclud@126
    31
StephaneLenclud@131
    32
        /// <summary>
StephaneLenclud@131
    33
        /// Register HID devices so that we receive corresponding WM_INPUT messages.
StephaneLenclud@131
    34
        /// </summary>
StephaneLenclud@131
    35
        protected void RegisterHidDevices()
StephaneLenclud@131
    36
        {
StephaneLenclud@131
    37
            // Register the input device to receive the commands from the
StephaneLenclud@131
    38
            // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
StephaneLenclud@131
    39
            // for the vendor defined usage page.
StephaneLenclud@128
    40
StephaneLenclud@131
    41
            RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[5];
StephaneLenclud@128
    42
StephaneLenclud@131
    43
            int i = 0;
StephaneLenclud@131
    44
            rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.WindowsMediaCenterRemoteControl;
StephaneLenclud@131
    45
            rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.WindowsMediaCenter.WindowsMediaCenterRemoteControl;
StephaneLenclud@131
    46
            rid[i].dwFlags = Const.RIDEV_INPUTSINK;
StephaneLenclud@131
    47
            rid[i].hwndTarget = Handle;
StephaneLenclud@128
    48
StephaneLenclud@131
    49
            i++;
StephaneLenclud@131
    50
            rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.Consumer;
StephaneLenclud@131
    51
            rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.Consumer.ConsumerControl;
StephaneLenclud@131
    52
            rid[i].dwFlags = Const.RIDEV_INPUTSINK;
StephaneLenclud@131
    53
            rid[i].hwndTarget = Handle;
StephaneLenclud@126
    54
StephaneLenclud@131
    55
            i++;
StephaneLenclud@131
    56
            rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.Consumer;
StephaneLenclud@131
    57
            rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.Consumer.Selection;
StephaneLenclud@131
    58
            rid[i].dwFlags = Const.RIDEV_INPUTSINK;
StephaneLenclud@131
    59
            rid[i].hwndTarget = Handle;
StephaneLenclud@125
    60
StephaneLenclud@131
    61
            i++;
StephaneLenclud@131
    62
            rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.GenericDesktopControls;
StephaneLenclud@131
    63
            rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.GenericDesktop.SystemControl;
StephaneLenclud@131
    64
            rid[i].dwFlags = Const.RIDEV_INPUTSINK;
StephaneLenclud@131
    65
            rid[i].hwndTarget = Handle;
StephaneLenclud@125
    66
StephaneLenclud@131
    67
            i++;
StephaneLenclud@131
    68
            rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.GenericDesktopControls;
StephaneLenclud@131
    69
            rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.GenericDesktop.GamePad;
StephaneLenclud@131
    70
            rid[i].dwFlags = Const.RIDEV_INPUTSINK;
StephaneLenclud@131
    71
            rid[i].hwndTarget = Handle;
StephaneLenclud@125
    72
StephaneLenclud@131
    73
            //i++;
StephaneLenclud@131
    74
            //rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.GenericDesktopControls;
StephaneLenclud@131
    75
            //rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.GenericDesktop.Keyboard;
StephaneLenclud@131
    76
            //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
StephaneLenclud@131
    77
            //rid[i].hwndTarget = Handle;
StephaneLenclud@125
    78
StephaneLenclud@131
    79
            //i++;
StephaneLenclud@131
    80
            //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
StephaneLenclud@131
    81
            //rid[i].usUsage = (ushort)Hid.UsageCollection.GenericDesktop.Mouse;
StephaneLenclud@131
    82
            //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
StephaneLenclud@131
    83
            //rid[i].hwndTarget = aHWND;
StephaneLenclud@125
    84
StephaneLenclud@125
    85
StephaneLenclud@131
    86
            iHidHandler = new SharpLib.Hid.Handler(rid);
StephaneLenclud@131
    87
            if (!iHidHandler.IsRegistered)
StephaneLenclud@131
    88
            {
StephaneLenclud@131
    89
                Debug.WriteLine("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
StephaneLenclud@131
    90
            }
StephaneLenclud@131
    91
            iHidHandler.OnHidEvent += HandleHidEventThreadSafe;
StephaneLenclud@131
    92
        }
StephaneLenclud@125
    93
StephaneLenclud@131
    94
        /// <summary>
StephaneLenclud@131
    95
        /// Here we receive HID events from our HID library.
StephaneLenclud@131
    96
        /// </summary>
StephaneLenclud@131
    97
        /// <param name="aSender"></param>
StephaneLenclud@131
    98
        /// <param name="aHidEvent"></param>
StephaneLenclud@131
    99
        public void HandleHidEventThreadSafe(object aSender, SharpLib.Hid.Event aHidEvent)
StephaneLenclud@131
   100
        {
StephaneLenclud@131
   101
            if (aHidEvent.IsStray)
StephaneLenclud@131
   102
            {
StephaneLenclud@131
   103
                //Stray event just ignore it
StephaneLenclud@131
   104
                return;
StephaneLenclud@131
   105
            }
StephaneLenclud@125
   106
StephaneLenclud@131
   107
            if (this.InvokeRequired)
StephaneLenclud@131
   108
            {
StephaneLenclud@131
   109
                //Not in the proper thread, invoke ourselves
StephaneLenclud@131
   110
                OnHidEventDelegate d = new OnHidEventDelegate(HandleHidEventThreadSafe);
StephaneLenclud@131
   111
                this.Invoke(d, new object[] { aSender, aHidEvent });
StephaneLenclud@131
   112
            }
StephaneLenclud@131
   113
            else
StephaneLenclud@131
   114
            {
StephaneLenclud@131
   115
                //We are in the proper thread
StephaneLenclud@131
   116
                if (aHidEvent.Usages.Count > 0
StephaneLenclud@131
   117
                    && aHidEvent.UsagePage == (ushort)Hid.UsagePage.WindowsMediaCenterRemoteControl
StephaneLenclud@131
   118
                    && aHidEvent.Usages[0] == (ushort)Hid.Usage.WindowsMediaCenterRemoteControl.GreenStart)
StephaneLenclud@131
   119
                //&& aHidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer
StephaneLenclud@131
   120
                //&& aHidEvent.Usages[0] == (ushort)Hid.Usage.ConsumerControl.ThinkPadFullscreenMagnifier)
StephaneLenclud@131
   121
                {
StephaneLenclud@131
   122
                    //First check if the process we want to launch already exists
StephaneLenclud@131
   123
                    string procName = Path.GetFileNameWithoutExtension(Properties.Settings.Default.StartFileName);
StephaneLenclud@131
   124
                    Process[] existingProcesses = Process.GetProcessesByName(procName);
StephaneLenclud@131
   125
                    if (existingProcesses == null || existingProcesses.Length == 0)
StephaneLenclud@131
   126
                    {
StephaneLenclud@131
   127
                        // Process do not exists just try to launch it
StephaneLenclud@131
   128
                        ProcessStartInfo start = new ProcessStartInfo();
StephaneLenclud@131
   129
                        // Enter in the command line arguments, everything you would enter after the executable name itself
StephaneLenclud@131
   130
                        //start.Arguments = arguments; 
StephaneLenclud@131
   131
                        // Enter the executable to run, including the complete path
StephaneLenclud@131
   132
                        start.FileName = Properties.Settings.Default.StartFileName;
StephaneLenclud@131
   133
                        start.WindowStyle = ProcessWindowStyle.Normal;
StephaneLenclud@131
   134
                        start.CreateNoWindow = true;
StephaneLenclud@131
   135
                        start.UseShellExecute = true;
StephaneLenclud@131
   136
                        // Run the external process & wait for it to finish
StephaneLenclud@131
   137
                        Process proc = Process.Start(start);
StephaneLenclud@125
   138
StephaneLenclud@131
   139
                        //SL: We could have used that too
StephaneLenclud@131
   140
                        //Shell32.Shell shell = new Shell32.Shell();
StephaneLenclud@131
   141
                        //shell.ShellExecute(Properties.Settings.Default.StartFileName);
StephaneLenclud@131
   142
                    }
StephaneLenclud@131
   143
                    else
StephaneLenclud@131
   144
                    {
StephaneLenclud@131
   145
                        //This won't work properly until we have a manifest that enables uiAccess.
StephaneLenclud@131
   146
                        //However uiAccess just won't work with ClickOnce so we will have to use a different deployment system.
StephaneLenclud@131
   147
                        SwitchToThisWindow(existingProcesses[0].MainWindowHandle, true);
StephaneLenclud@131
   148
                    }
StephaneLenclud@131
   149
                }
StephaneLenclud@131
   150
            }
StephaneLenclud@131
   151
        }
StephaneLenclud@125
   152
StephaneLenclud@131
   153
        /// <summary>
StephaneLenclud@131
   154
        /// We need to handle WM_INPUT.
StephaneLenclud@131
   155
        /// </summary>
StephaneLenclud@131
   156
        /// <param name="message"></param>
StephaneLenclud@131
   157
        protected override void WndProc(ref Message message)
StephaneLenclud@131
   158
        {
StephaneLenclud@131
   159
            switch (message.Msg)
StephaneLenclud@131
   160
            {
StephaneLenclud@131
   161
                case Const.WM_INPUT:
StephaneLenclud@131
   162
                    //Returning zero means we processed that message.
StephaneLenclud@131
   163
                    message.Result = new IntPtr(0);
StephaneLenclud@131
   164
                    iHidHandler.ProcessInput(ref message);
StephaneLenclud@131
   165
                    break;
StephaneLenclud@131
   166
            }
StephaneLenclud@131
   167
            //Is that needed? Check the docs.
StephaneLenclud@131
   168
            base.WndProc(ref message);
StephaneLenclud@131
   169
        }
StephaneLenclud@131
   170
    }
StephaneLenclud@125
   171
}