Làm cách nào để tạo lập trình các sự kiện nhấn phím trong C #?


107

Làm cách nào để tôi có thể lập trình tạo sự kiện mô phỏng một phím đang được nhấn trên bàn phím?


6
Bạn chỉ cần sự kiện để khai hỏa?
Daniel A. White

Tôi nghĩ rằng bạn phải bước vào mã không được quản lý để mô phỏng một lần nhấn phím 'thực'.
Jonas B

Vâng, tôi chỉ cần sự kiện để khai hỏa.
Dan Vogel

1
@GONeale: Chà, một nhận xét ba năm tuổi. Được rồi. Có, có những cách sử dụng hợp lệ cho điều này, đó là lý do tại sao API tồn tại ngay từ đầu. Tuy nhiên chúng rất ít và xa. Theo kinh nghiệm của tôi, nhiều người làm điều này vì họ không thực sự hiểu cách tốt nhất để giải quyết vấn đề, tức là "Tôi muốn gọi mã trong trình xử lý sự kiện nhấp vào nút của mình, nhưng không chỉ khi một nút được nhấp". Vì vậy, đối với người mới bắt đầu, có vẻ hợp lý khi mô phỏng một lần nhấp vào nút, khi những gì họ thực sự nên làm là lấy mã đó, ném nó vào một hàm và gọi nó từ nơi khác trong mã.
Ed S.

6
@EdS: Câu hỏi khá hay. Tôi có thể đã thêm nhiều chi tiết thừa về việc tạo bàn phím, và vẫn nhận được câu trả lời tương tự. Xem xét tôi đã nhận được chính xác những gì tôi cần, đó không phải là một câu hỏi "chất lượng kém" đối với tôi.
Dan Vogel

Câu trả lời:


147

Câu hỏi được gắn thẻ WPF nhưng câu trả lời cho đến nay là WinForms và Win32 cụ thể.

Để thực hiện điều này trong WPF, chỉ cần tạo một KeyEventArgs và gọi RaiseEvent trên mục tiêu. Ví dụ: để gửi một sự kiện Chèn khóa KeyDown đến phần tử hiện được tập trung:

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

Giải pháp này không dựa vào các cuộc gọi gốc hoặc nội bộ Windows nên đáng tin cậy hơn nhiều so với các giải pháp khác. Nó cũng cho phép bạn mô phỏng một lần nhấn phím trên một phần tử cụ thể.

Lưu ý rằng mã này chỉ áp dụng cho các sự kiện PreviewKeyDown, KeyDown, PreviewKeyUp và KeyUp. Nếu bạn muốn gửi các sự kiện TextInput, bạn sẽ thực hiện việc này thay thế:

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

Cũng lưu ý rằng:

  • Các điều khiển mong đợi nhận được các sự kiện Xem trước, ví dụ: PreviewKeyDown phải đứng trước KeyDown

  • Sử dụng target.RaiseEvent (...) gửi sự kiện trực tiếp đến đích mà không cần xử lý meta như trình tăng tốc, thành phần văn bản và IME. Đây thường là những gì bạn muốn. Mặt khác, nếu bạn thực sự làm những gì để mô phỏng các phím bàn phím thực tế vì lý do nào đó, bạn sẽ sử dụng InputManager.ProcessInput () để thay thế.


1
Tôi vừa thử gợi ý của bạn, tôi thấy không có tác dụng. Tôi đã đính kèm một trình xử lý sự kiện keyDown vào phần tử tập trung. Sự kiện tôi nêu ra đã được nhận, nhưng KeyState là Không, Mã quét là 0 và isDown là sai. Tôi cho rằng tôi đang nhận được các giá trị này vì đây là trạng thái thực tế của bàn phím. Nhấn một phím trên bàn phím thực, KeyState = Down, isDown = true và ScanCode có một giá trị.
Dan Vogel

25
Khi tôi thử mã đầu tiên của keydown, tôi gặp lỗi trong "target" không thể chuyển đổi nó thành hình ảnh tại sao?
kartal

3
Dan, bạn có biết cách mô phỏng cách nhấn phím bằng công cụ sửa đổi (ctrl / alt / shift) không? Đặc biệt tôi cần mô phỏng InputBinding: m_shell.InputBindings.Add (KeyBinding mới (m_command, Key.Insert, ModifierKeys.Control | ModifierKeys.Alt));
Coke

