123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855 |
- //#########################################################################################
- //★★★★★★★ http://www.cnpopsoft.com [华普软件] ★★★★★★★
- //★★★★★★★ 华普软件 - VB & C#.NET 专业论文与源码荟萃! ★★★★★★★
- //#########################################################################################
- /*
- * Copyright ?2005, Mathew Hall
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- */
- using System;
- using System.Drawing;
- using System.Globalization;
- using System.Windows.Forms;
- using XPTable.Events;
- using XPTable.Models;
- using XPTable.Renderers;
- using XPTable.Win32;
- namespace XPTable.Editors
- {
- /// <summary>
- /// A class for editing Cells that contain numbers
- /// </summary>
- public class NumberCellEditor : CellEditor, IEditorUsesRendererButtons
- {
- #region Class Data
- /// <summary>
- /// ID number for the up button
- /// </summary>
- protected static readonly int UpButtonID = 1;
- /// <summary>
- /// ID number for the down button
- /// </summary>
- protected static readonly int DownButtonID = 2;
- /// <summary>
- /// The current value of the editor
- /// </summary>
- private decimal currentValue;
- /// <summary>
- /// The value to increment or decrement when the up or down buttons are clicked
- /// </summary>
- private decimal increment;
- /// <summary>
- /// The maximum value for the editor
- /// </summary>
- private decimal maximum;
- /// <summary>
- /// The inximum value for the editor
- /// </summary>
- private decimal minimum;
- /// <summary>
- /// A string that specifies how editors value is formatted
- /// </summary>
- private string format;
- /// <summary>
- /// The amount the mouse wheel has moved
- /// </summary>
- private int wheelDelta;
- /// <summary>
- /// Indicates whether the arrow keys should be passed to the editor
- /// </summary>
- private bool interceptArrowKeys;
- /// <summary>
- /// Specifies whether the editors text value is changing
- /// </summary>
- private bool changingText;
- /// <summary>
- /// Initial interval between timer events
- /// </summary>
- private const int TimerInterval = 500;
- /// <summary>
- /// Current interval between timer events
- /// </summary>
- private int interval;
- /// <summary>
- /// Indicates whether the user has changed the editors value
- /// </summary>
- private bool userEdit;
- /// <summary>
- /// The bounding Rectangle of the up and down buttons
- /// </summary>
- private Rectangle buttonBounds;
- /// <summary>
- /// The id of the button that was pressed
- /// </summary>
- private int buttonID;
- /// <summary>
- /// Timer to to fire button presses at regular intervals while
- /// a button is pressed
- /// </summary>
- private Timer timer;
- #endregion
-
- #region Constructor
-
- /// <summary>
- /// Initializes a new instance of the NumberCellEditor class with default settings
- /// </summary>
- public NumberCellEditor()
- {
- TextBox textbox = new TextBox();
- textbox.AutoSize = false;
- textbox.BorderStyle = BorderStyle.None;
- this.Control = textbox;
- this.currentValue = new decimal(0);
- this.increment = new decimal(1);
- this.minimum = new decimal(0);
- this.maximum = new decimal(100);
- this.format = "G";
- this.wheelDelta = 0;
- this.interceptArrowKeys = true;
- this.userEdit = false;
- this.changingText = false;
- this.buttonBounds = Rectangle.Empty;
- this.buttonID = 0;
- this.interval = TimerInterval;
- }
- #endregion
- #region Methods
- /// <summary>
- /// Prepares the CellEditor to edit the specified Cell
- /// </summary>
- /// <param name="cell">The Cell to be edited</param>
- /// <param name="table">The Table that contains the Cell</param>
- /// <param name="cellPos">A CellPos representing the position of the Cell</param>
- /// <param name="cellRect">The Rectangle that represents the Cells location and size</param>
- /// <param name="userSetEditorValues">Specifies whether the ICellEditors
- /// starting value has already been set by the user</param>
- /// <returns>true if the ICellEditor can continue editing the Cell, false otherwise</returns>
- public override bool PrepareForEditing(Cell cell, Table table, CellPos cellPos, Rectangle cellRect, bool userSetEditorValues)
- {
- //
- if (!(table.ColumnModel.Columns[cellPos.Column] is NumberColumn))
- {
- throw new InvalidOperationException("Cannot edit Cell as NumberCellEditor can only be used with a NumberColumn");
- }
-
- if (!(table.ColumnModel.GetCellRenderer(cellPos.Column) is NumberCellRenderer))
- {
- throw new InvalidOperationException("Cannot edit Cell as NumberCellEditor can only be used with a NumberColumn that uses a NumberCellRenderer");
- }
-
- this.Minimum = ((NumberColumn) table.ColumnModel.Columns[cellPos.Column]).Minimum;
- this.Maximum = ((NumberColumn) table.ColumnModel.Columns[cellPos.Column]).Maximum;
- this.Increment = ((NumberColumn) table.ColumnModel.Columns[cellPos.Column]).Increment;
-
- return base.PrepareForEditing (cell, table, cellPos, cellRect, userSetEditorValues);
- }
- /// <summary>
- /// Sets the initial value of the editor based on the contents of
- /// the Cell being edited
- /// </summary>
- protected override void SetEditValue()
- {
- // make sure we start with a valid value
- this.Value = this.Minimum;
- // attempt to get the cells data
- this.Value = Convert.ToDecimal(this.EditingCell.Data);
- }
- /// <summary>
- /// Sets the contents of the Cell being edited based on the value
- /// in the editor
- /// </summary>
- protected override void SetCellValue()
- {
- this.EditingCell.Data = this.Value;
- }
- /// <summary>
- /// Starts editing the Cell
- /// </summary>
- public override void StartEditing()
- {
- this.TextBox.MouseWheel += new MouseEventHandler(OnMouseWheel);
- this.TextBox.KeyDown += new KeyEventHandler(OnTextBoxKeyDown);
- this.TextBox.KeyPress += new KeyPressEventHandler(OnTextBoxKeyPress);
- this.TextBox.LostFocus += new EventHandler(OnTextBoxLostFocus);
-
- base.StartEditing();
- this.TextBox.Focus();
- }
- /// <summary>
- /// Stops editing the Cell and commits any changes
- /// </summary>
- public override void StopEditing()
- {
- this.TextBox.MouseWheel -= new MouseEventHandler(OnMouseWheel);
- this.TextBox.KeyDown -= new KeyEventHandler(OnTextBoxKeyDown);
- this.TextBox.KeyPress -= new KeyPressEventHandler(OnTextBoxKeyPress);
- this.TextBox.LostFocus -= new EventHandler(OnTextBoxLostFocus);
-
- base.StopEditing();
- }
- /// <summary>
- /// Stops editing the Cell and ignores any changes
- /// </summary>
- public override void CancelEditing()
- {
- this.TextBox.MouseWheel -= new MouseEventHandler(OnMouseWheel);
- this.TextBox.KeyDown -= new KeyEventHandler(OnTextBoxKeyDown);
- this.TextBox.KeyPress -= new KeyPressEventHandler(OnTextBoxKeyPress);
- this.TextBox.LostFocus -= new EventHandler(OnTextBoxLostFocus);
-
- base.CancelEditing();
- }
- /// <summary>
- /// Sets the location and size of the CellEditor
- /// </summary>
- /// <param name="cellRect">A Rectangle that represents the size and location
- /// of the Cell being edited</param>
- protected override void SetEditLocation(Rectangle cellRect)
- {
- // calc the size of the textbox
- ICellRenderer renderer = this.EditingTable.ColumnModel.GetCellRenderer(this.EditingCellPos.Column);
- int buttonWidth = ((NumberCellRenderer) renderer).ButtonWidth;
- this.TextBox.Size = new Size(cellRect.Width - 1 - buttonWidth, cellRect.Height-1);
-
- // calc the location of the textbox
- this.TextBox.Location = cellRect.Location;
- this.buttonBounds = new Rectangle(this.TextBox.Left + 1, this.TextBox.Top, buttonWidth, this.TextBox.Height);
- if (((NumberColumn) this.EditingTable.ColumnModel.Columns[this.EditingCellPos.Column]).UpDownAlign == LeftRightAlignment.Left)
- {
- this.TextBox.Location = new Point(cellRect.Left + buttonWidth, cellRect.Top);
- this.buttonBounds.Location = new Point(cellRect.Left, cellRect.Top);
- }
- }
- /// <summary>
- /// Simulates the up button being pressed
- /// </summary>
- protected void UpButton()
- {
- if (this.UserEdit)
- {
- this.ParseEditText();
- }
- decimal num = this.currentValue;
- if (num > (new decimal(-1, -1, -1, false, 0) - this.increment))
- {
- num = new decimal(-1, -1, -1, false, 0);
- }
- else
- {
- num += this.increment;
- if (num > this.maximum)
- {
- num = this.maximum;
- }
- }
- this.Value = num;
- }
- /// <summary>
- /// Simulates the down button being pressed
- /// </summary>
- protected void DownButton()
- {
- if (this.UserEdit)
- {
- this.ParseEditText();
- }
- decimal num = this.currentValue;
- if (num < (new decimal(-1, -1, -1, true, 0) + this.increment))
- {
- num = new decimal(-1, -1, -1, true, 0);
- }
- else
- {
- num -= this.increment;
- if (num < this.minimum)
- {
- num = this.minimum;
- }
- }
- this.Value = num;
- }
- /// <summary>
- /// Updates the editors text value to the current value
- /// </summary>
- protected void UpdateEditText()
- {
- if (this.UserEdit)
- {
- this.ParseEditText();
- }
- this.ChangingText = true;
- this.Control.Text = this.currentValue.ToString(this.Format);
- }
- /// <summary>
- /// Checks the current value and updates the editors text value
- /// </summary>
- protected virtual void ValidateEditText()
- {
- this.ParseEditText();
- this.UpdateEditText();
- }
- /// <summary>
- /// Converts the editors current value to a number
- /// </summary>
- protected void ParseEditText()
- {
- try
- {
- this.Value = this.Constrain(decimal.Parse(this.Control.Text));
- }
- catch (Exception)
- {
- return;
- }
- finally
- {
- this.UserEdit = false;
- }
- }
- /// <summary>
- /// Ensures that the specified value is between the editors Maximun and
- /// Minimum values
- /// </summary>
- /// <param name="value">The value to be checked</param>
- /// <returns>A value is between the editors Maximun and Minimum values</returns>
- private decimal Constrain(decimal value)
- {
- if (value < this.minimum)
- {
- value = this.minimum;
- }
- if (value > this.maximum)
- {
- value = this.maximum;
- }
- return value;
- }
- /// <summary>
- /// Starts the Timer
- /// </summary>
- protected void StartTimer()
- {
- if (this.timer == null)
- {
- this.timer = new Timer();
- this.timer.Tick += new EventHandler(this.TimerHandler);
- }
- this.interval = TimerInterval;
- this.timer.Interval = this.interval;
- this.timer.Start();
- }
- /// <summary>
- /// Stops the Timer
- /// </summary>
- protected void StopTimer()
- {
- if (this.timer != null)
- {
- this.timer.Stop();
- this.timer.Dispose();
- this.timer = null;
- }
- }
- #endregion
- #region Properties
- /// <summary>
- /// Gets the TextBox used to edit the Cells contents
- /// </summary>
- public TextBox TextBox
- {
- get
- {
- return this.Control as TextBox;
- }
- }
- /// <summary>
- /// Gets or sets the editors current value
- /// </summary>
- protected decimal Value
- {
- get
- {
- if (this.UserEdit)
- {
- this.ValidateEditText();
- }
- return this.currentValue;
- }
- set
- {
- if (value != this.currentValue)
- {
- if (value < this.minimum)
- {
- value = this.maximum;
- }
- if (value > this.maximum)
- {
- value = this.maximum;
- }
- this.currentValue = value;
- this.UpdateEditText();
- }
- }
- }
- /// <summary>
- /// Gets or sets the value to increment or decrement when the up or down
- /// buttons are clicked
- /// </summary>
- protected decimal Increment
- {
- get
- {
- return this.increment;
- }
- set
- {
- if (value < new decimal(0))
- {
- throw new ArgumentException("increment must be greater than zero");
- }
- this.increment = value;
- }
- }
- /// <summary>
- /// Gets or sets the maximum value for the editor
- /// </summary>
- protected decimal Maximum
- {
- get
- {
- return this.maximum;
- }
- set
- {
- this.maximum = value;
-
- if (this.minimum > this.maximum)
- {
- this.minimum = this.maximum;
- }
- }
- }
- /// <summary>
- /// Gets or sets the minimum value for the editor
- /// </summary>
- protected decimal Minimum
- {
- get
- {
- return this.minimum;
- }
- set
- {
- this.minimum = value;
- if (this.minimum > this.maximum)
- {
- this.maximum = value;
- }
- }
- }
- /// <summary>
- /// Gets or sets the string that specifies how the editors contents
- /// are formatted
- /// </summary>
- protected string Format
- {
- get
- {
- return this.format;
- }
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException("value");
- }
-
- this.format = value;
- this.UpdateEditText();
- }
- }
- /// <summary>
- /// Gets or sets whether the editors text is being updated
- /// </summary>
- protected bool ChangingText
- {
- get
- {
- return this.changingText;
- }
- set
- {
- this.changingText = value;
- }
- }
- /// <summary>
- /// Gets or sets whether the arrow keys should be passed to the editor
- /// </summary>
- public bool InterceptArrowKeys
- {
- get
- {
- return this.interceptArrowKeys;
- }
- set
- {
- this.interceptArrowKeys = value;
- }
- }
- /// <summary>
- /// Gets or sets whether the user has changed the editors value
- /// </summary>
- protected bool UserEdit
- {
- get
- {
- return this.userEdit;
- }
- set
- {
- this.userEdit = value;
- }
- }
- #endregion
- #region Events
- /// <summary>
- /// Handler for the editors TextBox.MouseWheel event
- /// </summary>
- /// <param name="sender">The object that raised the event</param>
- /// <param name="e">A MouseEventArgs that contains the event data</param>
- protected internal virtual void OnMouseWheel(object sender, MouseEventArgs e)
- {
- bool up = true;
- this.wheelDelta += e.Delta;
- if (Math.Abs(this.wheelDelta) >= 120)
- {
- if (this.wheelDelta < 0)
- {
- up = false;
- }
- if (up)
- {
- this.UpButton();
- }
- else
- {
- this.DownButton();
- }
- this.wheelDelta = 0;
- }
- }
- /// <summary>
- /// Handler for the editors TextBox.KeyDown event
- /// </summary>
- /// <param name="sender">The object that raised the event</param>
- /// <param name="e">A KeyEventArgs that contains the event data</param>
- protected virtual void OnTextBoxKeyDown(object sender, KeyEventArgs e)
- {
- if (this.interceptArrowKeys)
- {
- if (e.KeyData == Keys.Up)
- {
- this.UpButton();
- e.Handled = true;
- }
- else if (e.KeyData == Keys.Down)
- {
- this.DownButton();
- e.Handled = true;
- }
- }
- if (e.KeyCode == Keys.Return)
- {
- this.ValidateEditText();
- }
- }
- /// <summary>
- /// Handler for the editors TextBox.KeyPress event
- /// </summary>
- /// <param name="sender">The object that raised the event</param>
- /// <param name="e">A KeyPressEventArgs that contains the event data</param>
- protected virtual void OnTextBoxKeyPress(object sender, KeyPressEventArgs e)
- {
- char enter = AsciiChars.CarriageReturn;
- char escape = AsciiChars.Escape;
- char tab = AsciiChars.HorizontalTab;
-
- NumberFormatInfo info = CultureInfo.CurrentCulture.NumberFormat;
-
- string decimalSeparator = info.NumberDecimalSeparator;
- string groupSeparator = info.NumberGroupSeparator;
- string negativeSign = info.NegativeSign;
- string character = e.KeyChar.ToString();
-
- if ((!char.IsDigit(e.KeyChar) && !character.Equals(decimalSeparator) && !character.Equals(groupSeparator)) &&
- !character.Equals(negativeSign) && (e.KeyChar != tab))
- {
- if ((Control.ModifierKeys & (Keys.Alt | Keys.Control)) == Keys.None)
- {
- e.Handled = true;
- if (e.KeyChar == enter)
- {
- if (this.EditingTable != null)
- {
- this.EditingTable.StopEditing();
- }
- }
- else if (e.KeyChar == escape)
- {
- if (this.EditingTable != null)
- {
- this.EditingTable.CancelEditing();
- }
- }
- else
- {
- NativeMethods.MessageBeep(0 /*MB_OK*/);
- }
- }
- }
- }
- /// <summary>
- /// Handler for the editors TextBox.LostFocus event
- /// </summary>
- /// <param name="sender">The object that raised the event</param>
- /// <param name="e">An EventArgs that contains the event data</param>
- protected virtual void OnTextBoxLostFocus(object sender, EventArgs e)
- {
- if (this.UserEdit)
- {
- this.ValidateEditText();
- }
- if (this.EditingTable != null)
- {
- this.EditingTable.StopEditing();
- }
- }
- /// <summary>
- /// Handler for the editors buttons MouseDown event
- /// </summary>
- /// <param name="sender">The object that raised the event</param>
- /// <param name="e">A CellMouseEventArgs that contains the event data</param>
- public void OnEditorButtonMouseDown(object sender, CellMouseEventArgs e)
- {
- this.ParseEditText();
- if (e.Y < this.buttonBounds.Top + (this.buttonBounds.Height / 2))
- {
- this.buttonID = UpButtonID;
-
- this.UpButton();
- }
- else
- {
- this.buttonID = DownButtonID;
-
- this.DownButton();
- }
- this.StartTimer();
- }
- /// <summary>
- /// Handler for the editors buttons MouseUp event
- /// </summary>
- /// <param name="sender">The object that raised the event</param>
- /// <param name="e">A CellMouseEventArgs that contains the event data</param>
- public void OnEditorButtonMouseUp(object sender, CellMouseEventArgs e)
- {
- this.StopTimer();
- this.buttonID = 0;
- }
- /// <summary>
- /// Handler for the editors Timer event
- /// </summary>
- /// <param name="sender">The object that raised the event</param>
- /// <param name="e">An EventArgs that contains the event data</param>
- private void TimerHandler(object sender, EventArgs e)
- {
- if (buttonID == 0)
- {
- this.StopTimer();
- return;
- }
- if (buttonID == UpButtonID)
- {
- this.UpButton();
- }
- else
- {
- this.DownButton();
- }
-
- this.interval *= 7;
- this.interval /= 10;
-
- if (this.interval < 1)
- {
- this.interval = 1;
- }
-
- this.timer.Interval = this.interval;
- }
- #endregion
- }
- }
|