Code Focused

Windows Forms: Don't Skimp on the Caps Lock Warning

If you've ever worked in an enterprise environment and fielded calls from employees unable to get into their accounts due to a depressed Caps Lock key, you know how essential the following tweak to your code can be.

When you activate the password-entry features on a Windows Forms TextBox control, you get a Caps Lock warning bubble for free (see Figure 1). The popup message provides a gentle reminder that it might be prudent to check the keyboard state before entering that secure password. And that gentleness is a big part of the problem. This isn't the era of ho-hum black-and-white Flash Gordon serials. We have the Marvel Cinematic Universe! If people are already finding those multi-hero fight scenes mundane, you better believe that you need more power in your Caps Lock warnings.

Well, perhaps it's not that bad. But there’s also the issue that if Caps Lock is already activated when the password field first appears, the message bubble doesn't show up. For these and various other reasons, I sometimes add a dedicated warning message right on the form. (See Figure 2.)

[Click on image for larger view.] Figure 1. The Standard Caps Lock Warning
[Click on image for larger view.] Figure 2. A Better Caps Lock Warning

It's a fairly straightforward coding process. First, add your password TextBox control to a form, and next to it put a Panel control, laden with warning signs and with its Visible property set to False. Then add the event handlers that manage the visibility of the warning message, as shown in Listing 1.

Listing 1: Managing Warning Message Visibility
private void PasswordField_Enter(object sender, EventArgs e)
{
  // ----- Monitor caps lock on arrival.
  PanelWarning.Visible = Control.IsKeyLocked(Keys.CapsLock);
}

private void PasswordField_Leave(object sender, EventArgs e)
{
  // ----- Monitor caps lock on departure.
  PanelWarning.Visible = false;
}

private void PasswordField_KeyDown(object sender, KeyEventArgs e)
{
  // ----- Monitor caps lock on activity.
  PanelWarning.Visible = Control.IsKeyLocked(Keys.CapsLock);
}

The problem is that the .NET-supplied message bubble still shows up, obscuring that lovely handcrafted warning panel. Under the hood, Windows Forms is deciding to show that bubble by monitoring control-level Windows messages, akin to .NET events. For tool-tip bubbles, a message known as EM_SHOWBALLOONTIP triggers the standard Caps Lock presentation. If you disable the monitoring of that message in the password textbox, the interruption goes away.

To build a tip-less text entry control, add a new class to your project named QuietTextBox and adjust it to use the standard TextBox class as its base class:

// ----- Assumes: using System.Windows.Forms;
public class QuietTextBox : TextBox
{
}

Internal messages within Windows are identified by 32-bit pre-defined integers, and the balloon-tip message has been assigned the hexadecimal value of 0x1503. Add that definition to the class:

private const int EM_SHOWBALLOONTIP = 0x1503;

Every form and control class in Windows Forms applications has a protected method named WndProc that handles all of the event-driven activity exposed by that form or control. To disable the balloon-tip message, override that method, watch for the specific message and add code that causes it to have no impact:

protected override void WndProc(ref Message m)
{
  // ----- Prevent the system-level Caps Lock message from showing up.
  if (m.Msg == EM_SHOWBALLOONTIP)
  {
    m.Result = (IntPtr)0;
    return;
  }
  base.WndProc(ref m);
}

That's all you need to hide the popup message. Build the project to make it available within the Windows Forms designer. There are a few ways to integrate this new control into a form, but I've found it easiest to add a regular password TextBox control to a form and then modify its definition within the form's Designer.cs file. Open that file and locate the two lines that define the password TextBox control:

// ----- Within the InitializeComponent method:
this.PasswordField = new System.Windows.Forms.TextBox();

// ----- And later, near the bottom of the file:
private System.Windows.Forms.TextBox PasswordField;

Modify these two lines, replacing the reference to the built-in TextBox control with the new QuietTextBox class:

// ----- Within the InitializeComponent method:
this.PasswordField = new QuietTextBox();

// ----- And later, near the bottom of the file:
private QuietTextBox PasswordField;

Implementing a similar Caps Lock warning in a Windows Presentation Foundation (WPF) application is even easier, because the PasswordBox control in that system doesn't present a bubble message automatically when Caps Lock is activated. As in a Windows Forms application, you add your password entry field and the warning-related elements to the XAML window surface:

<!-- NOTE: Most attributes omitted for brevity. -->
<PasswordBox x:Name="PasswordField" TabIndex="1"
  GotFocus="PasswordField_GotFocus"
  LostFocus="PasswordField_LostFocus"
  KeyDown="PasswordField_KeyDown" ... />
<Border x:Name="PanelWarning" Visibility="Hidden" ... >
  <Canvas ...>
    <Label Content="Warning!" ... />
    <Label Content="Caps Lock Is On" ... />
  </Canvas>
</Border>

Then add the event handlers, which will have slightly different event names and content from those in Windows Forms, as shown in Listing 2.

Listing 2: Adding Event Handlers
private void PasswordField_GotFocus(object sender, RoutedEventArgs e)
{
  // ----- Monitor caps lock.
  PanelWarning.Visibility =
    ((Keyboard.GetKeyStates(Key.CapsLock) & KeyStates.Toggled) > 0)
    ? Visibility.Visible : Visibility.Hidden;
}

private void PasswordField_LostFocus(object sender, RoutedEventArgs e)
{
  // ----- Monitor caps lock.
  PanelWarning.Visibility = Visibility.Hidden;
}

private void PasswordField_KeyDown(object sender, KeyEventArgs e)
{
  // ----- Monitor caps lock.
  PanelWarning.Visibility =
    ((Keyboard.GetKeyStates(Key.CapsLock) & KeyStates.Toggled) > 0)
    ? Visibility.Visible : Visibility.Hidden;
}

Caps Lock warnings might not seem like a big deal. But if you’ve ever worked in an enterprise environment and fielded calls from employees unable to get into their accounts due to a depressed (physically, not emotionally) Caps Lock key, then you know how essential such small updates to your code can be.

About the Author

Tim Patrick has spent more than thirty years as a software architect and developer. His two most recent books on .NET development -- Start-to-Finish Visual C# 2015, and Start-to-Finish Visual Basic 2015 -- are available from http://owanipress.com. He blogs regularly at http://wellreadman.com.

comments powered by Disqus

Featured

  • Hands On: New VS Code Insiders Build Creates Web Page from Image in Seconds

    New Vision support with GitHub Copilot in the latest Visual Studio Code Insiders build takes a user-supplied mockup image and creates a web page from it in seconds, handling all the HTML and CSS.

  • Naive Bayes Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the naive Bayes regression technique, where the goal is to predict a single numeric value. Compared to other machine learning regression techniques, naive Bayes regression is usually less accurate, but is simple, easy to implement and customize, works on both large and small datasets, is highly interpretable, and doesn't require tuning any hyperparameters.

  • VS Code Copilot Previews New GPT-4o AI Code Completion Model

    The 4o upgrade includes additional training on more than 275,000 high-quality public repositories in over 30 popular programming languages, said Microsoft-owned GitHub, which created the original "AI pair programmer" years ago.

  • Microsoft's Rust Embrace Continues with Azure SDK Beta

    "Rust's strong type system and ownership model help prevent common programming errors such as null pointer dereferencing and buffer overflows, leading to more secure and stable code."

  • Xcode IDE from Microsoft Archrival Apple Gets Copilot AI

    Just after expanding the reach of its Copilot AI coding assistant to the open-source Eclipse IDE, Microsoft showcased how it's going even further, providing details about a preview version for the Xcode IDE from archrival Apple.

Subscribe on YouTube

Upcoming Training Events