首页 > 技术文章 > 用Win32编写发送消息至Notepad++的程序

wh4am1 2018-03-31 09:16 原文

这次利用Win32编程写一个发送"Win32 Assembly,My First SendMessage Program !"

 

每个程序要发送消息至另一个程序的时候,通常使用SendMessage函数或PostMessage函数

两个函数的原型如下:

函数原型:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
参数:
hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息指定信息。
IParam:指定附加的消息指定信息。
返回值:返回值指定消息处理的结果,依赖于所发送的消息。

函数原型:PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
参数:
hWnd:其窗口程序将接收消息的窗口的句柄。
Msg:指定被发送的消息。
wParam:指定附加的消息指定信息。
IParam:指定附加的消息指定信息。
返回值:如果函数调用成功,返回非零,否则函数调用返回值为零。

 观看原型就会发现,程序发送时,需要指定函数的参数HWND hWnd。

也就是获取发送窗口的句柄(这里的句柄是指接受程序的窗口的句柄)。

 

利用spy++获取程序句柄

spy++是一款非常好用的工具,可以帮助程序员查看获取各种窗口的句柄以及类等。

打开之后,我们点击搜索->查找窗口->拖动查找工具到目标程序的窗口上

就会返回当前窗口的属性了

我们点击确定

找到后鼠标右键点击属性

找到类

这里的类名,就是我们等会要搜索句柄的参数。

 

利用类名查找窗口句柄

我们已经知道了窗口的类名

现在就利用FindWindow函数查看窗口的句柄

HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName);

 

lpClassName参数指向类名,lpWindowName指向窗口名,如果有指定的类名和窗口的名字则表示成功返回一个窗口的句柄。否则返回零。 invoke FindWindow,addr szNotepad,NULL

 

invoke FindWindow,addr szNotepad,NULL

 

现在有了句柄之后,就要查看程序的窗口客户区在哪(总不能让我发送到菜单栏吧~)。

这里为了方便,使用ChildWindowFromPoint函数做定位查找

函数原型:HWND ChildWindowFromPoint (HWND hWnd, LONG xPoint, LONG yPoint);
函数功能:返回父窗口中包含了指定点的第一个子窗口的句柄。
函数参数:hWnd 父窗口的句柄
xPoint 点的X坐标,以像素为单位
yPoint 点的Y坐标,以像素为单位
其中坐标参数指屏幕坐标
返回值:发现包含了指定点的第一个子窗口的句柄。如未发现任何窗口,则返回hWnd(父窗口的句柄)。如指定点位于父窗口外部,则返回零。

 

代码如下

invoke ChildWindowFromPoint,ecx,55,55

 

其中ecx为父窗口句柄

然后我们一个个字节的读入到累加器,再利用WM_CHAR消息发送。

当然,这得做个循环。

mov esi,_lpsz
@@:
lodsb
or al,al
jz @F
movzx eax,al
invoke PostMessage,@Notepad,WM_CHAR,eax,1
jmp @B
@@:

 

lodsb指令的作用是把ESI指向的存储单元读入到AL中去

其中,jz指令是为0则跳转

由于发送的字符串是以0结尾的,所以当字符串读完的时候,or al,al正好返回0

@F是向下一个@@标号跳转,@B则向上一个@@标号跳转。

整个程序代码如下:

;>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
;>>>>>>>包含文件>>>>>>>>
include windows.inc
include gdi32.inc
includelib gdi32.lib
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;>>>>>>>数据段>>>>>>>>
.data?
.const
szText db 'Win32 Assembly,My First SendMessage Program !',0
szNotFound db 'Notepad Process Not Start !',0
szSendOk db 'Send Message Successful !',0
szNotepad db 'Notepad++',0
szSendBox db 'System MessageBox',0
;>>>>>>>代码段>>>>>>>>
.code
;>>>>>>>发送到记事本>>>>>>>>
_SendMessage proc _lpsz
local @Notepad

pushad
xor eax,eax
invoke FindWindow,addr szNotepad,NULL
.if eax
mov ecx,eax
invoke ChildWindowFromPoint,ecx,55,55
.else
invoke MessageBox,NULL,offset szNotFound,offset szSendBox,MB_OK
.endif
.if eax
mov @Notepad,eax
mov esi,_lpsz
@@:
lodsb
or al,al
jz @F
movzx eax,al
invoke PostMessage,@Notepad,WM_CHAR,eax,1
jmp @B
@@:
invoke MessageBox,NULL,addr szSendOk,addr szSendBox,MB_OK
.endif
popad
ret
_SendMessage endp
;>>>>>>>主函数>>>>>>>>
start:
invoke _SendMessage,addr szText
invoke ExitProcess,NULL
;>>>>>>>程序结束>>>>>>>>
end start

 

 

代码中调用了MessageBox函数以验证是否发送成功。

 

推荐阅读