Disable autorepeat

  • Thread starter Thread starter MarcG
  • Start date Start date
M

MarcG

Is there a way to disable the autorepeat keyboard feature that sends multiple
characters if the key is held down? Alternately is there a feature that can
detect and ignore autorepeated characters?

Thx
Marc
 
Hi Marc,

Not sure if there's a feature to do specifically what you want without
heading into keyboard hooks via the native API. However, could you perhaps
simulate this behaviour by overriding the OnKeyPress of your control,
testing to see if the key code is identical to a previous (cached) value and
swallowing it before it gets handled?

Regards,
Alex
 
Thanks Alex, but I was hoping not to have to guess. If the key values change,
it's clear that it isn't autorepeat. If they are the same, I'd have to look
at the inter-arrival rate for a few characters to make a good deduction.

If I have to and if it's possible, it would be worth a trip to the platform
SDK to turn it off.

Marc
 
That's true, I hadn't thought about considering the time since the last key
stroke. You could of course measure that and compare it to the auto-repeat
rate of the system. You'd have to use something like SystemParameters or
GetSystemMetrics to determine what the auto-repeat rate of the system is
actually set to, but of course at that stage you're digging into API calls
again anyway.

I had another thought though - you might be able to set a flag in the
OnKeyDown and then another flag in the OnKeyUp handlers. That way, you
would only allow the keystroke in OnKeyDown if an OnKeyUp event had occurred
in between, i.e. two OnKeyDown events without an OnKeyUp between them means
that the key was simply held down rather than being pressed two separate
times. Might be worth a shot before you delve into low-level keyboard
hooks?
 
Hi Marc,

I spent several hours researching on how to disable keyboard repeat feature
and got it finally.

In fact, we can disable keyboard repeat feature through the Control Panel.

In detail, open the Control Panel,
if you're using Windows XP, double click the 'Accessibility Options' item.
In the Accessibility Options window, switch to the 'Keyboard' tab and
select the checkbox before the 'Use FilterKeys' option;

if you're using Windows Vista, double click the 'Ease of Access Center'
item and then click the 'Make the keyboard easier to use' link. In the
window opened, select the checkbox before the 'Turn on Filter Keys' option.

To turn on the Filter Keys feature programmatically, we can make use of the
SystemParametersInfo function. You can get the current value of the Filter
Keys setting by passing the SPI_GETFILTERKEYS parameter to the
SystemParametersInfo function when your application is run and set a new
value to this setting by passing the SPI_SETFILTERKEYS parameter to this
function. Remember to restore the original Filter Keys setting when the
application exits.

The following is a sample.

using System.Runtime.InteropServices;

public partial class Form1 : Form
{
int SPI_GETFILTERKEYS = 0x32;
int SPI_SETFILTERKEYS = 0x33;
int FKF_FILTERKEYSON = 1;

[DllImport("user32.dll")]
static extern bool SystemParametersInfo(int uiAction, int uiParam,
ref FilterKeys pvParam, uint fwinIni);

public struct FilterKeys
{
public UInt16 cbSize;
public int dwFlags;
public int iWaitMSec;
public int iDelayMSec;
public int iRepeatMSec;
public int iBounceMSec;
}

FilterKeys oldfilterkeys = new FilterKeys();
private void Form1_Load(object sender, EventArgs e)
{
oldfilterkeys.cbSize =
(UInt16)Marshal.SizeOf(typeof(FilterKeys));
bool result = SystemParametersInfo(SPI_GETFILTERKEYS,
Marshal.SizeOf(typeof(FilterKeys)), ref oldfilterkeys, 0);
FilterKeys newfilterkeys = oldfilterkeys;
newfilterkeys.dwFlags |= FKF_FILTERKEYSON;
newfilterkeys.iWaitMSec = 0;
newfilterkeys.iBounceMSec = 0;
newfilterkeys.iDelayMSec = 0;
newfilterkeys.iDelayMSec = 0;
// turn on the FilterKeys feature to disable keyboard
repeat
result = SystemParametersInfo(SPI_SETFILTERKEYS,
Marshal.SizeOf(typeof(FilterKeys)), ref newfilterkeys, 0);
}

void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// restore the original Filter Keys setting
SystemParametersInfo(SPI_SETFILTERKEYS,
Marshal.SizeOf(typeof(FilterKeys)), ref oldfilterkeys, 0);
}
}

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Alex, Linda,

Thanks for three great suggestions. Here's some more background.... I'm
building a suite of psych. performance test tasks. The problem I posed arose
because sometimes subjects fall asleep with their finger on the keyboard or
just hold a key down to "get through" the task. I don't want to treat either
character stream as responses.

Alex, I liked your KeyDown KeyDown KeyDown .... KeyUp check. That avoids the
mucking around with the API's.

Linda, the suggestion about using the Control Panel was really clever and
would work for me since in the test environment we can control the computer
configuration.

I really appreciate the work you did digging through the platform SDK - no
way I would have gone there myself.

It happens, not surprisingly, that since I am building a set of tasks, they
all derive from a common base class. However, one thing that differentiates
the tasks is their input handling, so all the key events are local to each
derived class. This means that I'd have to replicate and probably modify
Alex's solution in each task.

The Control Panel approach is elegantly simple - I never would have thought
of it, but I don't know if I can rely on the setup being done in all cases.

The API approach is rock solid. I can grab the current state in my common
initialization code and turn autorepeat off and restore the state in the
common exit handler. I doubt that the task could get out without generating a
FormClose event.

Thanks both,
Marc
 
Back
Top