Jypeli  5
The simple game programming library
KeyboardTextBuffer.cs
Siirry tämän tiedoston dokumentaatioon.
1 using System;
2 using System.Text;
3 using Microsoft.Xna.Framework.Input;
4 using System.Collections.Generic;
5 
6 namespace Jypeli.Controls
7 {
8 #if WINDOWS
9  public sealed class KeyboardTextBuffer: System.Windows.Forms.IMessageFilter
10  {
11  [Flags]
12  private enum KeyModifiers : int
13  {
14  None = 0x00,
15  LeftControl = 0x01,
16  RightControl = 0x02,
17  Control = 0x03,
18  LeftAlt = 0x04,
19  RightAlt = 0x08,
20  Alt = 0x0c,
21  LeftShift = 0x10,
22  RightShift = 0x20,
23  Shift = 0x30,
24  }
25 
26  private struct KeyData
27  {
28  public Keys Key;
29  public KeyModifiers Modifier;
30  }
31 
32  StringBuilder textData = new StringBuilder();
33  Stack<KeyData> keyData = new Stack<KeyData>();
34  KeyModifiers modifier;
35 
36 
37  public bool Enabled { get; set; }
38  public bool TranslateMessage { get; set; }
39 
40  public bool TabEnabled { get; set; }
41  public bool BackspaceEnabled { get; set; }
42  public bool MultilineEnabled { get; set; }
43 
44  public String Text { get { return textData.ToString(); } }
45  public int TextLength { get { return keyData.Count; } }
46 
47  public event Action TextChanged;
48 
49  private bool inTextChanged;
50  private void OnTextChanged()
51  {
52  if ( inTextChanged || TextChanged == null ) return;
53  inTextChanged = true;
54  TextChanged();
55  inTextChanged = false;
56  }
57 
58  public KeyboardTextBuffer()
59  {
60  System.Windows.Forms.Application.AddMessageFilter( this );
61  TranslateMessage = true;
62  }
63 
64  public void Clear()
65  {
66  textData.Length = 0;
67  OnTextChanged();
68  }
69 
70  #region IMessageFilter
71 
72  #region Enum
73 
74  protected enum Wm
75  {
76  Active = 6,
77  Char = 0x102,
78  KeyDown = 0x100,
79  KeyUp = 0x101,
80  SysKeyDown = 260,
81  SysKeyUp = 0x105
82  }
83 
84  protected enum Wa
85  {
86  Inactive,
87  Active,
88  ClickActive
89  }
90 
91  protected enum Vk
92  {
93  Alt = 0x12,
94  Control = 0x11,
95  Shift = 0x10
96  }
97 
98  #endregion
99 
100  #region Interop
101 
102  [System.Runtime.InteropServices.DllImport( "user32.dll", EntryPoint = "TranslateMessage" )]
103  protected extern static bool _TranslateMessage( ref System.Windows.Forms.Message m );
104 
105  #endregion
106 
107  bool System.Windows.Forms.IMessageFilter.PreFilterMessage( ref System.Windows.Forms.Message m )
108  {
109  if ( !Enabled )
110  return false;
111  //
112  switch ( (Wm)m.Msg )
113  {
114  case Wm.SysKeyDown:
115  case Wm.KeyDown:
116  if ( (m.LParam.ToInt32() & (1 << 30)) == 0 )//iff repeat count == 0
117  {
118  KeyData data;
119  switch ( (Vk)m.WParam )
120  {
121  case Vk.Control:
122  if ( (m.LParam.ToInt32() & (1 << 24)) == 0 )
123  {
124  data = new KeyData { Key = Keys.LeftControl, Modifier = modifier };
125  keyData.Push( data );
126  modifier |= KeyModifiers.LeftControl;
127  }
128  else
129  {
130  data = new KeyData { Key = Keys.RightControl, Modifier = modifier };
131  keyData.Push( data );
132  modifier |= KeyModifiers.RightControl;
133  }
134  break;
135  case Vk.Alt:
136  if ( (m.LParam.ToInt32() & (1 << 24)) == 0 )
137  {
138  data = new KeyData { Key = Keys.LeftAlt, Modifier = modifier };
139  keyData.Push( data );
140  modifier |= KeyModifiers.LeftAlt;
141  }
142  else
143  {
144  data = new KeyData { Key = Keys.RightAlt, Modifier = modifier };
145  keyData.Push( data );
146  modifier |= KeyModifiers.RightAlt;
147  }
148  break;
149  case Vk.Shift:
150  if ( (m.LParam.ToInt32() & (1 << 24)) == 0 )
151  {
152  data = new KeyData { Key = Keys.LeftShift, Modifier = modifier };
153  keyData.Push( data );
154  modifier |= KeyModifiers.LeftShift;
155  }
156  else
157  {
158  data = new KeyData { Key = Keys.RightShift, Modifier = modifier };
159  keyData.Push( data );
160  modifier |= KeyModifiers.RightShift;
161  }
162  break;
163  //
164  default:
165  data = new KeyData { Key = (Keys)m.WParam, Modifier = modifier };
166  keyData.Push( data );
167  break;
168  }
169  }
170 
171  if ( TranslateMessage )
172  _TranslateMessage( ref m );
173 
174  // Allow further processing of the message
175  // If true, Alt-F4 among other key combinations is disabled.
176  return false;
177 
178  case Wm.SysKeyUp:
179  case Wm.KeyUp:
180  switch ( (Vk)m.WParam )
181  {
182  case Vk.Control:
183  if ( (m.LParam.ToInt32() & (1 << 24)) == 0 )
184  modifier &= ~KeyModifiers.LeftControl;
185  else
186  modifier &= ~KeyModifiers.RightControl;
187  break;
188  case Vk.Alt:
189  if ( (m.LParam.ToInt32() & (1 << 24)) == 0 )
190  modifier &= ~KeyModifiers.LeftAlt;
191  else
192  modifier &= ~KeyModifiers.RightAlt;
193  break;
194  case Vk.Shift:
195  if ( (m.LParam.ToInt32() & (1 << 24)) == 0 )
196  modifier &= ~KeyModifiers.LeftShift;
197  else
198  modifier &= ~KeyModifiers.RightShift;
199  break;
200  }
201  return true;
202 
203  case Wm.Char:
204  //
205  char c = (char)m.WParam;
206  if ( c < (char)0x20
207  && !( TabEnabled && c == '\t' )
208  && !( MultilineEnabled && ( c == '\r' || c == '\n' ) )
209  && !( BackspaceEnabled && c == '\b' ) )
210  break;
211 
212  if ( c == '\r' )
213  c = '\n'; // Note: Control+ENTER will send \n, just ENTER will send \r
214 
215  if ( c == '\b' && textData.Length > 0 && textData[textData.Length - 1] != '\b' )
216  {
217  // Backspace
218  textData.Length--;
219  }
220  else
221  textData.Append( c );
222 
223  OnTextChanged();
224  return true;
225 
226  case Wm.Active:
227  if ( ((int)m.WParam & 0xffff) == (int)Wa.Inactive )
228  {
229  modifier = KeyModifiers.None;
230  }
231  break; // Must not filter
232  }
233  return false;
234  }
235 
236  #endregion
237  }
238 #endif
239 }
Key
Näppäimistön näppäin.
Definition: Key.cs:37