Como posso gerar eventos de pressionamento de tecla programaticamente em C #?


107

Como posso criar programaticamente um evento que simule uma tecla sendo pressionada no teclado?


6
Você só precisa que o evento seja disparado?
— Daniel A. White,

Acho que você teria que entrar no código não gerenciado para simular um pressionamento de tecla 'real'.
— Jonas B

Sim, só preciso que o evento seja disparado.
— Dan Vogel

1
@GONeale: Uau, um comentário de três anos. OK então. Sim, existem usos válidos para isso; é por isso que a API existe em primeiro lugar. No entanto, eles são poucos e distantes entre si. Na minha experiência, muitas pessoas fazem isso porque não entendem realmente a melhor maneira de resolver um problema, ou seja, "Quero chamar o código em meu manipulador de eventos de clique de botão, mas não apenas quando um botão é clicado". Portanto, para um iniciante, parece lógico simular um clique de botão, quando o que eles realmente deveriam fazer é pegar esse código, jogá-lo em uma função e chamá-lo de outro lugar no código.
— Ed S.

6
@EdS: A pergunta foi direta ao ponto. Eu poderia ter acrescentado muitos detalhes em excesso sobre a criação de um teclado e ainda obter a mesma resposta. Considerando que recebi exatamente o que precisava, não me parece uma pergunta de "baixa qualidade".
— Dan Vogel

Respostas:


147

A pergunta está marcada como WPF, mas as respostas até agora são WinForms e Win32 específicos.

Para fazer isso no WPF, basta construir um KeyEventArgs e chamar RaiseEvent no destino. Por exemplo, para enviar um evento KeyDown da tecla Insert para o elemento atualmente em foco:

  var key = Key.Insert;                    // Key to send
  var target = Keyboard.FocusedElement;    // Target element
  var routedEvent = Keyboard.KeyDownEvent; // Event to send

  target.RaiseEvent(
    new KeyEventArgs(
      Keyboard.PrimaryDevice,
      PresentationSource.FromVisual(target),
      0,
      key)
    { RoutedEvent=routedEvent }
  );

Esta solução não depende de chamadas nativas ou internas do Windows e deve ser muito mais confiável do que as outras. Também permite simular um pressionamento de tecla em um elemento específico.

Observe que este código só se aplica a eventos PreviewKeyDown, KeyDown, PreviewKeyUp e KeyUp. Se você quiser enviar eventos TextInput, faça o seguinte:

  var text = "Hello";
  var target = Keyboard.FocusedElement;
  var routedEvent = TextCompositionManager.TextInputEvent;

  target.RaiseEvent(
    new TextCompositionEventArgs(
      InputManager.Current.PrimaryKeyboardDevice,
      new TextComposition(InputManager.Current, target, text))
    { RoutedEvent = routedEvent }
  );

Observe também que:

  • Os controles esperam receber eventos de visualização, por exemplo, PreviewKeyDown deve preceder KeyDown

  • O uso de target.RaiseEvent (...) envia o evento diretamente para o destino sem meta-processamento, como aceleradores, composição de texto e IME. Normalmente é isso que você deseja. Por outro lado, se você realmente fizer o que simular as teclas reais do teclado por algum motivo, deverá usar InputManager.ProcessInput ().


1
Acabei de tentar sua sugestão, não vejo efeito. Anexei um manipulador de eventos keyDown ao elemento em foco. O evento que levantei é recebido, mas o KeyState é Nenhum, o ScanCode é 0 e isDown é falso. Presumo que estou obtendo esses valores porque esse é o estado real do teclado. Pressionar uma tecla no teclado real, KeyState = Down, isDown = true e ScanCode tem um valor.
— Dan Vogel

24
quando tentei o primeiro código de keydown, obtive erro no "target" não consigo convertê-lo para visual por quê?
— kartal de

3
Dan, você sabe como emular o pressionamento de uma tecla com um modificador (ctrl / alt / shift)? Particularmente, preciso simular InputBinding: m_shell.InputBindings.Add (new KeyBinding (m_command, Key.Insert, ModifierKeys.Control | ModifierKeys.Alt));
— Shrike de

