ABL - The Problem Solver - .Net FAQ
 

Home
Mission
News
Blog
Tools
FAQ
Publications
Downloads
Contact
Contents

 

Frequently asked questions

.NET FAQ Visual FoxPro FAQ

 


Keyboard input of numeric values and commas as decimal separator in a DataGridView

One of the questions I frequently get is how to get the same behavior as Excel when entering numeric values. With the same behavior I mean that Excel detects the current users setting for decimal separator and makes the point on the numeric keyboard input the correct character. This is only done for the numeric keypad, the point and comma on regular part of the keyboard remain unchanged. Doing so in a single TextBox isn't all that hard, see this for an explanation, but in a DataGridView things get a bit more complicated. The code below does the trick though so you don't have to figure it out :-).

 

Imports System.Windows.Forms

 

''' <summary>

''' Standard textbox for all numeric input.

''' </summary>

''' <remarks></remarks>

Class NumericTextBox

    Inherits TextBox

 

    ''' <summary>

    ''' Preprocesses keyboard or input messages within the message loop before they are dispatched.

    ''' </summary>

    ''' <param name="msg"></param>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Public Overrides Function PreProcessMessage(ByRef msg As Message) As Boolean

        If msg.Msg = &H102 Then

            If msg.WParam.Equals(New IntPtr(&H2E)) _

               AndAlso msg.LParam.Equals(New IntPtr(&H530001)) Then

                ' Point in the numeric keypad pressed

                If System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator = "," Then

                    ' And the decimal separator is a ',' for the current settings

                    ' Change the message to enter a comma instead of a poin

                    msg.WParam = New IntPtr(&H2C)

                    msg.LParam = New IntPtr(&H330001)

                End If

            End If

        End If

 

        ' Do the default actions

        Return MyBase.PreProcessMessage(msg)

    End Function

End Class

 

 

''' <summary>

''' DataGridView to support numeric input.

''' </summary>

''' <remarks></remarks>

Class NumericDataGridView

    Inherits DataGridView

 

    ''' <summary>

    ''' Preprocesses keyboard or input messages within the message loop before they are dispatched.

    ''' </summary>

    ''' <param name="msg"></param>

    ''' <returns></returns>

    ''' <remarks>

    ''' Required for the first key stroke in a cell. The others are handled by the NumericTextBox::PreProcessMessage().

    ''' </remarks>

    Public Overrides Function PreProcessMessage(ByRef msg As Message) As Boolean

        If msg.Msg = &H102 Then

            If msg.WParam.Equals(New IntPtr(&H2E)) _

               AndAlso msg.LParam.Equals(New IntPtr(&H530001)) Then

                ' Point in the numeric keypad pressed

                If System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator = "," Then

                    ' And the decimal separator is a ',' for the current settings

                    ' Change the message to enter a comma instead of a poin

                    msg.WParam = New IntPtr(&H2C)

                    msg.LParam = New IntPtr(&H330001)

                    Return False

                End If

            End If

        End If

 

        ' Do the default actions

        Return MyBase.PreProcessMessage(msg)

    End Function

End Class

 

 

 

''' <summary>

''' DataGridView column to support numeric input.

''' </summary>

''' <remarks></remarks>

Class NumericDataGridViewTextBoxColumn

    Inherits DataGridViewColumn

 

    Sub New()

        MyBase.New(New NumericDataGridViewTextBoxCell)

    End Sub

End Class

 

 

 

''' <summary>

''' DataGridView cell to support numeric input.

''' </summary>

''' <remarks></remarks>

Class NumericDataGridViewTextBoxCell

    Inherits DataGridViewTextBoxCell

 

    ''' <summary>

    ''' Gets the type of the cell's hosted editing control.

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Public Overrides ReadOnly Property EditType() As System.Type

        Get

            Return GetType(NumericCellTextBox)

        End Get

    End Property

 

 

    ''' <summary>

    ''' Gets or sets the data type of the values in the cell.

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Public Overrides ReadOnly Property ValueType() As System.Type

        Get

            Return GetType(String)

        End Get

    End Property

End Class

 

 

 

''' <summary>

''' DataGridView TextBox Cell to support numeric input.

''' </summary>

''' <remarks></remarks>

