它们不但能够转移为WM,该函数合成三次击键事件

 http://baike.baidu.com/view/1080077.htm

 

 keybd_event
  函数功用:该函数合成一反击键事件。系统可利用那种合成的击键事件来发出WM_KEYUP或WM_KEYDOWN音信,键盘驱动程序的中止处理程序调用keybd_event函数。在Windows
NT中该函数己被选择SendInput来取代它。

 

————————————————– 

http://www.cnblogs.com/yedaoq/archive/2010/12/30/1922305.html

http://www.cnblogs.com/yedaoq/archive/2010/12/30/1922305.html

SendInput模拟键盘输入的标题

 

SendInput模拟键盘输入的题材

SendInput模拟键盘输入的标题

 

不久前触及到这些函数,因而领悟了一晃,统计一下列在那。

本人掌握它的角度是怎么样通过它向移动窗口输入字符,那是广明代序都有的职能(作者猜Visual
Assist X就用了那么些意义)。

依据MSDN,此函数模拟按键操作,将一部分音信插入键盘或鼠标的输入流中,Windows对它进行拍卖,生成对应的WM_KEYDOWN或WM_KEYUP事件,这个事件与平时键盘输入一起进入应用程序的消息循环,它们不但可以转换为WM_CHAMurano音讯,还足以变换为其余(诸如加快键)等音讯。

采纳它来发送字符新闻,并不曾看起来那么简单。那有多个须求考虑的题材:

1.
输入法的变换。例如须求向移动窗口发送一些英文字符,我们恐怕想象那样来落到实处:获取对应键盘字符的杜撰键码,发送3个SendInput。可是只要移动窗口正在使用一个输入法,那么大家发送出去的新闻,会进去输入法的Composition窗口,最后被转移为象形文字或被撇下。唯有当输入法关闭时,程序运营的功用才会像我们盼望的那么,在运动窗口中显示出英文字符。

2.
对此华语字符,应该怎么发送给活动窗口?由于SendInput模拟的是WM_KEYDOWN和WM_KEYUP事件,根据一般的笔触,大家是还是不是相应取得粤语字符的输入法编码(拼音或五笔码),然后向运动窗口发送编码相关的SendInput?那那不单供给活动窗口打开输入法,甚至还要获知它的编码格局。

由此看来,若直接如想象中那样采纳SendInput来输入字符,则必须分析活动窗口的输入法情形。而且输入英文时,供给关闭输入法,输入汉语时,又供给打开输入法。若真要以那样的思路来贯彻,则势必是为难成功的。

 

那么,有没有不依靠活动窗口输入法境况的方法呢?

其实是有的,使用SendInput模拟键盘输入时,其参数是KEYBDINPUT结构,通过将其dwFlags成员设置KEYEVENTF_UNICODE就足以了。使用此措施,只需将KEYBDINPUT.wScan设置为字符的Unicode编码即可。对于英文字符,不需求关闭活动窗口的输入法;对于华语字符,也不供给活动窗口打开输入法和将字符转换为输入法编码。

MSDN对此方法的表达为:INPUT_KEYBOA汉兰达D帮忙非键盘的输入形式,例如手写识别或语音识别,通过KEYEVENTF_UNICODE标识,这么些情势与键盘(文本)输入别无二致。若是内定了KEYEVENTF_UNICODE,SendInput发送3个WM_KEYDOWN或WM_KEYUP消息给移动窗口的线程音信队列,音信的wParam参数为VK_PACKET。GetMessage或PeedMessage一旦获得此音信,就把它传递给TranslateMessage,TranslateMessage依据wScan中钦赐的Unicode字符爆发1个WM_CHA大切诺基音信。若窗口是ANSI窗口,则Unicode字符会自动转换为对应的ANSI字符。

 

其它索要向活动窗口输入字符(包含英文)的遵守均应使用那种方法来达成。事实上,键盘音信转换为字符音讯的进度是很复杂的,那只怕与键盘布局、区域、换档状态等很多因素有关,那也是Windows要动用TranslateMessage来转换音信的原委。因而,不应有总结透过击键事件来企图向活动窗口输入特定的字符。

 

经测试,SendInput还有七个值得注意的地点:

1.
没有为KEYBDINPUT.dwFlags指定KEYEVENTF_KEYUP标识时,SendInput将生成WM_KEYDOWN音信,不然生成WM_KEYUP新闻,由于唯有WM_KEYDOWN会转换为字符新闻,因而,若以输入字符为对象,则不应内定KEYEVENTF_KEYUP标识。

2.
若是大家想达到实际做一遍击键所发出的效益:顺序发生1个WM_KEYDOWN和一个WM_KEYUP事件。则必须各自以不点名KEYEVENTF_KEYUP和指定KEYEVENTF_KEYUP的点子执行一次SendInput操作。SendInput允许在三次调用中发送多个模拟音信:

  INPUT input[2]; 
  memset(input, 0, 2 * 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));

