Bagaimana saya bisa secara terprogram menghasilkan peristiwa penekanan tombol di C #?

107

Bagaimana saya bisa secara terprogram membuat acara yang akan mensimulasikan tombol yang ditekan pada keyboard?

Dan Vogel
sumber
6
Apakah Anda hanya perlu mengaktifkan acara?
Daniel A. White
Saya pikir Anda harus masuk ke kode tidak terkelola untuk mensimulasikan penekanan tombol 'nyata'.
Jonas B
Ya, saya hanya ingin acara tersebut diaktifkan.
Dan Vogel
1
@GONeale: Wow, komentar berusia tiga tahun. Baiklah. Ya, ada kegunaan yang valid untuk ini, itulah mengapa API ada di tempat pertama. Namun mereka sedikit dan jarang. Dalam pengalaman saya, banyak orang melakukan ini karena mereka tidak benar-benar memahami cara terbaik untuk mengatasi masalah, yaitu, "Saya ingin memanggil kode di event handler klik tombol saya, tetapi tidak hanya ketika tombol diklik". Jadi, untuk pemula, tampaknya logis untuk mensimulasikan klik tombol, ketika yang seharusnya mereka lakukan adalah mengambil kode itu, memasukkannya ke dalam fungsi, dan memanggilnya dari tempat lain dalam kode.
Ed S.
6
@ EDS: Pertanyaannya cukup langsung ke intinya. Saya bisa menambahkan banyak detail berlebih tentang membuat keypad, dan masih mendapat jawaban yang sama. Mengingat saya mendapatkan apa yang saya butuhkan, itu bukan pertanyaan yang "berkualitas buruk" bagi saya.
Dan Vogel

Jawaban:

147

Pertanyaannya diberi tag WPF tetapi jawabannya sejauh ini adalah WinForms dan Win32 spesifik.

Untuk melakukan ini di WPF, cukup buat KeyEventArgs dan panggil RaiseEvent pada target. Misalnya, untuk mengirim acara Sisipkan KeyDown ke elemen yang saat ini difokuskan:

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 }
);

Solusi ini tidak bergantung pada panggilan asli atau internal Windows dan harus jauh lebih andal daripada yang lain. Ini juga memungkinkan Anda untuk mensimulasikan penekanan tombol pada elemen tertentu.

Perhatikan bahwa kode ini hanya berlaku untuk peristiwa PreviewKeyDown, KeyDown, PreviewKeyUp, dan KeyUp. Jika Anda ingin mengirim peristiwa TextInput, Anda akan melakukan ini sebagai gantinya:

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 }
);

Perhatikan juga bahwa:

  • Kontrol mengharapkan untuk menerima peristiwa Pratinjau, misalnya PreviewKeyDown harus mendahului KeyDown

  • Menggunakan target.RaiseEvent (...) mengirimkan peristiwa langsung ke target tanpa meta-processing seperti akselerator, komposisi teks, dan IME. Ini biasanya yang Anda inginkan. Di sisi lain, jika Anda benar-benar melakukan apa untuk mensimulasikan tombol keyboard sebenarnya karena alasan tertentu, Anda akan menggunakan InputManager.ProcessInput () sebagai gantinya.

Ray Burns
sumber
1
Saya baru saja mencoba saran Anda, saya tidak melihat efeknya. Saya telah memasang event handler keyDown ke elemen terfokus. Peristiwa yang saya angkat diterima, tetapi KeyState adalah Tidak Ada, ScanCode-nya 0, dan isDown salah. Saya berasumsi saya mendapatkan nilai-nilai ini karena ini adalah kondisi keyboard yang sebenarnya. Menekan tombol pada keyboard sebenarnya, KeyState = Down, isDown = true, dan ScanCode memiliki nilai.
Dan Vogel
25
ketika saya mencoba kode pertama keydown saya mendapat kesalahan dalam "target" tidak dapat mengubahnya menjadi visual mengapa?
kartal
3
Dan, apakah Anda tahu cara meniru penekanan tombol dengan pengubah (ctrl / alt / shift)? Khusus Saya perlu mensimulasikan InputBinding: m_shell.InputBindings.Add (KeyBinding baru (m_command, Key.Insert, ModifierKeys.Control | ModifierKeys.Alt));
Shrike
14
Tentang masalah target , saya menyelesaikannya dengan menggunakan Keyboard.PrimaryDevice.ActiveSourcelihat stackoverflow.com/questions/10820990/…
OscarRyz
4
Jawaban ini sangat bagus, tetapi tidak dapat digunakan untuk mengirim kunci dengan pengubah, seperti yang dicatat @Shrike. (Misalnya Ctrl+C)
ANeves
27

