您当前的位置:首页 > 计算机 > 编程开发 > C语言

怎样中断一个Windows程序?

时间:01-03来源:作者:点击数:

没有一个普通的方法可以中断一个Windows程序,从而让你去完成一项必需的任务(如果这就是你的目标的话)。Windows 3.x是一种不支持优先调度的多任务操作系统,换句话说,它是一种合作性(cooperative)的多任务操作系统——原因之一就是你无法简单地从当前正在由处理器控制着的一个Windows程序中抢占一段时间。如果你看一下Windows API,你会发现PeekMessage()和WaitMessage()这样一些函数,在Microsoft的帮助文档中有这样一段介绍这些函数的话:

函数GetMessage(),PeekMessage()和WaitMessage()把控制权交给别的应用程序,允许别的应用程序运行的唯一方法就是使用这些函数。如果一个应用程序长时间不调用这些函数,那么它就阻止了别的应用程序的运行。

尽管这样,你还是可以中断一个Windows程序的。一种办法是在你的Windows程序中建立一个定时器,它每隔一段时间就会发出信号,只要你的程序处于激活的状态,那么在定时器发出信号的时候,你就能获得时间来完成各种所需的工作。但是,从技术角度来讲,这种方法并没有中断一个程序的处理过程——它只是应用了Windows的合作性多任务性能。如果你需要中断一个Windows程序,你可以使用过滤函数(filter function,也叫做hook function,即钩子函数)。Windows中的过滤函数与DOS中的中断处理程序相似(见20.12和20.17),你可用它“挂上(hook)”某个Windows事件,并在该事件发生时执行相应的任务。实际上,你可以用一个使用了一个或多个可用的钩子(hook)的过滤器来监视Windows中的几乎每一条消息。下面的例子使用了键盘钩子,因为它要使你能随时按一个特定的组合键来中断一个程序。该例挂上了键盘事件链,并且在Ctrl+Alt+F6键按下时打开一个消息框。不管当前正在执行的是哪一个应用程序,该例都能起作用。

 # include <dos.h>
 # include <windows.h>
 DWORD FAR PASCAL  __loadds KeyBoardProc(int,WORD,DWORD);
 static FARPROC nextKeyboardFilter=NULL;
                                                            
 BOOL shiftKeyDown ,ctrlIKeyDown ;
 # define REPEAT-COUNT       0x000000FF       /* test key repeat */
 # define KEY_WAS_UP         0x80000000        /* test WM_KEYUP */
 # define ALT KEY_DWN        0x20000000        /* test ALT key state */
 # define EAT_THE_KEY         1                   /* swallow keystroke */
 # define SEND_KEY ON         0                  /* act on keystroke ~ */
 BOOL useAltKey=TRUE;        /* use Alt key in sequence */
 BOOL useCtrlKey=TRUE;       /* also use Ctrl key */
 BOOL useShiftKey=FALSE;      /* don't use Shift key */
 /* Entry point into the DLL. Do all necessary initialization here */
 int FAR PASCAL LibMain (hModule,wDataSeg,cbHeapSize,lpszCmdLine)
 HANDLE hModule ;
 WORD wDataSeg ;
 WORD cbHeapSize ;
 LPSTR lpszCmdLine ;
       /* initialize key state variables to zero */
       shiftKeyDown = 0 ;
       ctrlKeyDown = 0 ;
       return 1 ;
   /* The keyboard filter searches for the hotkey key sequence.
      If it gets it, it eats the key and displays a message box.
      Any other key is sent on to Windows. */
 DWORD FAR PASCAL    _loadds
 KeyBoardProc (int nCode, WORD wParam, DWORD lParam)
     BOOL fCallDefProc ;
     DWORD dwResult = 0 ;
     dwResult=SEND_KEY_ON ;       /* default to send key on */
     fCallDefProc=TRUE;               /* default to calling DefProc */
switch (nCode) {
     case HC ACTION :
     case HC-NOREMOVE :
           /* If key is Shift , save it */
           if (wParam= = (WORD)VK_SHIFT) (
                 shiftKeyDown = ( (1Param & KEY_WAS_UP) ? 0 : 1 ) ;
                 break ;
           /* If key is Ctrl,save it */
           else if(wParam= = (WORD)VK_CONTROL) {
                 ctrlKeyDown=((lParam & KEY WAS UP)? 0:1);
                 break ;
           /* If key is the F6 key,act on it */
           else if(wParam= = (WORD)VK_F6) {
                  /* Leave if the F6 key was a key release and not press */
                  if (lParam * KEY_WAS_UP) break;
                  /* Make sure Alt key is in desired state, else leave */
                  if((useAltKey) && ! (lParam & ALT_KEY_DOWN) ) {
                       break ;
                  else if((!useAltKey) && (lParam & ALT KEY_DOWN)){
                       break ;
                  /* Make sure Shift key in desired state, else leave */
                  if(useShiftKey && ! shiftKeyDown){
                       break ;
                  else if ( !useShiftKey && shiftKeyDown) {
                       break ;
                  /* Make sure Ctrl key in desired state, else leave */
                  if(useCtrlKey && ! ctrlKeyDown){
                       break ;
                  else if ( !useCtrlKey && ctrlKeyDown) {
                      break ;
              }
                 /* Eat the keystroke, and don't call DefProc */
                 dwResult = EAT_THE_KEY;
                 fCallDefProc =FALSE ;
                 /* We made it, so Ctrl+Alt+F6 was pressed! */
                 MessageBox (NULL, (LPSTR)" You pressed Ctrl + Alt + F6!" , (LPSTR)" Keyboard
                                              Hook" ,MB_OK) ;
                 break ;
              }
        default :
                 fCallDefProc = TRUE ;
                 break ;
    }
if((nCode<0) | (fCallDefProc && (nextKeyboardFilter ! =NULL)))
     dwResult = DefHookProc (nCode, wParam, lParam,&nextKeyboardFilter) ;
     return (dwResult) ;
}
/* This function is called by the application to set up or tear
     down the filter function hooks.  */
void FAR PASCAL
SetupFilters (BOOL install)
{
     if (install) {
           next KeyboardFilter = SetWindowsHook (WH-KEYBOARD,
                                                            (FARPROC) KeyBoardProc) ;
    }
     else {
           UnhookWindowsHook (WH-KEYBOARD, (FARPROC)KeyBoardProe) ;
           nextKeyboardFitter = NULL ;
    }
}

Microsoft强调最好把过滤函数放在DLL中而不是放在应用程序中(注意在DLL中有LibMain()而没有WinMain()),为了实现上述应用,你需要编写一个普通的Windows应用程序来调用SetupFilters()函数——当该函数的参数值为TRUE时,该程序就开始监视键盘输入;当该函数的参数值为FALSE时,该程序就停止监视键盘输入。如果该程序被激活并且调用了SetupFilters(TRUE),回调函数KeyBoardProc()就会接收所有的键盘输入,而不管你是否正在运行其它的Windows程序。如果你按下Ctrl+Altq+F6,屏幕上就会出现一个小的消息框,通知你这些键被你按下了。在按下这些键的那一刹那,正在运行的那个程序被中断了。

注意,在DOS Shell下,键盘过滤函数不会接收键盘输入,但是在出现象询问你是否真的要退出Windows这样的系统模式对话框时,它会接收键盘输入并且中断该对话框。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门