ฉันจะสร้างเหตุการณ์การกดแป้นโดยใช้โปรแกรมใน C # ได้อย่างไร


107

ฉันจะสร้างเหตุการณ์ที่จำลองการกดแป้นบนแป้นพิมพ์โดยใช้โปรแกรมได้อย่างไร


6
คุณเพียงแค่ต้องการให้เหตุการณ์เกิดขึ้น?
Daniel

ฉันคิดว่าคุณต้องเข้าสู่รหัสที่ไม่มีการจัดการเพื่อจำลองการกดแป้นแบบ 'จริง'
Jonas B

ใช่ฉันแค่ต้องการให้เหตุการณ์เริ่มขึ้น
Dan Vogel

1
@GONeale: ว้าวคอมเม้นสามขวบ โอเคถ้าอย่างนั้น. ใช่มีการใช้งานที่ถูกต้องสำหรับสิ่งนี้นั่นคือเหตุผลที่ API มีอยู่ตั้งแต่แรก อย่างไรก็ตามพวกเขามีน้อยและอยู่ไกล จากประสบการณ์ของฉันหลายคนทำเช่นนี้เพราะพวกเขาไม่เข้าใจวิธีที่ดีที่สุดในการแก้ไขปัญหานั่นคือ "ฉันต้องการเรียกรหัสในตัวจัดการเหตุการณ์การคลิกปุ่มของฉัน แต่ไม่ใช่เฉพาะเมื่อมีการคลิกปุ่มเท่านั้น" ดังนั้นสำหรับผู้เริ่มต้นดูเหมือนว่าจะมีเหตุผลที่จะจำลองการคลิกปุ่มเมื่อสิ่งที่พวกเขาควรทำจริงๆคือเอารหัสนั้นโยนลงในฟังก์ชันและเรียกใช้จากที่อื่นในรหัส
Ed S.

6
@EdS: คำถามค่อนข้างตรงประเด็น ฉันสามารถเพิ่มรายละเอียดส่วนเกินจำนวนมากเกี่ยวกับการสร้างปุ่มกดได้และยังคงได้รับคำตอบเหมือนเดิม เมื่อพิจารณาว่าฉันได้สิ่งที่ต้องการแล้วดูเหมือนว่าจะไม่ใช่คำถาม "คุณภาพต่ำ" สำหรับฉัน
Dan Vogel

คำตอบ:


147

คำถามถูกแท็ก WPF แต่คำตอบจนถึงตอนนี้คือ WinForms และ Win32 ที่เฉพาะเจาะจง

หากต้องการทำสิ่งนี้ใน WPF เพียงแค่สร้าง KeyEventArgs และเรียก RaiseEvent บนเป้าหมาย ตัวอย่างเช่นในการส่งเหตุการณ์ KeyDown ของคีย์แทรกไปยังองค์ประกอบที่โฟกัสในปัจจุบัน:

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

โซลูชันนี้ไม่ได้อาศัยการโทรแบบเนทีฟหรือภายในของ Windows และควรมีความน่าเชื่อถือมากกว่าวิธีอื่น ๆ นอกจากนี้ยังช่วยให้คุณจำลองการกดแป้นบนองค์ประกอบเฉพาะได้

โปรดทราบว่ารหัสนี้ใช้ได้กับเหตุการณ์ PreviewKeyDown, KeyDown, PreviewKeyUp และ KeyUp เท่านั้น หากคุณต้องการส่งเหตุการณ์ TextInput คุณจะดำเนินการนี้แทน:

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

โปรดทราบว่า:

  • การควบคุมคาดว่าจะได้รับเหตุการณ์การแสดงตัวอย่างเช่น PreviewKeyDown ควรนำหน้า KeyDown

  • การใช้ target.RaiseEvent (... ) ส่งเหตุการณ์ไปยังเป้าหมายโดยตรงโดยไม่ต้องมีการประมวลผลเมตาเช่นตัวเร่งการจัดองค์ประกอบข้อความและ IME นี่คือสิ่งที่คุณต้องการตามปกติ ในทางกลับกันหากคุณทำสิ่งที่จำลองแป้นคีย์บอร์ดจริงด้วยเหตุผลบางประการคุณจะใช้ InputManager.ProcessInput () แทน


1
ฉันลองทำตามคำแนะนำของคุณแล้วไม่เห็นผลใด ๆ ฉันได้แนบตัวจัดการเหตุการณ์ keyDown เข้ากับองค์ประกอบที่โฟกัสแล้ว เหตุการณ์ที่ฉันยกขึ้นได้รับแล้ว แต่ KeyState ไม่ใช่ไม่มี ScanCode เป็น 0 และ isDown เป็นเท็จ ฉันคิดว่าฉันได้รับค่าเหล่านี้เพราะนี่คือสถานะจริงของแป้นพิมพ์ การกดปุ่มบนแป้นพิมพ์จริง KeyState = Down, isDown = true และ ScanCode จะมีค่า
Dan Vogel

25
เมื่อฉันลองรหัสแรกของคีย์ดาวน์ฉันพบข้อผิดพลาดใน "เป้าหมาย" ไม่สามารถแปลงเป็นภาพได้ทำไม?
kartal

