//######################################################################################### //★★★★★★★ 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.Windows.Forms; using System.Windows.Forms.Design; using XPTable.Events; using XPTable.Models; using XPTable.Win32; namespace XPTable.Editors { /// /// Base class for Cell editors /// public abstract class CellEditor : ICellEditor, IMouseMessageFilterClient, IKeyMessageFilterClient { #region Event Handlers /// /// Occurs when the CellEditor begins editing a Cell /// public event CellEditEventHandler BeginEdit; /// /// Occurs when the CellEditor stops editing a Cell /// public event CellEditEventHandler EndEdit; /// /// Occurs when the editing of a Cell is cancelled /// public event CellEditEventHandler CancelEdit; #endregion #region Class Data /// /// The Control that is performing the editing /// private Control control; /// /// The Cell that is being edited /// internal Cell cell; /// /// The Table that contains the Cell being edited /// private Table table; /// /// A CellPos that represents the position of the Cell being edited /// private CellPos cellPos; /// /// The Rectangle that represents the Cells location and size /// private Rectangle cellRect; /// /// A MouseMessageFilter that receives mouse messages before they /// are dispatched to their destination /// private MouseMessageFilter mouseMessageFilter; /// /// A KeyMessageFilter that receives key messages before they /// are dispatched to their destination /// private KeyMessageFilter keyMessageFilter; #endregion #region Constructor /// /// Initializes a new instance of the CellEditor class with default settings /// protected CellEditor() { this.control = null; this.cell = null; this.table = null; this.cellPos = CellPos.Empty; this.cellRect = Rectangle.Empty; this.mouseMessageFilter = new MouseMessageFilter(this); this.keyMessageFilter = new KeyMessageFilter(this); } #endregion #region Methods /// /// Prepares the CellEditor to edit the specified Cell /// /// The Cell to be edited /// The Table that contains the Cell /// A CellPos representing the position of the Cell /// The Rectangle that represents the Cells location and size /// Specifies whether the ICellEditors /// starting value has already been set by the user /// true if the ICellEditor can continue editing the Cell, false otherwise public virtual bool PrepareForEditing(Cell cell, Table table, CellPos cellPos, Rectangle cellRect, bool userSetEditorValues) { // this.cell = cell; this.table = table; this.cellPos = cellPos; this.cellRect = cellRect; // check if the user has already set the editors value for us if (!userSetEditorValues) { this.SetEditValue(); } this.SetEditLocation(cellRect); // raise the BeginEdit event CellEditEventArgs e = new CellEditEventArgs(cell, this, table, cellPos.Row, cellPos.Column, cellRect); e.Handled = userSetEditorValues; this.OnBeginEdit(e); // if the edit has been canceled, remove the editor and return false if (e.Cancel) { this.RemoveEditControl(); return false; } return true; } /// /// Sets the location and size of the CellEditor /// /// A Rectangle that represents the size and location /// of the Cell being edited protected abstract void SetEditLocation(Rectangle cellRect); /// /// Sets the initial value of the editor based on the contents of /// the Cell being edited /// protected abstract void SetEditValue(); /// /// Sets the contents of the Cell being edited based on the value /// in the editor /// protected abstract void SetCellValue(); /// /// Displays the editor to the user and adds it to the Table's Control /// collection /// protected virtual void ShowEditControl() { this.control.Parent = this.table; this.control.Visible = true; } /// /// Conceals the editor from the user, but does not remove it from the /// Table's Control collection /// protected virtual void HideEditControl() { this.control.Visible = false; } /// /// Conceals the editor from the user and removes it from the Table's /// Control collection /// protected virtual void RemoveEditControl() { this.control.Visible = false; this.control.Parent = null; this.table.Focus(); this.cell = null; this.table = null; this.cellPos = CellPos.Empty; this.cellRect = Rectangle.Empty; } /// /// Starts editing the Cell /// public virtual void StartEditing() { this.ShowEditControl(); Application.AddMessageFilter(this.keyMessageFilter); Application.AddMessageFilter(this.mouseMessageFilter); } /// /// Stops editing the Cell and commits any changes /// public virtual void StopEditing() { Application.RemoveMessageFilter(this.keyMessageFilter); Application.RemoveMessageFilter(this.mouseMessageFilter); // CellEditEventArgs e = new CellEditEventArgs(this.cell, this, this.table, this.cellPos.Row, this.cellPos.Column, this.cellRect); this.table.OnEditingStopped(e); this.OnEndEdit(e); if (!e.Cancel && !e.Handled) { this.SetCellValue(); } this.RemoveEditControl(); } /// /// Stops editing the Cell and ignores any changes /// public virtual void CancelEditing() { Application.RemoveMessageFilter(this.keyMessageFilter); Application.RemoveMessageFilter(this.mouseMessageFilter); // CellEditEventArgs e = new CellEditEventArgs(this.cell, this, this.table, this.cellPos.Row, this.cellPos.Column, this.cellRect); this.table.OnEditingCancelled(e); this.OnCancelEdit(e); this.RemoveEditControl(); } /// /// Filters out a mouse message before it is dispatched /// /// The Control that will receive the message /// A WindowMessage that represents the message to process /// Specifies the WParam field of the message /// Specifies the LParam field of the message /// true to filter the message and prevent it from being dispatched; /// false to allow the message to continue to the next filter or control public virtual bool ProcessMouseMessage(Control target, WindowMessage msg, int wParam, int lParam) { if (msg == WindowMessage.WM_LBUTTONDOWN || msg == WindowMessage.WM_RBUTTONDOWN || msg == WindowMessage.WM_MBUTTONDOWN || msg == WindowMessage.WM_XBUTTONDOWN || msg == WindowMessage.WM_NCLBUTTONDOWN || msg == WindowMessage.WM_NCRBUTTONDOWN || msg == WindowMessage.WM_NCMBUTTONDOWN || msg == WindowMessage.WM_NCXBUTTONDOWN) { Point cursorPos = Cursor.Position; if (target != this.EditingTable && target != this.Control) { this.EditingTable.StopEditing(); } } return false; } /// /// Filters out a key message before it is dispatched /// /// The Control that will receive the message /// A WindowMessage that represents the message to process /// Specifies the WParam field of the message /// Specifies the LParam field of the message /// true to filter the message and prevent it from being dispatched; /// false to allow the message to continue to the next filter or control public virtual bool ProcessKeyMessage(Control target, WindowMessage msg, int wParam, int lParam) { return false; } #endregion #region Properties /// /// Gets or sets the Control that is being used to edit the Cell /// protected Control Control { get { return this.control; } set { this.control = value; } } /// /// Gets the Cell that is being edited /// public Cell EditingCell { get { return this.cell; } } /// /// Gets the Table that contains the Cell being edited /// public Table EditingTable { get { return this.table; } } /// /// Gets a CellPos that represents the position of the Cell being edited /// public CellPos EditingCellPos { get { return this.cellPos; } } /// /// Gets whether the CellEditor is currently editing a Cell /// public bool IsEditing { get { return this.cell != null; } } #endregion #region Events /// /// Raises the BeginEdit event /// /// A CellEditEventArgs that contains the event data protected virtual void OnBeginEdit(CellEditEventArgs e) { if (this.BeginEdit != null) { this.BeginEdit(this, e); } } /// /// Raises the EndEdit event /// /// A CellEditEventArgs that contains the event data protected virtual void OnEndEdit(CellEditEventArgs e) { if (this.EndEdit != null) { this.EndEdit(this, e); } } /// /// Raises the CancelEdit event /// /// A CellEditEventArgs that contains the event data protected virtual void OnCancelEdit(CellEditEventArgs e) { if (this.CancelEdit != null) { this.CancelEdit(this, e); } } #endregion } }