source: 2013/30/MiskaK/MW2(My Warfare 2)/Paranneltu Jypeli/Controls/KeyboardTextBuffer.cs @ 4507

Revision 4507, 7.8 KB checked in by anlakane, 6 years ago (diff)

Talletus.

Line 
1using System;
2using System.Text;
3using Microsoft.Xna.Framework.Input;
4using System.Collections.Generic;
5
6namespace 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}
Note: See TracBrowser for help on using the repository browser.