对于不同应用程序之间的窗口中可以互发消息 方法是通过SendMessage 或者PostMessage 函数,用法为:
invoke PostMessage,hWnd,Msg,wParam,lParam
invoke SendMessage,hWnd,Msg,wParam,lParam
对于WM_SETTEXT来说 wParam=0 lParam=(LPARAM)(LPCTSTR)lpsz
首先拷贝FirstWindow中的代码 在回调函数中加入以下代码:
.elseif eax == WM_SETTEXTinvoke wsprintf,addr szBuffer,addr szReceive,\
lParam,lParam
invoke MessageBox,hWnd,offset szBuffer,addr szCaptionMain,MB_OK
同时在数据段中加上下列定义:
szCaptionMain db 'Receive Message',0
szReceive db 'Receive WM_SETTEXT message',0dh,0ah
db 'param: %08x',0dh,0ah
db 'text: "%s"',0dh,0ah,0
调用如下语句:
invoke wsprintf,addr szBuffer,addr szReceive,lParam,lParam
将收到的结果存放到szBuffer中 然后将szBuffer中的内容在一个消息框中显示出来:
invoke MessageBox,hWnd,offset szBuffer,addr szCaptionMain,MB_OK
接收程序就写好了
下面来写发送程序;
发送程序利用FindWindow函数找到接收窗口的窗口句柄,FindWindow函数使用方法是:
invoke FindWindow,lpClassName,lpWindowName
.if eax
mov hWin,eax
.endif
send.exe源代码如下:;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 2nd Edition>
; by 罗云彬, http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Send.asm
; 从一个程序向另一个窗口程序发送消息 之 发送程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Send.asm
; Link /subsystem:windows Send.obj
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.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 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
receive.exe
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 2nd Edition>
; by 罗云彬, http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Receive.asm
; 从一个程序向另一个窗口程序发送消息 之 消息接收程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Receive.asm
; Link /subsystem:windows Receive.obj
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.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',0
szReceive db 'Receive WM_SETTEXT message',0dh,0ah
db 'param: %08x',0dh,0ah
db 'text: "%s"',0dh,0ah,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain proc uses ebx edi esi,hWnd,uMsg,wParam,lParam
mov eax,uMsg
;********************************************************************
.if eax == WM_CLOSE
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
;********************************************************************
; 收到 WM_SETTEXT 消息则将消息字符串和字符串地址显示出来
;********************************************************************
.elseif eax == WM_SETTEXT
invoke wsprintf,addr szBuffer,addr szReceive,\
lParam,lParam
invoke 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:MSG
invoke 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,\
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
课件字符串正确的传了过来 但是地址却不是发送地址。因为当Windows在处理SendMessage的时候检查消息类型 发现发送的的消息参数是一个指针的时候。Windows对指针指向的内容更进行一些处理,以便能够正常的传递进目标进程中。
Windows首先创建一块共享内存,并将WM_SETTEXT消息lParam指向的字符串拷贝到该内存中,然后在发消息到其他进程,并将共享内存在目标进程中的地址发送给目标窗口过程,目标窗口郭城处理完消息后 函数返回 共享内存释放。(内存映射文件技术)
为了能够在不同进程的窗口间自由地任意拷贝任意类型的数据。windows提供了一个特殊消息 WM_COPYDATA
COPYDATASTRUCT STRUCT
dwData DWORD ?;附加字段
cbData DWORD ?;数据长度
lpData DWORD ?;数据位置指针
COPYDATASTRUCT ENDS
.data
stCopyData COPYDATASTRUCT <>
.code
...
invoke SendMessage,hDestWnd,WM_COPYDATA,hWnd,addr stCopyData
hDestWnd为目标窗口句柄 wParam指定为hWnd 是当前窗口的句柄 lParam 指向已经填充完毕的COPYDATASTRUCT
SendMessage 和 PostMessage的区别
对于普通消息 两者几乎没有区别,但对于WM_SETTEXT WM_COPYDATA等在参数中用到指针的消息来说 两者就有所不同
当用PostMessage函数实现上述消息时,会发现根本接收不到消息,这是因为,当消息参数中用到指针时,用PostMessage函数来发送消息都不会成功。该函数不能用于任何参数中用到指针的消息、