3
แดนคุณรู้วิธีเลียนแบบการกดปุ่มด้วยตัวปรับแต่ง (ctrl / alt / shift) หรือไม่? Particulary ฉันต้องการจำลอง InputBinding: m_shell.InputBindings.Add (ใหม่ KeyBinding (m_command, Key.Insert, ModifierKeys.Control | ModifierKeys.Alt));
Shrike

14
เกี่ยวกับปัญหาเป้าหมายฉันดำเนินการโดยใช้Keyboard.PrimaryDevice.ActiveSourceดูstackoverflow.com/questions/10820990/…
OscarRyz

4
คำตอบนี้ดีมาก แต่ไม่สามารถใช้ในการส่งคีย์ด้วยตัวปรับแต่งดังที่ @Shrike กล่าวไว้ (เช่นCtrl+C)
ANeves

27

ในการสร้างเหตุการณ์สำคัญโดยไม่มี Windows Forms Context เราสามารถใช้วิธีการต่อไปนี้

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

โค้ดตัวอย่างได้รับด้านล่าง:

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

รายการของคีย์เสมือนมีการกำหนดไว้ที่นี่

เพื่อให้ได้ภาพที่สมบูรณ์โปรดใช้ลิงค์ด้านล่าง http://tksinghal.blogspot.in/2011/04/how-to-press-and-hold-keyboard-key.html


เหมาะถ้าหน้าต่างของคุณจะอยู่ด้านบน มันแก้ไขสถานการณ์ของฉันได้บางส่วนขอบคุณ!
Sergey

นอกจากคำตอบของ Rajesh แล้วหากคุณต้องการทำในแพลตฟอร์มมือถือคุณต้องนำเข้า "coredll.ddl"
user1123236

21

ฉันไม่ได้ใช้ แต่SendKeysอาจทำในสิ่งที่คุณต้องการ

ใช้ SendKeys เพื่อส่งการกดแป้นพิมพ์และการกดแป้นพิมพ์ร่วมกันไปยังแอปพลิเคชันที่ใช้งานอยู่ คลาสนี้ไม่สามารถสร้างอินสแตนซ์ได้ หากต้องการส่งการกดแป้นพิมพ์ไปยังชั้นเรียนและดำเนินการตามขั้นตอนของโปรแกรมของคุณต่อทันทีให้ใช้ Send หากต้องการรอกระบวนการใด ๆ ที่เริ่มต้นโดยการกดแป้นพิมพ์ให้ใช้ SendWait

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

ไมโครซอฟท์มีตัวอย่างการใช้งานบางอย่างเพิ่มเติมที่นี่


3
ฉันลองใช้ SendKeys.Send และได้รับ InvalidOperationException นี้: "SendKeys ไม่สามารถทำงานในแอปพลิเคชันนี้ได้เนื่องจากแอปพลิเคชันไม่ได้จัดการข้อความ Windows ให้เปลี่ยนแอปพลิเคชันเพื่อจัดการข้อความหรือใช้เมธอด SendKeys.SendWait" การใช้ SendKey.SendWait ไม่มีผล
Dan Vogel

ตรวจสอบให้แน่ใจว่าคุณไม่ได้ส่งเหตุการณ์สำคัญให้ตัวเอง เปลี่ยนโฟกัสไปที่กระบวนการที่เหมาะสมก่อนที่จะส่งเหตุการณ์ บทความที่เชื่อมโยงที่สองมีความช่วยเหลือบางประการ
Michael Petrotta

11

ได้อย่างง่ายดาย! (เพราะมีคนอื่นทำงานให้เราแล้ว ... )

หลังจากใช้เวลามากในการพยายามทำสิ่งนี้กับคำตอบที่แนะนำฉันเจอโครงการ codeplex Windows Input Simulatorซึ่งทำให้ง่ายเหมือนจำลองการกดปุ่ม:

  1. ติดตั้งแพคเกจสามารถทำได้หรือจากตัวจัดการแพ็คเกจ NuGet หรือจากคอนโซลตัวจัดการแพ็คเกจเช่น:

    ติดตั้งแพ็คเกจ InputSimulator

  2. ใช้รหัส 2 บรรทัดนี้:

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

แค่นี้แหละ!

------- แก้ไข --------

หน้าโครงการบน codeplex ถูกตั้งค่าสถานะด้วยเหตุผลบางประการนี่คือลิงก์ไปยังแกลเลอรี NuGet


วิธีนี้ใช้งานได้ดีมาก แต่ฉันไม่สามารถหาวิธีทำให้มันทำงานได้โดยใช้คีย์หลายชุด
user1234433222

เมื่อคุณพูดว่าการรวมกันของคีย์คุณหมายถึงเช่น CTRL-C หรือไม่?
Ravid Goldenberg

ใช่หรือแม้ว่าคุณต้องการให้แอปพลิเคชันคอนโซลทำงานแบบเต็มหน้าจอเช่น Alt-Enter ฉันรู้ว่าคุณสามารถใช้ F11 เพื่อเข้าสู่แบบเต็มหน้าจอได้ แต่จะเป็นการดีที่จะเห็นว่า Alt-Enter จะทำงานได้หรือไม่ :)
user1234433222

1
คุณสามารถทำได้แม้ว่าฉันจะไม่ได้ลองใช้เพียงแค่ใช้ inputSimulator.Keyboard.ModifiedKeyStroke (VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C);
Ravid Goldenberg

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.