很早以前写了一个刷卡程序,功能是定时监控读卡器,当发现有IC卡放到读卡器上后,自动识别出卡号,然后带着这个卡号搜索一个英文用户名和卡号的对照表,最后把英文用户名直接自动输入到当前光标所在的位置。本来程序一直用得好好的,可是最近遇到了一个新问题——因为用户名现在居然可以用中文了!所以这下麻烦大了……

原先实现英文的自动输入,用的是keybd_event函数,直接模拟键盘事件。但是要输入中文,貌似没有输入法还是不行,难道还要我先用keybd_event调出输入法,然后输入拼音?这个思路想想就很恐怖,所以赶紧就上网搜解决方案去了。可是搜了一圈下来,只有寥寥几篇提到解决方案,虽然网上搜索结果众多,但是基本上就是这几个版本贴来贴去,浪费了我好多时间。

不幸的事情还在后头,虽然有人提到SendInput函数可以输入中文,但是语焉不详,按照他提供的点滴的代码,我死活就是没有试出来。所以最后中文搜索的结果,除了认识了这个SendInput函数之外,没有更多的收获。后来不死心,换了英文搜索,还真找到了一个比较接近我需求的,老外写的VB版本的SendInput的例子,试验了以下,果然可以输入中文。大喜之下,决定花点时间研究一下人家的源代码,然后写一个VC的版本。

摸索了两天之后,发现实现中文自动输入还真不难,因为SendInput确实支持,所以终于可以不用输入法了,万幸。特意整理了几个函数,共享一下。

首先是,头文件必须包含以下两个:
#include <winable.h>
#include <atlconv.h>

前者是SendInput函数要用到,后者是字符串转换的时候要用到。

void SendAscii(wchar_t data, BOOL shift)
{
 INPUT input[2];
 memset(input, 0, 2 * sizeof(INPUT));
 
 if (shift)
 {
   input[0].type = INPUT_KEYBOARD;
   input[0].ki.wVk = VK_SHIFT;
   SendInput(1, input, sizeof(INPUT));
 }

input[0].type = INPUT_KEYBOARD;
 input[0].ki.wVk = data;

input[1].type = INPUT_KEYBOARD;
 input[1].ki.wVk = data;
 input[1].ki.dwFlags = KEYEVENTF_KEYUP;

SendInput(2, input, sizeof(INPUT));

if (shift)
 {
   input[0].type = INPUT_KEYBOARD;
   input[0].ki.wVk = VK_SHIFT;
   input[0].ki.dwFlags = KEYEVENTF_KEYUP;
   SendInput(1, input, sizeof(INPUT));  
 }
}

void SendUnicode(wchar_t data)
{
 INPUT input[2];
 memset(input, 0, 2 * sizeof(INPUT));
 
 input[0].type = INPUT_KEYBOARD;
 input[0].ki.wVk = 0;
 input[0].ki.wScan = data;
 input[0].ki.dwFlags = 0x4;//KEYEVENTF_UNICODE;
 
 input[1].type = INPUT_KEYBOARD;
 input[1].ki.wVk = 0;
 input[1].ki.wScan = data;
 input[1].ki.dwFlags = KEYEVENTF_KEYUP | 0x4;//KEYEVENTF_UNICODE;
 
 SendInput(2, input, sizeof(INPUT));
}

//为方便使用,下面这个函数包装了前两个函数。

void SendKeys(CString msg)
{
 short vk;
 BOOL shift;

USES_CONVERSION;
 wchar_t* data = T2W(msg.GetBuffer(0));
 int len = wcslen(data);

for(int i=0;i<len;i++)
 {
   if (data[i]>=0 && data[i]<256) //ascii字符
   {
     vk = VkKeyScanW(data[i]);

if (vk == -1)
     {
       SendUnicode(data[i]);
     }
     else
     {
       if (vk < 0)
       {
         vk = ~vk + 0x1;
       }
       
       shift = vk >> 8 & 0x1;
       
       if (GetKeyState(VK_CAPITAL) & 0x1)
       {
         if (data[i]>='a' && data[i]<='z' || data[i]>='A' && data[i]<='Z')
         {
           shift = !shift;
         }
       }

SendAscii(vk & 0xFF, shift);
     }
   }
   else //unicode字符
   {
     SendUnicode(data[i]);
   }
 }
}

直接调用SendKeys函数就可以在当前光标的位置自动输入指定的字符串,下面的例子演示了如何自动打开记事本程序并输入一段话:
void CSendInputDlg::OnTest()
{
 ShellExecute(NULL, NULL, "notepad.exe", NULL, NULL, SW_SHOWNORMAL);
 
 Sleep(500); //为了确保记事本程序打开完毕,稍等片刻

CWnd *pWnd = FindWindow(NULL, "无标题 - 记事本");
 if (pWnd)
 {
   pWnd->SetForegroundWindow();
   SendKeys("我是sway,我爱中国!\nI love China!\nEmail: \b\b");
 }
}

