Qt模拟键盘点击分为两种情况:
情况一:模拟键盘输入到系统窗口,整个系统都接收这个模拟输入。
情况二:模拟键盘输入到指定的软件,只有指定的软件接收模拟输入。
情况一实现方式:
头文件:windows.h
使用
void keybd_event(BYTE bVk, BYTE bScan, DWORD dwFlags,DWORD dwExtraInfo);
参数:
第一个为按键的虚拟键值,如回车键为 vk_return, tab 键为 vk_tab(其他具体的参见附录:常用模拟键的键值对照表跟ASCII码表相同;
第二个参数为扫描码,一般不用设置,用 0 代替就行;
第三个参数为选项标志,如果为 keydown 则置 0 即可,如果为 keyup 则设成"KEYEVENTF_KEYUP";
第四个参数一般也是置 0 即可。
或者
Uint SendInput(UINT nInputs, LPINPUT pInputs, int cbSize );
参数:
nInput 指定ninput 数组中元素的个数。就是插入事件的个数。
pInput 指向一个类型为INPUT的数组变量,该数组中的每个元素代表一个将要插入到线程事件中去的键盘或鼠标事件。
cbSize 指定INPUT结构的大小。如果cbSize不是INPUT结构的大小,则函数将失败返回。
详细使用方法参考sendinput详细介绍
,ketbd_event详细介绍
代码示例:
例子1:模拟按下’A’键
keybd_event(65,0,0,0);
keybd_event(65,0,KEYEVENTF_KEYUP,0);
例子2:模拟按下’ALT+F4’键
keybd_event(18,0,0,0);
keybd_event(115,0,0,0);
keybd_event(115,0,KEYEVENTF_KEYUP,0);
keybd_event(18,0,KEYEVENTF_KEYUP,0);
例子3:单键输入
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));
}
例子4:多键输入
void keyboardTreeKey(unsigned short key1, unsigned short key2, unsigned short key3){
INPUT input[6];
memset(input, 0, sizeof(input));
input[0].type = input[1].type = input[2].type = input[3].type = input[4].type = input[5].type = INPUT_KEYBOARD;
input[0].ki.wVk = input[3].ki.wVk = key1;// VK_CONTROL;
input[1].ki.wVk = input[4].ki.wVk = key2;//VK_MENU;
input[2].ki.wVk = input[5].ki.wVk = key3;
input[3].ki.dwFlags = input[4].ki.dwFlags = input[5].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(6, input, sizeof(INPUT));
}
键盘命令分按下和抬起,都要传入,例如input[0]和input[3]代表key1的按下和抬起。
情况二实现方式:
头文件:windows.h
使用
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam;
参数:
hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息指定信息。
IParam:指定附加的消息指定信息。
返回值:返回值指定消息处理的结果,依赖于所发送的消息。
备注:需要用HWND_BROADCAST通信的应用程序应当使用函数RegisterWindowMessage来为应用程序间的通信取得一个唯一的消息。
例子1:模拟按下’A’键
HWND hwnd = 0;
for(int i = 0 ;i < 7;++i){
hwnd = FindWindow(NULL,L"yjd"); //获取指定程序yjd的窗口句柄
qDebug() << __FUNCTION__ << __LINE__ << hwnd;
if(hwnd != NULL){
break;
}
::Sleep(1000);
}
if (NULL != m_hwnd)
{
std::thread th([=](){ //单独启动一个线程进行数据传递
::SendMessage(m_hwnd, WM_SYSKEYDOWN, 65, 0)
});
th.detach();//传递结束后,进行关闭线程
}
例子2:模拟按下Shift+'A’键
HWND hwnd = 0;
for(int i = 0 ;i < 7;++i){
hwnd = FindWindow(NULL,L"yjd"); //获取指定程序yjd的窗口句柄
qDebug() << __FUNCTION__ << __LINE__ << hwnd;
if(hwnd != NULL){
break;
}
::Sleep(1000);
}
if (NULL != m_hwnd)
{
std::thread th([=](){ //单独启动一个线程进行数据传递
PostMessage(m_hwnd, WM_KEYDOWN, VK_SHIFT, 0x20380001);
PostMessage(m_hwnd, WM_KEYDOWN, 65, 0x20210001);
QThread::msleep(20);
// PostMessage(m_hwnd, WM_SYSCHAR, 65, 0x20210001);
PostMessage(m_hwnd, WM_SYSKEYUP, 65, 0xE0210001);
PostMessage(m_hwnd, WM_SYSKEYUP, VK_SHIFT, 0xC0380001);
});
th.detach();//传递结束后,进行关闭线程
}
这里使用的SendMessage,其实也可以使用PostMessage,它们的区别为:
主要在于是否等待其他程序消息处理。PostMessage只是把消息放入队列,不管其他程序是否处理都返回,然后继续执行;而SendMessage必须等待其他程序处理消息后才返回,继续执行。这两个函数的返回值也不同,PostMessage的返回值表示PostMessage函数执行是否正确,而SendMessage的返回值表示其他程序处理消息后的返回值,跟Qt的sendEvent和postEvent差不多的原理。
鼠标移动模拟,这里介绍鼠标针对整个系统窗口移动,想要实现限定到指定窗口移动暂时还没有思路。
SetCursorPos实现方式
POINT cp;
GetCursorPos(&cp); //获取光标位置
SetCursorPos(cp.x+3,cp.y); //设置光标位置
mouse_event实现方式
mouse_event(MOUSEEVENTF_MOVE,1,0,0,0); //默认相对于当前位置水平向右移动
1、鼠标左键按下和松开两个事件的组合即一次单击(右键类似):
mouse_event (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 )
2、两次连续的鼠标左键单击事件 构成一次鼠标双击事件:
mouse_event (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 )
mouse_event (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 )
3、使用绝对坐标移动鼠标:
mouse_event (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 500, 500, 0, 0)
需要说明的是,如果没有使用MOUSEEVENTF_ABSOLUTE,函数默认的是相对于鼠标当前位置的点,如果dx,和dy,用0,0表示,这函数认为是当前鼠标所在的点。
SendIput实现方式
INPUT input[1];
memset(input, 0, 1 * sizeof(INPUT));
input[0].type = INPUT_MOUSE;
input[0].mi.dx = 1;
input[0].mi.dy = 0;
input[0].mi.dwFlags = MOUSEEVENTF_MOVE;;
SendInput(1, input, sizeof(INPUT));
SendIputhe的dwFlags和mouse_event操作方式是一样的。
const int MOUSEEVENTF_MOVE = 0x0001; 移动鼠标
const int MOUSEEVENTF_LEFTDOWN = 0x0002; 模拟鼠标左键按下
const int MOUSEEVENTF_LEFTUP = 0x0004; 模拟鼠标左键抬起
const int MOUSEEVENTF_RIGHTDOWN = 0x0008; 模拟鼠标右键按下
const int MOUSEEVENTF_RIGHTUP = 0x0010; 模拟鼠标右键抬起
const int MOUSEEVENTF_MIDDLEDOWN = 0x0020; 模拟鼠标中键按下
const int MOUSEEVENTF_MIDDLEUP = 0x0040; 模拟鼠标中键抬起
const int MOUSEEVENTF_ABSOLUTE = 0x8000; 标示是否采用绝对坐标
为什么我没有使用PostMessage来实现,因为它们似乎是无效的。
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby数组,我们在StackOverflow上找到一
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参
当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?
是否可以为特定(或所有)项目使用多个布局?例如,我有几个项目,我想对其应用两种不同的布局。一个是绿色的,一个是蓝色的(但是)。我想将它们编译到我的输出目录中的两个不同文件夹中(例如v1和v2)。我一直在玩弄规则和编译block,但我不知道这是怎么回事。因为,每个项目在编译过程中只编译一次,我不能告诉nanoc第一次用layout1编译,第二次用layout2编译。我试过这样的东西,但它导致输出文件损坏。compile'*'doifitem.binary?#don’tfilterbinaryitemselsefilter:erblayout'layout1'layout'layout2'
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o