窗口间的通信(消息互发与数据传递)
一.窗口间的消息互发:
首先建立一个接收程序:ReceiveMessage.exe
代码:
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include gdi32.inc
includelib gdi32.lib
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
szBuffer db 256 dup(?)
hInstance dd ?
hWinMain dd ?.const
szCaptionMain db 'Receive Message',0 //收到消息后的语句
szReceive db 'Receive WM_SETTEXT message',0dh,0ahdb 'param: %08x',0dh,0ahdb 'text: "%s"',0dh,0ah
szClassNamedb'MyClass',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain procuses ebx edi esi hWnd,uMsg,wParam,lParam
local @stPs:PAINTSTRUCT
local @stRect:RECT
local @hDcmov eax,uMsg
;********************************************************************
.if eax ==WM_PAINT
invoke BeginPaint,hWnd,addr @stPs
mov @hDc,eaxinvoke GetClientRect,hWnd,addr @stRect
invoke DrawText,@hDc,NULL,-1,\
addr @stRect,\
DT_SINGLELINE or DT_CENTER or DT_VCENTERinvoke EndPaint,hWnd,addr @stPs
;********************************************************************
.elseif eax == WM_CLOSE
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL.elseif eax == WM_SETTEXT //此处是当接收到WM_SETTEXT消息后的操作invoke wsprintf,addr szBuffer,addr szReceive,lParam,lParaminvoke MessageBox,hWnd,offset szBuffer,addr szCaptionMain,MB_OK
;********************************************************************
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
;********************************************************************
xor eax,eax
ret_ProcWinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WinMain proc
local @stWndClass:WNDCLASSEX
local @stMsg:MSGinvoke GetModuleHandle,NULL
mov hInstance,eax
invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
;********************************************************************
; 注册窗口类
;********************************************************************
invoke LoadCursor,0,IDC_ARROW
mov @stWndClass.hCursor,eax
push hInstance
pop @stWndClass.hInstance
mov @stWndClass.cbSize,sizeof WNDCLASSEX
mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW
mov @stWndClass.lpfnWndProc,offset _ProcWinMain
mov @stWndClass.hbrBackground,COLOR_WINDOW + 1
mov @stWndClass.lpszClassName,offset szClassName
invoke RegisterClassEx,addr @stWndClass
;********************************************************************
; 建立并显示窗口
;********************************************************************
invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\
WS_OVERLAPPEDWINDOW,\
100,100,600,400,\
NULL,NULL,hInstance,NULL
mov hWinMain,eax
invoke ShowWindow,hWinMain,SW_SHOWNORMAL
invoke UpdateWindow,hWinMain
;********************************************************************
; 消息循环
;********************************************************************
.while TRUE
invoke GetMessage,addr @stMsg,NULL,0,0
.break .if eax == 0
invoke TranslateMessage,addr @stMsg
invoke DispatchMessage,addr @stMsg
.endw
ret_WinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
call _WinMain
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
如下图所示:
下面建立发送消息的程序SendMessage.exe
代码:
.386
.model flat,stdcall
option casemap:none
;*******************************************
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;*******************************************
.data
hWnd dd ?
szBuffer db 256 dup(?)
;*******************************************
.const
szCaption db 'SendMessage',0
szStart db 'Press OK to start SendMessage,param: %08x!',0
szReturn db 'SendMessage returned!',0
szDestClass db 'MyClass',0
szText db 'Text send to other windows',0
szNotFound db 'Receive Message Window not found!',0
;*******************************************
.code
start:
invoke FindWindow,addr szDestClass,NULL
.if eax
mov hWnd,eax
invoke wsprintf,addr szBuffer,addr szStart,addr szText
invoke MessageBox,NULL,offset szBuffer,\
offset szCaption,MB_OK
invoke SendMessage,hWnd,WM_SETTEXT,0,addr szText
invoke MessageBox,NULL,offset szReturn,\
offset szCaption,MB_OK
.else
invoke MessageBox,NULL,offset szNotFound,\
offset szCaption,MB_OK
.endif
invoke ExitProcess,NULL
;*******************************************
end start
运行如下图所示:
点击确定:
点击确定:
点击确定退出程序。
上面是简单介绍了在两个窗口间发送消息的过程,下面来分析一下两个程序:
首先是接收窗口:首先借用了WINDOWS的一个基本窗口模板,建立一个基本窗口,只需要在该程序的窗口过程中(即回调函数中)自定义添加当收到WM_SETTEXT消息后做出的操作即可,也没有其他什么东西。
然后就是发送窗口:在发送窗口中首先需要用到一个需要清楚的API函数:
FindWindow()
功能:
这个函数检索处理顶级窗口的类名和窗口名称匹配指定的字符串,如果有指定的类名和窗口的名字则表示成功返回一个窗口的句柄
原型:
HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName);参数:lpClassName指向一个以null结尾的、用来指定类名的字符串或一个可以确定类名字符串的原子。如果这个参数是一个原子,那么它必须是一个在调用此函数前已经通过GlobalAddAtom函数创建好的全局原子。这个原子(一个16bit的值),必须被放置在lpClassName的低位字节中,lpClassName的高位字节置零。如果该参数为null时,将会寻找任何与lpWindowName参数匹配的窗口。lpWindowName指向一个以null结尾的、用来指定窗口名(即窗口标题)的字符串。如果此参数为NULL,则匹配所有窗口名。返回值:如果函数执行成功,则返回值是拥有指定窗口类名或窗口名的窗口的句柄。如果函数执行失败,则返回值为 NULL 知道这个函数的功能就可以理解运用此函数通过字符串‘MyClass’找到目标窗口,利用SendMessage()函数向目标窗口发送消息,当目标窗口的消息循环机制接收到消息后,等待消息机制的处理,然后由WINDOWS调用回调函数(提前定义好的子函数_ProcWinMain)然后根据自定义操作执行,到此窗口间的消息互发成功结束。
二.下面介绍窗口间的数据传递,在WM_SETTEXT这一类的消息中,windows可以将参数所指的字符串传递到目标窗口的过程中,但是这些消息都有他们的本职工作,并且传递的数据也只限于以0结尾的字符串。为了能够在不同进程的窗口见自由的拷贝任意类型的数据,,windows提供了一个特殊的窗口消息——WM_COPYDATA。
WM_COPYDATA消息用一个COPYDATASTRUCT结构来描述要拷贝的数据的长度和位置:
COPYDATASTRUCT STRUCT
dwData DWORD ? ;附加字段
cbData DWORD ? ;数据长度
lpData DWORD ? ;数据位置指针
COPYDATASTRUCT ENDS
其中dwData字段是一个备用字段,可以存放任何值,例如,我们有可能向另外的进程发送数据的同时用一个数字来表示数据的数据类型,此时就可以用上这个字段;cbData字段用来描述需要拷贝的数据的长度(字节)
lpData用来描述要发送的数据的指针。填充好数据结构后,用SendMessage函数就可以将数据发送给目标窗口过程:
.data
stCopyData COPYDATASTRUCT<>
.code
...
invoke SendMessage,hDestWnd,WM_COPYDATA,hWnd,addr stCopyData
当windos收到WM_COPYDATA消息后,会根据cbData字段的长度建立共享内存区,并且将lpData所指向的数据拷贝到共享内存区,然后定位共享内存中的数据在目标进程中的地址,将该地址存放到COPYDATASTRUCT中的lpData字段中去,然后将变更后的COPYDATASTRUCT结构发送到目标进程中去,目标进程可以通过结构中的lpData字段查找到定位数据。目标窗口过程返回后,windows释放掉共享内存,SendMessage函数返回。
上面介绍了窗口间传送数据的方法过程,下面用代码实现:
首先建立接收窗口:
代码:
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include gdi32.inc
includelib gdi32.lib
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?hInstance dd ?
hWinMain dd ?
szBuffer db 512 dup (?).const
szClassName db'MyClass',0
szCaptionMain db'Receive Message',0szReceive db 'Receive WM_COPYDATA message',0dh,0ah
db 'length: %08x',0dh,0ah
db 'text address: %08x',0dh,0ah
db 'text: "%s"',0dh,0ah,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain procuses ebx edi esi,hWnd,uMsg,wParam,lParammov eax,uMsg
;********************************************************************
.if eax ==WM_CLOSE
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
;********************************************************************
; 收到 WM_COPYDATA 消息将消息附带的数据长度和字符串数据显示出来
;********************************************************************
.elseif eax == WM_COPYDATA
mov eax,lParam
assume eax:ptr COPYDATASTRUCT ;注意此处
invoke wsprintf,addr szBuffer,addr szReceive,\
[eax].cbData,[eax].lpData,[eax].lpData
invoke MessageBox,hWnd,offset szBuffer,addr szCaptionMain,MB_OK
assume eax:nothing ;注意此处
;********************************************************************
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
;********************************************************************
xor eax,eax
ret_ProcWinMain endp;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WinMain proc
local @stWndClass:WNDCLASSEX
local @stMsg:MSGinvoke GetModuleHandle,NULL
mov hInstance,eax
invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
;********************************************************************
; 注册窗口类
;********************************************************************
invoke LoadCursor,0,IDC_ARROW
mov @stWndClass.hCursor,eax
push hInstance
pop @stWndClass.hInstance
mov @stWndClass.cbSize,sizeof WNDCLASSEX
mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW
mov @stWndClass.lpfnWndProc,offset _ProcWinMain
mov @stWndClass.hbrBackground,COLOR_WINDOW + 1
mov @stWndClass.lpszClassName,offset szClassName
invoke RegisterClassEx,addr @stWndClass
;********************************************************************
; 建立并显示窗口
;********************************************************************
invoke CreateWindowEx,WS_EX_CLIENTEDGE or WS_EX_TOPMOST,offset szClassName,offset szCaptionMain,\
WS_OVERLAPPEDWINDOW,\
50,50,200,150,\
NULL,NULL,hInstance,NULL
mov hWinMain,eax
invoke ShowWindow,hWinMain,SW_SHOWNORMAL
invoke UpdateWindow,hWinMain
;********************************************************************
; 消息循环
;********************************************************************
.while TRUE
invoke GetMessage,addr @stMsg,NULL,0,0
.break .if eax == 0
invoke TranslateMessage,addr @stMsg
invoke DispatchMessage,addr @stMsg
.endw
ret_WinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
call _WinMain
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
接收窗口就是在一个基本的窗口模板的窗口过程中添加自定义操作,但是有两处需要注意,那就是在代码的窗口过程中出现的两处assume语句(代码种右边注释处),第一个assume语句相于设定把通用寄存器eax与结构COPYDATASTRUCT关联起来(个人感觉就像宏定义,等同),如后面的语句用eax代替COPYDATASTRUCT结构使用结构中的成员;第二个assume语句就是取消第一个assume的设定
接下来建立发送窗口:
代码:
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
hWnd dd ?
szBuffer db 512 dup (?)
stCopyData COPYDATASTRUCT <>szCaption db 'SendMessage',0
szStart db 'Press OK to start SendMessage, text address: %08x!',0
szReturn db 'SendMessage returned!',0
szDestClass db'MyClass',0;目标窗口的窗口类
szText db 'Text send to other windows',0
szNotFound db 'Receive Message Window not found!',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
start:
invoke FindWindow,addr szDestClass,NULL ;注意此处
.if eax
mov hWnd,eax;找到目标窗口则发送消息
invoke wsprintf,addr szBuffer,addr szStart,addr szText
invoke MessageBox,NULL,offset szBuffer,offset szCaption,MB_OK
mov stCopyData.cbData,sizeof szText
mov stCopyData.lpData,offset szText
invoke SendMessage,hWnd,WM_COPYDATA,0,addr stCopyData
invoke MessageBox,NULL,offset szReturn,offset szCaption,MB_OK
.else
invoke MessageBox,NULL,offset szNotFound,offset szCaption,MB_OK
.endif
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
点击确定:
点击确定:
上面是发送窗口及截图,注意API函数FindWindow()的使用
到此窗口间的数据传送结束。
窗口间的通信(消息互发与数据传递)相关推荐
- SuperSocket 入门,实现客户端和服务端消息互发
源码地址:SuperSocket入门,实现客户端和服务端消息互发_supersocket客户端实现,supersocket客户端-C#代码类资源-CSDN下载 运行出来效果如下: 服务端: 客户端: ...
- mfc获取子窗口句柄_前端设计-JavaScript中父窗口与子窗口间的通信
父窗体与子窗体之间的通信 在之前文章讲解windows程序设计过程中,我们曾描述了windows程序窗口之间通信与控制实现方法与过程,如窗体之间参数传递等.本文主要从Web程序开发前端JavaScri ...
- python多窗口传递信息_PyQT5 中两个界面之间数据传递
在使用PyQT5做GUI桌面应用程序设计时,经常需要对在两个界面之间做信号的传递,这个时候我们需要通过建立信号pyqtSignal 然后通过Connect 相应的槽函数来完成界面之间的数据传递. 1. ...
- linux 环境下的进程间的通信——消息队列传输结构体
linux 环境下的进程间的通信方式主要有:管道,有名和无名管道, 这种方式适用于具有亲缘关系的进程之间的通信: 信号: 消息队列: 共享内存: 信号量: 套接字: 这次主要涉及消息队列: 1. 需要 ...
- MFC为窗口创建线程,以及线程与窗口间的通信
1.定义向线程传递的参数类型,例如(可以根据自己的需要来定义): struct t_DebugerThreadParam {HWND m_hMainWnd;HWND m_hDebugerWnd;CSt ...
- 一个服务器端和多个客户端消息互发_python:OSError: [WinError 10022] 提供了一个无效的参数...
在使用socket模块进行编程时,如果不注意,很容易就遇到[OSError: [WinError 10022] 提供了一个无效的参数]这个错误.我在网上查阅了资料,通过自己的验证,出现这个错误是因为在 ...
- 使用WM_COPYDATA消息在不同进程间或窗口间通信传递数据
WM_COPYDATA消息类型属于windows系统标准消息类型,主要用于进程间或不同窗口间进行信息传递,使用此消息的同时在接收端需要重写窗口的消息处理函数DefWndProc,以便读取消息内容. 为 ...
- 浅析 postMessage 方法介绍、如何接收数据(监听message事件及其属性介绍)、使用postMessage的安全注意事项、具体使用方式(父子页面如何互发消息、接收消息)
postMessage 是 html5 引入的API,postMessage()方法允许来自不同源的脚本采用异步方式进行有效的通信,可以实现跨文本文档.多窗口.跨域消息传递,多用于窗口间数据通信,这也 ...
- 【GO语言】实现同步传输系统:局域网内手机和电脑互传文件互发消息。go语言练手项目
GO语言实现同步传输系统:局域网内手机和电脑互传文件互发消息 项目总览: 一.项目功能展示 1.用手机传输文件到电脑 2.用手机传输图片到电脑 3.用电脑传输文字到手机 4.服务器显示情况,端口信息: ...
- 如何实现服务器转发客户端消息,socket 怎么实现服务器与客户端不停的互发消息呢?...
在 java Socket应用的 3-4节 我把老师的代码修改了一下可以手动输入文字让对面的服务器/客户端接受, 下面是代码: //客户端 package 通讯; import java.io.Buf ...
最新文章
- mysql union all 别名_MySQL Union合并查询数据及表别名、字段别名用法分析
- 在Linux(Ubuntu)下搭建ASP.NET Core环境并运行 继续跨平台
- ES6新特性5:类(Class)和继承(Extends)
- windows内核试验05_中断现场
- 存clob为空的值_给Oracle数据库中CLOB字段插入空值
- tmux命令启动MySQL_tmux启动脚本
- 使用canvas绘制动画时钟
- 蓝字冲销是什么意思_梦见上学 做梦梦到上学是什么意思 梦到上学有哪些预兆...
- xp如何快速锁定计算机,Window XP中快速锁定计算机两法
- Spring| BeanCurrentlyInCreationException: Error creating bean with name ‘‘xxx“
- 【LOJ】#3123. 「CTS2019 | CTSC2019」重复
- CSS3与页面布局学习总结(八)——浏览器兼容与前端性能优化
- 添加Copy To和Move To 到系统右键菜单中(Vista 也适用)
- android iphone字体,网站中的字体设置--兼容苹果、pc、安卓系统的字体设置
- B. Shashlik Cooking
- (一)数字图像处理基础知识点
- 计算机的隐藏功能应用,电脑也有隐藏功能, 你知道吗?
- 家族关系查询系统程序设计算法思路_大数据结构课程设计(家族关系查询系统)要点...
- Fluent报错cl-set-default-save-dir: path does not exist.
- LUNA崩了背后的原因
热门文章
- win10如何打开摄像头_win10系统,蓝牙关闭,如何打开?
- python创建数据集_python 生成环形人工数据集
- 新安装的apache无法解析php,apache无法解析php
- 页码太靠上怎么办_醉酒后难受怎么办?酸奶、解酒药都不靠谱,最实用的还是3个方法...
- vue调用日期_Vue 前端开发——打印功能实现
- 最大后验估计_极大似然估计 V.S. 贝叶斯估计
- 小程序仿微视_争抢流量!腾讯微视也要开始搞短视频带货
- linux安装mysql_Linux学习笔记-安装MySQL
- mysql索引小结_[数据库]mysql索引小结_星空网
- acm运行时错误_计人即讯|ACM纳新赛