00001 #region --- License ---
00002
00003
00004
00005 #endregion
00006
00007 #region --- Using directives ---
00008
00009 using System;
00010 using System.Collections.Generic;
00011 using System.Text;
00012 using System.Runtime.InteropServices;
00013 using System.Diagnostics;
00014 using Microsoft.Win32;
00015 using OpenTK.Input;
00016
00017 #endregion
00018
00019 namespace OpenTK.Platform.Windows
00020 {
00021 internal class WinRawKeyboard : IKeyboardDriver, IDisposable
00022 {
00023 private List<KeyboardDevice> keyboards = new List<KeyboardDevice>();
00024 private IntPtr window;
00025
00026 #region --- Constructors ---
00027
00028 internal WinRawKeyboard()
00029 : this(IntPtr.Zero)
00030 {
00031 }
00032
00033 internal WinRawKeyboard(IntPtr windowHandle)
00034 {
00035 Debug.WriteLine("Initializing keyboard driver (WinRawKeyboard).");
00036 Debug.Indent();
00037
00038 this.window = windowHandle;
00039
00040 UpdateKeyboardList();
00041
00042 Debug.Unindent();
00043 }
00044
00045 #endregion
00046
00047 #region internal static void UpdateKeyboardList()
00048
00049 internal void UpdateKeyboardList()
00050 {
00051 int count = WinRawInput.DeviceCount;
00052 RawInputDeviceList[] ridl = new RawInputDeviceList[count];
00053 for (int i = 0; i < count; i++)
00054 ridl[i] = new RawInputDeviceList();
00055 Functions.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize);
00056
00057
00058 for (int i = 0; i < count; i++)
00059 {
00060 uint size = 0;
00061 Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size);
00062 IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size);
00063 Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size);
00064 string name = Marshal.PtrToStringAnsi(name_ptr);
00065 Marshal.FreeHGlobal(name_ptr);
00066 if (name.ToLower().Contains("root"))
00067 {
00068
00069 continue;
00070 }
00071 else if (ridl[i].Type == RawInputDeviceType.KEYBOARD || ridl[i].Type == RawInputDeviceType.HID)
00072 {
00073
00074
00075
00076
00077
00078
00079 string[] split = name.Split('#');
00080
00081 string id_01 = split[0];
00082 string id_02 = split[1];
00083 string id_03 = split[2];
00084
00085
00086 string findme = string.Format(
00087 @"System\CurrentControlSet\Enum\{0}\{1}\{2}",
00088 id_01, id_02, id_03);
00089
00090 RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme);
00091
00092 string deviceDesc =
00093 (string)regkey.GetValue("DeviceDesc");
00094 string deviceClass =
00095 (string)regkey.GetValue("Class");
00096 if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("keyboard"))
00097 {
00098 KeyboardDevice kb = new KeyboardDevice();
00099 kb.Description = deviceDesc;
00100
00101
00102 RawInputDeviceInfo info = new RawInputDeviceInfo();
00103 int devInfoSize = API.RawInputDeviceInfoSize;
00104 Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICEINFO,
00105 info, ref devInfoSize);
00106
00107 kb.NumberOfLeds = info.Device.Keyboard.NumberOfIndicators;
00108 kb.NumberOfFunctionKeys = info.Device.Keyboard.NumberOfFunctionKeys;
00109 kb.NumberOfKeys = info.Device.Keyboard.NumberOfKeysTotal;
00110
00111 kb.DeviceID = ridl[i].Device;
00112
00113
00114
00115 this.RegisterKeyboardDevice(kb);
00116 keyboards.Add(kb);
00117
00118 }
00119 }
00120 }
00121 }
00122
00123 #endregion
00124
00125 #region internal void RegisterKeyboardDevice(Keyboard kb)
00126
00127 internal void RegisterKeyboardDevice(KeyboardDevice kb)
00128 {
00129 RawInputDevice[] rid = new RawInputDevice[1];
00130
00131 rid[0] = new RawInputDevice();
00132 rid[0].UsagePage = 1;
00133 rid[0].Usage = 6;
00134 rid[0].Flags = RawInputDeviceFlags.INPUTSINK;
00135 rid[0].Target = window;
00136
00137 if (!Functions.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize))
00138 {
00139 throw new ApplicationException(
00140 String.Format(
00141 "Raw input registration failed with error: {0}. Device: {1}",
00142 Marshal.GetLastWin32Error(),
00143 rid[0].ToString())
00144 );
00145 }
00146 else
00147 {
00148 Debug.Print("Registered keyboard {0}", kb.ToString());
00149 }
00150 }
00151
00152 #endregion
00153
00154 #region internal bool ProcessKeyboardEvent(API.RawInput rin)
00155
00161 internal bool ProcessKeyboardEvent(RawInput rin)
00162 {
00163
00164
00165 switch (rin.Header.Type)
00166 {
00167 case RawInputDeviceType.KEYBOARD:
00168 bool pressed =
00169 rin.Data.Keyboard.Message == (int)WindowMessage.KEYDOWN ||
00170 rin.Data.Keyboard.Message == (int)WindowMessage.SYSKEYDOWN;
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 int index;
00183 if (keyboards.Count > 0) index = 0;
00184 else return false;
00185
00186
00187
00188 switch (rin.Data.Keyboard.VKey)
00189 {
00190 case VirtualKeys.SHIFT:
00191 keyboards[index][Input.Key.ShiftLeft] = keyboards[index][Input.Key.ShiftRight] = pressed;
00192 return true;
00193
00194 case VirtualKeys.CONTROL:
00195 keyboards[index][Input.Key.ControlLeft] = keyboards[index][Input.Key.ControlRight] = pressed;
00196 return true;
00197
00198 case VirtualKeys.MENU:
00199 keyboards[index][Input.Key.AltLeft] = keyboards[index][Input.Key.AltRight] = pressed;
00200 return true;
00201
00202 default:
00203 if (!WMInput.KeyMap.ContainsKey(rin.Data.Keyboard.VKey))
00204 Debug.Print("Virtual key {0} ({1}) not mapped.",
00205 rin.Data.Keyboard.VKey, (int)rin.Data.Keyboard.VKey);
00206 else
00207 keyboards[index][WMInput.KeyMap[rin.Data.Keyboard.VKey]] = pressed;
00208
00209 return false;
00210 }
00211
00212 default:
00213 throw new ApplicationException("Windows raw keyboard driver received invalid data.");
00214 }
00215 }
00216
00217 #endregion
00218
00219 #region --- IInputDevice Members ---
00220
00221 public string Description
00222 {
00223 get { throw new Exception("The method or operation is not implemented."); }
00224 }
00225
00226 public Input.InputDeviceType DeviceType
00227 {
00228 get { return Input.InputDeviceType.Keyboard; }
00229 }
00230
00231 #endregion
00232
00233 #region --- IKeyboardDriver Members ---
00234
00235 public IList<KeyboardDevice> Keyboard
00236 {
00237 get { return keyboards; }
00238 }
00239
00240 #endregion
00241
00242 #region --- IDisposable Members ---
00243
00244 private bool disposed;
00245
00246 public void Dispose()
00247 {
00248 Dispose(true);
00249 GC.SuppressFinalize(this);
00250 }
00251
00252 private void Dispose(bool manual)
00253 {
00254 if (!disposed)
00255 {
00256 if (manual)
00257 {
00258 keyboards.Clear();
00259 }
00260 disposed = true;
00261 }
00262 }
00263
00264 ~WinRawKeyboard()
00265 {
00266 Dispose(false);
00267 }
00268
00269 #endregion
00270 }
00271 }