/// <summary> /// Constructor called to initialize the event args with the key pressed by the user. /// </summary> /// <param name="c"></param> public KeyPressEventArgs(Textbox field, char c) { _field = field; _char = c; }
/// <summary> /// A method that loops and processes keystrokes until the form is complete, /// either by <see cref="FormComplete">FormComplete</see> or /// <see cref="FormCancelled">FormCancelled</see> events. /// </summary> private void LoopForKeypress() { // Loop for keypresses. Since we're doing all the work of processing, we have // to trap special keypresses and respond appropriately while (true) { // Blocks on the next function call. ConsoleKeyInfo cki = Console.ReadKey(true); ConsoleKey nKey = cki.Key; // A key's been pressed. Figure out what to do. // All actions will be against the current field, stored in _field. char cChar = cki.KeyChar; if (cChar != 0) { // Guard against unprintable chars. KeyPressEventArgs kpea = new KeyPressEventArgs(_field, cChar); if (_keyPressEvent != null) _keyPressEvent(this, kpea); if (!kpea.Cancel) { // Process the keystroke. It wasn't cancelled. switch (nKey) { case ConsoleKey.Backspace: // Backspace pressed // Is there a character to backspace over? if (_field.Text.Length > 0) { _field.Text = _field.Text.Substring(0, _field.Text.Length - 1); Refresh(_field); } break; case ConsoleKey.Tab: // Tab -> Move to the next field. if (cki.Modifiers == ConsoleModifiers.Shift) { // Go backwards. _currentField--; // If we're at the first field, move to the last. if (_currentField == -1) _currentField = _textboxes.Count - 1; } else { // Go forwards _currentField++; // If we're in the last field already, move back to the first. if (_currentField == _textboxes.Count) _currentField = 0; } // Set the current field to the next one in the collection. _field = _textboxes[_currentField]; _textboxes.FocusField = _field; // Move the cursor to the location of the next field, accomodating // any text that may already be there.. Console.SetCursorPosition(_field.Location.X + _field.Text.Length, _field.Location.Y); break; case ConsoleKey.Enter: // Enter -> Fire the complete event if it's wired. if (_formCompleteEvent != null) { FormCompleteEventArgs fcea = new FormCompleteEventArgs(); _formCompleteEvent(this, fcea); // The listener of this event will set the Cancel field if they // want to re-use the form. If not cancelled, the form will // be destroyed. if (!fcea.Cancel) { // Get rid of this form. A new one will be displayed. // Unusual to call Dispose() on oneself, but it saves a lot of // code in the clients if this is the default behaviour, rather // than forcing every single event to call Dispose() on the // passed-in sender parameter. ((IDisposable)this).Dispose(); return; } // else the current form will be reused. Go back for more keys. } break; case ConsoleKey.Escape: // Esc -> Fire the cancelled event if it's wired. if (this.FormCancelled != null) { this.FormCancelled(this, System.EventArgs.Empty); ((IDisposable)this).Dispose(); return; } break; default: // Any other keystroke if (_field != null) { // May not be an active textbox. if (_field.Text.Length < _field.Length) { // The field is not yet full. It can be appended to. _field.NonEventingText += cChar; Console.ForegroundColor = _field.Foreground; Console.BackgroundColor = _field.Background; if (_field.PasswordChar != char.MinValue) // It's a password field. Display the password character. Console.Write(_field.PasswordChar); else // Not a password type field. Show the actual character. Console.Write(cChar); } // Field already full => no keystrokes accepted. } break; } // Keystroke was not cancelled } // Character was printable } // End of switch statement } // End loop for keypresses }
/// <summary> /// Draws the current form onto the console. /// </summary> /// <param name="clear">A <see cref="bool">bool</see> indicating whether or /// not the screen should be cleared before it is redrawn.</param> public void Render(bool clear) { Console.ResetColor(); if (clear) Console.Clear(); Console.Title = _name; // Resize the window and the buffer to the form's size. if (Console.BufferHeight != _height || Console.BufferWidth != _width) { Console.SetWindowSize(_width, _height); Console.SetBufferSize(_width, _height); } if (Console.WindowHeight != _height || Console.WindowWidth != _width) { Console.SetBufferSize(_width, _height); Console.SetWindowSize(_width, _height); } // Draw the lines first. foreach (Line line in _lines) { Console.BackgroundColor = line.Colour; if (line.Orientation == Line.LineOrientation.Horizontal) { // Instructions for drawing a horizontal line. Console.SetCursorPosition(line.Location.X, line.Location.Y); Console.Write(new string(' ', line.Length)); } else { // Instructions for drawing a vertical line. Int32 x = line.Location.X; for (Int32 i = line.Location.Y; i < line.Location.Y + line.Length; i++) { Console.SetCursorPosition(x, i); Console.Write(" "); } } } // Draw the labels next. foreach (Label label in _labels) Refresh(label); // Now draw the textboxes. foreach (Textbox text in _textboxes) Refresh(text); // If any textboxes are defined for the form, pick the first one and position // the cursor accordingly. if (_textboxes.Count > 0) { _field = _textboxes[0]; _textboxes.FocusField = _field; Console.SetCursorPosition(_field.Location.X + _field.Text.Length, _field.Location.Y); Console.CursorVisible = true; } else // Otherwise, hide the cursor. Console.CursorVisible = false; _labels.Rendered(); _textboxes.Rendered(); if (_keyThread.Name == null) { // Start the thread that listens for keypresses. _keyThread.Name = "Keypress loop for " + _name; _keyThread.Start(); } }
public void SetFocus(Textbox field) { for (Int32 i = 0; i < _textboxes.Count; i++) if (_textboxes[i] == field) { _field = Textboxes[i]; _currentField = i; Console.ForegroundColor = _field.Foreground; Console.BackgroundColor = _field.Background; Console.SetCursorPosition(_field.Location.X + _field.Text.Length, _field.Location.Y); return; } throw new InvalidOperationException(field.Name + " not found."); }
/// <summary> /// Appends a <see cref="Textbox">Textbox</see> to the list. /// </summary> /// <param name="t">The <see cref="Textbox">Textbox</see> to add.</param> public void Add(Textbox t) { _textboxes.Add(t); }
/// <summary> /// Reads Xml when the <see cref="Textboxes">Textboxes</see> is to be deserialized /// from a stream.</summary> /// <param name="reader">The stream from which the object will be deserialized.</param> void System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader reader) { if (!reader.IsEmptyElement) { while (reader.Read()) { if (reader.NodeType == System.Xml.XmlNodeType.EndElement) { reader.Read(); break; } Textbox textbox = new Textbox(); ((IXmlSerializable)textbox).ReadXml(reader); _textboxes.Add(textbox); reader.Read(); } } else reader.Read(); }