在VC中使用SendInput函数实现中文的自动输入的更多相关文章

  1. VC++中的延时函数

    原文链接:http://www.educity.cn/develop/478947.html VC中提供了很多关于时间操作的函数,编写程序时我们可以跟据定时的不同精度要求选择不同的时间函数来完成定时和 ...

  2. 解决 openSUSE 中 Sublime Text 3 的中文显示和输入问题

    测试环境 系统版本:openSUSE Leap 42.2 桌面环境:KDE Plasma 5输入法:fcitx-rime (中州韵) 见周围用 Windows 和 macOS 的小伙伴几乎都在用简单强 ...

  3. VC中常见API函数使用方法(经验版)

    ***********************************************声明*************************************************** ...

  4. VC中基于 Windows 的精确定时[转]

    在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间,定时刷新屏幕上的进度条,上位 机定时向下位机发送命令和传送数据等.特别是在对控制性能要求较高的实时控制系统和数据采集系统中,就更需要 ...

  5. VC中基于 Windows 的精确定时

    在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间,定时刷新屏幕上的进度条,上位 机定时向下位机发送命令和传送数据等.特别是在对控制性能要求较高的实时控制系统和数据采集系统中,就更需要 ...

  6. python中的zip()函数和map()函数

    一.zip()函数 1.语法: zip(iterable, ...) 参数说明: iterable,...-- 一个或多个迭代器; 在python2中: zip() 函数用于将可迭代的对象作为参数,将 ...

  7. 【thrift】vc中使用thrift中文字符串乱码问题解决

    问题描述: VC中使用Apache thrift时,如果字符串中包含中文,会出现乱码问题,这个问题的原因是由于thrift为了达到跨语言交互而使用了UTF-8格式发送字符串,这点对java或者C#不会 ...

  8. VC中实现GCC的2个比较常用的位运算函数

    在GCC中内嵌了两个位运算的函数,但在VC中并没有这两个函数(有相似函数). //返回前导的0的个数. int __builtin_clz (unsigned int x) //返回后面的0个个数,和 ...

  9. 如何在VC中查询中文,及QT5的中文处理

    1,VC中查询所有含中文字符串 使用正则表达式,查询内容为: (".*[\u4E00-\u9FA5]+)|([\u4E00-\u9FA5]+.*") 这样,就可以把代码中的中文都查 ...

随机推荐

  1. centos6.8安装mysql5.6【转】

    首先先要去看看本机有没有默认的mysql, 本地默认有的,我们应先卸载,在安装新的这个逻辑. rpm -qa | grep mysql 我本机默认安装的mysql5.1.73 下一步删除 rpm -e ...

  2. Mac安装MAT报错问题

    安装mat报错,提示在/.eclipse/1528649425_macosx_cocoa_x86_64/configuration/1539332382530.log路径下查看错误日志, 原因是/pr ...

  3. docker stack 部署nginx

    =============================================== 2018/7/29_第1次修改                       ccb_warlock == ...

  4. 启动tomcat的时候爆出如下错误

    The JRE_HOME environment variable is not defined correctly This environment 解决办法: https://blog.csdn. ...

  5. 模板引擎--hogan

    学习地址:https://www.imooc.com/article/18493 Hogan的github地址镇楼:https://github.com/twitter/hogan.js

  6. nGrinder的安装与使用

    背景 性能压测工具之前使用的是jmeter,这次说的是nGrinder,先直接搬运两者之间的比较 比较点 JMeter nGrinder 结果 实现语言 Java Java = License Apa ...

  7. C#数组 List、Dictionary 、Arrary、ArrayList

    #region Dictionary 泛型集合,动态修改查询.查询和排序 Dictionary<string, string> dic = new Dictionary<string ...

  8. 系统管理员常用的Linux命令

    整理Linux的一些基本系统管理命令作为备忘 ========================================================================= 查看文 ...

  9. Django 2.1版本与Django 1.8.3的一些区别(转)

    Django 2.1版本与Django 1.8.3的一些区别     我在刚开始学习的时候使用的Django版本是1.8.3的,后来在安装其它软件的时候,可能需要2.1的版本,自动帮我更新了Djang ...

  10. SmartSVN11 Mac版 注册码序列号

    Name=apipostAddress=1337 iNViSiBLE Str.Email=3257132998@qq.comFreeUpdatesUntil=2099-09-26LicenseCoun ...