Class NumericCellTextBox

    Inherits NumericTextBox

    Implements IDataGridViewEditingControl

 

    ' Private fields to store state

    Private _dataGridView As DataGridView

    Private _rowIndex As Integer

    Private _valueChanged As Boolean

 

 

    ''' <summary>

    ''' Changes the control's user interface (UI) to be consistent with the specified cell style.

    ''' </summary>

    ''' <param name="dataGridViewCellStyle"></param>

    ''' <remarks></remarks>

    Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As DataGridViewCellStyle) _

        Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl

 

        Me.BackColor = dataGridViewCellStyle.BackColor

        Me.Font = dataGridViewCellStyle.Font

        Me.ForeColor = dataGridViewCellStyle.ForeColor

    End Sub

 

 

    ''' <summary>

    ''' Gets or sets the DataGridView that contains the combo box control.

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Public Property EditingControlDataGridView() As DataGridView _

        Implements IDataGridViewEditingControl.EditingControlDataGridView

        Get

            Return _dataGridView

        End Get

        Set(ByVal value As DataGridView)

            _dataGridView = value

        End Set

    End Property

 

 

    ''' <summary>

    ''' Gets or sets the formatted representation of the current value of the text box control.

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Public Property EditingControlFormattedValue() As Object _

        Implements IDataGridViewEditingControl.EditingControlFormattedValue

        Get

            Return Text

        End Get

        Set(ByVal value As Object)

            Text = value.ToString()

        End Set

    End Property

 

 

    ''' <summary>

    ''' Gets or sets the index of the owning cell's parent row.

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Public Property EditingControlRowIndex() As Integer _

        Implements IDataGridViewEditingControl.EditingControlRowIndex

        Get

            Return _rowIndex

        End Get

        Set(ByVal value As Integer)

            _rowIndex = value

        End Set

    End Property

 

 

    ''' <summary>

    ''' Gets or sets a value indicating whether the value of the editing control differs from the value of the hosting cell.

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Public Property EditingControlValueChanged() As Boolean _

        Implements IDataGridViewEditingControl.EditingControlValueChanged

        Get

            Return _valueChanged

        End Get

        Set(ByVal value As Boolean)

            _valueChanged = value

        End Set

    End Property

 

 

    ''' <summary>

    ''' Determines whether the specified key is a regular input key that the editing control should process or a special key that the DataGridView should process.

    ''' </summary>

    ''' <param name="keyData"></param>

    ''' <param name="dataGridViewWantsInputKey"></param>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Public Function EditingControlWantsInputKey(ByVal keyData As Keys, ByVal dataGridViewWantsInputKey As Boolean) As Boolean _

        Implements IDataGridViewEditingControl.EditingControlWantsInputKey

 

        Return True

    End Function

 

 

    ''' <summary>

    ''' Gets the cursor used during editing.

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Public ReadOnly Property EditingPanelCursor() As Cursor _

        Implements IDataGridViewEditingControl.EditingPanelCursor

        Get

            Return MyBase.Cursor

        End Get

    End Property

 

 

    ''' <summary>

    ''' Retrieves the formatted value of the cell.

    ''' </summary>

    ''' <param name="context"></param>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Public Function GetEditingControlFormattedValue(ByVal context As DataGridViewDataErrorContexts) As Object _

        Implements IDataGridViewEditingControl.GetEditingControlFormattedValue

 

        Return Text

    End Function

 

 

    ''' <summary>

    ''' Prepares the currently selected cell for editing.

    ''' </summary>

    ''' <param name="selectAll"></param>

    ''' <remarks></remarks>

    Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) _

        Implements IDataGridViewEditingControl.PrepareEditingControlForEdit

    End Sub

 

 

    ''' <summary>

    ''' Gets a value indicating whether the cell contents need to be repositioned whenever the value changes.

    ''' </summary>

    ''' <value></value>

    ''' <returns></returns>

    ''' <remarks></remarks>

    Public ReadOnly Property RepositionEditingControlOnValueChange() As Boolean _

        Implements IDataGridViewEditingControl.RepositionEditingControlOnValueChange

        Get

            Return False

        End Get

    End Property

 

 

    ''' <summary>

    ''' Raises the TextChanged event and notify that the cell value has changed.

    ''' </summary>

    ''' <param name="e"></param>

    ''' <remarks></remarks>

    Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)

        MyBase.OnTextChanged(e)

        _valueChanged = True

        _dataGridView.NotifyCurrentCellDirty(True)

    End Sub

End Class

 


 

Send mail to webmaster@TheProblemSolver.nl with questions or comments about this web site.
Copyright © 1995 - 2007 ABL - The Problem Solver
Last modified: 10/21/06
WF
RSS 2.0