RemoteControlDevice.cs
author sl
Wed, 03 Dec 2014 21:54:45 +0100
changeset 16 9a3e77655031
parent 15 2044181ade12
child 17 8f7e35c3bfd1
permissions -rw-r--r--
Now supporting alternative codes for program guid and properties/info.
sl@0
     1
using System;
sl@0
     2
using System.Windows.Forms;
sl@0
     3
using System.Runtime.InteropServices;
sl@0
     4
using System.Diagnostics;
sl@8
     5
using Hid.UsageTables;
sl@9
     6
using Win32;
sl@0
     7
sl@6
     8
namespace Devices.RemoteControl
sl@0
     9
{
sl@6
    10
sl@0
    11
	public enum InputDevice
sl@0
    12
	{
sl@0
    13
		Key,
sl@0
    14
		Mouse,
sl@0
    15
		OEM
sl@0
    16
	}
sl@0
    17
sl@0
    18
sl@0
    19
	public enum RemoteControlButton
sl@0
    20
	{
sl@0
    21
		Clear,
sl@0
    22
		Down,
sl@0
    23
		Left,
sl@0
    24
		Digit0,
sl@0
    25
		Digit1,
sl@0
    26
		Digit2,
sl@0
    27
		Digit3,
sl@0
    28
		Digit4,
sl@0
    29
		Digit5,
sl@0
    30
		Digit6,
sl@0
    31
		Digit7,
sl@0
    32
		Digit8,
sl@0
    33
		Digit9,
sl@0
    34
		Enter,
sl@0
    35
		Right,
sl@0
    36
		Up,
sl@0
    37
sl@0
    38
		Back,
sl@0
    39
		ChannelDown,
sl@0
    40
		ChannelUp,
sl@0
    41
		FastForward,
sl@0
    42
		VolumeMute,
sl@0
    43
		Pause,
sl@0
    44
		Play,
sl@0
    45
        PlayPause,
sl@0
    46
		Record,
sl@0
    47
		PreviousTrack,
sl@0
    48
		Rewind,
sl@0
    49
		NextTrack,
sl@0
    50
		Stop,
sl@0
    51
		VolumeDown,
sl@0
    52
		VolumeUp,
sl@0
    53
sl@0
    54
		RecordedTV,
sl@0
    55
		Guide,
sl@0
    56
		LiveTV,
sl@12
    57
		MoreInfo,
sl@12
    58
        Print,
sl@0
    59
		DVDMenu,
sl@0
    60
		DVDAngle,
sl@0
    61
		DVDAudio,
sl@0
    62
		DVDSubtitle,
sl@0
    63
		MyMusic,
sl@0
    64
		MyPictures,
sl@0
    65
		MyVideos,
sl@0
    66
		MyTV,
sl@0
    67
		OEM1,
sl@0
    68
		OEM2,
sl@0
    69
		StandBy,
sl@0
    70
		TVJump,
sl@0
    71
sl@0
    72
		Unknown
sl@0
    73
	}
sl@0
    74
sl@0
    75
sl@0
    76
	#region RemoteControlEventArgs
sl@0
    77
sl@0
    78
	public class RemoteControlEventArgs : EventArgs
sl@0
    79
	{
sl@3
    80
        RemoteControlButton _rcb;
sl@0
    81
		InputDevice _device;
sl@3
    82
        MceButton iMceButton;
sl@0
    83
sl@3
    84
        public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
sl@0
    85
		{
sl@3
    86
            iMceButton = MceButton.Null;
sl@0
    87
			_rcb = rcb;
sl@0
    88
			_device = device;
sl@0
    89
		}
sl@0
    90
sl@3
    91
        public RemoteControlEventArgs(MceButton mce, InputDevice device)
sl@3
    92
        {
sl@3
    93
            iMceButton = mce;
sl@3
    94
            _rcb = RemoteControlButton.Unknown;
sl@3
    95
            _device = device;
sl@3
    96
        }
sl@0
    97
sl@0
    98
		public RemoteControlEventArgs()
sl@0
    99
		{
sl@3
   100
            iMceButton = MceButton.Null;
sl@0
   101
			_rcb = RemoteControlButton.Unknown;
sl@0
   102
			_device = InputDevice.Key;
sl@0
   103
		}
sl@0
   104
sl@0
   105
		public RemoteControlButton Button
sl@0
   106
		{
sl@0
   107
			get { return _rcb;  }
sl@0
   108
			set { _rcb = value; }
sl@0
   109
		}
sl@0
   110
sl@3
   111
        public MceButton MceButton
sl@3
   112
        {
sl@3
   113
            get { return iMceButton; }
sl@3
   114
            set { iMceButton = value; }
sl@3
   115
        }
sl@3
   116
sl@0
   117
		public InputDevice Device
sl@0
   118
		{
sl@0
   119
			get { return _device;  }
sl@0
   120
			set { _device = value; }
sl@0
   121
		}
sl@0
   122
	}
sl@0
   123
sl@0
   124
	#endregion RemoteControlEventArgs
sl@0
   125
sl@0
   126
sl@0
   127
	public sealed class RemoteControlDevice
sl@0
   128
	{
sl@0
   129
		public delegate void RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
sl@0
   130
		public event RemoteControlDeviceEventHandler ButtonPressed;
sl@0
   131
sl@12
   132
        public delegate void HidUsageHandler(ushort aUsage);
sl@12
   133
        
sl@12
   134
sl@0
   135
		//-------------------------------------------------------------
sl@0
   136
		// constructors
sl@0
   137
		//-------------------------------------------------------------
sl@0
   138
sl@15
   139
		public RemoteControlDevice(IntPtr aHWND)
sl@0
   140
		{
sl@0
   141
			// Register the input device to receive the commands from the
sl@0
   142
			// remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
sl@0
   143
			// for the vendor defined usage page.
sl@0
   144
sl@0
   145
			RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[3];
sl@0
   146
sl@0
   147
			rid[0].usUsagePage = 0xFFBC;
sl@0
   148
			rid[0].usUsage = 0x88;
sl@15
   149
            rid[0].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@15
   150
            rid[0].hwndTarget = aHWND;
sl@0
   151
sl@0
   152
			rid[1].usUsagePage = 0x0C;
sl@0
   153
			rid[1].usUsage = 0x01;
sl@15
   154
            rid[1].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@15
   155
            rid[1].hwndTarget = aHWND;
sl@0
   156
sl@0
   157
			rid[2].usUsagePage = 0x0C;
sl@0
   158
			rid[2].usUsage = 0x80;
sl@15
   159
            rid[2].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@15
   160
            rid[2].hwndTarget = aHWND;
sl@0
   161
sl@15
   162
			if (!Function.RegisterRawInputDevices(rid,(uint) rid.Length,(uint) Marshal.SizeOf(rid[0])))
sl@0
   163
			{
sl@15
   164
                throw new ApplicationException("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
sl@0
   165
			}
sl@0
   166
		}
sl@0
   167
sl@0
   168
sl@0
   169
		//-------------------------------------------------------------
sl@0
   170
		// methods
sl@0
   171
		//-------------------------------------------------------------
sl@0
   172
sl@0
   173
		public void ProcessMessage(Message message)
sl@0
   174
		{
sl@0
   175
			switch (message.Msg)
sl@0
   176
			{
sl@15
   177
				case Const.WM_KEYDOWN:
sl@15
   178
                    ProcessKeyDown(message.WParam);
sl@0
   179
					break;
sl@15
   180
                case Const.WM_APPCOMMAND:
sl@15
   181
					ProcessAppCommand(message.LParam);
sl@0
   182
					break;
sl@15
   183
                case Const.WM_INPUT:
sl@0
   184
					ProcessInputCommand(ref message);
sl@0
   185
                    message.Result = new IntPtr(0);
sl@0
   186
					break;
sl@0
   187
			}
sl@0
   188
sl@0
   189
		}
sl@0
   190
sl@0
   191
sl@0
   192
		//-------------------------------------------------------------
sl@0
   193
		// methods (helpers)
sl@0
   194
		//-------------------------------------------------------------
sl@0
   195
sl@15
   196
		private void ProcessKeyDown(IntPtr wParam)
sl@0
   197
		{
sl@0
   198
			RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   199
sl@15
   200
            switch (wParam.ToInt32())
sl@0
   201
			{
sl@0
   202
				case (int) Keys.Escape:
sl@0
   203
					rcb = RemoteControlButton.Clear;
sl@0
   204
					break;
sl@0
   205
				case (int) Keys.Down:
sl@0
   206
					rcb = RemoteControlButton.Down;
sl@0
   207
					break;
sl@0
   208
				case (int) Keys.Left:
sl@0
   209
					rcb = RemoteControlButton.Left;
sl@0
   210
					break;
sl@0
   211
				case (int) Keys.D0:
sl@0
   212
					rcb = RemoteControlButton.Digit0;
sl@0
   213
					break;
sl@0
   214
				case (int) Keys.D1:
sl@0
   215
					rcb = RemoteControlButton.Digit1;
sl@0
   216
					break;
sl@0
   217
				case (int) Keys.D2:
sl@0
   218
					rcb = RemoteControlButton.Digit2;
sl@0
   219
					break;
sl@0
   220
				case (int) Keys.D3:
sl@0
   221
					rcb = RemoteControlButton.Digit3;
sl@0
   222
					break;
sl@0
   223
				case (int) Keys.D4:
sl@0
   224
					rcb = RemoteControlButton.Digit4;
sl@0
   225
					break;
sl@0
   226
				case (int) Keys.D5:
sl@0
   227
					rcb = RemoteControlButton.Digit5;
sl@0
   228
					break;
sl@0
   229
				case (int) Keys.D6:
sl@0
   230
					rcb = RemoteControlButton.Digit6;
sl@0
   231
					break;
sl@0
   232
				case (int) Keys.D7:
sl@0
   233
					rcb = RemoteControlButton.Digit7;
sl@0
   234
					break;
sl@0
   235
				case (int) Keys.D8:
sl@0
   236
					rcb = RemoteControlButton.Digit8;
sl@0
   237
					break;
sl@0
   238
				case (int) Keys.D9:
sl@0
   239
					rcb = RemoteControlButton.Digit9;
sl@0
   240
					break;
sl@0
   241
				case (int) Keys.Enter:
sl@0
   242
					rcb = RemoteControlButton.Enter;
sl@0
   243
					break;
sl@0
   244
				case (int) Keys.Right:
sl@0
   245
					rcb = RemoteControlButton.Right;
sl@0
   246
					break;
sl@0
   247
				case (int) Keys.Up:
sl@0
   248
					rcb = RemoteControlButton.Up;
sl@0
   249
					break;
sl@0
   250
			}
sl@0
   251
sl@0
   252
			if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
sl@15
   253
				this.ButtonPressed(this, new RemoteControlEventArgs(rcb, GetDevice(wParam)));
sl@0
   254
		}
sl@0
   255
sl@0
   256
sl@15
   257
		private void ProcessAppCommand(IntPtr lParam)
sl@0
   258
		{
sl@0
   259
			RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   260
sl@15
   261
            int cmd = Macro.GET_APPCOMMAND_LPARAM(lParam);
sl@15
   262
                //(int) (((ushort) (param >> 16)) & ~Const.FAPPCOMMAND_MASK);
sl@0
   263
sl@0
   264
			switch (cmd)
sl@0
   265
			{
sl@15
   266
                case Const.APPCOMMAND_BROWSER_BACKWARD:
sl@0
   267
					rcb = RemoteControlButton.Back;
sl@0
   268
					break;
sl@15
   269
                case Const.APPCOMMAND_MEDIA_CHANNEL_DOWN:
sl@0
   270
					rcb = RemoteControlButton.ChannelDown;
sl@0
   271
					break;
sl@15
   272
                case Const.APPCOMMAND_MEDIA_CHANNEL_UP:
sl@0
   273
					rcb = RemoteControlButton.ChannelUp;
sl@0
   274
					break;
sl@15
   275
                case Const.APPCOMMAND_MEDIA_FAST_FORWARD:
sl@0
   276
					rcb = RemoteControlButton.FastForward;
sl@0
   277
					break;
sl@15
   278
                case Const.APPCOMMAND_VOLUME_MUTE:
sl@0
   279
					rcb = RemoteControlButton.VolumeMute;
sl@0
   280
					break;
sl@15
   281
                case Const.APPCOMMAND_MEDIA_PAUSE:
sl@0
   282
					rcb = RemoteControlButton.Pause;
sl@0
   283
					break;
sl@15
   284
                case Const.APPCOMMAND_MEDIA_PLAY:
sl@0
   285
					rcb = RemoteControlButton.Play;
sl@0
   286
					break;
sl@15
   287
                case Const.APPCOMMAND_MEDIA_PLAY_PAUSE:
sl@0
   288
                    rcb = RemoteControlButton.PlayPause;
sl@0
   289
                    break;
sl@15
   290
                case Const.APPCOMMAND_MEDIA_RECORD:
sl@0
   291
					rcb = RemoteControlButton.Record;
sl@0
   292
					break;
sl@15
   293
                case Const.APPCOMMAND_MEDIA_PREVIOUSTRACK:
sl@0
   294
					rcb = RemoteControlButton.PreviousTrack;
sl@0
   295
					break;
sl@15
   296
                case Const.APPCOMMAND_MEDIA_REWIND:
sl@0
   297
					rcb = RemoteControlButton.Rewind;
sl@0
   298
					break;
sl@15
   299
                case Const.APPCOMMAND_MEDIA_NEXTTRACK:
sl@0
   300
					rcb = RemoteControlButton.NextTrack;
sl@0
   301
					break;
sl@15
   302
                case Const.APPCOMMAND_MEDIA_STOP:
sl@0
   303
					rcb = RemoteControlButton.Stop;
sl@0
   304
					break;
sl@15
   305
                case Const.APPCOMMAND_VOLUME_DOWN:
sl@0
   306
					rcb = RemoteControlButton.VolumeDown;
sl@0
   307
					break;
sl@15
   308
                case Const.APPCOMMAND_VOLUME_UP:
sl@0
   309
					rcb = RemoteControlButton.VolumeUp;
sl@0
   310
					break;
sl@0
   311
			}
sl@0
   312
sl@0
   313
			if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
sl@15
   314
                this.ButtonPressed(this, new RemoteControlEventArgs(rcb, GetDevice(lParam)));
sl@0
   315
		}
sl@0
   316
sl@12
   317
        /// <summary>
sl@12
   318
        /// 
sl@12
   319
        /// </summary>
sl@12
   320
        /// <param name="aUsage"></param>
sl@12
   321
        private void HidConsumerDeviceHandler(ushort aUsage)
sl@12
   322
        {
sl@12
   323
            if (aUsage == 0)
sl@12
   324
            {
sl@12
   325
                //Just skip those
sl@12
   326
                return;
sl@12
   327
            }
sl@12
   328
sl@12
   329
            if (Enum.IsDefined(typeof(ConsumerControl), aUsage) && aUsage != 0) //Our button is a known consumer control
sl@12
   330
            {
sl@12
   331
                if (this.ButtonPressed != null)
sl@12
   332
                {
sl@12
   333
                    RemoteControlButton button=RemoteControlButton.Unknown;
sl@16
   334
                    if (aUsage == (ushort)ConsumerControl.AppCtrlProperties || aUsage == (ushort)ConsumerControl.MceProperties)
sl@12
   335
                    {
sl@12
   336
                        button = RemoteControlButton.MoreInfo;
sl@12
   337
                    }
sl@16
   338
                    else if (aUsage == (ushort)ConsumerControl.AppCtrlPrint)
sl@12
   339
                    {
sl@12
   340
                        button = RemoteControlButton.Print;
sl@12
   341
                    }
sl@16
   342
                    else if (aUsage == (ushort)ConsumerControl.MediaSelectProgramGuide || aUsage == (ushort)ConsumerControl.MceProgramGuide)
sl@12
   343
                    {
sl@12
   344
                        button = RemoteControlButton.Guide;
sl@12
   345
                    }
sl@12
   346
                    this.ButtonPressed(this, new RemoteControlEventArgs(button, InputDevice.OEM));
sl@12
   347
                }
sl@12
   348
            }
sl@12
   349
            else
sl@12
   350
            {
sl@12
   351
                Debug.WriteLine("Unknown Consumer Control!");
sl@12
   352
            }
sl@12
   353
        }
sl@12
   354
sl@12
   355
        /// <summary>
sl@12
   356
        /// 
sl@12
   357
        /// </summary>
sl@12
   358
        /// <param name="aUsage"></param>
sl@12
   359
        private void HidMceRemoteHandler(ushort aUsage)
sl@12
   360
        {
sl@12
   361
            if (aUsage == 0)
sl@12
   362
            {
sl@12
   363
                //Just skip those
sl@12
   364
                return;
sl@12
   365
            }
sl@12
   366
sl@12
   367
sl@12
   368
            if (Enum.IsDefined(typeof(MceButton), aUsage) && aUsage != 0) //Our button is a known MCE button
sl@12
   369
            {
sl@12
   370
                if (this.ButtonPressed != null)
sl@12
   371
                {
sl@12
   372
                    this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)aUsage, InputDevice.OEM));
sl@12
   373
                }
sl@12
   374
            }
sl@12
   375
            else
sl@12
   376
            {
sl@12
   377
                Debug.WriteLine("Unknown MCE button!");
sl@12
   378
            }
sl@12
   379
sl@12
   380
        }
