网站首页 > 技术文章 正文
SendMessage函数会一点程序的人都知道,它的意思就是向窗口发送消息.向本地进程创建的窗口发送消息.SendMessage的操作会很简单:它只是将指定的窗口过程作为子程序来调用.当窗口过程处理完消息后,会向SendMessage返回一个值。SendMessage再向调用线程返回应该值。
然而,如果一个线程将消息发送给其它线程创建的窗口,SendMessage会复杂很多。Windows会要求创建窗口线程处理消息。因此调用SendMessage不一定会成功。因为我们发送消息有关的数据不在其它线程中,不过你的消息会追加到被调用线程窗口的消息队列中。可能有时你用SendMessage向其它程序成功的发送过消息的经验。对我也有过。因为成功了,所以就没深入一点研究过。
现在用SendMessage修改我我正在编辑文本的记事本的窗口标题
Dim strTitle as String
strTitle="How are you"
Call SendMessage(FindWindow("Notepad","text.txt - Notepad"),WM_SETTEXT,0,strTitle)
咦成功了,stTitle不是在自己的进程空间吗?记事本程序怎么能访问我的地址空间呢?答案是当调用SendMessage时,该函数中的代码要检查是事发送一个WM_SETTEXT消息。如果是,它将地址空间中以0结尾的字符串放到一个内存映射文件中。该内存映射文件将被其它进程所共享。然后它将消息发送到其它进程的线程。当接受线程准备好处理WM_SETTEXT消息时,它确定包含新窗口标题副本的,被共享的内存映射文件在其自己的的地址的空间位置。不过大多数消息不需要这样的处理,只有在进程间发送数据才这样。
那是不是进程间发送消息都会这样建立一个共享的内存映射文件呢,答案是否定的。尤其是在自己定义的消息时。这个时候怎么办呢?一种方法是用WM_COPYDATA消息,一种方法可以用ReadProcessMemory和WriteProcessMemory函数从其它进程读取数据和写入数据
WM_COPYDATA消息是一个特殊的消息同进它与一个特殊的结构体一起使用。来看看这个结构体的形式
Public Type COPYDATASTRUCT
dwData As Long
cbData As Long
lpData As Long
End Type
其中cbData 成员指定了你想要发送给其它进程的字节数,lpData指定要发送的数据的第一个字节地址,dwData成员留给自己用。当SendMessage 看到正在发送的的WM_COPYDATA消息时,它创建一个大小为cbData字节的内存映射文件,并且将数据从你的地址空间复制到该内存映射文件中,然后将消息发送到目标窗口,当接受窗口处理该消息时,lParam参数指向一个存在于接收进程地空间的COPYDATASTRUCT结构。应该结构的lpData成员指向接收进程的地址空间中的共享内存。
现在我们讨论第二种方法,这种方法主要是在其它进程中开避一段内存区域,怎么开避就要用到VirtualAllocEx这个函数了.现在我们用一个实例说明一下,在运行中输入msconfig 打开我们的配置,选择启动项选项卡看看有些什么启动项,现在我就要让全部启动项不不钩选上。
pHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, ProcessID)
'先在远程进程中分配内存
pMyItemMemory = VirtualAllocEx(pHandle, 0, Len(myItem), MEM_COMMIT, PAGE_READWRITE)
'做好读取和改变ListView中Item项目属性的工作
myItem.Mask = LVIF_STATE
myItem.iItem = pRow
myItem.StateMask = -1
'把属性写入远程进程
Result = WriteProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), szInByte)
'向远程进程发送消息
retValue = SendMessage(hWindow, LVM_GETITEM, 0, ByVal pMyItemMemory)
'把读取的远程进程写入本地缓冲区
Result = ReadProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), szOutByte)
'修改读取后的信息
myItem.State = (myItem.State And (Not LVIS_STATEIMAGEMASK)) Or &H1000
'把读取后的信息写入远程进程
Result = WriteProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), szInByte)
'向远程进程发送消息
Result = SendMessage(hWindow, LVM_SETITEM, 0, ByVal pMyItemMemory)
'释放分配的远程内存
Result = VirtualFreeEx(pHandle, pMyItemMemory, 0, MEM_RELEASE)
Result = CloseHandle(pHandle)
猜你喜欢
- 2024-09-21 5分钟了解Handler错误使用场景(handlerexecution)
- 2024-09-21 魔兽世界:不会用宏的快来看 教你入门宏命令 老油条请评论区补充
- 2024-09-21 老外给你发“sorry,WC”,你知道他说的是什么意思吗?
- 2024-09-21 面试官:你来简单回答一下RocketMQ的默认发送流程
- 2024-09-21 Spring Boot 集成RocketMQ:使用模板类发送和消费延时消息
- 2024-09-21 记一次 .NET某医疗器械清洗系统 卡死分析
- 2024-09-21 Spring Boot+RocketMQ 实现多实例分布式环境下的事件驱动
- 2024-09-21 聊聊rocketmq的ExtProducerResetConfiguration
- 1514℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 569℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 510℃MySQL service启动脚本浅析(r12笔记第59天)
- 486℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 485℃启用MySQL查询缓存(mysql8.0查询缓存)
- 467℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 446℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 444℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)