但事实上,那将造成不产生别的音信。那五个音信必须分开发送,如下所示:

  INPUT input[2]; 
  memset(input, 0, 2 * sizeof(INPUT));

  input[0].type = INPUT_KEYBOARD; 
  input[0].ki.wVk = data; 
  SendInput(1, input, sizeof(INPUT));

 

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

  SendInput(1, input + 1, sizeof(INPUT));

 

有关第一点内容,小编很不常常。因为事先有人在网上帖的代码是统一发送的,想必有人那样做过同时成功了。笔者不知晓是或不是与系统或其余因素有关。小编也曾试图尝试消除此题材,但一向不马到功成:

1.
基于MSDN,KEYBDINPUT.time是1个日子戳,假使为零,系统将使用它本身的光阴戳。由此笔者难以置信四个一起发送的轩然大波,是还是不是因为其时间戳相同,而被忽略掉了。于是自身在上述代码中显式设置了该属性,再统一发送,结果如故是尚未发出别的音信。

2.
自家分别品尝了三种状态:合并发送的两条新闻都并未点名KEYEVENTF_KEYUP(期望获得多个一律的字符输入);合并发送的两条音讯具有不相同的虚构键码且都不点名KEYEVENTF_KEYUP(期望获取八个不等的字符输入)。结果还是依然退步,没有产生任何音信。

自家不晓得那是或不是意味着:对于键盘输入,不允许将新闻合并发送。

若您领会当中原因或测试到与笔者不相同的光景,请与自个儿交换:yedaoq@126.com

 

有关文化:

1.
输入法也得以处理SendInput发送的Unicode音信,具体办法不详。见MSDN中ImmGetProperty方法的参考:当dwIndex参数为IGP_PROPERTY时,IME_PROP_ACCEPT_WIDE_VKEY是贰个恐怕的重临值,它象征IME会处理SendInput函数以VK_PACKET注入的Unicode字符,若重回值无该标识,则Unicode字符会直接发送给应用程序。

近来触及到这一个函数,由此通晓了一晃,计算一下列在那。

本人询问它的着眼点是怎么通过它向活动窗口输入字符,那是举不胜举顺序都有个别职能(作者猜Visual
Assist X就用了那一个效应)。

基于MSDN,此函数模拟按键操作,将一些消息插入键盘或鼠标的输入流中,Windows对它举行拍卖,生成对应的WM_KEYDOWN或WM_KEYUP事件,那几个事件与日常键盘输入一起进去应用程序的音讯循环,它们不仅可以转移为WM_CHAQX56消息,仍是能够转移为其余(诸如加快键)等音信。

采纳它来发送字符音信,并没有看起来那么简单。那有四个须求考虑的标题:

1.
输入法的转移。例如须要向活动窗口发送一些英文字符,大家只怕想象那样来促成:获取对应键盘字符的虚拟键码,发送几个SendInput。不过倘诺移动窗口正在选拔二个输入法,那么我们发送出去的音讯,会进入输入法的Composition窗口,最后被转换为象形文字或被废弃。唯有当输入法关闭时,程序运营的法力才会像大家期待的那么,在移动窗口中显得出英文字符。

2.
对此华语字符,应该怎么发送给活动窗口?由于SendInput模拟的是WM_KEYDOWN和WM_KEYUP事件,依照一般的思绪,大家是或不是应当获得汉语字符的输入法编码(拼音或五笔码),然后向移动窗口发送编码相关的SendInput?那那不光须求活动窗口打开输入法,甚至还要获知它的编码格局。

总的看,若直接如想象中那样选取SendInput来输入字符,则必须分析活动窗口的输入法处境。而且输入英文时,须要关闭输入法,输入普通话时,又供给打开输入法。若真要以那样的笔触来落实,则一定是麻烦成功的。

那么,有没有不借助活动窗口输入法情形的艺术啊?

骨子里是一对,使用SendInput模拟键盘输入时,其参数是KEYBDINPUT结构,通过将其dwFlags成员设置KEYEVENTF_UNICODE就足以了。使用此方法,只需将KEYBDINPUT.wScan设置为字符的Unicode编码即可。对于英文字符,不须求关闭活动窗口的输入法;对于华语字符,也不须要活动窗口打开输入法和将字符转换为输入法编码。

MSDN对此措施的验证为:INPUT_KEYBOALANDD帮助非键盘的输入情势,例如手写识别或语音识别,通过KEYEVENTF_UNICODE标识,这个主意与键盘(文本)输入别无二致。若是钦命了KEYEVENTF_UNICODE,SendInput发送二个WM_KEYDOWN或WM_KEYUP信息给移动窗口的线程音信队列,音信的wParam参数为VK_PACKET。GetMessage或PeedMessage一旦获得此音信,就把它传递给TranslateMessage,TranslateMessage根据wScan中钦赐的Unicode字符发生2个WM_CHA汉兰达新闻。若窗口是ANSI窗口,则Unicode字符会自动转换为对应的ANSI字符。