sl@12
   381
sl@0
   382
sl@0
   383
		private void ProcessInputCommand(ref Message message)
sl@0
   384
		{
sl@15
   385
            //We received a WM_INPUT message
sl@7
   386
            Debug.WriteLine("================WM_INPUT================");
sl@6
   387
sl@15
   388
            //Check if we received this message while in background or foreground
sl@15
   389
            if (Macro.GET_RAWINPUT_CODE_WPARAM(message.WParam) == Const.RIM_INPUT)
sl@15
   390
            {
sl@15
   391
                Debug.WriteLine("================FOREGROUND");
sl@15
   392
            }
sl@15
   393
            else if (Macro.GET_RAWINPUT_CODE_WPARAM(message.WParam) == Const.RIM_INPUTSINK)
sl@15
   394
            {
sl@15
   395
                Debug.WriteLine("================BACKGROUND");
sl@15
   396
            }
sl@0
   397
sl@10
   398
            //Declare a pointer
sl@10
   399
            IntPtr rawInputBuffer = IntPtr.Zero;
sl@0
   400
sl@10
   401
            try
sl@10
   402
            {
sl@10
   403
                //Fetch raw input
sl@11
   404
                RAWINPUT rawInput = new RAWINPUT();
sl@11
   405
                if (!RawInput.GetRawInputData(message.LParam, ref rawInput, ref rawInputBuffer))
sl@6
   406
                {
sl@6
   407
                    return;
sl@6
   408
                }
sl@6
   409
sl@10
   410
                //Fetch device info
sl@10
   411
                RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO();
sl@11
   412
                if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
sl@10
   413
                {
sl@10
   414
                    return;
sl@10
   415
                }
sl@11
   416
               
sl@6
   417
sl@11
   418
                if (rawInput.header.dwType == Const.RIM_TYPEHID)  //Check that our raw input is HID                        
sl@6
   419
                {
sl@11
   420
                    Debug.WriteLine("WM_INPUT source device is HID.");
sl@11
   421
                    //Get Usage Page and Usage
sl@13
   422
                    Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
sl@10
   423
sl@12
   424
                    //
sl@13
   425
                    HidUsageHandler usagePageHandler=null;
sl@12
   426
sl@14
   427
                    //Check if this an MCE remote HID message
sl@14
   428
                    if (deviceInfo.hid.usUsagePage == (ushort)Hid.UsagePage.MceRemote && deviceInfo.hid.usUsage == (ushort)Hid.UsageId.MceRemoteUsage)
sl@12
   429
                    {                        
sl@13
   430
                        usagePageHandler = HidMceRemoteHandler;
sl@12
   431
                    }
sl@14
   432
                    //Check if this is a consumer control HID message
sl@14
   433
                    else if (deviceInfo.hid.usUsagePage == (ushort)Hid.UsagePage.Consumer && deviceInfo.hid.usUsage == (ushort)Hid.UsageId.ConsumerControl)
sl@12
   434
                    {
sl@13
   435
                        usagePageHandler = HidConsumerDeviceHandler;
sl@12
   436
                    }
sl@14
   437
                    //Unknown HID message
sl@12
   438
                    else
sl@6
   439
                    {
sl@14
   440
                        Debug.WriteLine("Unknown HID message.");
sl@6
   441
                        return;
sl@6
   442
                    }
sl@0
   443
sl@11
   444
                    if (!(rawInput.hid.dwSizeHid > 1     //Make sure our HID msg size more than 1. In fact the first ushort is irrelevant to us for now
sl@11
   445
                        && rawInput.hid.dwCount > 0))    //Check that we have at least one HID msg
sl@3
   446
                    {
sl@11
   447
                        return;
sl@11
   448
                    }
sl@11
   449
sl@11
   450
sl@11
   451
                    //Allocate a buffer for one HID input
sl@11
   452
                    byte[] hidInput = new byte[rawInput.hid.dwSizeHid];
sl@11
   453
sl@11
   454
                    //For each HID input in our raw input
sl@11
   455
                    for (int i = 0; i < rawInput.hid.dwCount; i++)
sl@11
   456
                    {
sl@11
   457
                        //Compute the address from which to copy our HID input
sl@11
   458
                        int hidInputOffset = 0;
sl@11
   459
                        unsafe
sl@3
   460
                        {
sl@11
   461
                            byte* source = (byte*)rawInputBuffer;
sl@11
   462
                            source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
sl@11
   463
                            hidInputOffset = (int)source;
sl@11
   464
                        }
sl@11
   465
sl@11
   466
                        //Copy HID input into our buffer
sl@11
   467
                        Marshal.Copy(new IntPtr(hidInputOffset), hidInput, 0, rawInput.hid.dwSizeHid);
sl@11
   468
sl@11
   469
                        //Print HID raw input in our debug output
sl@11
   470
                        string hidDump = "HID " + rawInput.hid.dwCount + "/" + rawInput.hid.dwSizeHid + ":";
sl@11
   471
                        foreach (byte b in hidInput)
sl@11
   472
                        {
sl@11
   473
                            hidDump += b.ToString("X2");
sl@11
   474
                        }
sl@11
   475
                        Debug.WriteLine(hidDump);
sl@11
   476
                        
sl@11
   477
                        ushort usage = 0;
sl@11
   478
                        //hidInput[0] //Not sure what's the meaning of the code at offset 0
sl@11
   479
                        if (hidInput.Length == 2)
sl@11
   480
                        {
sl@11
   481
                            //Single byte code
sl@11
   482
                            usage = hidInput[1]; //Get button code
sl@11
   483
                        }
sl@11
   484
                        else if (hidInput.Length > 2) //Defensive
sl@11
   485
                        {
sl@11
   486
                            //Assuming double bytes code
sl@12
   487
                            usage = (ushort)((hidInput[2] << 8) + hidInput[1]);
sl@11
   488
                        }
sl@11
   489
sl@13
   490
                        Debug.WriteLine("Usage: 0x" + usage.ToString("X4"));
sl@13
   491
sl@13
   492
                        //Call on our Usage Page handler
sl@13
   493
                        usagePageHandler(usage);
sl@3
   494
                    }
sl@11
   495
sl@10
   496
                }
sl@11
   497
                else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
sl@10
   498
                {
sl@11
   499
                    Debug.WriteLine("WM_INPUT source device is Mouse.");
sl@10
   500
                    // do mouse handling...
sl@10
   501
                }
sl@11
   502
                else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
sl@10
   503
                {
sl@11
   504
                    Debug.WriteLine("WM_INPUT source device is Keyboard.");
sl@10
   505
                    // do keyboard handling...
sl@11
   506
sl@10
   507
                }
sl@10
   508
            }
sl@10
   509
            finally
sl@10
   510
            {
sl@10
   511
                //Always executed when leaving our try block
sl@10
   512
                Marshal.FreeHGlobal(rawInputBuffer);
sl@10
   513
            }
sl@0
   514
		}
sl@0
   515
sl@0
   516
sl@15
   517
		private InputDevice GetDevice(IntPtr lParam)
sl@0
   518
		{
sl@0
   519
			InputDevice inputDevice;
sl@0
   520
sl@15
   521
            switch (Macro.GET_DEVICE_LPARAM(lParam))
sl@0
   522
			{
sl@15
   523
				case Const.FAPPCOMMAND_OEM:
sl@0
   524
					inputDevice = InputDevice.OEM;
sl@0
   525
					break;
sl@15
   526
				case Const.FAPPCOMMAND_MOUSE:
sl@0
   527
					inputDevice = InputDevice.Mouse;
sl@0
   528
					break;
sl@0
   529
				default:
sl@0
   530
					inputDevice = InputDevice.Key;
sl@0
   531
					break;
sl@0
   532
			}
sl@0
   533
sl@0
   534
			return inputDevice;
sl@0
   535
		}
sl@0
   536
	}
sl@0
   537
}