Search code examples
c#.netwinformsglobalizationcultureinfo

Culture-Specific Handling of Number Pad Decimal Key in Windows Forms


We have a .NET 2.0 Windows Forms application with lots of custom controls. A few years ago, we globalized our application, so users see the appropriate culture-specific symbols and translations.

A French Canadian customer has asked us to change how our application handles the number pad decimal key. Our numeric controls are not doing anything when the user presses this key.

I switched my Windows regional settings to French - Canada and debugged our application. I see the current culture and current UI culture are set to fr-CA.

In OnKeyDown and OnKeyPress I see the difference between the keyboard period (Keys.OemPeriod) and number pad period (Keys.Decimal). The specific keystroke comes across in OnKeyDown. However, in both cases, the OnKeyPress event gives our control a period:

Key               OnKeyDown      OnKeyPress
================= ============== ==========
Main Keyboard     Keys.OemPeriod "." 
Number Pad Period Keys.Decimal   "."

Our numeric controls handle number input in the OnKeyPress event. Since the period is not a decimal separator in the current culture, the control reject this character.

Is the globalization setting supposed to translate Keys.Decimal (number pad ".") into a comma automatically, or is our application supposed to change Keys.Decimal into the culture-specific decimal separator? I expected .NET to make this translation automatically.


Solution

  • The OnKeyDown event is generated by the Windows WM_KEYDOWN event. WM_KEYDOWN is sending our application a Key.Decimal event.

    Similarly, the OnKeyPress event is generated directly from the WM_CHAR event. In the case of French - Canadian regional settings (with Canadian French keyboard), Windows sends a WM_CHAR event with a period when the user presses the number pad decimal key. However, in the case of French - Belgian settings with the "Belgian (Comma)" input settings, Windows sends a WM_CHAR event with a comma.

    So this is neither a .NET bug nor a bug in our application. The regional input settings affects the behavior of the Decimal key.

    However, some applications do respond differently in French - Canadian settings. For example, both Excel and Windows Calculator both translate Keys.Decimal into a comma instead of a period. These applications may have special handling for this case.

    We could add code to our application to track a decimal key and handle it differently. For example:

    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (e.KeyData == Keys.Decimal)
            m_DecimalKey = true;
    }
    
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        ...
        if (m_DecimalKey || e.KeyChar == CultureInfo.CurrentUICulture.NumberFormat.NumberDecimalSeparator)
        {
            // this is a decimal separator
        }
    }
    
    protected virtual void OnKeyUp(KeyEventArgs e)
    {
        if (e.KeyData == Keys.Decimal)
            m_DecimalKey = false;
    }