其余索要向运动窗口输入字符(包括英文)的功用均应利用那种办法来兑现。事实上,键盘音信转换为字符新闻的经过是很复杂的,那只怕与键盘布局、区域、换档状态等诸多成分有关,那也是Windows要使用TranslateMessage来转换新闻的原因。由此,不应该总结透过击键事件来企图向活动窗口输入特定的字符。

经测试,SendInput还有三个值得注意的地点:

1.
没有为KEYBDINPUT.dwFlags指定KEYEVENTF_KEYUP标识时,SendInput将生成WM_KEYDOWN新闻,不然生成WM_KEYUP音讯,由于唯有WM_KEYDOWN会转换为字符音信,由此,若以输入字符为对象,则不应钦命KEYEVENTF_KEYUP标识。

2.
假设大家想达到实际做二反扑键所爆发的效应:顺序产生二个WM_KEYDOWN和一个WM_KEYUP事件。则必须各自以不点名KEYEVENTF_KEYUP和指定KEYEVENTF_KEYUP的方法实行贰次SendInput操作。SendInput允许在1遍调用中发送多个模拟新闻:

INPUT input[2];
memset(input, 0, 2 * 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));

但实质上,那将招致不产生别的音讯。那五个音信必须分离发送,如下所示:

INPUT input[2];
memset(input, 0, 2 * sizeof(INPUT));

input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = data;
SendInput(1, input, sizeof(INPUT));

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

SendInput(1, input + 1, sizeof(INPUT));

关于第叁点内容,小编很有疑点。因为事先有人在网上帖的代码是联合发送的,想必有人如此做过同时成功了。笔者不掌握是或不是与系统或任何因素有关。笔者也曾打算尝试化解此难点,但并未大功告成:

1.
基于MSDN,KEYBDINPUT.time是二个日子戳,若是为零,系统将运用它和谐的时日戳。因而笔者难以置信多个一块发送的事件,是否因为其时间戳相同,而被忽略掉了。于是笔者在上述代码中显式设置了该属性,再统一发送,结果仍然是尚未暴发别的消息。

2.
小编分别品尝了二种景况:合并发送的两条音信都未曾点名KEYEVENTF_KEYUP(期望获取多个一律的字符输入);合并发送的两条信息具有差别的虚拟键码且都不钦赐KEYEVENTF_KEYUP(期望获得多个不等的字符输入)。结果依旧还是退步,没有生出其余新闻。

自个儿不知道那是否意味:对于键盘输入,不允许将新闻合并发送。

若你精晓当中缘由或测试到与自家不相同的情景,请与本身联系:yedaoq@126.com

连带知识:

1.
输入法也得以处理SendInput发送的Unicode消息,具体措施不详。见MSDN中ImmGetProperty方法的参考:当dwIndex参数为IGP_PROPERTY时,IME_PROP_ACCEPT_WIDE_VKEY是一个可能的重返值,它代表IME会处理SendInput函数以VK_PACKET注入的Unicode字符,若重临值无该标识,则Unicode字符会直接发送给应用程序。 


http://xylvhp.blog.163.com/blog/static/31123614201101104644542/

在VC中运用SendInput函数实现中文的活动输入(ZZ)

2011-01-11 12:46:44| 分类: C++
|字号
订阅

第壹是,头文件必须包涵以下八个:
#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:
xmujava@163.com\t\n2010-05-21 \b\b”);
}
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

SendInput模拟键盘和鼠标事件

INPUT kbinput[5];
ZeroMemory( &kbinput, sizeof(INPUT)*5 );

kbinput[0].type = INPUT_KEYBOARD;
kbinput[0].ki.wVk = ‘Z’;

kbinput[1].type = INPUT_KEYBOARD;
kbinput[1].ki.wVk = ‘W’;

kbinput[2].type = INPUT_KEYBOARD;
kbinput[2].ki.wVk = ‘J’;
//kbinput[2].ki.dwFlags = KEYEVENTF_KEYUP;

kbinput[3].type=INPUT_MOUSE;
kbinput[3].mi.dx=100;
kbinput[3].mi.dy=100;
kbinput[3].mi.mouseData=0;
kbinput[3].mi.dwFlags=MOUSEEVENTF_RIGHTDOWN;

kbinput[4].type=INPUT_MOUSE;
kbinput[4].mi.dx=100;
kbinput[4].mi.dy=100;
kbinput[4].mi.mouseData=0;
kbinput[4].mi.dwFlags=MOUSEEVENTF_RIGHTUP;

UINT uRet = SendInput( 5, kbinput, sizeof(INPUT) ); 

 

相关文章