C#使用SendMessage发送组合键

有时需要出发菜单功能,例如发送ALT + F打开应用程序的文件菜单,如何使用SendMessage实现呢?

使用用spy++截取的ALT+F的消息内容(如何使用spy++,请熟悉的高手指点下,我使用spy++ lite没有得到):
<00001> 000310DC P WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:0 fAltDown:1 fRepeat:0 fUp:0
<00002> 000310DC P WM_SYSKEYDOWN nVirtKey:'F' cRepeat:1 ScanCode:21 fExtended:0 fAltDown:1 fRepeat:0 fUp:0
<00003> 000310DC P WM_SYSCHAR chCharCode:'102' (102) cRepeat:1 ScanCode:21 fExtended:0 fAltDown:1 fRepeat:0 fUp:0
<00004> 000310DC P WM_SYSKEYUP nVirtKey:'F' cRepeat:1 ScanCode:21 fExtended:0 fAltDown:1 fRepeat:1 fUp:1
<00005> 000310DC P WM_KEYUP nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:0 fAltDown:0 fRepeat:1 fUp:1

 

转换为 SendMessage

[DllImport("user32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(IntPtr hwnd, int wMsg, uint wParam, uint lParam);

 

SendMessage(hwnd, 0x0104, 0x00000012, 0x20380001);//(0x00000012 == VK_MENU(ALT键))
SendMessage(hwnd, 0x0104, 0x00000046, 0x20210001);//这一行可以省略(0x00000046 == 'F')

SendMessage(hwnd, 0x0106, 0x00000066, 0x20210001);//发送一个char 'f'
SendMessage(hwnd, 0x0105, 0x00000046, 0xE0210001);//这一行可以省略(0x00000046 == 'F')
SendMessage(hwnd, 0x0105, 0x00000012, 0xC0380001);//(0x00000012 == VK_MENU(ALT键))

 

过程是这样的: 

首先 发送了一个 ALT按下 //(WM_SYSKEYDOWN == 0x0104)

然后 发送了一个 'F'键      //这里省略可以实现同样功能 系统兼容性问题 建议发送这个键

然后 发送了一个 字符'f'    //(WM_SYSCHAR == 0x0106)

然后 抬起按键     'F'键     //这里省略可以实现同样功能 系统兼容性问题 建议发送这个键

最后 抬起按键     ALT键    //(WM_SYSKEYUP == 0x0105)

 

要实现类似功能 比如 ALT + a 可以这么写

SendMessage(hwnd, 0x0104, 0x00000012, 0x20380001);//0x00000012可以写成0x12
SendMessage(hwnd, 0x0104, 0x00000041, 0x201E0001);//0x00000041可以写成0x41

SendMessage(hwnd, 0x0106, (int)'a', 0x20210001);// (把char转换为 int 或者API声明时传递参数wParam为char) 
SendMessage(hwnd, 0x0105, 0x00000041, 0xE01E0001);//0x00000041 == 'A'
SendMessage(hwnd, 0x0105, 0x00000012, 0xC0380001);//

 

下面列举一下键盘按键对应值:

//Windows 使用的256个虚拟键码
public const int VK_LBUTTON = 0x1
public const int VK_RBUTTON = 0x2
public const int VK_CANCEL = 0x3
public const int VK_MBUTTON = 0x4
public const int VK_BACK = 0x8
public const int VK_TAB = 0x9
public const int VK_CLEAR = 0xC
public const int VK_RETURN = 0xD
public const int VK_SHIFT = 0x10
public const int VK_CONTROL = 0x11
public const int VK_MENU = 0x12
public const int VK_PAUSE = 0x13
public const int VK_CAPITAL = 0x14
public const int VK_ESCAPE = 0x1B
public const int VK_SPACE = 0x20
public const int VK_PRIOR = 0x21
public const int VK_NEXT = 0x22
public const int VK_END = 0x23
public const int VK_HOME = 0x24
public const int VK_LEFT = 0x25
public const int VK_UP = 0x26
public const int VK_RIGHT = 0x27
public const int VK_DOWN = 0x28
public const int VK_Select = 0x29
public const int VK_PRINT = 0x2A
public const int VK_EXECUTE = 0x2B
public const int VK_SNAPSHOT = 0x2C
public const int VK_Insert = 0x2D
public const int VK_Delete = 0x2E
public const int VK_HELP = 0x2F
public const int VK_0 = 0x30
public const int VK_1 = 0x31
public const int VK_2 = 0x32
public const int VK_3 = 0x33
public const int VK_4 = 0x34
public const int VK_5 = 0x35
public const int VK_6 = 0x36
public const int VK_7 = 0x37
public const int VK_8 = 0x38
public const int VK_9 = 0x39
public const int VK_A = 0x41
public const int VK_B = 0x42
public const int VK_C = 0x43
public const int VK_D = 0x44
public const int VK_E = 0x45
public const int VK_F = 0x46
public const int VK_G = 0x47
public const int VK_H = 0x48
public const int VK_I = 0x49
public const int VK_J = 0x4A
public const int VK_K = 0x4B
public const int VK_L = 0x4C
public const int VK_M = 0x4D
public const int VK_N = 0x4E
public const int VK_O = 0x4F
public const int VK_P = 0x50
public const int VK_Q = 0x51
public const int VK_R = 0x52
public const int VK_S = 0x53
public const int VK_T = 0x54
public const int VK_U = 0x55
public const int VK_V = 0x56
public const int VK_W = 0x57
public const int VK_X = 0x58
public const int VK_Y = 0x59
public const int VK_Z = 0x5A
public const int VK_STARTKEY = 0x5B
public const int VK_CONTEXTKEY = 0x5D
public const int VK_NUMPAD0 = 0x60
public const int VK_NUMPAD1 = 0x61
public const int VK_NUMPAD2 = 0x62
public const int VK_NUMPAD3 = 0x63
public const int VK_NUMPAD4 = 0x64
public const int VK_NUMPAD5 = 0x65
public const int VK_NUMPAD6 = 0x66
public const int VK_NUMPAD7 = 0x67
public const int VK_NUMPAD8 = 0x68
public const int VK_NUMPAD9 = 0x69
public const int VK_MULTIPLY = 0x6A
public const int VK_ADD = 0x6B
public const int VK_SEPARATOR = 0x6C
public const int VK_SUBTRACT = 0x6D
public const int VK_DECIMAL = 0x6E
public const int VK_DIVIDE = 0x6F
public const int VK_F1 = 0x70
public const int VK_F2 = 0x71
public const int VK_F3 = 0x72
public const int VK_F4 = 0x73
public const int VK_F5 = 0x74
public const int VK_F6 = 0x75
public const int VK_F7 = 0x76
public const int VK_F8 = 0x77
public const int VK_F9 = 0x78
public const int VK_F10 = 0x79
public const int VK_F11 = 0x7A
public const int VK_F12 = 0x7B
public const int VK_F13 = 0x7C
public const int VK_F14 = 0x7D
public const int VK_F15 = 0x7E
public const int VK_F16 = 0x7F
public const int VK_F17 = 0x80
public const int VK_F18 = 0x81
public const int VK_F19 = 0x82
public const int VK_F20 = 0x83
public const int VK_F21 = 0x84
public const int VK_F22 = 0x85
public const int VK_F23 = 0x86
public const int VK_F24 = 0x87
public const int VK_NUMLOCK = 0x90
public const int VK_OEM_SCROLL = 0x91
public const int VK_OEM_1 = 0xBA
public const int VK_OEM_PLUS = 0xBB
public const int VK_OEM_COMMA = 0xBC
public const int VK_OEM_MINUS = 0xBD
public const int VK_OEM_PERIOD = 0xBE
public const int VK_OEM_2 = 0xBF
public const int VK_OEM_3 = 0xC0
public const int VK_OEM_4 = 0xDB
public const int VK_OEM_5 = 0xDC
public const int VK_OEM_6 = 0xDD
public const int VK_OEM_7 = 0xDE
public const int VK_OEM_8 = 0xDF
public const int VK_ICO_F17 = 0xE0
public const int VK_ICO_F18 = 0xE1
public const int VK_OEM102 = 0xE2
public const int VK_ICO_HELP = 0xE3
public const int VK_ICO_00 = 0xE4
public const int VK_ICO_CLEAR = 0xE6
public const int VK_OEM_RESET = 0xE9
public const int VK_OEM_JUMP = 0xEA
public const int VK_OEM_PA1 = 0xEB
public const int VK_OEM_PA2 = 0xEC
public const int VK_OEM_PA3 = 0xED
public const int VK_OEM_WSCTRL = 0xEE
public const int VK_OEM_CUSEL = 0xEF
public const int VK_OEM_ATTN = 0xF0
public const int VK_OEM_FINNISH = 0xF1
public const int VK_OEM_COPY = 0xF2
public const int VK_OEM_AUTO = 0xF3
public const int VK_OEM_ENLW = 0xF4
public const int VK_OEM_BACKTAB = 0xF5
public const int VK_ATTN = 0xF6
public const int VK_CRSEL = 0xF7
public const int VK_EXSEL = 0xF8
public const int VK_EREOF = 0xF9
public const int VK_PLAY = 0xFA
public const int VK_ZOOM = 0xFB
public const int VK_NONAME = 0xFC
public const int VK_PA1 = 0xFD
public const int VK_OEM_CLEAR = 0xFE

 

按照以上对照表 写快捷键 CTRL + F :

 

SendMessage(hwnd, 0x0104, 0x11, 0x20380001);//0x11 == VK_CONTROL == ALT键

SendMessage(hwnd, 0x0104, (int)'F', 0x20210001);//

SendMessage(hwnd, 0x0106, (int)'f', 0x20210001);// 
SendMessage(hwnd, 0x0105, (int)'F', 0xE0210001);//
SendMessage(hwnd, 0x0105, 0x11, 0xC0380001);//

 

忘记说了 关于参数 lParam 是这么说的:

Parameters

nVirtKey 
Value of  wParam. Specifies the virtual-key code of the key being pressed. 
lKeyData 
Value of  lParam. Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown in the following table. 
ValueDescription
0–15Specifies the repeat count for the current message. The value is the number of times the keystroke is auto-repeated as a result of the user holding down the key. If the keystroke is held long enough, multiple messages are sent. However, the repeat count is not cumulative.
16–23Specifies the scan code. The value depends on the original equipment manufacturer (OEM).
24Specifies whether the key is an extended key, such as the right-hand alt and ctrl keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.
25–28Reserved; do not use.
29Specifies the context code. The value is 1 if the ALT key is down while the key is pressed; it is 0 if the WM_SYSKEYDOWN message is posted to the active window because no window has the keyboard focus.
30Specifies the previous key state. The value is 1 if the key is down before the message is sent, or it is 0 if the key is up.
31Specifies the transition state. The value is always 0 for a WM_SYSKEYDOWN message.

 

0-15位:指定当前消息的重复次数。其值就是用户按下该键后自动重复的次数,但是重复次数不累积
16-23位:指定其扫描码,其值依赖于OEM厂商
24位:指定该按键是否为扩展按键,所谓扩展按键就是Ctrl,Alt之类的,如果是扩展按键,其值为1,否则为0 
25-28位:保留字段,暂时不可用 
29位:指定按键时的上下文,其值为1时表示在按键时Alt键被按下,其值为0表示WM_SYSKEYDOWN消息因没有任何窗口有键盘焦点而被发送到当前活动窗口。 
30位:指定该按键之前的状态,其值为1时表示该消息发送前,该按键是被按下的,其值为0表示该消息发送前该按键是抬起的。 
31位:指定其转换状态,对WM_SYSKEYDOWN消息而言,其值总为0。

 

具体可以参考 http://msdn.microsoft.com/zh-cn/library/ms646286(en-us,VS.85).aspx 

如果你想知道这些参数的含义 你可以直接输入1 就可以了表示按键的次数

 

lParam资讯

在四个按键讯息(WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN和WM_SYSKEYUP)中,wParam讯息参数含有上面所讨论的虚拟键码,而lParam讯息参数则含有对了解按键非常有用的其他资讯。lParam的32位分为6个栏位,如图所示。
  在Win 3.x中,WPARAM是16位的,而LPARAM是32位的,两者有明显的区别。因为地址通常是32位的,所以LPARAM被用来传递地址,这个习惯在Win32 API中仍然能够看到。在Win32 API中,WPARAM和LPARAM都是32位,所以没有什么本质的区别。Windows的消息必须参考帮助文件才能知道具体的含义。如果是你定义的消息,愿意怎么使这两个参数都行。但是习惯上,我们愿意使用LPARAM传递地址,而WPARAM传递其他参数。
以上方法可以打开主菜单上的第一层菜单如文件(F),但是文件下面的二级菜单采用此方法无效果,请熟悉的高手指点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/37635.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手把手教程:解除AppleID「双重验证」

大家好&#xff0c;我是可夫小子&#xff0c;关注AIGC、读书和自媒体。解锁更多ChatGPT、AI绘画玩法。加&#xff1a;keeepdance&#xff0c;备注&#xff1a;chatgpt&#xff0c;拉你进群。 在前面的文章中&#xff0c;我共享了两个美区ID给大家下载ChatGPT App&#xff0c;可…

Web前端工程师-优秀简历汇总

分享一下我老师大神的人工智能教程&#xff01;零基础&#xff0c;通俗易懂&#xff01;http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章。分享知识&#xff0c;造福人民&#xff0c;实现我们中华民族伟大复兴&#xff01; Web前端工程师-优秀简历汇总 1. http://ww…

xpath爬取智联招聘--大数据开发职位并保存为csv

先上项目效果图&#xff1a; 本次爬取的URL为智联招聘的网址&#xff1a;https://www.zhaopin.com/ 首先先登录上去&#xff0c;为了保持我们代码的时效性&#xff0c;让每个人都能直接运行代码出结果&#xff0c;我们要获取到我们登录上去的cookies&#xff0c;并把他放在表头…

用python爬取前程无忧网大数据岗位信息并分析

爬虫的基本思路 1、在前程无忧官网检索“大数据”的结果中&#xff0c;每条检索结果详情对应的URL存在a标签的href属性中&#xff0c;通过组合选择器可以找到每条检索结果详情的URL。 2、前程无忧的招聘岗位信息数据固定的放在HTML的各个标签内&#xff0c;通过id选择器、标签…

前端工程师简历

总结一下 理解Web,W3C标准 (一淘,SAE,云适配,Zealer,小米,蘑菇街,DNSpod,百姓网) jQuery (云适配,金蚕网络,小米) 跨浏览器适配 (一淘,Zealer,蘑菇街,) HTML5 (云适配,小米,金蚕网络,DNSPod,新浪手机微博) Web语义化 (云适配) 后端语言或经验 (一淘,云适配,小米,金蚕) Ba…

人工智能简历-计算机视觉简历

前言 很多粉丝私我&#xff0c;说面试的事情。 这玩意我不理解&#xff0c;因为如果是计算机科班出身&#xff0c;计算机行业我觉得闭着眼睛找。 简历这玩意我真不会。。。 分享2个东西给大家。 第一个是 出国/在国外找实习/外企的英文简历。 比较流行的是一页。 第二个…

基于requests+pyecharts的前程无忧工作岗位可视化分析

今年大学毕业生预计突破900万大关。 每年毕业的大学生数量是在逐年增加。 根据教育部最新官方数据&#xff0c;预测明年也就是2021年我国高校毕业生人数将达到909万人&#xff0c;首次突破900万人&#xff01;到2022年&#xff0c;我国高校毕业生人数将超过1000万人&#xff01…

全网首次拆解前端简历,合格的简历长这样...

刷脉脉常遇见各种留帖&#xff0c;内容无非两种&#xff1a;吐槽简历只读不回&#xff0c;面试屡次被挂&#xff01; 同是前端人&#xff0c;理解大家的不易。替那些工作 2~3 年还写不好简历的前端干着急。 前些天&#xff0c;就挂掉了一个工作 3 年的前端。他的简历就可以当作…

一个Web前端实习生的简历

以下是我大三时候做的简历&#xff0c;其中“基础信息”中的链接全都失效了&#xff0c;其中好多技术现在都不会&#xff0c;还各种“熟悉”、“精通”&#xff0c;当年真的很能装啊????哈哈哈。 职业信息 姓名 XXX 电话 XXXXXXXXXXX 坐标 南京 NanJing 邮箱 XXXXX…

简历自动化抓取,一键get百份求职简历

这次我们就来聊一聊实用性比较高的爬虫案例:简历自动化抓取,一键get百份求职简历。 本次爬取非常顺利,本以为会遇到几个反爬措施,除了定位遇到几个小坑之外,其余地方皆是一帆风顺,值得提一下的地方主要就是下载链接的随机抓取,会更好的具有拟态磨合从而使效率略高(本来…

【大数据实战】招聘网站职位分析

通过采集招聘网站大数据职位信息、利用数据清洗、数据分析、jieba分词、数据挖掘完成整体项目的开发工作。任务包含爬取招聘网站大数据职位信息、使用BeautifulSoup清洗职位信息网页、使用PySpark对智联数据进行分析、对招聘职位信息进行探索分析、使用结巴分词对岗位描述进行分…

自动化测试岗位求职简历编写规范+注意事项,让你的简历脱颖而出

目录 前言 1.个人信息 2.教育背景(写最高学历) 3.个人技能(按精通/掌握/熟练/了解层次来写) 4.工作经历 5.工作经验/项目经历 6.自我评价 总结 前言 挑选一个阅读舒适度不错的模板 HR和面试官看的简历多&#xff0c;都是快速阅读&#xff0c;舒适度特别重要&#xff1b…

360笔试——校招

目录 试题 参考答案 试题

投递简历总是石沉大海?HR表现的机会都不给你?【Python爬虫实战:简历模板采集】

简历模板下载 工具准备项目思路解析简易源码分享 工具准备 数据来源: 站长素材 开发环境&#xff1a;win10、python3.7 开发工具&#xff1a;pycharm、Chrome 项目思路解析 找到进入详情页面的超链接地址&#xff0c;以及对应简历的名字 提取出参数信息 使用xpath语法的时候…

如何用python主抓取股市数据并分析?

导读&#xff1a;在本文中我们研究白酒股票市场的数据。使用baostock来获取股票信息&#xff0c;可视化它们的不同&#xff0c;最后将使用一些方法来分析股票的风险&#xff0c;基于其以前的历史表现。我们还将通过长期短期记忆(LSTM)方法来预测未来的股票价格。注意&#xff0…

选出均线组合多头排列的牛股!股票量化分析工具QTYX-V2.5.6

前言 有些大牛股启动后会以连续快速的风格&#xff0c;开启一轮势不可挡的上涨。 我们来看下“中油资本”这只票上涨中期的特征。我们观察它的形态特征会发现&#xff0c;它的均线系统以多头排列姿态快速发散。在出现这种形态的初期买入的话&#xff0c;上涨效应很强。 于是&am…

cisp-pte通关靶场思路分享

文章写在cisp-pte通关靶场思路分享

15.PDE和PTE属性

一、PDE PTE 结构 低12位是权限位。 低1位是P位&#xff0c;P1代表有效&#xff0c;P0代表无效 低2位是RW位&#xff0c;RW0表示只读&#xff0c;RW1表示可读可写。 低3位是U/S位&#xff0c;U/S1表示用户及超级用户都可以操作页表&#xff0c;U/S0表示只有超级用户可以操作…

Windows保护模式学习笔记(七)—— PDEPTE

Windows保护模式学习笔记&#xff08;七&#xff09;—— PDE&PTE Cr3PDE&#xff08;页目录表项&#xff09;PTE&#xff08;页表项&#xff09;物理页的属性10-10-12分页的补充 实验1&#xff1a;证明PTE的特征1第一步&#xff1a;选择一个进程的Cr3第二步&#xff1a;查…

PTE学习作业

##被攻击者服务器为Linux&#xff1a;加粗样式 1.基础题目之SQL注入 所谓SQL注入&#xff0c;就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串&#xff0c;最终达到欺骗服务器执行恶意的SQL命令。 通过SQL注入漏洞读取/tmp/360/key文件,答案就在文件中。 …