A program for my nieces: The ABCs, part 3


One problem I discovered when my nieces ran my initial ABC program was that they had a habit of holding down a key, thereby triggering autorepeat. I had instructed them not to mash the keyboard but rather to press only one key at a time, and while they were good at adhering to the "one key at a time" rule, they also interpreted it as "type really slowly" and ended up autorepeating a lot.

So let's disable keyboard autorepeat.

Of course, one way to do this would be to change the system keyboard autorepeat setting, but that would be using global state to manage a local problem. Instead, we just filter the autorepeats out of our edit control:

LRESULT CALLBACK EditSubclassProc(
    HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
    UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
  switch (uMsg) {
  case WM_NCDESTROY:
    RemoveWindowSubclass(hwnd, EditSubclassProc, uIdSubclass);
    break;
  case WM_CHAR:
    if ((lParam & 0x40000000) && wParam != VK_BACK) return 0;
    break;
  }
    return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}

BOOL
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
  ...

  SetWindowSubclass(g_hwndChild, EditSubclassProc, 0, 0);
  SetWindowFont(g_hwndChild, g_hfEdit, TRUE);

  return TRUE;
}

Bit 30 in the lParam of a WM_CHAR message says whether the key was already down. If we see that bit set, then we know that the message was an autorepeat and we throw the message away. (But I let the backspace key through because that lets me erase a lot of text quickly.)

It's important that the subclass procedure be removed before the window is destroyed. One way of doing this is to remove the subclass procedure in the parent window's WM_DESTROY handler, but since I don't have one, and I'm too lazy to make one, I go for the alternate method of doing just-in-time deregistration by removing the subclass procedure in the subclass procedure itself.

This version of the program managed to keep my nieces happy for quite some time. We'll tinker with it some more next week.

Comments (9)
  1. Chris B says:

    My hunch would be that your nieces prefer to navigate using the mouse, but it may be nice to allow the arrow keys auto-repeat as well.

    [It never occurred to them that navigation was an option. They always appended text and erased with backspace. -Raymond]
  2. Joshua says:

     case WM_NCDESTROY:

       RemoveWindowSubclass(hwnd, EditSubclassProc, uIdSubclass);

    Nice!

  3. Sounds like we need a "bool IsPrintable(WORD vKey)" helper function.

  4. Alex Cohn says:

    What bad could happen if subclassing is not removed? I assume that the window is destroyed when the whole process goes to quit anyway, and I hope the OS will clean up after the shutdown.

    [In this case, yes, it all gets cleaned up at process termination, but in the more general case, you have a memory leak. -Raymond]
  5. Mark Y says:

    What's wrong with mashing the keyboard, so to speak? I mean, obviously you won't learn letters that way, but if you're just having fun, why not?

    [Keyboard mashing leads to accidental hotkey invocation. -Raymond]
  6. Mark Y says:

    What's so bad about hotkeys?  Your program hardly has any, and most of the Windows ones aren't particularly destructive.

  7. Gabe says:

    Mark: Your definition of "destructive" clearly doesn't anticipate young children (or cats, for that matter)! And remember, if something happens, they won't be able to tell you what they did.

    For one thing, Win+D or Win+M just makes the whole program disappear. That's certainly destructive, if not permanent, but that alone means that you have to be there providing constant supervision.

    Pressing Win+P can make your screen go black. Good luck figuring that one out!

    Some OEM software has hotkeys for rotating the display. "Uncle Raymond! The computer is upside down!" If you don't know those hotkeys already, that's hard to fix with your screen upside down.

    Win+E will bring up Explorer. Entering random keystrokes into Explorer can easily delete random files or give them random names, among other things.

    Win plus a number will bring up whatever app is in that number's position on the task bar. I'd hate to imagine what kind of havoc they could wreak with some important app that might be sitting haplessly minimized in Raymond's task bar. I suppose email could be the most destructive.

  8. Mark Y says:

    Gabe: Wow.  Ok.  I take it back.

  9. Vlad says:

    So why not just run it in a fullscreen VM with most VM hotkeys disabled?

    [You vastly overestimate the computing capabilities of my laptop in 2005. Also: Overkill. -Raymond]

Comments are closed.