OSDN Git Service

14515d3d78f127a038582d8e6535aeee81700923
[strokestylet/CsWin10Desktop3.git] / FDK24 / 入力 / 個別 / Keyboard.cs
1 using System;
2 using System.Collections.Generic;
3
4 namespace FDK.入力
5 {
6         public class Keyboard : FDK.入力.IInputDevice, IDisposable
7         {
8                 public InputDeviceType 入力デバイス種別 => ( InputDeviceType.Keyboard );
9
10                 public Keyboard( IntPtr hWindow )
11                 {
12                         FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
13                         try
14                         {
15                                 this._Window = hWindow;
16
17                                 #region " キーの押下状態配列を初期化する。"
18                                 //-----------------
19                                 for( int i = 0; i < 256; i++ )
20                                         this._現在のキーの押下状態[ i ] = false;
21                                 //-----------------
22                                 #endregion
23
24                                 // DirectInput を生成する。
25                                 var di = new SharpDX.DirectInput.DirectInput();
26
27                                 #region " キーボードが接続されていないなら、this.Device = null のままとする。"
28                                 //-----------------
29                                 if( 0 == di.GetDevices( SharpDX.DirectInput.DeviceType.Keyboard, SharpDX.DirectInput.DeviceEnumerationFlags.AttachedOnly ).Count )
30                                 {
31                                         this._Device = null; // これは、エラーではない。
32                                         return;
33                                 }
34                                 //-----------------
35                                 #endregion
36
37                                 // デバイスを生成する。
38                                 this._Device = new SharpDX.DirectInput.Keyboard( di );
39
40                                 // デバイスの協調モードを設定する。
41                                 this._Device.SetCooperativeLevel(
42                                         this._Window,
43                                         SharpDX.DirectInput.CooperativeLevel.NoWinKey |
44                                         SharpDX.DirectInput.CooperativeLevel.Foreground |
45                                         SharpDX.DirectInput.CooperativeLevel.NonExclusive );
46
47                                 // デバイスの入力バッファサイズを設定する。
48                                 this._Device.Properties.BufferSize = Keyboard._デバイスの入力バッファサイズ;
49                         }
50                         finally
51                         {
52                                 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
53                         }
54                 }
55
56                 public void Dispose()
57                 {
58                         FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
59                         try
60                         {
61                                 FDK.Utilities.解放する( ref this._Device );
62                         }
63                         finally
64                         {
65                                 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
66                         }
67                 }
68
69                 public void ポーリングする()
70                 {
71                         if( null == this._Device )
72                                 return; // 準正常。
73
74                         this._入力イベントリスト.Clear(); // Acquire 前にクリアしておく(Acquire の失敗時にリストが空であるように)。
75
76                         #region " Acquire する。失敗(非アクティブ、ウィンドウ終了時など)したら、何もしない。 "
77                         //-----------------
78                         try
79                         {
80                                 this._Device.Acquire();
81                         }
82                         catch
83                         {
84                                 //Log.WARNING( "キーボードデバイスの Acquire に失敗しました。" );
85                                 return;
86                         }
87                         //-----------------
88                         #endregion
89
90                         try
91                         {
92                                 // ポーリングを行う。
93                                 this._Device.Poll();
94
95                                 // ポーリング結果から状態配列を更新する。
96                                 var timeStamp = FDK.カウンタ.QPCTimer.生カウント;    // なるべく早くに取得しておく。
97                                 foreach( var k in this._Device.GetBufferedData() )
98                                 {
99                                         if( k.IsPressed )
100                                         {
101                                                 #region " (a) 押された "
102                                                 //-----------------
103                                                 this._入力イベントリスト.Add(
104                                                         new InputEvent() {
105                                                                 Key = (int) k.Key,
106                                                                 Velocity = 255,
107                                                                 TimeStamp = timeStamp,    // DirectInput の TimeStamp は使わない。
108                                                                 押された = true,
109                                                                 離された = false,
110                                                         } );
111
112                                                 this._現在のキーの押下状態[ (int) k.Key ] = true;
113                                                 //-----------------
114                                                 #endregion
115                                         }
116                                         else if( k.IsReleased )
117                                         {
118                                                 #region " (b) 離された "
119                                                 //-----------------
120                                                 this._入力イベントリスト.Add(
121                                                         new InputEvent() {
122                                                                 Key = (int) k.Key,
123                                                                 Velocity = 255,
124                                                                 TimeStamp = timeStamp,    // DirectInput の TimeStamp は使わない。
125                                                                 押された = false,
126                                                                 離された = true,
127                                                         } );
128
129                                                 this._現在のキーの押下状態[ (int) k.Key ] = true;
130                                                 //-----------------
131                                                 #endregion
132                                         }
133                                 }
134                         }
135                         catch( SharpDX.SharpDXException )
136                         {
137                                 // たまに DIERR_INPUTLOST が発生するが、再度 Acquire すればいいだけなので無視する。
138                         }
139                 }
140
141                 public bool キーが押された( int key )
142                 {
143                         InputEvent dummy;
144                         return this.キーが押された( key, out dummy );
145                 }
146
147                 public bool キーが押された( int key, out InputEvent ev )
148                 {
149                         ev = null;
150
151                         if( null == this._Device )
152                                 return false;   // 準正常。
153
154                         // 検索 & 戻り値格納。
155                         ev = this._入力イベントリスト.Find( ( item ) => { return ( item.Key == key ) && ( item.押された ); } );
156
157                         // 非 null なら見つかった。
158                         return ( null != ev ) ? true : false;
159                 }
160
161                 public bool キーが押された( SharpDX.DirectInput.Key key )
162                 {
163                         InputEvent dummy;
164                         return this.キーが押された( (int) key, out dummy );
165                 }
166
167                 public bool キーが押された( SharpDX.DirectInput.Key key, out InputEvent ev )
168                 {
169                         return this.キーが押された( (int) key, out ev );
170                 }
171
172                 public bool キーが押されている( int key )
173                 {
174                         if( null == this._Device )   // 準正常。
175                                 return false;
176
177                         return this._現在のキーの押下状態[ key ];
178                 }
179
180                 public bool キーが押されている( SharpDX.DirectInput.Key key )
181                 {
182                         return this.キーが押されている( (int) key );
183                 }
184
185                 public bool キーが離された( int key )
186                 {
187                         InputEvent dummy;
188                         return this.キーが離された( key, out dummy );
189                 }
190
191                 public bool キーが離された( int key, out InputEvent ev )
192                 {
193                         ev = null;
194
195                         if( null == this._Device )
196                                 return false;   // 準正常。
197
198                         // 検索 & 戻り値格納。
199                         ev = this._入力イベントリスト.Find( ( item ) => { return ( item.Key == key ) && ( item.離された ); } );
200
201                         // 非 null なら見つかった。
202                         return ( null != ev ) ? true : false;
203                 }
204
205                 public bool キーが離された( SharpDX.DirectInput.Key key )
206                 {
207                         InputEvent dummy;
208                         return this.キーが離された( (int) key, out dummy );
209                 }
210
211                 public bool キーが離された( SharpDX.DirectInput.Key key, out InputEvent ev )
212                 {
213                         return this.キーが離された( (int) key, out ev );
214                 }
215
216                 public bool キーが離されている( int key )
217                 {
218                         if( null == this._Device )   // 準正常。
219                                 return false;
220
221                         return !( this._現在のキーの押下状態[ key ] );
222                 }
223
224                 public bool キーが離されている( SharpDX.DirectInput.Key key )
225                 {
226                         return this.キーが離されている( (int) key );
227                 }
228
229                 private const int _デバイスの入力バッファサイズ = 32;
230                 private SharpDX.DirectInput.Keyboard _Device = null; // キーボードがアタッチされていない場合は null 。
231                 private IntPtr _Window = IntPtr.Zero;
232                 /// <summary>
233                 ///             ポーリングごとに累積更新された最終の結果。
234                 /// </summary>
235                 private readonly bool[] _現在のキーの押下状態 = new bool[ 256 ];
236                 private readonly List<InputEvent> _入力イベントリスト = new List<InputEvent>();
237         }
238 }