Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simulate a keypress for X seconds

Tags:

c#

winforms

Here is my code that I use to simulate a tab-keypress in a certain process:

[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);

public Form1()
{
    PostMessage(MemoryHandler.GetMainWindowHandle(), 
               (int)KeyCodes.WMessages.WM_KEYDOWN, 
               (int)KeyCodes.VKeys.VK_TAB, 0);

    InitializeComponent();
}

Is there any way to extend it so that it presses the key for (example) 1 second, instead of just tapping it?

Please note that I'm not interested in a Thread.Sleep() solution that blocks the UI thread.

like image 962
Johan Avatar asked Jul 31 '13 22:07

Johan


People also ask

How do you simulate keystrokes?

To simulate native-language keystrokes, you can also use the [Xnn] or [Dnn] constants in the string passed to the Keys method. nn specifies the virtual-key code of the key to be “pressed”. For instance, [X221]u[X221]e will “type” the u and e characters with the circumflex accent.

How do you automate key presses?

You'll need to start by downloading and installing AutoHotkey, which is a simple scripting language that allows you to create easy scripts. Once you do that, right-click anywhere and choose New –> AutoHotkey Script. This simple script will wait every 30 minutes and press the Spacebar.


3 Answers

The repeating of a keystroke when you hold it down is a feature that's built into the keyboard controller. A microprocessor that's built into the keyboard itself. The 8042 microcontroller was the traditional choice, the keyboard device driver still carries its name.

So, no, this is not done by Windows and PostMessage() is not going to do it for you. Not exactly a problem, you can simply emulate it with a Timer.

like image 191
Hans Passant Avatar answered Sep 20 '22 00:09

Hans Passant


If you want to simulate what Windows does with messages, you likely want to find out how fast the key repeat rate is. That can be found at HKEY_CURRENT_USER\Control Panel\Keyboard\KeyboardSpeed. there's also the KeyboardDelay value.

What Windows does is send a WM_KEYDOWN and a WM_CHAR when a key is initially pressed. Then, if the key is still pressed after KeyboardDelay time span, the WM_KEYDOWN and WM_CHAR pair are repeated every KeyboardSpeed until the key is depressed--at which point WM_KEYUP is sent.

I would suggest using a Timer to send the messages at a specific frequencies.

Update:

for example:

int keyboardDelay, keyboardSpeed;
using (var key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Keyboard"))
{
    Debug.Assert(key != null);
    keyboardDelay = 1;
    int.TryParse((String)key.GetValue("KeyboardDelay", "1"), out keyboardDelay);
    keyboardSpeed = 31;
    int.TryParse((String)key.GetValue("KeyboardSpeed", "31"), out keyboardSpeed);
}

maxRepeatedCharacters = 30; // repeat char 30 times
var startTimer = new System.Windows.Forms.Timer {Interval = keyboardSpeed};
startTimer.Tick += startTimer_Tick;
startTimer.Start();
var repeatTimer = new System.Windows.Forms.Timer();
repeatTimer.Interval += keyboardDelay;
repeatTimer.Tick += repeatTimer_Tick;

//...

private static void repeatTimer_Tick(object sender, EventArgs e)
{
    PostMessage(MemoryHandler.GetMainWindowHandle(),
               (int)KeyCodes.WMessages.WM_KEYDOWN,
               (int)KeyCodes.VKeys.VK_TAB, 0);
    PostMessage(MemoryHandler.GetMainWindowHandle(),
                (int)KeyCodes.WMessages.WM_CHAR,
                (int)KeyCodes.VKeys.VK_TAB, 0);

    counter++;
    if (counter > maxRepeatedCharacters)
    {
        Timer timer = sender as Timer;
        timer.Stop();
    }
}

private static void startTimer_Tick(object sender, EventArgs eventArgs)
{
    Timer timer = sender as Timer;
    timer.Stop();
    PostMessage(MemoryHandler.GetMainWindowHandle(),
               (int)KeyCodes.WMessages.WM_KEYDOWN,
               (int)KeyCodes.VKeys.VK_TAB, 0);
    PostMessage(MemoryHandler.GetMainWindowHandle(),
               (int)KeyCodes.WMessages.WM_CHAR,
               (int)KeyCodes.VKeys.VK_TAB, 0);
}
like image 26
Peter Ritchie Avatar answered Sep 18 '22 00:09

Peter Ritchie


When holding a key down on a physical keyboard, repeated keystrokes are passed to the active window. This is not built into the keyboard, but is a Windows feature.

You can simulate this by doing the following steps in order:

  1. Send a keydown message.
  2. Run a timer at 30 ms intervals (the default in Windows, changeable through Ease of Access settings), sending a keypress message to the window at each tick.
  3. Send a keyup message.
like image 35
Ming Slogar Avatar answered Sep 20 '22 00:09

Ming Slogar