Server/MainForm.Hid.cs
author StephaneLenclud
Wed, 02 Sep 2015 16:02:24 +0200
changeset 153 95f253aaf588
parent 152 03a1757a38df
child 154 5ecbb2f57a16
permissions -rw-r--r--
Persisting selection of optical drive to eject.
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@150
    10
using Microsoft.Win32.SafeHandles;
StephaneLenclud@125
    11
//
StephaneLenclud@125
    12
using Hid = SharpLib.Hid;
StephaneLenclud@125
    13
using SharpLib.Win32;
StephaneLenclud@125
    14
StephaneLenclud@125
    15
namespace SharpDisplayManager
StephaneLenclud@125
    16
{
StephaneLenclud@138
    17
    /// <summary>
StephaneLenclud@138
    18
    /// Implement handling of HID input reports notably to be able to launch an application using the Green Start button from IR remotes.
StephaneLenclud@138
    19
    /// </summary>
StephaneLenclud@131
    20
    [System.ComponentModel.DesignerCategory("Code")]
StephaneLenclud@131
    21
    public class MainFormHid : Form
StephaneLenclud@131
    22
    {
StephaneLenclud@131
    23
        [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "SwitchToThisWindow")]
StephaneLenclud@131
    24
        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
    25
        //
StephaneLenclud@131
    26
        public delegate void OnHidEventDelegate(object aSender, Hid.Event aHidEvent);
StephaneLenclud@126
    27
StephaneLenclud@131
    28
        /// <summary>
StephaneLenclud@131
    29
        /// Use notably to handle green start key from IR remote control
StephaneLenclud@131
    30
        /// </summary>
StephaneLenclud@131
    31
        private Hid.Handler iHidHandler;
StephaneLenclud@126
    32
StephaneLenclud@131
    33
        /// <summary>
StephaneLenclud@131
    34
        /// Register HID devices so that we receive corresponding WM_INPUT messages.
StephaneLenclud@131
    35
        /// </summary>
StephaneLenclud@131
    36
        protected void RegisterHidDevices()
StephaneLenclud@131
    37
        {
StephaneLenclud@131
    38
            // Register the input device to receive the commands from the
StephaneLenclud@131
    39
            // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
StephaneLenclud@131
    40
            // for the vendor defined usage page.
StephaneLenclud@128
    41
StephaneLenclud@131
    42
            RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[5];
StephaneLenclud@128
    43
StephaneLenclud@131
    44
            int i = 0;
StephaneLenclud@131
    45
            rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.WindowsMediaCenterRemoteControl;
StephaneLenclud@131
    46
            rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.WindowsMediaCenter.WindowsMediaCenterRemoteControl;
StephaneLenclud@131
    47
            rid[i].dwFlags = Const.RIDEV_INPUTSINK;
StephaneLenclud@131
    48
            rid[i].hwndTarget = Handle;
StephaneLenclud@128
    49
StephaneLenclud@131
    50
            i++;
StephaneLenclud@131
    51
            rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.Consumer;
StephaneLenclud@131
    52
            rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.Consumer.ConsumerControl;
StephaneLenclud@131
    53
            rid[i].dwFlags = Const.RIDEV_INPUTSINK;
StephaneLenclud@131
    54
            rid[i].hwndTarget = Handle;
StephaneLenclud@126
    55
StephaneLenclud@131
    56
            i++;
StephaneLenclud@131
    57
            rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.Consumer;
StephaneLenclud@131
    58
            rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.Consumer.Selection;
StephaneLenclud@131
    59
            rid[i].dwFlags = Const.RIDEV_INPUTSINK;
StephaneLenclud@131
    60
            rid[i].hwndTarget = Handle;
StephaneLenclud@125
    61
StephaneLenclud@131
    62
            i++;
StephaneLenclud@131
    63
            rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.GenericDesktopControls;
StephaneLenclud@131
    64
            rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.GenericDesktop.SystemControl;
StephaneLenclud@131
    65
            rid[i].dwFlags = Const.RIDEV_INPUTSINK;
StephaneLenclud@131
    66
            rid[i].hwndTarget = Handle;
StephaneLenclud@125
    67
StephaneLenclud@131
    68
            i++;
StephaneLenclud@131
    69
            rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.GenericDesktopControls;
StephaneLenclud@131
    70
            rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.GenericDesktop.GamePad;
StephaneLenclud@131
    71
            rid[i].dwFlags = Const.RIDEV_INPUTSINK;
StephaneLenclud@131
    72
            rid[i].hwndTarget = Handle;
StephaneLenclud@125
    73
StephaneLenclud@131
    74
            //i++;
StephaneLenclud@131
    75
            //rid[i].usUsagePage = (ushort)SharpLib.Hid.UsagePage.GenericDesktopControls;
StephaneLenclud@131
    76
            //rid[i].usUsage = (ushort)SharpLib.Hid.UsageCollection.GenericDesktop.Keyboard;
StephaneLenclud@131
    77
            //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
StephaneLenclud@131
    78
            //rid[i].hwndTarget = Handle;
StephaneLenclud@125
    79
StephaneLenclud@131
    80
            //i++;
StephaneLenclud@131
    81
            //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
StephaneLenclud@131
    82
            //rid[i].usUsage = (ushort)Hid.UsageCollection.GenericDesktop.Mouse;
StephaneLenclud@131
    83
            //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
StephaneLenclud@131
    84
            //rid[i].hwndTarget = aHWND;
StephaneLenclud@125
    85
StephaneLenclud@125
    86
StephaneLenclud@131
    87
            iHidHandler = new SharpLib.Hid.Handler(rid);
StephaneLenclud@131
    88
            if (!iHidHandler.IsRegistered)
StephaneLenclud@131
    89
            {
StephaneLenclud@131
    90
                Debug.WriteLine("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
StephaneLenclud@131
    91
            }
StephaneLenclud@131
    92
            iHidHandler.OnHidEvent += HandleHidEventThreadSafe;
StephaneLenclud@131
    93
        }
StephaneLenclud@125
    94
StephaneLenclud@131
    95
        /// <summary>
StephaneLenclud@131
    96
        /// Here we receive HID events from our HID library.
StephaneLenclud@131
    97
        /// </summary>
StephaneLenclud@131
    98
        /// <param name="aSender"></param>
StephaneLenclud@131
    99
        /// <param name="aHidEvent"></param>
StephaneLenclud@131
   100
        public void HandleHidEventThreadSafe(object aSender, SharpLib.Hid.Event aHidEvent)
StephaneLenclud@131
   101
        {
StephaneLenclud@131
   102
            if (aHidEvent.IsStray)
StephaneLenclud@131
   103
            {
StephaneLenclud@131
   104
                //Stray event just ignore it
StephaneLenclud@131
   105
                return;
StephaneLenclud@131
   106
            }
StephaneLenclud@125
   107
StephaneLenclud@131
   108
            if (this.InvokeRequired)
StephaneLenclud@131
   109
            {
StephaneLenclud@131
   110
                //Not in the proper thread, invoke ourselves
StephaneLenclud@131
   111
                OnHidEventDelegate d = new OnHidEventDelegate(HandleHidEventThreadSafe);
StephaneLenclud@131
   112
                this.Invoke(d, new object[] { aSender, aHidEvent });
StephaneLenclud@131
   113
            }
StephaneLenclud@131
   114
            else
StephaneLenclud@131
   115
            {
StephaneLenclud@150
   116
                if (aHidEvent.Usages.Count == 0)
StephaneLenclud@150
   117
                {
StephaneLenclud@150
   118
                    //No usage, nothing to do then
StephaneLenclud@150
   119
                    return;
StephaneLenclud@150
   120
                }
StephaneLenclud@150
   121
StephaneLenclud@131
   122
                //We are in the proper thread
StephaneLenclud@150
   123
                if (aHidEvent.UsagePage == (ushort) Hid.UsagePage.WindowsMediaCenterRemoteControl)
StephaneLenclud@131
   124
                {
StephaneLenclud@150
   125
                    switch (aHidEvent.Usages[0])
StephaneLenclud@131
   126
                    {
StephaneLenclud@150
   127
                        case (ushort)Hid.Usage.WindowsMediaCenterRemoteControl.GreenStart:
StephaneLenclud@150
   128
                            HandleGreenStart();
StephaneLenclud@150
   129
                            break;
StephaneLenclud@150
   130
                        case (ushort)Hid.Usage.WindowsMediaCenterRemoteControl.Eject:
StephaneLenclud@150
   131
                        case (ushort)Hid.Usage.WindowsMediaCenterRemoteControl.Ext2:
StephaneLenclud@150
   132
                            HandleEject();
StephaneLenclud@150
   133
                            break;
StephaneLenclud@131
   134
                    }
StephaneLenclud@131
   135
                }
StephaneLenclud@152
   136
StephaneLenclud@152
   137
                //Keep this for debug when only ThinkPad keyboard is available
StephaneLenclud@152
   138
                if (aHidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer && aHidEvent.Usages[0] == (ushort)Hid.Usage.ConsumerControl.ThinkPadFullscreenMagnifier)
StephaneLenclud@152
   139
                {
StephaneLenclud@152
   140
                    HandleEject();
StephaneLenclud@152
   141
                }
StephaneLenclud@152
   142
StephaneLenclud@131
   143
            }
StephaneLenclud@131
   144
        }
StephaneLenclud@125
   145
StephaneLenclud@151
   146
        /// <summary>
StephaneLenclud@151
   147
        /// 
StephaneLenclud@151
   148
        /// </summary>
StephaneLenclud@151
   149
        /// <param name="data"></param>
StephaneLenclud@151
   150
        /// <returns></returns>
StephaneLenclud@151
   151
        private IntPtr MarshalToPointer(object data)
StephaneLenclud@151
   152
        {
StephaneLenclud@151
   153
            IntPtr buf = Marshal.AllocHGlobal(
StephaneLenclud@151
   154
                Marshal.SizeOf(data));
StephaneLenclud@151
   155
            Marshal.StructureToPtr(data,
StephaneLenclud@151
   156
                buf, false);
StephaneLenclud@151
   157
            return buf;
StephaneLenclud@151
   158
        }
StephaneLenclud@151
   159
StephaneLenclud@151
   160
        /// <summary>
StephaneLenclud@151
   161
        /// 
StephaneLenclud@151
   162
        /// </summary>
StephaneLenclud@151
   163
        /// <returns></returns>
StephaneLenclud@152
   164
        private SafeFileHandle OpenVolume(string aDriveName)
StephaneLenclud@150
   165
        {
StephaneLenclud@152
   166
            return Function.CreateFile("\\\\.\\" + aDriveName,
StephaneLenclud@150
   167
                               SharpLib.Win32.FileAccess.GENERIC_READ,
StephaneLenclud@150
   168
                               SharpLib.Win32.FileShare.FILE_SHARE_READ | SharpLib.Win32.FileShare.FILE_SHARE_WRITE,
StephaneLenclud@150
   169
                               IntPtr.Zero,
StephaneLenclud@150
   170
                               CreationDisposition.OPEN_EXISTING,
StephaneLenclud@150
   171
                               0,
StephaneLenclud@150
   172
                               IntPtr.Zero);
StephaneLenclud@150
   173
        }
StephaneLenclud@150
   174
StephaneLenclud@150
   175
        /// <summary>
StephaneLenclud@150
   176
        /// 
StephaneLenclud@150
   177
        /// </summary>
StephaneLenclud@151
   178
        /// <param name="aVolume"></param>
StephaneLenclud@151
   179
        /// <returns></returns>
StephaneLenclud@151
   180
        private bool LockVolume(SafeFileHandle aVolume)
StephaneLenclud@151
   181
        {
StephaneLenclud@151
   182
            //Hope that's doing what I think it does
StephaneLenclud@151
   183
            IntPtr dwBytesReturned=new IntPtr();
StephaneLenclud@151
   184
            //Should not be needed but I'm not sure how to pass NULL in there.
StephaneLenclud@151
   185
            OVERLAPPED overlapped=new OVERLAPPED();
StephaneLenclud@151
   186
StephaneLenclud@151
   187
            int tries = 0;
StephaneLenclud@151
   188
            const int KMaxTries = 100;
StephaneLenclud@151
   189
            const int KSleepTime = 10;
StephaneLenclud@151
   190
            bool success = false;
StephaneLenclud@151
   191
StephaneLenclud@151
   192
            while (!success && tries < KMaxTries)
StephaneLenclud@151
   193
            {
StephaneLenclud@151
   194
                success = Function.DeviceIoControl(aVolume, Const.FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, dwBytesReturned, ref overlapped);
StephaneLenclud@151
   195
                System.Threading.Thread.Sleep(KSleepTime);
StephaneLenclud@151
   196
                tries++;
StephaneLenclud@151
   197
            }
StephaneLenclud@151
   198
StephaneLenclud@151
   199
            return success;
StephaneLenclud@151
   200
        }
StephaneLenclud@151
   201
StephaneLenclud@151
   202
        /// <summary>
StephaneLenclud@151
   203
        /// 
StephaneLenclud@151
   204
        /// </summary>
StephaneLenclud@151
   205
        /// <param name="aVolume"></param>
StephaneLenclud@151
   206
        /// <returns></returns>
StephaneLenclud@151
   207
        private bool DismountVolume(SafeFileHandle aVolume)
StephaneLenclud@151
   208
        {
StephaneLenclud@151
   209
            //Hope that's doing what I think it does
StephaneLenclud@151
   210
            IntPtr dwBytesReturned = new IntPtr();
StephaneLenclud@151
   211
            //Should not be needed but I'm not sure how to pass NULL in there.
StephaneLenclud@151
   212
            OVERLAPPED overlapped=new OVERLAPPED();
StephaneLenclud@151
   213
StephaneLenclud@151
   214
            return Function.DeviceIoControl(aVolume, Const.FSCTL_DISMOUNT_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, dwBytesReturned, ref overlapped);
StephaneLenclud@151
   215
        }
StephaneLenclud@151
   216
StephaneLenclud@151
   217
StephaneLenclud@151
   218
StephaneLenclud@151
   219
        /// <summary>
StephaneLenclud@151
   220
        /// 
StephaneLenclud@151
   221
        /// </summary>
StephaneLenclud@151
   222
        /// <param name="aVolume"></param>
StephaneLenclud@151
   223
        /// <param name="aPreventRemoval"></param>
StephaneLenclud@151
   224
        /// <returns></returns>
StephaneLenclud@151
   225
        private bool PreventRemovalOfVolume(SafeFileHandle aVolume, bool aPreventRemoval)
StephaneLenclud@151
   226
        {
StephaneLenclud@151
   227
            //Hope that's doing what I think it does
StephaneLenclud@151
   228
            IntPtr dwBytesReturned = new IntPtr();
StephaneLenclud@151
   229
            //Should not be needed but I'm not sure how to pass NULL in there.
StephaneLenclud@151
   230
            OVERLAPPED overlapped = new OVERLAPPED();
StephaneLenclud@151
   231
            //
StephaneLenclud@151
   232
            PREVENT_MEDIA_REMOVAL preventMediaRemoval = new PREVENT_MEDIA_REMOVAL();
StephaneLenclud@151
   233
            preventMediaRemoval.PreventMediaRemoval = Convert.ToByte(aPreventRemoval);
StephaneLenclud@151
   234
            IntPtr preventMediaRemovalParam = MarshalToPointer(preventMediaRemoval);
StephaneLenclud@151
   235
StephaneLenclud@151
   236
            bool result = Function.DeviceIoControl(aVolume, Const.IOCTL_STORAGE_MEDIA_REMOVAL, preventMediaRemovalParam, Convert.ToUInt32(Marshal.SizeOf(preventMediaRemoval)), IntPtr.Zero, 0, dwBytesReturned, ref overlapped);
StephaneLenclud@151
   237
StephaneLenclud@151
   238
            Marshal.FreeHGlobal(preventMediaRemovalParam);
StephaneLenclud@151
   239
StephaneLenclud@151
   240
            return result;
StephaneLenclud@151
   241
        }
StephaneLenclud@151
   242
StephaneLenclud@151
   243
        /// <summary>
StephaneLenclud@151
   244
        /// 
StephaneLenclud@151
   245
        /// </summary>
StephaneLenclud@151
   246
        /// <param name="aVolume"></param>
StephaneLenclud@151
   247
        /// <returns></returns>
StephaneLenclud@151
   248
        private bool AutoEjectVolume(SafeFileHandle aVolume)
StephaneLenclud@151
   249
        {
StephaneLenclud@151
   250
            //Hope that's doing what I think it does
StephaneLenclud@151
   251
            IntPtr dwBytesReturned = new IntPtr();
StephaneLenclud@151
   252
            //Should not be needed but I'm not sure how to pass NULL in there.
StephaneLenclud@151
   253
            OVERLAPPED overlapped=new OVERLAPPED();
StephaneLenclud@151
   254
StephaneLenclud@151
   255
            return Function.DeviceIoControl(aVolume, Const.IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, IntPtr.Zero, 0, dwBytesReturned, ref overlapped);
StephaneLenclud@151
   256
        }
StephaneLenclud@151
   257
StephaneLenclud@152
   258
        /// <summary>
StephaneLenclud@152
   259
        /// Not working.
StephaneLenclud@152
   260
        /// </summary>
StephaneLenclud@152
   261
        /// <param name="aVolume"></param>
StephaneLenclud@152
   262
        /// <returns></returns>
StephaneLenclud@152
   263
        private bool CloseTray(SafeFileHandle aVolume)
StephaneLenclud@152
   264
        {
StephaneLenclud@152
   265
            //Hope that's doing what I think it does
StephaneLenclud@152
   266
            IntPtr dwBytesReturned = new IntPtr();
StephaneLenclud@152
   267
            //Should not be needed but I'm not sure how to pass NULL in there.
StephaneLenclud@152
   268
            OVERLAPPED overlapped=new OVERLAPPED();
StephaneLenclud@152
   269
StephaneLenclud@152
   270
            return Function.DeviceIoControl(aVolume, Const.IOCTL_STORAGE_LOAD_MEDIA, IntPtr.Zero, 0, IntPtr.Zero, 0, dwBytesReturned, ref overlapped);
StephaneLenclud@152
   271
        }
StephaneLenclud@152
   272
StephaneLenclud@152
   273
        
StephaneLenclud@151
   274
        
StephaneLenclud@151
   275
StephaneLenclud@151
   276
StephaneLenclud@151
   277
        /// <summary>
StephaneLenclud@151
   278
        /// Perform media ejection.
StephaneLenclud@151
   279
        /// </summary>
StephaneLenclud@150
   280
        private void HandleEject()
StephaneLenclud@150
   281
        {
StephaneLenclud@153
   282
            string drive = ((MainForm)this).OpticalDriveToEject();
StephaneLenclud@153
   283
            if (drive.Length!=2)
StephaneLenclud@153
   284
            {
StephaneLenclud@153
   285
                //Not a proper drive spec.
StephaneLenclud@153
   286
                //Probably 'None' selected.
StephaneLenclud@153
   287
                return;
StephaneLenclud@153
   288
            }
StephaneLenclud@153
   289
StephaneLenclud@153
   290
            SafeFileHandle handle = OpenVolume(drive);
StephaneLenclud@151
   291
            if (handle.IsInvalid)
StephaneLenclud@151
   292
            {
StephaneLenclud@151
   293
                return;
StephaneLenclud@151
   294
            }
StephaneLenclud@151
   295
StephaneLenclud@151
   296
            if (LockVolume(handle) && DismountVolume(handle))
StephaneLenclud@151
   297
            {
StephaneLenclud@151
   298
                Debug.Write("Volume was dismounted.");
StephaneLenclud@151
   299
StephaneLenclud@152
   300
                if (PreventRemovalOfVolume(handle,false))
StephaneLenclud@151
   301
                {
StephaneLenclud@152
   302
                    if (AutoEjectVolume(handle))
StephaneLenclud@152
   303
                    {
StephaneLenclud@152
   304
                        Debug.Write("Media was ejected");
StephaneLenclud@152
   305
                    }
StephaneLenclud@152
   306
                    //else if (CloseTray(handle))
StephaneLenclud@152
   307
                    //{
StephaneLenclud@152
   308
                    //    Debug.Write("Media was loaded");
StephaneLenclud@152
   309
                    //}                    
StephaneLenclud@151
   310
                }
StephaneLenclud@151
   311
            }
StephaneLenclud@150
   312
        }
StephaneLenclud@150
   313
StephaneLenclud@150
   314
        /// <summary>
StephaneLenclud@150
   315
        /// 
StephaneLenclud@150
   316
        /// </summary>
StephaneLenclud@150
   317
        private void HandleGreenStart()
StephaneLenclud@150
   318
        {
StephaneLenclud@150
   319
            //First check if the process we want to launch already exists
StephaneLenclud@150
   320
            string procName = Path.GetFileNameWithoutExtension(Properties.Settings.Default.StartFileName);
StephaneLenclud@150
   321
            Process[] existingProcesses = Process.GetProcessesByName(procName);
StephaneLenclud@150
   322
            if (existingProcesses == null || existingProcesses.Length == 0)
StephaneLenclud@150
   323
            {
StephaneLenclud@150
   324
                // Process do not exists just try to launch it
StephaneLenclud@150
   325
                ProcessStartInfo start = new ProcessStartInfo();
StephaneLenclud@150
   326
                // Enter in the command line arguments, everything you would enter after the executable name itself
StephaneLenclud@150
   327
                //start.Arguments = arguments; 
StephaneLenclud@150
   328
                // Enter the executable to run, including the complete path
StephaneLenclud@150
   329
                start.FileName = Properties.Settings.Default.StartFileName;
StephaneLenclud@150
   330
                start.WindowStyle = ProcessWindowStyle.Normal;
StephaneLenclud@150
   331
                start.CreateNoWindow = true;
StephaneLenclud@150
   332
                start.UseShellExecute = true;
StephaneLenclud@150
   333
                // Run the external process & wait for it to finish
StephaneLenclud@150
   334
                Process proc = Process.Start(start);
StephaneLenclud@150
   335
StephaneLenclud@150
   336
                //SL: We could have used that too
StephaneLenclud@150
   337
                //Shell32.Shell shell = new Shell32.Shell();
StephaneLenclud@150
   338
                //shell.ShellExecute(Properties.Settings.Default.StartFileName);
StephaneLenclud@150
   339
            }
StephaneLenclud@150
   340
            else
StephaneLenclud@150
   341
            {
StephaneLenclud@150
   342
                //This won't work properly until we have a manifest that enables uiAccess.
StephaneLenclud@150
   343
                //However uiAccess just won't work with ClickOnce so we will have to use a different deployment system.
StephaneLenclud@150
   344
                SwitchToThisWindow(existingProcesses[0].MainWindowHandle, true);
StephaneLenclud@150
   345
            }            
StephaneLenclud@150
   346
        }
StephaneLenclud@131
   347
        /// <summary>
StephaneLenclud@131
   348
        /// We need to handle WM_INPUT.
StephaneLenclud@131
   349
        /// </summary>
StephaneLenclud@131
   350
        /// <param name="message"></param>
StephaneLenclud@131
   351
        protected override void WndProc(ref Message message)
StephaneLenclud@131
   352
        {
StephaneLenclud@131
   353
            switch (message.Msg)
StephaneLenclud@131
   354
            {
StephaneLenclud@131
   355
                case Const.WM_INPUT:
StephaneLenclud@131
   356
                    //Returning zero means we processed that message.
StephaneLenclud@131
   357
                    message.Result = new IntPtr(0);
StephaneLenclud@131
   358
                    iHidHandler.ProcessInput(ref message);
StephaneLenclud@131
   359
                    break;
StephaneLenclud@131
   360
            }
StephaneLenclud@131
   361
            //Is that needed? Check the docs.
StephaneLenclud@131
   362
            base.WndProc(ref message);
StephaneLenclud@131
   363
        }
StephaneLenclud@131
   364
    }
StephaneLenclud@125
   365
}