I think you can catch the backspace in TableControlCurrentCellControlKeyMessage. It may be hit twice, so check the Msg to do things only once.
Keys keyCode = (Keys) ((int)e.Inner.Msg.WParam) & Keys.KeyCode;
if(e.Inner.Msg.Msg == 0x100) //WM_KEYDOWN
{
Console.WriteLine("WM_KEYDOWN->" + keyCode.ToString());
}
else if(e.Inner.Msg.Msg == 0x101) //WM_KEYUP
{
Console.WriteLine("WM_KEYUP->" + keyCode.ToString());
}
To handle the ReadOnly problem, you can use the QueryCellStyleInfo event. If the e.TableCellIdentity.TableCellType is a filter cell, then set e.Style.ReadOnly = false.
In version 3.2, you can add custom fustions that can be used in expressions. I think adding a custom function would be the simplest way to handle this. Below is the class refernce entry on adding a custom function.
/// Adds a function to the Function Library.
///
/// The name of the function to be added.
/// The function to be added.
/// True if successfully added, False otherwise
///
/// LibraryFunction is a delegate the defines the signature of functions that
/// you can add to the Function Library.
/// Adding a custom function requires two steps. The first is to register a name
/// and LibraryFunction delegate with the ExpressionFielEvaluator object. The second step
/// is to add a method to your code that implements the LibraryFunction delegate to perform
/// the calculations you want done.
///
/// There are restrictions on the use Functions within expressions. Functions can only be used
/// stand-alone. They cannot be used as part of a more complex expression. So,
/// "Func([Col1], 2*[Col2]+1)" is a valid use of a function named Func that accepts two
/// arguments. But "2 * Func([Col1], 2*[Col2]+1) + 1" is not valid. If you need to use
/// functions in algebraic expressions, then first add an Expression field that uses the
/// function stand-alone. Then in your algebraic expression, you can refer to this Expression
/// field. Argument used in library function calls, can be any algebraic combination of
/// fields and constants, but they cannot contain function references. During calculations, the
/// arguments are fully evaluated before being passed into the method you implement.
///
/// In the sample below,
/// ComputeFunc is the name of the method we add to our code to compute the function value.
/// Func is the string name that we use in an expression to reference the custom function as in
/// "Func([Col1], [Col2])".
///
/// // step 1 - register the function name and delegate
/// ExpressionFieldEvaluator evaluator = this.groupingEngine.TableDescriptor.ExpressionFieldEvaluator;
//.CreateExpressionFieldEvaluator(this.groupingEngine.TableDescriptor);
/// evaluator.AddFunction("Func", new ExpressionFieldEvaluator.LibraryFunction(ComputeFunc));
///
/// //. . .
///
/// // step 1 - defining the method
/// // Computes the absolute value of arg1-2*arg2
/// // parameter s- a list of 2 arguments
/// // returns string holding computed value
/// public string ComputeFunc(string s)
/// {
/// //get the list delimiter (for en-us, its is a comma)
/// char comma = Convert.ToChar(this.gridGroupingControl1.Culture.TextInfo.ListSeparator);
/// string[] ss = s.Split(comma);
/// if(ss.GetLength(0) != 2)
/// throw new ArgumentException("Requires 2 arguments.");
/// double arg1, arg2;
/// if(double.TryParse(ss[0], System.Globalization.NumberStyles.Any, null, out arg1)
/// && double.TryParse(ss[1], System.Globalization.NumberStyles.Any, null, out arg2))
/// {
/// return Math.Abs(arg1 - 2 * arg2).ToString();
/// }
/// return "";
/// }
///
///
/// '' step 1 - register the function name and delegate
/// Dim evaluator As ExpressionFieldEvaluator = Me.groupingEngine.TableDescriptor.ExpressionFieldEvaluator
/// evaluator.AddFunction("Func", New ExpressionFieldEvaluator.LibraryFunction(AddressOf ComputeFunc))
///
/// ''. . .
///
/// '' step 1 - defining the method
/// '' Computes the absolute value of arg1-2*arg2
/// '' parameter s- a list of 2 arguments
/// '' returns string holding computed value
/// Public Function ComputeFunc(s As String) As String
/// ''get the list delimiter (for en-us, its is a comma)
/// Dim comma As Char = Convert.ToChar(Me.gridGroupingControl1.Culture.TextInfo.ListSeparator)
/// Dim ss As String() = s.Split(comma)
/// If ss.GetLength(0) <> 2 Then
/// Throw New ArgumentException("Requires 2 arguments.")
/// End If
/// Dim arg1, arg2 As Double
/// If Double.TryParse(ss(0), System.Globalization.NumberStyles.Any, Nothing, arg1) _
/// AndAlso Double.TryParse(ss(1), System.Globalization.NumberStyles.Any, Nothing, arg2) Then
/// Return Math.Abs((arg1 - 2 * arg2)).ToString()
/// End If
/// Return ""
/// End Function ''ComputeFunc