Untuk menghasilkan peristiwa kunci tanpa Konteks Formulir Windows, kita dapat menggunakan metode berikut,

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

kode contoh diberikan di bawah ini:

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;
}

Daftar Kunci Virtual ditentukan di sini .

Untuk mendapatkan gambaran lengkapnya, silakan gunakan tautan di bawah ini, http://tksinghal.blogspot.in/2011/04/how-to-press-and-hold-keyboard-key.html

Rajesh
sumber
Cocok, jika jendela Anda akan berada di atas. Ini sebagian menyelesaikan situasi saya, terima kasih!
Sergey
Sebagai tambahan untuk jawaban Rajesh, jika Anda ingin melakukan ini di platform seluler, Anda harus mengimpor "coredll.ddl"
user1123236
21

Saya belum menggunakannya, tetapi SendKeys mungkin melakukan apa yang Anda inginkan.

Gunakan SendKeys untuk mengirim kombinasi tombol dan tombol ke aplikasi yang aktif. Kelas ini tidak dapat dibuat instance-nya. Untuk mengirim penekanan tombol ke kelas dan segera melanjutkan alur program Anda, gunakan Kirim. Untuk menunggu proses apa pun yang dimulai dengan penekanan tombol, gunakan SendWait.

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

Microsoft memiliki beberapa contoh penggunaan lainnya di sini .

Michael Petrotta
sumber
3
Saya mencoba menggunakan SendKeys.Send dan mendapatkan InvalidOperationException ini: "SendKeys tidak dapat berjalan di dalam aplikasi ini karena aplikasi tidak menangani pesan Windows. Ubah aplikasi untuk menangani pesan, atau gunakan metode SendKeys.SendWait." Menggunakan SendKey.SendWait tidak berpengaruh.
Dan Vogel
Pastikan Anda tidak mengirimkan peristiwa penting tersebut kepada diri Anda sendiri. Alihkan fokus ke proses yang tepat sebelum mengirim acara. Artikel terkait kedua memiliki beberapa bantuan tentang itu.
Michael Petrotta
11

Mudah! (karena orang lain sudah melakukan pekerjaan untuk kita ...)

Setelah menghabiskan banyak waktu mencoba ini dengan jawaban yang disarankan, saya menemukan proyek codeplex ini Windows Input Simulator yang membuatnya sesederhana mungkin untuk mensimulasikan penekanan tombol:

  1. Instal paketnya, bisa dilakukan atau dari manajer paket NuGet atau dari konsol manajer paket seperti:

    Instal-Paket InputSimulator

  2. Gunakan 2 baris kode ini:

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

Dan itu dia!

------- EDIT --------

Halaman proyek pada codeplex ditandai karena beberapa alasan, ini adalah tautan ke galeri NuGet.

Ravid Goldenberg
sumber
Ini bekerja dengan sangat baik, namun saya belum dapat menemukan cara membuat ini berfungsi dengan kombinasi tombol,
user1234433222
Saat Anda mengatakan kombinasi tombol yang Anda maksud seperti CTRL-C?
Ravid Goldenberg
ya atau bahkan jika Anda ingin aplikasi konsol menjadi layar penuh misalnya Alt-Enter, saya tahu Anda dapat menggunakan F11 untuk memasuki layar penuh tetapi alangkah baiknya jika Alt-Enter berfungsi :)
user1234433222
1
Anda bisa melakukannya, meskipun saya belum mencobanya, cukup gunakan inputSimulator.Keyboard.ModifiedKeyStroke (VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C);
Ravid Goldenberg