root/Apple Wireless Keyboard Helper/trunk/Misuzilla.Applications.AppleWirelessKeyboardHelper/Helper.cs

Revision 366, 9.8 kB (checked in by tomoyo, 11 months ago)

FRなキーボードにも対応してみた。

  • Property svn:keywords set to Id
Line 
1using System;
2using System.Diagnostics;
3using System.IO;
4using System.Runtime.InteropServices;
5using System.Windows.Forms;
6using Microsoft.Win32.SafeHandles;
7using WiimoteLib;
8
9namespace Misuzilla.Applications.AppleWirelessKeyboardHelper
10{
11    internal class Helper : IDisposable
12    {
13        public event EventHandler<AppleKeyboardEventArgs> FnKeyCombinationDown;
14        public event EventHandler<AppleKeyboardEventArgs> KeyDown;
15        public event EventHandler<AppleKeyboardEventArgs> KeyUp;
16        public event EventHandler<KeyEventArgs> SpecialKeyDown;
17
18        public event EventHandler Disconnected;
19
20        public Boolean CurrentPowerButtonIsDown;
21        public AppleKeyboardKeys CurrentKeyState;
22
23        private Stream _stream;
24        private Win32.HookHandle _hHook;
25
26        private const UInt32 VIDApple = 0x5ac;
27        private const UInt32 PIDAppleWirelessKeyboardUS = 0x22c;
28        private const UInt32 PIDAppleWirelessKeyboardFR = 0x22d;
29        private const UInt32 PIDAppleWirelessKeyboardJIS = 0x22e;
30
31        /// <summary>
32        ///
33        /// </summary>
34        internal Boolean Start()
35        {
36            if (_stream != null)
37                throw new InvalidOperationException("�w���p�[�͂��łɎ�s���ł��B");
38
39            Guid guid;
40            HIDImports.HidD_GetHidGuid(out guid);
41
42            IntPtr hDevInfo = HIDImports.SetupDiGetClassDevs(ref guid, null, IntPtr.Zero, HIDImports.DIGCF_DEVICEINTERFACE);
43            HIDImports.SP_DEVICE_INTERFACE_DATA diData = new HIDImports.SP_DEVICE_INTERFACE_DATA();
44            diData.cbSize = Marshal.SizeOf(diData);
45
46            UInt32 index = 0;
47            while (HIDImports.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref guid, index++, ref diData))
48            {
49                HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA diDetail = new HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA();
50                diDetail.cbSize = (IntPtr.Size == 8) ? (UInt32)8 : 5; // x64:8, x86:5
51
52                UInt32 size;
53                HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, IntPtr.Zero, 0, out size, IntPtr.Zero);
54                if (HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, ref diDetail, size, out size, IntPtr.Zero))
55                {
56                    Debug.WriteLine("Device: " + diDetail.DevicePath); Debug.Indent();
57                    SafeFileHandle mHandle = HIDImports.CreateFile(diDetail.DevicePath, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, HIDImports.EFileAttributes.Overlapped, IntPtr.Zero);
58                    HIDImports.HIDD_ATTRIBUTES attrib = new HIDImports.HIDD_ATTRIBUTES();
59                    attrib.Size = Marshal.SizeOf(attrib);
60
61                    if (HIDImports.HidD_GetAttributes(mHandle.DangerousGetHandle(), ref attrib))
62                    {
63                        Debug.WriteLine(String.Format("VendorID:{0:x}, ProductID:{1:x}, VersionNumber:{2:x}", attrib.VendorID, attrib.ProductID, attrib.VersionNumber));
64                        if (attrib.VendorID == VIDApple &&
65                           (attrib.ProductID == PIDAppleWirelessKeyboardUS || attrib.ProductID == PIDAppleWirelessKeyboardJIS || attrib.ProductID == PIDAppleWirelessKeyboardFR))
66                        {
67                            _stream = new FileStream(mHandle, FileAccess.ReadWrite, 22, true);
68                            //break;
69                        }
70                        else
71                        {
72                            mHandle.Close();
73                        }
74                    }
75                    Debug.Unindent();
76                }
77            }
78
79            if (_stream != null)
80            {
81                Byte[] buffer = new Byte[22];
82                _stream.BeginRead(buffer, 0, buffer.Length, SpecialKeyStateChanged, buffer);
83                return true;
84            }
85            else
86            {
87                // Not Connected
88                return false;
89            }
90        }
91
92        public Boolean Hook()
93        {
94            if (_hHook != null)
95                throw new InvalidOperationException("�t�b�N�͂��łɎ�s�������܂��B");
96
97            // hook
98            Win32.HookProcedure = KeyboardHookProc;
99            _hHook = Win32.SetWindowsHookEx(Win32.WH_KEYBOARD_LL, Win32.HookProcedure, Win32.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
100
101            return !_hHook.IsInvalid;
102        }
103
104        private void OnSpecialKeyDown()
105        {
106            if (SpecialKeyDown != null)
107                SpecialKeyDown(this, new KeyEventArgs(CurrentPowerButtonIsDown, CurrentKeyState));
108        }
109       
110        private void OnFnKeyCombinationDown(AppleKeyboardKeys appleKeyState, Keys key, Win32.KeyboardHookEventStruct keyEventStruct)
111        {
112            if (FnKeyCombinationDown != null)
113                FnKeyCombinationDown(this, new AppleKeyboardEventArgs(appleKeyState, key, keyEventStruct));
114        }
115       
116        private Boolean OnKeyDown(AppleKeyboardKeys appleKeyState, Keys key, Win32.KeyboardHookEventStruct keyEventStruct)
117        {
118            if (KeyDown != null)
119            {
120                AppleKeyboardEventArgs eArgs = new AppleKeyboardEventArgs(appleKeyState, key, keyEventStruct);
121                KeyDown(this, eArgs);
122                return eArgs.Handled;
123            }
124            else
125            {
126                return false;
127            }
128        }
129       
130        private Boolean OnKeyUp(AppleKeyboardKeys appleKeyState, Keys key, Win32.KeyboardHookEventStruct keyEventStruct)
131        {
132            if (KeyUp != null)
133            {
134                AppleKeyboardEventArgs eArgs = new AppleKeyboardEventArgs(appleKeyState, key, keyEventStruct);
135                KeyUp(this, eArgs);
136                return eArgs.Handled;
137            }
138            else
139            {
140                return false;
141            }
142        }
143
144        private IntPtr KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
145        {
146            Win32.KeyboardHookEventStruct keyEventStruct = (Win32.KeyboardHookEventStruct)Marshal.PtrToStructure(lParam, typeof(Win32.KeyboardHookEventStruct));
147            //Debug.WriteLine(String.Format("{0}, {1}, {2}", nCode, wParam, lParam));
148            Debug.WriteLine(keyEventStruct);
149           
150            switch ((Keys)keyEventStruct.wVk)
151            {
152                case Keys.LShiftKey:
153                case Keys.RShiftKey:
154                case Keys.LMenu:
155                case Keys.RMenu:
156                case Keys.LControlKey:
157                case Keys.RControlKey:
158                    return Win32.CallNextHookEx(_hHook, nCode, wParam, lParam);
159            }
160
161            // ���������������͖�������            if (keyEventStruct.dwExtraInfo != (IntPtr)0x37564)
162            {
163                Boolean handled = false;
164                switch ((Int32) wParam)
165                {
166                    case Win32.WM_KEYUP:
167                        handled = OnKeyUp(CurrentKeyState, Keys.None, keyEventStruct);
168                        break;
169                    case Win32.WM_KEYDOWN:
170                        handled = OnKeyDown(CurrentKeyState, Keys.None, keyEventStruct);
171                        break;
172                }
173                if (handled)
174                    return (IntPtr) 1;
175
176                if ((CurrentKeyState & AppleKeyboardKeys.Fn) == AppleKeyboardKeys.Fn)
177                {
178                    if ((Int32) wParam == Win32.WM_KEYDOWN || (Int32) wParam == Win32.WM_SYSKEYDOWN) // KEYDOWN
179                        OnFnKeyCombinationDown(CurrentKeyState, (Keys) keyEventStruct.wVk, keyEventStruct);
180                    //else if ((Int32)wParam == Win32.WM_KEYUP || (Int32)wParam == Win32.WM_SYSKEYUP) // KEYUP
181                    //    OnFnKeyCombinationUp(CurrentKeyState, (Keys)keyEventStruct.wVk, keyEventStruct);
182                    return (IntPtr) 1;
183                }
184            }
185            return Win32.CallNextHookEx(_hHook, nCode, wParam, lParam);
186        }
187
188        private void SpecialKeyStateChanged(IAsyncResult ar)
189        {
190            if (_stream == null || !ar.IsCompleted)
191                return;
192
193            try
194            {
195                _stream.EndRead(ar);
196            }
197            catch (OperationCanceledException) { }
198            catch (IOException ioe)
199            {
200                // restart (reconnected)
201                Debug.WriteLine("Restart: " + ioe.Message);
202                if (Disconnected != null)
203                    Disconnected(this, EventArgs.Empty);
204                return;
205            }
206
207            Byte[] buffer = ar.AsyncState as Byte[];
208            foreach (Byte b in buffer)
209                Debug.Write(String.Format("{0:x2} ", b));
210
211            if (buffer[0] == 0x11)
212            {
213                Debug.Write((AppleKeyboardKeys) buffer[1]);
214                CurrentKeyState = (AppleKeyboardKeys) buffer[1];
215            }
216            else if (buffer[0] == 0x13)
217            {
218                Debug.Write(buffer[1] == 1 ? "Power (Down)" : "Power (Up)");
219                CurrentPowerButtonIsDown = (buffer[1] == 1);
220            }
221
222            OnSpecialKeyDown();
223
224            Debug.WriteLine("");
225
226            _stream.BeginRead(buffer, 0, buffer.Length, SpecialKeyStateChanged, buffer);
227        }
228
229        public void Unhook()
230        {
231            if (_hHook != null && !_hHook.IsInvalid)
232            {
233                _hHook.Dispose();
234            }
235            _hHook = null;
236        }
237       
238        public void Shutdown()
239        {
240            if (_stream != null)
241            {
242                _stream.Close();
243                _stream = null;
244            }
245        }
246
247        #region IDisposable �����o
248
249        public void Dispose()
250        {
251            Unhook();
252            Shutdown();
253        }
254
255        #endregion
256    }
257}
Note: See TracBrowser for help on using the browser.