窗口间的通信(消息互发与数据传递)

来源:互联网 发布:协同过滤算法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()的使用

到此窗口间的数据传送结束。

1 0
原创粉丝点击