📄 lion-tut-c14.htm
字号:
<BR><B>
invoke EnableMenuItem,hMenu,IDM_CREATE_PROCESS,MF_GRAYED</B>
<BR><B>
invoke EnableMenuItem,hMenu,IDM_TERMINATE,MF_ENABLED</B>
<BR><B>
.else</B>
<BR><B>
invoke EnableMenuItem,hMenu,IDM_CREATE_PROCESS,MF_ENABLED</B>
<BR><B>
invoke EnableMenuItem,hMenu,IDM_TERMINATE,MF_GRAYED</B>
<BR><B>
.endif</B> <BR><B> .else</B>
<BR><B> invoke
EnableMenuItem,hMenu,IDM_CREATE_PROCESS,MF_ENABLED</B>
<BR><B> invoke
EnableMenuItem,hMenu,IDM_TERMINATE,MF_GRAYED</B>
<BR><B> .endif</B>
<BR><B> .ELSEIF uMsg==WM_COMMAND</B>
<BR><B> mov eax,wParam</B>
<BR><B> .if lParam==0</B>
<BR><B> .if
ax==IDM_CREATE_PROCESS</B>
<BR><B>
.if processInfo.hProcess!=0</B>
<BR><B>
invoke CloseHandle,processInfo.hProcess</B>
<BR><B>
mov processInfo.hProcess,0</B>
<BR><B>
.endif</B>
<BR><B>
invoke GetStartupInfo,ADDR startInfo</B>
<BR><B>
invoke CreateProcess,ADDR programname,NULL,NULL,NULL,FALSE,\</B>
<BR><B>
NORMAL_PRIORITY_CLASS,\</B>
<BR><B>
NULL,NULL,ADDR startInfo,ADDR processInfo</B>
<BR><B>
invoke CloseHandle,processInfo.hThread</B>
<BR><B>
.elseif ax==IDM_TERMINATE</B>
<BR><B>
invoke GetExitCodeProcess,processInfo.hProcess,ADDR ExitCode</B>
<BR><B>
.if ExitCode==STILL_ACTIVE</B>
<BR><B>
invoke TerminateProcess,processInfo.hProcess,0</B>
<BR><B>
.endif</B>
<BR><B>
invoke CloseHandle,processInfo.hProcess</B>
<BR><B>
mov processInfo.hProcess,0</B>
<BR><B>
.else</B>
<BR><B>
invoke DestroyWindow,hWnd</B>
<BR><B>
.endif</B> <BR><B> .endif</B>
<BR><B> .ELSE</B>
<BR><B> invoke
DefWindowProc,hWnd,uMsg,wParam,lParam</B>
<BR><B> ret</B>
<BR><B> .ENDIF</B> <BR><B>
xor eax,eax</B> <BR><B> ret</B>
<BR><B>WndProc endp</B> <BR><B>end start</B>
<H3><FONT
color=#ff0000>分析:</FONT></H3>应用程序创建主窗口,保存菜单句柄以备后用。当用户在主菜单中选择了“Process”菜单项后,消息处理过程中接收到WM_INITMENUPOPUP消息,我们在此处修改弹出式菜单中的菜单项的“使能”和“非使能”,以便同一菜单有不同的显示。
<P><B> .ELSEIF uMsg==WM_INITMENUPOPUP</B>
<BR><B> invoke
GetExitCodeProcess,processInfo.hProcess,ADDR ExitCode</B>
<BR><B> .if eax==TRUE</B>
<BR><B> .if
ExitCode==STILL_ACTIVE</B>
<BR><B>
invoke EnableMenuItem,hMenu,IDM_CREATE_PROCESS,MF_GRAYED</B>
<BR><B>
invoke EnableMenuItem,hMenu,IDM_TERMINATE,MF_ENABLED</B>
<BR><B>
.else</B>
<BR><B>
invoke EnableMenuItem,hMenu,IDM_CREATE_PROCESS,MF_ENABLED</B>
<BR><B>
invoke EnableMenuItem,hMenu,IDM_TERMINATE,MF_GRAYED</B>
<BR><B>
.endif</B> <BR><B> .else</B>
<BR><B> invoke
EnableMenuItem,hMenu,IDM_CREATE_PROCESS,MF_ENABLED</B>
<BR><B> invoke
EnableMenuItem,hMenu,IDM_TERMINATE,MF_GRAYED</B>
<BR><B> .endif</B>
<P>我们之所以处理该消息的目的就是让菜单显示时有不同的外观以方便用户的使用。譬如;新进程尚未运行时,我们就变亮(使能)“菜单项“start
process”,而变灰(非使能)菜单项“terminate
process”。当新进程运行起来后,菜单的外观就应该是相反的。<BR>首先我们调用GetExitCodeProcess函数,其中传入由CreateProcess返回的句柄。如果GetExitCodeProcess返回FALSE,则表示进程尚未运行,我们就让菜单项“terminate
process”变灰;如果返回TRUE,表示新进程已经启动了,我们再检测是否正在运行,这通过比较ExitCode是否等于STILL_ACTIVE
来完成,如果相等,表示进程仍在运行,我们就让菜单项“start process”变灰,因为在我们的简单的应用程序中不提供同时运行多个进程的能<FONT
size=-1>力。 </FONT>
<P><B> .if
ax==IDM_CREATE_PROCESS</B>
<BR><B>
.if processInfo.hProcess!=0</B>
<BR><B>
invoke CloseHandle,processInfo.hProcess</B>
<BR><B>
mov processInfo.hProcess,0</B>
<BR><B>
.endif</B>
<BR><B>
invoke GetStartupInfo,ADDR startInfo</B>
<BR><B>
invoke CreateProcess,ADDR programname,NULL,NULL,NULL,FALSE,\</B>
<BR><B>
NORMAL_PRIORITY_CLASS,\</B>
<BR><B>
NULL,NULL,ADDR startInfo,ADDR processInfo</B>
<BR><B>
invoke CloseHandle,processInfo.hThread</B> <BR> <BR>当用户选择了菜单项“start
process”时,我们先检测结构体PROCESS_INFORMATION中的成员变量hPRocess是否已经关闭。如果是第一次启动应用程序,那该变量为0,因为我们在.data分段定义结构体时已经初始化该值为0。如果该值不为0,则表明新进程已经结束,但是我们尚未关闭该进程的句柄(以减少该进程的引用记数),我们在此处完成该动作。<BR>我们调用GetStartupInfo函数来填充启动信息的结构体变量,而该变量将被传递到CreateProcess函数中去。调用CreateProcess生成新进程,我们不检查该函数的返回值为的是让问题简化一些,在实际应用中,必须做该项工作。在调用CreateProcess后,我们立即关闭在进程信息结构体参数中返回的主线程句柄,关闭线程句柄为的是减少该内核对象的引用记数,否则即使该线程退出后,其内核对象仍惨存在内核中得不到释放,这会引起资源泄露。进程其实也是一样,之所以我们不在该处关闭进程的句柄是因为稍后我们还要用该句柄去得到一些和进程相关的信息,至于线程,我们的应用程序不需要其相关信息。
<P><B> .elseif
ax==IDM_TERMINATE</B>
<BR><B>
invoke GetExitCodeProcess,processInfo.hProcess,ADDR ExitCode</B>
<BR><B>
.if ExitCode==STILL_ACTIVE</B>
<BR><B>
invoke TerminateProcess,processInfo.hProcess,0</B>
<BR><B>
.endif</B>
<BR><B>
invoke CloseHandle,processInfo.hProcess</B>
<BR><B>
mov processInfo.hProcess,0</B>
<P>当用户选择了菜单项“terminate
process”后,我们调用函数GetExitCodeProcess来检查新进程是否还存在,如果还存在我们就调用函数TerminateProcess来结束它。另外我们把它的句柄关闭掉,因为我们再也不用它了。
<HR SIZE=1>
<DIV align=center>
<SCRIPT language=JavaScript1.1 src="../lion-tut-c13.files/textclick"></SCRIPT>
<BR></DIV><!-- 10:1 文本广告交换 -->
<DIV align=center>
<SCRIPT language=JavaScript1.1 src="../lion-tut-c13.files/c21.htm"></SCRIPT>
<!-- 10:1 文本广告交换 --></DIV>
<HR SIZE=1>
<DIV align=center>翻译:Lxx.阿龙,校对:LuoYunBin's Win32 ASM Page, <A
href="http://asm.yeah.net/">http://asm.yeah.net/</A></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -