首页 > 其他分享 >Winform虚拟/模拟键盘

Winform虚拟/模拟键盘

时间:2023-05-23 16:24:38浏览次数:33  
标签:KEYEVENTF KEYUP KEYDOWN 键盘 虚拟 keybd VirtualKeyCode event Winform

项目需要在触摸屏上增加一个虚拟键盘。记录下过程中遇到的问题及解决方法。

1.模拟按键

网上找到如下3种方法

1)SendKeys.Send

测试单独的shift不好用,所以最终未采纳此方法

SendKeys.Send("^{E}");//shift+e
SendKeys.Send("{Enter}");

2)keybd_event

最终选择了这个方法,简单有效。

虚拟按键对照表:https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes

[DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true)]
public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
[DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true)]
public static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
public static uint KEYEVENTF_KEYDOWN = 0;// 键按下 KEYEVENTF_KEYDOWN = 0
public static uint KEYEVENTF_KEYUP = 2;//键弹起 KEYEVENTF_KEYUP = 2
keybd_event(0x14, 0, KEYEVENTF_KEYDOWN, 0); //键按下 KEYEVENTF_KEYDOWN = 0
keybd_event(0x14, 0, KEYEVENTF_KEYUP, 0); //键弹起 KEYEVENTF_KEYUP = 2

3)PostMessage

这个方法也是简单有效,但是据说有些其他问题,没有仔细研究,有兴趣的可以自己研究。

[DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
public static extern int PostMessage(IntPtr hWnd, int Msg, Keys wParam, int lParam);

PostMessage(textBox2.Handle, 256, Keys.D, 2);//模拟按下2次 Keys.D

2.各种类型键的处理

微软对键盘输入有进行了分类,可以参考这个。

https://learn.microsoft.com/zh-cn/windows/win32/learnwin32/keyboard-input

1)CapsLock键/NumLock键

想要实现键盘按下抬起与界面效果相同,就需要捕获键盘操作。我使用了Hook

以下这篇博客写的很清晰明了,就不赘述了。

https://www.cnblogs.com/chorm590/p/14199978.html

在hook回调函数中做了如下处理

private int keyboardHookCallback(int code, IntPtr wParam, IntPtr lParam)
{
  if (code < 0)
    {
       return User32.CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
    }
   else
   {
     Keyboard_LL_Hook_Data khd = (Keyboard_LL_Hook_Data)Marshal.PtrToStructure(lParam, typeof(Keyboard_LL_Hook_Data));
      System.Diagnostics.Debug.WriteLine($"key event:{wParam}, key code:{khd.vkCode}, event time:{khd.time}");
      if ((int)wParam == 256 && khd.vkCode == 0x14)
      {
        IsCapsLockDown = !IsCapsLockDown;
      }
      return User32.CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
   }
}
private bool isCapsLockDown;
private bool IsCapsLockDown
{
  get { return isCapsLockDown; }
   set
    {
      isCapsLockDown = value;
       this.buttonCapsLock.BackColor = value ? Color.Gray : Control.DefaultBackColor;
    }
}
private void buttonCapsLock_Click(object sender, EventArgs e)
{
  User32.keybd_event(VirtualKeyCode.CAPS_LOCK, 0, 0, 0);   //键按下 KEYEVENTF_KEYDOWN = 0
   User32.keybd_event(VirtualKeyCode.CAPS_LOCK, 0, 2, 0);  //键弹起 KEYEVENTF_KEYUP = 2
}

初始化时同步键盘CapsLock/NumLock状态,使用user32.GetKeyState.返回值等于1则按下状态

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern short GetKeyState(int keyCode);
public static bool GetState(byte VKeyCode)
{
   return (User32.GetKeyState(VKeyCode) == 1);
}

2)其他组合键处理

ctrl+shift切换输入法,只响应这一种功能键+功能键。其他小伙伴有好的方法可以分享一下。

3)输入键+组合键

如ctrl+c,ctrl+v,ctrl+a,ctrl+z等等。

此方法不是最优方式,可以改进功能键存放在Queue中,遍历功能键,按顺序响应。

private void HandleKeysCombin(byte VKCode)
{
  //设置焦点控件
   this.ActiveControl = this.m_CustomActiveControl;
   lock (this)
   {
     if (IsCtrlDown)
      {
        keybd_event(VirtualKeyCode.CTRL, 0, KEYEVENTF_KEYDOWN, 0);                //键按下 KEYEVENTF_KEYDOWN = 0
      }
      if (IsShiftDown)
      {
        keybd_event(VirtualKeyCode.SHIFT, 0, KEYEVENTF_KEYDOWN, 0);                //键按下 KEYEVENTF_KEYDOWN = 0
      }
      if (IsAltDown)
      {
        keybd_event(VirtualKeyCode.ALT, 0, KEYEVENTF_KEYDOWN, 0);                //键按下 KEYEVENTF_KEYDOWN = 0
      }
      keybd_event(VKCode, VKCode, User32.KEYEVENTF_KEYDOWN, 0);                //键按下 KEYEVENTF_KEYDOWN = 0
      keybd_event(VKCode, VKCode, User32.KEYEVENTF_KEYUP, 0);           //键弹起 KEYEVENTF_KEYUP = 2
      if (IsCtrlDown)
      {
        keybd_event(VirtualKeyCode.CTRL, 0, KEYEVENTF_KEYUP, 0);                //键弹起 KEYEVENTF_KEYUP = 2
         IsCtrlDown = false;
      }
      if (IsShiftDown)
      {
        keybd_event(VirtualKeyCode.SHIFT, 0, KEYEVENTF_KEYUP, 0);              //键弹起 KEYEVENTF_KEYUP = 2
         IsShiftDown = false;
      }
      if (IsAltDown)
      {
         keybd_event(VirtualKeyCode.ALT, 0, KEYEVENTF_KEYUP, 0);                //键弹起 KEYEVENTF_KEYUP = 2
        IsAltDown = false;
     }
  }
}

3.窗体/UserControl焦点的处理

这篇里面方法简单好用,不赘述

 https://blog.csdn.net/accomp/article/details/7209052

标签:KEYEVENTF,KEYUP,KEYDOWN,键盘,虚拟,keybd,VirtualKeyCode,event,Winform
From: https://www.cnblogs.com/lotusgu/p/17422796.html

相关文章

  • C# Winform按钮避免重复点击
    btn_01.Enabled=false;//执行任务的函数和代码//执行任务的函数和代码Application.DoEvents();btn_01.Enabled=true;就是让应用程序的消息队列自动走完(在按钮正常前清空消息队列即可)......
  • c# winform定时刷新
     Thread多线程publicpartialclassForm2:Form{//横向滚动条记录的是像素位数//竖向滚动条记录的行的索引值intVerticalScrollIndex=0;intHorizontalOffset=0;publicForm2(){Initializ......
  • 盘点界面控件DevExpress WinForms的几大应用程序主题
    DevExpressWinForm控件包含了50+个自定义皮肤,其中涵盖了MicrosoftOffice和Windows11启发式的应用程序主题。PS:DevExpressWinForm拥有180+组件和UI库,能为WindowsForms平台创建具有影响力的业务解决方案。DevExpressWinForm能完美构建流畅、美观且易于使用的应用程序,无论是Of......
  • VMware虚拟机联网详述
    VMware虚拟机联网详述网络上东西都是虚拟的,你把握不住1.虚拟网络组件虚拟机(VirtualMachine)在物理计算机上通过虚拟化技术创建的一台虚拟计算机。它具有自己的操作系统、应用程序和网络配置,可以独立运行和管理。虚拟化软件(VirtualizationSoftware)物理机上用于创建、......
  • mkvirtualenv创建虚拟环境指定python版本号
    mkvirtualenv创建的虚拟环境,不指定具体的python版本时,默认使用的python版本是添加的环境变量中设置的pyhton版本。mkvirtualenv可以指定python版本,如:mkvirtualenv--python=python3.10venvname#venvname虚拟环境名称或者mkvirtualenv-ppython3.10venvname#venvna......
  • Winform设置成默认以管理员方式启动的方法
     很多exe应用如果不以管理员权限运行,达不到运行目的,也会让用户很困扰。解决方法:1、在项目上右键添加新文件,选择新建app.manifest文件 2、按照下图参照注释部分修改trustInfo节点中的配置即可还有另外一个方法。这个需要写在Program.cs里面。staticvoidMain(s......
  • FX110曝光:Royal Q APP虚拟骗局
    近期,一位马来西亚汇友爆料称其被引诱在RoyalQAPP加入了投资项目,结果怎么也出不了金。三番两次,盈利却取不出来据汇友描述,他发现自己无意间被一匿名者邀请加入了一个名为“RoyalQTrade”的电报群。在群组里,每天都有很多人晒出大量的盈利截图,晒出来的数据很是刺激眼球。看得多了......
  • 5.1 从键盘任意输入一个整数,不使用计算绝对值函数编程计算并输出该实数的绝对值
    设计思路:对正数和负数分情况编程,编程设计程序代码:#include<stdio.h>intmain(){inta;scanf("%d",&a);if(a<=0){a=-a;printf("%d",a);}elseprintf("%d",a);return0;}总结:if判断语句应用。......
  • 26 KVM热迁移虚拟机
    26KVM热迁移虚拟机26.1总体介绍26.1.1概述当虚拟机在物理机上运行时,物理机可能存在资源分配不均,造成负载过重或过轻的情况。另外,物理机存在硬件更换、软件升级、组网调整、故障处理等操作,如何在不中断业务的情况下完成这些操作十分重要。虚拟机热迁移技术可以在业务连续前提......
  • 深入理解 python 虚拟机:魔术方法之数学计算
    深入理解python虚拟机:魔术方法之数学计算在本篇文章当中主要给大家介绍在python当中一些常见的魔术方法,本篇文章主要是关于与数学计算相关的一些魔术方法,在很多科学计算的包当中都使用到了这些魔术方法。大小比较当我们在Python中定义自己的类时,可以通过重写一些特殊方法来......