RemoteControlDevice.cs
author StephaneLenclud
Sun, 15 Feb 2015 22:13:33 +0100
changeset 64 8c2380995bb7
parent 40 b3e177062849
child 66 3461ee6800e3
permissions -rw-r--r--
Adding input capabilities description to device list.
     1 using System;
     2 using System.Windows.Forms;
     3 using System.Runtime.InteropServices;
     4 using System.Diagnostics;
     5 using System.Text;
     6 using Microsoft.Win32.SafeHandles;
     7 
     8 using Hid.UsageTables;
     9 using Win32;
    10 
    11 
    12 
    13 namespace Devices.RemoteControl
    14 {
    15 
    16     public enum InputDevice
    17     {
    18         Key,
    19         Mouse,
    20         OEM
    21     }
    22 
    23 
    24     public enum RemoteControlButton
    25     {
    26         Clear,
    27         Down,
    28         Left,
    29         Digit0,
    30         Digit1,
    31         Digit2,
    32         Digit3,
    33         Digit4,
    34         Digit5,
    35         Digit6,
    36         Digit7,
    37         Digit8,
    38         Digit9,
    39         Enter,
    40         Right,
    41         Up,
    42 
    43         Back,
    44         ChannelDown,
    45         ChannelUp,
    46         FastForward,
    47         VolumeMute,
    48         Pause,
    49         Play,
    50         PlayPause,
    51         Record,
    52         PreviousTrack,
    53         Rewind,
    54         NextTrack,
    55         Stop,
    56         VolumeDown,
    57         VolumeUp,
    58 
    59         RecordedTV,
    60         Guide,
    61         LiveTV,
    62         MoreInfo,
    63         Print,
    64         DVDMenu,
    65         DVDAngle,
    66         DVDAudio,
    67         DVDSubtitle,
    68         MyMusic,
    69         MyPictures,
    70         MyVideos,
    71         MyTV,
    72         OEM1,
    73         OEM2,
    74         StandBy,
    75         TVJump,
    76 
    77         Unknown
    78     }
    79 
    80 
    81     #region RemoteControlEventArgs
    82 
    83     public class RemoteControlEventArgs : EventArgs
    84     {
    85         RemoteControlButton _rcb;
    86         InputDevice _device;
    87         WindowsMediaCenterRemoteControl iMceButton;
    88         ConsumerControl iConsumerControl;
    89 
    90         public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
    91         {
    92             SetNullButtons();
    93             //
    94             _rcb = rcb;
    95             _device = device;
    96         }
    97 
    98         public RemoteControlEventArgs(ConsumerControl aConsumerControl, InputDevice device)
    99         {
   100             SetNullButtons();
   101             //
   102             iConsumerControl = aConsumerControl;
   103             _device = device;
   104         }
   105 
   106 
   107         public RemoteControlEventArgs(WindowsMediaCenterRemoteControl mce, InputDevice device)
   108         {
   109             SetNullButtons();
   110             //
   111             iMceButton = mce;
   112             _device = device;
   113         }
   114 
   115         private void SetNullButtons()
   116         {
   117             iConsumerControl = ConsumerControl.Null;
   118             iMceButton = WindowsMediaCenterRemoteControl.Null;
   119             _rcb = RemoteControlButton.Unknown;
   120         }
   121 
   122         public RemoteControlEventArgs()
   123         {
   124             iMceButton = WindowsMediaCenterRemoteControl.Null;
   125             _rcb = RemoteControlButton.Unknown;
   126             _device = InputDevice.Key;
   127         }
   128 
   129         public RemoteControlButton Button
   130         {
   131             get { return _rcb; }
   132             set { _rcb = value; }
   133         }
   134 
   135         public WindowsMediaCenterRemoteControl MceButton
   136         {
   137             get { return iMceButton; }
   138             set { iMceButton = value; }
   139         }
   140 
   141         public ConsumerControl ConsumerControl
   142         {
   143             get { return iConsumerControl; }
   144             set { iConsumerControl = value; }
   145         }
   146 
   147         public InputDevice Device
   148         {
   149             get { return _device; }
   150             set { _device = value; }
   151         }
   152     }
   153 
   154     #endregion RemoteControlEventArgs
   155 
   156 
   157     public sealed class RemoteControlDevice
   158     {
   159         public delegate bool RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
   160         public event RemoteControlDeviceEventHandler ButtonPressed;
   161 
   162         /// <summary>
   163         /// Return true if the usage was processed.
   164         /// </summary>
   165         /// <param name="aUsage"></param>
   166         /// <returns></returns>
   167         public delegate bool HidUsageHandler(ushort aUsage);
   168 
   169         public Hid.HidHandler iHidHandler;
   170 
   171 
   172         //-------------------------------------------------------------
   173         // constructors
   174         //-------------------------------------------------------------
   175 
   176         public RemoteControlDevice(IntPtr aHWND)
   177         {
   178             // Register the input device to receive the commands from the
   179             // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
   180             // for the vendor defined usage page.
   181 
   182             RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[4];
   183 
   184             int i = 0;
   185             rid[i].usUsagePage = (ushort)Hid.UsagePage.WindowsMediaCenterRemoteControl;
   186             rid[i].usUsage = (ushort)Hid.UsageCollectionWindowsMediaCenter.WindowsMediaCenterRemoteControl;
   187             rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
   188             rid[i].hwndTarget = aHWND;
   189 
   190             i++;
   191             rid[i].usUsagePage = (ushort)Hid.UsagePage.Consumer;
   192             rid[i].usUsage = (ushort)Hid.UsageCollectionConsumer.ConsumerControl;
   193             rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
   194             rid[i].hwndTarget = aHWND;
   195 
   196             i++;
   197             rid[i].usUsagePage = (ushort)Hid.UsagePage.Consumer;
   198             rid[i].usUsage = (ushort)Hid.UsageCollectionConsumer.Selection;
   199             rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
   200             rid[i].hwndTarget = aHWND;
   201 
   202             i++;
   203             rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
   204             rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.SystemControl;
   205             rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
   206             rid[i].hwndTarget = aHWND;
   207 
   208 			//i++;
   209 			rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
   210 			rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.GamePad;
   211 			rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
   212 			rid[i].hwndTarget = aHWND;
   213 
   214             //i++;
   215             //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
   216             //rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.Keyboard;
   217             //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
   218             //rid[i].hwndTarget = aHWND;
   219 
   220             //i++;
   221             //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
   222             //rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.Mouse;
   223             //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
   224             //rid[i].hwndTarget = aHWND;
   225 
   226 
   227             iHidHandler = new Hid.HidHandler(rid);
   228             if (!iHidHandler.IsRegistered)
   229             {
   230                 Debug.WriteLine("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
   231             }
   232             iHidHandler.OnHidEvent += HandleHidEvent;
   233         }
   234 
   235 
   236         //-------------------------------------------------------------
   237         // methods
   238         //-------------------------------------------------------------
   239 
   240         public void ProcessMessage(Message message)
   241         {
   242             switch (message.Msg)
   243             {
   244                 case Const.WM_KEYDOWN:
   245                     ProcessKeyDown(message.WParam);
   246                     break;
   247                 case Const.WM_INPUT:
   248                     //Returning zero means we processed that message.
   249                     message.Result = new IntPtr(0);
   250                     ProcessInputCommand(ref message);
   251                     break;
   252             }
   253 
   254         }
   255 
   256 
   257         //-------------------------------------------------------------
   258         // methods (helpers)
   259         //-------------------------------------------------------------
   260 
   261         private void ProcessKeyDown(IntPtr wParam)
   262         {
   263             RemoteControlButton rcb = RemoteControlButton.Unknown;
   264 
   265             switch (wParam.ToInt32())
   266             {
   267                 case (int)Keys.Escape:
   268                     rcb = RemoteControlButton.Clear;
   269                     break;
   270                 case (int)Keys.Up:
   271                     rcb = RemoteControlButton.Up;
   272                     break;
   273                 case (int)Keys.Down:
   274                     rcb = RemoteControlButton.Down;
   275                     break;
   276                 case (int)Keys.Left:
   277                     rcb = RemoteControlButton.Left;
   278                     break;
   279                 case (int)Keys.Right:
   280                     rcb = RemoteControlButton.Right;
   281                     break;
   282                 case (int)Keys.Enter:
   283                     rcb = RemoteControlButton.Enter;
   284                     break;
   285                 case (int)Keys.D0:
   286                     rcb = RemoteControlButton.Digit0;
   287                     break;
   288                 case (int)Keys.D1:
   289                     rcb = RemoteControlButton.Digit1;
   290                     break;
   291                 case (int)Keys.D2:
   292                     rcb = RemoteControlButton.Digit2;
   293                     break;
   294                 case (int)Keys.D3:
   295                     rcb = RemoteControlButton.Digit3;
   296                     break;
   297                 case (int)Keys.D4:
   298                     rcb = RemoteControlButton.Digit4;
   299                     break;
   300                 case (int)Keys.D5:
   301                     rcb = RemoteControlButton.Digit5;
   302                     break;
   303                 case (int)Keys.D6:
   304                     rcb = RemoteControlButton.Digit6;
   305                     break;
   306                 case (int)Keys.D7:
   307                     rcb = RemoteControlButton.Digit7;
   308                     break;
   309                 case (int)Keys.D8:
   310                     rcb = RemoteControlButton.Digit8;
   311                     break;
   312                 case (int)Keys.D9:
   313                     rcb = RemoteControlButton.Digit9;
   314                     break;
   315             }
   316 
   317             if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
   318             {
   319                 Debug.WriteLine("KeyDown: " + rcb.ToString());
   320                 this.ButtonPressed(this, new RemoteControlEventArgs(rcb, InputDevice.Key));
   321             }
   322         }
   323 
   324 
   325         /// <summary>
   326         /// 
   327         /// </summary>
   328         /// <param name="aUsage"></param>
   329         private bool HidConsumerDeviceHandler(ushort aUsage)
   330         {
   331             if (aUsage == 0)
   332             {
   333                 //Just skip those
   334                 return false;
   335             }
   336 
   337             if (Enum.IsDefined(typeof(ConsumerControl), aUsage) && aUsage != 0) //Our button is a known consumer control
   338             {
   339                 if (this.ButtonPressed != null)
   340                 {
   341                     return this.ButtonPressed(this, new RemoteControlEventArgs((ConsumerControl)aUsage, InputDevice.OEM));
   342                 }
   343                 return false;
   344             }
   345             else
   346             {
   347                 Debug.WriteLine("Unknown Consumer Control!");
   348                 return false;
   349             }
   350         }
   351 
   352         /// <summary>
   353         /// 
   354         /// </summary>
   355         /// <param name="aUsage"></param>
   356         private bool HidMceRemoteHandler(ushort aUsage)
   357         {
   358             if (aUsage == 0)
   359             {
   360                 //Just skip those
   361                 return false;
   362             }
   363 
   364 
   365             if (Enum.IsDefined(typeof(WindowsMediaCenterRemoteControl), aUsage) && aUsage != 0) //Our button is a known MCE button
   366             {
   367                 if (this.ButtonPressed != null)
   368                 {
   369                     return this.ButtonPressed(this, new RemoteControlEventArgs((WindowsMediaCenterRemoteControl)aUsage, InputDevice.OEM));
   370                 }
   371                 return false;
   372             }
   373             else
   374             {
   375                 Debug.WriteLine("Unknown MCE button!");
   376                 return false;
   377             }
   378         }
   379 
   380         /// <summary>
   381         /// 
   382         /// </summary>
   383         /// <param name="message"></param>
   384         private void ProcessInputCommand(ref Message message)
   385         {
   386             //We received a WM_INPUT message
   387             Debug.WriteLine("================WM_INPUT================");
   388 
   389             iHidHandler.ProcessInput(message);
   390 
   391         }
   392 
   393         /// <summary>
   394         /// 
   395         /// </summary>
   396         /// <param name="aSender"></param>
   397         /// <param name="aHidEvent"></param>
   398         void HandleHidEvent(object aSender, Hid.HidEvent aHidEvent)
   399         {
   400             HidUsageHandler usagePageHandler = null;
   401 
   402             //Check if this an MCE remote HID message
   403             if (aHidEvent.UsagePage == (ushort)Hid.UsagePage.WindowsMediaCenterRemoteControl && aHidEvent.UsageCollection == (ushort)Hid.UsageCollectionWindowsMediaCenter.WindowsMediaCenterRemoteControl)
   404             {
   405                 usagePageHandler = HidMceRemoteHandler;
   406             }
   407             //Check if this is a consumer control HID message
   408             else if (aHidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer && aHidEvent.UsageCollection == (ushort)Hid.UsageCollectionConsumer.ConsumerControl)
   409             {
   410                 usagePageHandler = HidConsumerDeviceHandler;
   411             }
   412             //Unknown HID message
   413             else
   414             {
   415                 Debug.WriteLine("Unknown HID message.");
   416                 return;
   417             }
   418 
   419             foreach (ushort usage in aHidEvent.Usages)
   420             {
   421                 usagePageHandler(usage);
   422             }
   423         }
   424     }
   425 }
   426