14
Sobre o problema de destino , resolvi usando Keyboard.PrimaryDevice.ActiveSourcever stackoverflow.com/questions/10820990/…
— OscarRyz

4
Essa resposta é muito boa, mas não pode ser usada para enviar uma tecla com um modificador, como observou @Shrike. (Ex Ctrl+C.)
— ANeves

28

Para produzir eventos chave sem o contexto do Windows Forms, podemos usar o seguinte método,

[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);

o código de amostra é fornecido abaixo:

const int VK_UP = 0x26; //up key
const int VK_DOWN = 0x28;  //down key
const int VK_LEFT = 0x25;
const int VK_RIGHT = 0x27;
const uint KEYEVENTF_KEYUP = 0x0002;
const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
int press()
{
    //Press the key
    keybd_event((byte)VK_UP, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
    return 0;
}

A lista de chaves virtuais é definida aqui .

Para obter a imagem completa, use o link abaixo, http://tksinghal.blogspot.in/2011/04/how-to-press-and-hold-keyboard-key.html


Adequado, se sua janela for para cima. Isso resolveu parcialmente minha situação, obrigado!
— Sergey de

Além da resposta de Rajesh, se você quiser fazer isso na plataforma móvel, você deve importar "coredll.ddl"
— user1123236

22

Eu não usei, mas SendKeys pode fazer o que você quiser.

Use SendKeys para enviar pressionamentos de tecla e combinações de pressionamento de tecla para o aplicativo ativo. Esta classe não pode ser instanciada. Para enviar um pressionamento de tecla a uma classe e continuar imediatamente com o fluxo do seu programa, use Enviar. Para aguardar qualquer processo iniciado pelo pressionamento de tecla, use SendWait.

System.Windows.Forms.SendKeys.Send("A");
System.Windows.Forms.SendKeys.Send("{ENTER}");

A Microsoft tem mais alguns exemplos de uso aqui .


3
Tentei usar SendKeys.Send e recebo esta InvalidOperationException: "SendKeys não pode ser executado dentro deste aplicativo porque o aplicativo não está manipulando mensagens do Windows. Altere o aplicativo para lidar com mensagens ou use o método SendKeys.SendWait." Usar SendKey.SendWait não tem efeito.
— Dan Vogel

Certifique-se de não enviar o evento principal para você mesmo. Mude o foco para o processo adequado antes de enviar o evento. O segundo artigo vinculado tem alguma ajuda nisso.
— Michael Petrotta

11

Facilmente! (porque outra pessoa já fez o trabalho para nós ...)

Depois de passar muito tempo tentando fazer isso com as respostas sugeridas, me deparei com este projeto codeplex do Windows Input Simulator que simplificou ao máximo a simulação de um pressionamento de tecla:

  1. A instalação do pacote pode ser feita a partir do gerenciador de pacotes NuGet ou do console do gerenciador de pacotes como:

    Install-Package InputSimulator

  2. Use estas 2 linhas de código:

    inputSimulator = new InputSimulator() inputSimulator.Keyboard.KeyDown(VirtualKeyCode.RETURN)

E é isso!

-------EDITAR--------

A página do projeto no codeplex está sinalizada por algum motivo, este é o link para a galeria NuGet.


Isso funciona muito bem, mas não consegui descobrir como fazê-lo funcionar com uma combinação de teclas,
— user1234433222

Quando você diz combinação de teclas, quer dizer CTRL-C?
— Ravid Goldenberg

sim, ou mesmo se você quiser que um aplicativo de console vá para tela inteira, por exemplo, Alt-Enter, sei que você pode usar F11 para entrar em tela inteira, mas seria bom ver se Alt-Enter funcionaria :)
— user1234433222

1
Bem, você pode fazer isso, embora eu não tenha tentado, basta usar inputSimulator.Keyboard.ModifiedKeyStroke (VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C);
— Ravid Goldenberg de

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.