14
Về vấn đề mục tiêu , tôi đã giải quyết bằng cách sử dụng Keyboard.PrimaryDevice.ActiveSourcexem stackoverflow.com/questions/10820990/…
OscarRyz

4
Câu trả lời này rất hay, nhưng nó không thể được sử dụng để gửi một khóa có bổ trợ, như @Shrike đã lưu ý. (Ví dụ Ctrl+C:)
ANeves

27

Để tạo các sự kiện chính mà không có Ngữ cảnh của Windows Forms, Chúng tôi có thể sử dụng phương pháp sau,

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

mã mẫu được đưa ra dưới đây:

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

Danh sách các phím ảo được xác định tại đây .

Để có được bức tranh hoàn chỉnh, vui lòng sử dụng liên kết dưới đây, http://tksinghal.blogspot.in/2011/04/how-to-press-and-hold-keyboard-key.html


Thích hợp, nếu cửa sổ của bạn sẽ ở trên cùng. Nó giải quyết một phần tình huống của tôi, cảm ơn!
Sergey

Một bổ sung cho câu trả lời Rajesh, nếu bạn muốn làm điều này trong nền tảng di động, bạn phải nhập "coredll.ddl"
user1123236

21

Tôi chưa sử dụng nó, nhưng SendKeys có thể làm những gì bạn muốn.

Sử dụng SendKeys để gửi các tổ hợp phím và tổ hợp phím tới ứng dụng đang hoạt động. Không thể khởi tạo lớp này. Để gửi một tổ hợp phím tới một lớp và ngay lập tức tiếp tục với luồng chương trình của bạn, hãy sử dụng Gửi. Để đợi bất kỳ quá trình nào bắt đầu bằng cách nhấn phím, hãy sử dụng SendWait.

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

Microsoft có thêm một số ví dụ sử dụng ở đây .


3
Tôi đã thử sử dụng SendKeys.Send và nhận được lỗi này là InvalidOperationException: "SendKeys không thể chạy bên trong ứng dụng này vì ứng dụng không xử lý thư Windows. Thay đổi ứng dụng để xử lý thư hoặc sử dụng phương thức SendKeys.SendWait." Sử dụng SendKey.SendWait không có tác dụng.
Dan Vogel

Đảm bảo rằng bạn không gửi sự kiện quan trọng cho chính mình. Chuyển tiêu điểm sang quy trình thích hợp trước khi gửi sự kiện. Bài viết được liên kết thứ hai có một số trợ giúp về điều đó.
Michael Petrotta

11

Một cách dễ dàng! (bởi vì ai đó đã làm công việc cho chúng tôi ...)

Sau khi dành nhiều thời gian để cố gắng làm điều này với các câu trả lời được đề xuất, tôi đã xem qua dự án codeplex Windows Input Simulator này, nó làm cho nó đơn giản như có thể để mô phỏng một phím bấm:

  1. Cài đặt gói, có thể được thực hiện hoặc từ trình quản lý gói NuGet hoặc từ bảng điều khiển trình quản lý gói như:

    Install-Package InputSimulator

  2. Sử dụng 2 dòng mã này:

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

Và đó là nó!

-------BIÊN TẬP--------

Trang dự án trên codeplex bị gắn cờ vì lý do nào đó, đây là liên kết đến thư viện NuGet.


Điều này hoạt động rất tốt, tuy nhiên tôi không thể tìm thấy cách làm cho nó hoạt động với sự kết hợp của các phím,
user1234433222

Khi bạn nói tổ hợp phím, bạn có nghĩa là giống như CTRL-C?
Ravid Goldenberg

vâng hoặc thậm chí nếu bạn muốn có một ứng dụng giao diện điều khiển để đi toàn màn hình ví dụ Alt-Enter, tôi biết bạn có thể sử dụng F11 để nhập toàn màn hình nhưng nó sẽ được tốt đẹp để xem nếu Alt-Enter sẽ làm việc :)
user1234433222

1
Bạn có thể làm điều đó, mặc dù tôi chưa thử, chỉ cần sử dụng inputSimulator.Keyboard.ModifiedKeyStroke (VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C);
Ravid Goldenberg

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.