窗口间的数据通信之消息通信
Windows窗口之间的通信有多种方式,据我所知的就有:通过Socket、互发消息、剪贴板等,我用Win32 ASM演示了通过互发消息进行通信的两种方式,一种方式通过发送WM_SETTEXT,进行简单的字符串的通信;一种方式通过WM_COPYDATA的方 式进行复杂数据通信。
演示程序和代码下载:
WinComunication.zip (6.3 KiB, 453 hits)
程序界面:

接收端的CallBack:
- ;窗口回调函数
_WndProc proc hwnd:HWND,msg:UINT, wParam:WPARAM, lParam:LPARAM
;local RecCDS:COPYDATASTRUCT
mov eax,msg
.if eax == WM_CREATE
invoke CreateWindowEx,0,offset szEditClass, 0,WS_CHILD or WS_VISIBLE or WS_VSCROLL or ES_LEFT or ES_MULTILINE or ES_AUTOVSCROLL, 0, 0, 0, 0, hwnd, IDEDIT, hInstance, 0
mov hEditWnd,eax
invoke _SetFont,eax
.elseif eax == WM_SETTEXT
invoke SendMessage, hEditWnd, EM_SETSEL, -1, -1
invoke SendMessage, hEditWnd, EM_REPLACESEL, 0, lParam
.elseif eax == WM_COPYDATA
mov ebx,lParam
invoke SendMessage, hEditWnd, EM_SETSEL, -1, -1;invoke SendMessage, hEditWnd, EM_REPLACESEL, 0, [ ebx + COPYDATASTRUCT.lpData ] ; 可有用这种方式定位结构体
;也可以用这种方式定位结构体
assume ebx:ptr COPYDATASTRUCT
invoke SendMessage, hEditWnd, EM_REPLACESEL, 0, [ ebx ].lpData
assume ebx:nothing.elseif eax == WM_CLOSE
invoke DestroyWindow,hwnd
invoke PostQuitMessage,0
.elseif eax == WM_SIZE
mov eax,lParam
mov bx,ax
shr eax,16
invoke MoveWindow, hEditWnd, 1, 1, ebx, eax, TRUE
.else
invoke DefWindowProc,hwnd,msg,wParam,lParam
ret
.endif
xor eax,eax
ret
_WndProc endp
发送端的CallBack:
- ;窗口回调函数
_CallWnd proc hwnd:HWND, msg:UINT, wParam:WPARAM, lParam:LPARAM
local SendCDS:COPYDATASTRUCT
mov eax,msg.if eax == WM_CREATE
invoke CreateWindowEx,0,CTEXT(“BUTTON”),CTEXT(“WM_SETTEXT发送”),\
WS_CHILD or WS_VISIBLE, 125,80,150,30,hwnd, IDM_BTN_SETTEXT,hInstance,0invoke _SetFont,eax
invoke CreateWindowEx,0,CTEXT(“BUTTON”),CTEXT(“WM_COPYDATA发送”),\
WS_CHILD or WS_VISIBLE, 125,150,150,30,hwnd, IDM_BTN_COPYDATA,hInstance,0invoke _SetFont,eax
call _CheckTarget
.elseif eax == WM_COMMAND;SetText按钮按下
.if wParam == IDM_BTN_SETTEXT
call _CheckTarget
.if hTargetWin != 0
invoke SendMessage, hTargetWin, WM_SETTEXT,0,offset szSetText_Data
;invoke MessageBox, 0, CTEXT(“我发送了WM_SETTEXT到接收端”),CTEXT(“信息”),0
.endif
.endif;CopyData按钮按下
.if wParam == IDM_BTN_COPYDATA
call _CheckTarget
.if hTargetWin != 0
invoke RtlZeroMemory,addr SendCDS,sizeof COPYDATASTRUCTinvoke _GetStringLen,offset szCopyData_Data
mov SendCDS.cbData ,eax
mov SendCDS.lpData ,offset szCopyData_Data
invoke SendMessage, hTargetWin, WM_COPYDATA,hwnd,addr SendCDS
;invoke MessageBox, 0, CTEXT(“我发送了WM_CopyData到接收端”),CTEXT(“信息”),0
.endif
.endif
.elseif eax == WM_CLOSE
invoke DestroyWindow,hwnd
invoke PostQuitMessage,0
.else
invoke DefWindowProc,hwnd,msg,wParam,lParam
ret
.endif
xor eax,eax
ret
_CallWnd endp
通过这个小程序学不到以下几点,感觉不错呵呵:
1.提高手写Asm代码的熟练程序,除了查看一下WNDCLASS的几个结构成员的名子外,在不查考其他什么资料的情况下,已经能将Win32 SDK框架窗口代码写出来了。为了提高手写熟练的锻练我暂时停用Aogo MASMPlus了,改用SlickEdit进行手写。等熟练后再使用MasmPlus,这是个很不错的工具。
2.让我明白原来窗口程序和对话框程序有很大的不同,比如CreateWindowsEx建立窗口程序,就不执行WM_InitDIALOG这个消息。这一点让大牛老K同志狠狠BS了一顿,失败。做Windows程序这么多年了,居然这一点还不知道。
3.在ASM中写子程序总是忘记在最后ret,总是让程序给跑飞了。这个问题上一次就吃过苦了。还是老忘记,都者写惯了C/C++的结果,希望下次不要再出现。
4.明白了结构在ASM中两表示方式。参见接收端的CallBack。
5.PostMessage是不能进行WM_COPYDATA进行数据共享的。