窗口间的通信(消息互发与数据传递)
来源:互联网 发布:协同过滤算法python包 编辑:程序博客网 时间:2024/06/07 11:05
一.窗口间的消息互发:
首先建立一个接收程序:ReceiveMessage.exe
代码:
.386.model flat,stdcalloption casemap:none;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; Include 文件定义;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>include windows.incinclude gdi32.incincludelib gdi32.libinclude user32.incincludelib user32.libinclude kernel32.incincludelib kernel32.lib;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 数据段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.data?szBuffer db 256 dup(?)hInstance dd ?hWinMain dd ?.constszCaptionMain db 'Receive Message',0 //收到消息后的语句szReceive db 'Receive WM_SETTEXT message',0dh,0ah db 'param: %08x',0dh,0ah db 'text: "%s"',0dh,0ahszClassNamedb'MyClass',0;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 代码段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.code;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 窗口过程;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>_ProcWinMain procuses ebx edi esi hWnd,uMsg,wParam,lParamlocal @stPs:PAINTSTRUCTlocal @stRect:RECTlocal @hDcmov eax,uMsg;********************************************************************.if eax ==WM_PAINTinvoke BeginPaint,hWnd,addr @stPsmov @hDc,eaxinvoke GetClientRect,hWnd,addr @stRectinvoke DrawText,@hDc,NULL,-1,\addr @stRect,\DT_SINGLELINE or DT_CENTER or DT_VCENTERinvoke EndPaint,hWnd,addr @stPs;********************************************************************.elseif eax == WM_CLOSEinvoke DestroyWindow,hWinMaininvoke PostQuitMessage,NULL .elseif eax == WM_SETTEXT //此处是当接收到WM_SETTEXT消息后的操作 invoke wsprintf,addr szBuffer,addr szReceive,lParam,lParam invoke MessageBox,hWnd,offset szBuffer,addr szCaptionMain,MB_OK;********************************************************************.elseinvoke DefWindowProc,hWnd,uMsg,wParam,lParamret.endif;********************************************************************xor eax,eaxret_ProcWinMain endp;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>_WinMain proclocal @stWndClass:WNDCLASSEXlocal @stMsg:MSGinvoke GetModuleHandle,NULLmov hInstance,eaxinvoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass;********************************************************************; 注册窗口类;********************************************************************invoke LoadCursor,0,IDC_ARROWmov @stWndClass.hCursor,eaxpush hInstancepop @stWndClass.hInstancemov @stWndClass.cbSize,sizeof WNDCLASSEXmov @stWndClass.style,CS_HREDRAW or CS_VREDRAWmov @stWndClass.lpfnWndProc,offset _ProcWinMainmov @stWndClass.hbrBackground,COLOR_WINDOW + 1mov @stWndClass.lpszClassName,offset szClassNameinvoke RegisterClassEx,addr @stWndClass;********************************************************************; 建立并显示窗口;********************************************************************invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\WS_OVERLAPPEDWINDOW,\100,100,600,400,\NULL,NULL,hInstance,NULLmov hWinMain,eaxinvoke ShowWindow,hWinMain,SW_SHOWNORMALinvoke UpdateWindow,hWinMain;********************************************************************; 消息循环;********************************************************************.while TRUEinvoke GetMessage,addr @stMsg,NULL,0,0.break .if eax == 0invoke TranslateMessage,addr @stMsginvoke DispatchMessage,addr @stMsg.endwret_WinMain endp;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>start:call _WinMaininvoke 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,stdcalloption casemap:none;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; Include 文件定义;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>include windows.incinclude gdi32.incincludelib gdi32.libinclude user32.incincludelib user32.libinclude kernel32.incincludelib kernel32.lib;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 数据段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.data?hInstance dd ?hWinMain dd ?szBuffer db 512 dup (?).constszClassName db'MyClass',0szCaptionMain db'Receive Message',0szReceive db 'Receive WM_COPYDATA message',0dh,0ahdb 'length: %08x',0dh,0ahdb 'text address: %08x',0dh,0ahdb 'text: "%s"',0dh,0ah,0;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 代码段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.code;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 窗口过程;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>_ProcWinMain procuses ebx edi esi,hWnd,uMsg,wParam,lParammov eax,uMsg;********************************************************************.if eax ==WM_CLOSEinvoke DestroyWindow,hWinMaininvoke PostQuitMessage,NULL;********************************************************************; 收到 WM_COPYDATA 消息将消息附带的数据长度和字符串数据显示出来;********************************************************************.elseif eax == WM_COPYDATAmov eax,lParamassume eax:ptr COPYDATASTRUCT ;注意此处invoke wsprintf,addr szBuffer,addr szReceive,\[eax].cbData,[eax].lpData,[eax].lpDatainvoke MessageBox,hWnd,offset szBuffer,addr szCaptionMain,MB_OKassume eax:nothing ;注意此处;********************************************************************.elseinvoke DefWindowProc,hWnd,uMsg,wParam,lParamret.endif;********************************************************************xor eax,eaxret_ProcWinMain endp;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>_WinMain proclocal @stWndClass:WNDCLASSEXlocal @stMsg:MSGinvoke GetModuleHandle,NULLmov hInstance,eaxinvoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass;********************************************************************; 注册窗口类;********************************************************************invoke LoadCursor,0,IDC_ARROWmov @stWndClass.hCursor,eaxpush hInstancepop @stWndClass.hInstancemov @stWndClass.cbSize,sizeof WNDCLASSEXmov @stWndClass.style,CS_HREDRAW or CS_VREDRAWmov @stWndClass.lpfnWndProc,offset _ProcWinMainmov @stWndClass.hbrBackground,COLOR_WINDOW + 1mov @stWndClass.lpszClassName,offset szClassNameinvoke 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,NULLmov hWinMain,eaxinvoke ShowWindow,hWinMain,SW_SHOWNORMALinvoke UpdateWindow,hWinMain;********************************************************************; 消息循环;********************************************************************.while TRUEinvoke GetMessage,addr @stMsg,NULL,0,0.break .if eax == 0invoke TranslateMessage,addr @stMsginvoke DispatchMessage,addr @stMsg.endwret_WinMain endp;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>start:call _WinMaininvoke ExitProcess,NULL;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>end start
接收窗口就是在一个基本的窗口模板的窗口过程中添加自定义操作,但是有两处需要注意,那就是在代码的窗口过程中出现的两处assume语句(代码种右边注释处),第一个assume语句相于设定把通用寄存器eax与结构COPYDATASTRUCT关联起来(个人感觉就像宏定义,等同),如后面的语句用eax代替COPYDATASTRUCT结构使用结构中的成员;第二个assume语句就是取消第一个assume的设定
接下来建立发送窗口:
代码:
.386.model flat,stdcalloption casemap:none;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; Include 文件定义;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>include windows.incinclude user32.incincludelib user32.libinclude kernel32.incincludelib kernel32.lib;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 数据段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.datahWnd dd ?szBuffer db 512 dup (?)stCopyData COPYDATASTRUCT <>szCaption db 'SendMessage',0szStart db 'Press OK to start SendMessage, text address: %08x!',0szReturn db 'SendMessage returned!',0szDestClass db'MyClass',0;目标窗口的窗口类szText db 'Text send to other windows',0szNotFound db 'Receive Message Window not found!',0;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 代码段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.codestart:invoke FindWindow,addr szDestClass,NULL ;注意此处.if eaxmov hWnd,eax;找到目标窗口则发送消息invoke wsprintf,addr szBuffer,addr szStart,addr szTextinvoke MessageBox,NULL,offset szBuffer,offset szCaption,MB_OKmov stCopyData.cbData,sizeof szTextmov stCopyData.lpData,offset szTextinvoke SendMessage,hWnd,WM_COPYDATA,0,addr stCopyDatainvoke MessageBox,NULL,offset szReturn,offset szCaption,MB_OK.elseinvoke MessageBox,NULL,offset szNotFound,offset szCaption,MB_OK.endifinvoke ExitProcess,NULL;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>end start
点击确定:
点击确定:
上面是发送窗口及截图,注意API函数FindWindow()的使用
到此窗口间的数据传送结束。
- 窗口间的通信(消息互发与数据传递)
- 窗口间的消息传递
- JS 子窗口与父窗口间的数据传递
- JS 子窗口与父窗口间的数据传递
- 窗口消息的传递
- C#进程间通信,传递消息给其它窗口
- 子窗口与父窗口的消息传递
- 子窗口与父窗口的消息传递
- windows 消息机制、窗口过程与线程间消息传递
- windows 消息机制、窗口过程与线程间消息传递
- 窗口消息的传递(一)
- 窗口消息的传递(二)
- VC 窗口创建以及窗口之间传递数据、传递消息(模态、非模态)
- VC 窗口创建以及窗口之间传递数据、传递消息(模态、非模态)
- VC 窗口创建以及窗口之间传递数据、传递消息(模态、非模态)
- MFC (通过WM_COPYDATA消息) 进程间通信以及数据传递
- 父窗口与子窗口的数据传递问题
- 数据、消息的传递
- BZOJ3223文艺平衡树
- 118. Pascal's Triangle
- 文章标题
- C++中值传递、指针传递、引用传递的总结
- Android多媒体播放器 MediaPlayer使用
- 窗口间的通信(消息互发与数据传递)
- Android 时间轴的实现
- 【杭电-oj】-2020-绝对值排序(冒泡排序注意第二个for ,负数变正数但原变量值不变可先平方)
- HDU 1257SDOI(贪心)
- 2016校招百度美团360机器学习岗面试经历
- HTML5上传图片及其相关知识点
- CodeForces 219D-H - Choosing Capital for Treeland-树DP
- python类、对象、方法、属性之类与对象笔记
- HDU 1074The Highest Mark(状压DP)