汇编教程:管道
2008-10-14 09:35:35 来源:WEB开发网现在有趣的事来了,我们将改变此 Edit 控件的文本颜色和背景色。当 Edit 控件将要重画客户区时,它会给父窗口发送 WM_CTLCOLOREDIT 消息。参数 wParam 包含了用于画控件自己的客户区设备描述符的句柄 (HDC) 。我们可以利用这种机制来修改 HDC 的特性。
.elseif uMsg==WM_CTLCOLOREDIT
invoke SetTextColor,wParam,Yellow
invoke SetTextColor,wParam,Black
invoke GetStockObject,BLACK_BRUSH
ret
SetTextColor 把文本颜色变为黄色,背景颜色变为黑色。最后我们返回一个通过调用GetStockObject 而得到黑色刷子的句柄。处理WM_CTLCOLOREDIT 必须返回一个刷子的句柄,因为 Windows 将要使用这个刷子来重画 Edit 控件的背景。在这个例子中,我希望背景是黑色,所以返回了一个黑色刷子的句柄。
现在当用户选择 Assemble 子菜单时,就会创建一个匿名管道。
.if ax==IDM_ASSEMBLE
mov sat.niLength,sizeof SECURITY_ATTRIBUTES
mov sat.lpSecurityDescriptor,NULL
mov sat.bInheritHandle,TRUE
在调用CreatePipe 之前,必须要填写SECURITY_ATTRIBUTES 结构。如果我们不关心安全性的话,可以在lpSecurityDescriptor 成员中填入 NULL 。bInheritHandle 则必须为 TRUE ,这样管道的句柄才可以被子进程继承。本文来自编程入门网
invoke CreatePipe,addr hRead,addr hWrite,addr sat,NULL
在此之后,我们调用CreatePipe 来创建管道,如果成功,那么变量hRead 和 hWrite 将分别被填入相应的管道的读出端和写入端的句柄。
mov startupinfo.cb,sizeof STARTUPINFO
invoke GetStartupInfo,addr startupinfo
mov eax, hWrite
mov startupinfo.hStdOutput,eax
mov startupinfo.hStdError,eax
mov startupinfo.dwFlags, STARTF_USESHOWWINDOW+ STARTF_USESTDHANDLES
mov startupinfo.wShowWindow,SW_HIDE
下一步就是填写STARTUPINFO 结构了。调用 GetStartupinfo 用父进程的缺省值来填写STARTUPINFO 结构。如果要使程序同时工作在 Windows9x 和 Windows NT 下,就必须调用GetStartupInfo 来填写STARTUPINFO 结构。调用返回后,就可以修改重要的成员了。因为我们要子进程输出到父进程而不是缺省的标准输出和标准错误,所以我们把hStdOutput 和 hStdError 都赋成管道写端的句柄。为了隐藏子进程的主窗口,必须把成员变量wShowWidow 赋值为SW_HIDE 。最后通过把成员 dwFlags 赋值为STARTF_USESHOWWINDOW 和 STARTF_USESTDHANDLES 来指明成员hStdOutput, hStdError 和 wShowWindow 是有效的。
invoke CreateProcess, NULL, addr CommandLine, NULL, NULL, TRUE, NULL, NULL, NULL, addr startupinfo, addr pinfo
现在调用CreateProcess 来创建子进程。注意为使管道工作,参数bInheritHandles 必须设置为TRUE。 invoke CloseHandle,hWrite 成功创建子进程之后,在父进程中必须关闭管道的写端。我们已经把写端的句柄通过结构STARTUPINFO 传给了子进程。如果不关闭,那么管道就有两个写入端,而这样的管道是不会工作的。所以必须在创建子进程后但在读数据前关闭这个句柄。
.while TRUE
invoke RtlZeroMemory,addr buffer,1024
invoke ReadFile,hRead,addr buffer,1023,addr bytesRead,NULL
.if eax==NULL
.break
.endif
invoke SendMessage,hwndEdit,EM_SETSEL,-1,0
invoke SendMessage,hwndEdit,EM_REPLACESEL,FALSE,addr buffer
.endw
现在已经准备好从子进程的标准输出读数据了。直到再也没有数据了,即 ReadFile 返回为 NULL时才会退出循环,否则一直会等待数据。我们调用ReadFile 之前先调用RtlZeroMemory 来清空内存,并且用管道的读句柄代替文件句柄。注意读数据的最大长度为 1023 ( sizeof(buffer)-1 ),因为我们需要把接受的字符变为一个 Edit 控件可以处理的 ASCII 串。当ReadFile 返回时,就把此数据传给 Edit 控件。然而这有一个小小的问题,如果使用SetWindowText API 往 Edit 控件中写数据,新数据就会覆盖已存在的旧数据,而我们想把新数据添加在已有数据的后面。为达此目的,首先通过发送一个 wParam 为-1的 EM_SETSEL 消息,把 Edit 控件的输入焦点移动到文本的末端;然后发送一个 EM_REPLACESEL 消息把数据添加后面。
invoke CloseHandle,hRead
当ReadFile 返回为NULL时,就跳出循环并关闭管道的读句柄。
更多精彩
赞助商链接