CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C++ Builder >  基础类

请问在c++builder中怎样做钩子程序

楼主softman_2000(超越昨天)2002-04-04 09:01:58 在 C++ Builder / 基础类 提问

能给出一个代码吗?  
  我的程序是这样的,  
  LRESULT   __stdcall   MyFunc(int   nCode,WPARAM   wParam,LPARAM   lParam)  
  {  
                  return   CallNextHookEx(hook,nCode,wParam,lParam);  
  }  
   
  安装钩子:  
  hook=SetWindowsHookEx(WH_KEYBOARD_LL,MyFunc,HInstance,   0);  
  题是错误说类型转换的问题,我对cbuilder不熟,那位高手能够致电一下,不胜感激。 问题点数:20、回复次数:5Top

1 楼dycdyc123(重出江湖)回复于 2002-04-04 09:05:03 得分 12

前不久我给该网站写了一些关于API函数的文章,其中曾提到过HOOK中文意思就是“钩子”的意思。这种函数是Windows消息处理机制的一部分,通过设置“钩子”,应用程序可以在系统级对所有消息、事件进行过滤,访问在正常情况下无法访问的消息。当然,这么做也是需要付出一定的代价的。由于多了这么一道处理过程,系统性能会受到一定的影响,所以大家在必要的时候才使用“钩子”,并在使用完毕及时将其删除。  
   
    首先让我们看看HOOK函数是怎么安装、调用和删除的。应用程序通常是调用SetWindowsHookEx()函数来进行安装的,其函数的原型如下:  
   
  SetWindowsHookEx(  
   
  Int   idHook;  
   
  HOOKPROC   lpfn;  
   
  HINSTANCE   hMod;  
   
  DWORD   dwThreadId;  
   
  );  
   
  参数说明:  
   
  idHook   是”钩子”的类型,”钩子”的类型一共有13种,具体如下表:  
   
  “钩子”类型    
    解释    
     
  WH_CALLWNDPROC    
    系统将消息发送到指定窗口之前的“钩子”    
     
  WH_CALLWNDPROCRET    
    消息已经在窗口中处理的“钩子”    
     
  WH_CBT    
    基于计算机培训的“钩子”    
     
  WH_DEBUG    
    差错“钩子”    
     
  WH_FOREGROUNDIDLE    
    前台空闲窗口“钩子”    
     
  WH_GETMESSAGE    
    接收消息投递的“钩子”    
     
  WH_JOURNALPLAYBACK    
    回放以前通过WH_JOURNALRECORD“钩子”记录的输入消息    
     
  WH_JOURNALRECORD    
    输入消息记录“钩子”    
     
  WH_KEYBOARD    
    键盘消息“钩子”    
     
  WH_MOUSE    
    鼠标消息“钩子”    
     
  WH_MSGFILTER    
    对话框、消息框、菜单或滚动条输入消息“钩子”    
     
  WH_SHELL    
    外壳“钩子”    
     
  WH_SYSMSGFILTER    
    系统消息“钩子”    
     
   
  lpfn   指向“钩子”过程的指针。  
   
  hMod   “钩子”过程所在模块的句柄。  
   
  dwThreadId   “钩子”相关线程的标识。  
   
    通常我们都是把”钩子”做成动态链接库,这样的好处是可以是系统内的每个进程访问。但是也可以在系统中直接调用,我的建议还是用动态库。如果用动态库的话,那么SetWindowsHookEx()中的第三个参数就是该动态链接库模块的句柄;对于一个只供单个进程访问的”钩子”,可以将其”钩子”过程放在安装”钩子”的同一个线程内,此时SetWindowsHookEx()中的第三个参数为该线程的hInstance。安装”钩子”有两种方法:1.你可以把他做成动态连接库文件,和程序一起编译。2.你可以在程序的任何地方直接调用。第2种的方法太麻烦,我不建议用,在这里我就不详细介绍啦。相比之下第1种比较简单。其”钩子”的过程都在动态链接库内完成。SetWindowsHookEx()函数是一个安装函数,如故一个由某种类型的”钩子”监视的事件发生,系统就会调用相应类型的”钩子”链开始处的”钩子”过程,”钩子”链的每个”钩子”过程都要考虑是否把事件传递给下一个”钩子”过程。如果要传递的话,就要调用CallNestHookEx()函数。这个函数成功时返回”钩子”链中下一个”钩子”过程的返回值,返回值的类型依赖于”钩子”的类型。这个函数的原型如下:  
   
  LRESULT   CallNextHookEx(  
   
  HHOOK   hhk;  
   
  int   nCode;  
   
  WPARAM   wParam;  
   
  LPARAM   lParam;  
   
  );  
   
    其中hhk为当前”钩子”的句柄,由SetWindowsHookEx()函数返回。NCode为传给”钩子”过程的事件代码。wParam和lParam   分别是传给”钩子”过程的wParam值,其具体含义与”钩子”类型有关。  
   
  释放”钩子”  
   
    释放”钩子”比较简单,他只有一个参数。当不在需要”钩子”时,应及时将其释放。他是调用UnhookWindowsHookEx()函数来实现的,函数原型如下:  
   
  UnhookWindowsHookEx(  
   
  HHOOK   hhk;  
   
  );  
   
  函数成功返回TRUE,否则返回FALSE。  
   
  如果我这样讲您还是不明白的话,请看下面给出的一些典型“钩子”代码和说明。  
   
  LRESULT   WINAPI   CallWndProc(int   nCode,WPARAM   wParam,LPARAM   lParam)  
   
  {  
   
  if(nCode<0)  
   
  return   CallNextHookEx(NULL,nCode,wParam,lParam);  
   
  switch(nCode)  
   
  {  
   
  case   HC_ACTION:  
   
  //”钩子”程序要处理什么的代码  
   
  break;  
   
  default:  
   
  break;  
   
  }  
   
  return   CallNextHookEx(NULL,nCode,wParam,lParam);  
   
  }  
   
    这是WH_CALLWNDPROC”钩子”的代码,此”钩子”允许程序监视由函数SendMessage发送给窗口过程的消息。系统将消息发送到目的窗口之前调用WH_CALLWNDPROC   “钩子”过程。  
   
  LRESULT   WINAPI   CallwndProc(int   nCode,WPARAM,wParam,LPARAM   lParam)  
   
  {  
   
  if(nCode<0)   return   callNextHookEx(NULL,nCode,wParam,lParam);  
   
  switch(nCode)  
   
  {  
   
  case   HC_ACTION:  
   
  switch(wParam)  
   
  {  
   
  Case   PM_REMOVE:  
   
  //某个应用程序调用了GetMessage函数或者是带PM_REMOVE参数的//PeekMessage函数,从消息队列中移去一个消息。  
   
  Break;  
   
  Case   PM_NOREMOVE:  
   
  //某个应用程序以PM_NOREMOVE为参数调用PeekMessage函数  
   
  break;  
   
  default:  
   
  break;  
   
  }  
   
  break;  
   
  default:  
   
  break;  
   
  }  
   
  return   CallNextHookEx(NULL,nCode,wParam,lParam);  
   
  }  
   
    这是调用WH_GETMESSAGE的函数,此函数允许应用程序监视函数GetMessage和   PeekMessage返回的消息。应用程序可以用钩子WH_GETMESSAGE来监视鼠标和键盘的输入以及其他系统发送到消息队列中的消息。  
   
  LRESULT   CALLBACK   CBTProc(int   nCode,WPARAM   wParam,LPARAM   lParam)  
   
  {  
   
  If(nCode<0)   Return   callNextHookEx(NULL,nCode,wParam,lParam);  
   
  Switch(nCode)  
   
  {  
   
  case   HCBT_ACTIVATE:  
   
  //系统将激活一个窗口  
   
  break;  
   
  case   HCBT_CLICKSKIPPED:  
   
  //系统从系统消息队列中移去一个鼠标消息  
   
  break;  
   
  case   HCBT_CREATEWND:  
   
  //系统将创建一个窗口  
   
  break;  
   
  case   HCBT_DESTROYWND:  
   
  //系统将关闭一个窗口  
   
  break;  
   
  case   HCBT_KEYSKIPPED:  
   
  //系统从系统消息队列中移去一个键盘消息  
   
  break;  
   
  case   HCBT_MINMAX:  
   
  //系统将最大化或最小化一个窗口  
   
  break;  
   
  case   HCBT_MOVESIZE:  
   
  //系统将移动一个窗口或改变一个窗口的大小  
   
  break;  
   
  case   HCBT_QS:  
   
  //系统在系统消息队列中检索到WM_QUEUESYNC消息  
   
  break;  
   
  case   HCBT_SETFOCUS:  
   
  //系统设置键盘输入窗口  
   
  break;  
   
  case   HCBT_SYSCOMMAND:  
   
  //将要执行一个系统命令  
   
  break;  
   
  default:  
   
  //可以添加其他代码  
   
  break;  
   
  }  
   
  return   CallNextHookEx(NULL,nCode,wParam,lParam);  
   
  }  
   
    每种”钩子”类型都有其对应的函数,这些函数的参数都是一样的,有兴趣的朋友可以在MSDN中找的他们的详细说明。  
   
  下面我给出一个完整的”钩子”安装和删除的过程的代码。  
   
  #include   "stdafx.h"  
   
  #include   "hook.h"  
   
  HINSTANCE   hInstance;  
   
  HHOOK   hhkKeyboard;  
   
  BOOL   APIENTRY   DllMain(   HANDLE   hModule,DWORD   ul_reason_for_call,   LPVOID   lpReserved)  
   
  {  
   
  switch   (ul_reason_for_call)  
   
  {  
   
  case   DLL_PROCESS_ATTACH:  
   
  case   DLL_THREAD_ATTACH:  
   
  case   DLL_THREAD_DETACH:  
   
  case   DLL_PROCESS_DETACH:  
   
  break;  
   
  }  
   
  hInstance=(HINSTANCE)hModule;  
   
  return   TRUE;  
   
  }  
   
  LRESULT   KeyboardProc(int   nCode,WPARAM   wParam,LPARAM   lParam)  
   
  {  
   
  MessageBeep(-1);  
   
  return   CallNextHookEx(NULL,nCode,wParam,lParam);  
   
  }  
   
  HOOK_API   BOOL   EnableKeyboardCapture()  
   
  {  
   
  if(!(hhkKeyboard=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hInstance,0)))  
   
  return   FALSE;  
   
  return   TRUE;  
   
  }  
   
  HOOK_API   BOOL   DisableKeyboardCapture()  
   
  {  
   
  return   UnhookWindowsHookEx(hhkKeyboard);  
   
  }  
   
  注意:这是一个动态链接库文件。  
   
  在程序中要想调用“钩子”的时候,有EnableKeyboardCapture()函数就可以啦,但你按键的时候就回发出声音。Top

2 楼softman_2000(超越昨天)回复于 2002-04-04 09:12:46 得分 0

这给老兄,你真厉害,十分佩服你,也十分感激你,叫个朋友可以吗?Top

3 楼diabloyj(大菠萝)回复于 2002-04-04 09:40:04 得分 0

非常佩服  
  别说微笑江湖  
  就是大笑江湖   狂笑江湖都行啊。Top

4 楼zken(乱码)回复于 2002-04-04 10:58:40 得分 0

微笑老兄,我对你的仰慕有如滔滔江水。。。收藏先Top

5 楼bigwhiteshark(变性鲨鱼)回复于 2002-04-06 11:45:48 得分 8

闲来无事,在WIN2K下用BCB5.0做了个键盘挂钩小程序,监视全局按键情况。Hook安放和回调函数放在一个单独DLL中,DLL原码如下:  
     
  //----------------------------------------------------------------------------------------------------  
  extern   "C"   __declspec(dllexport)   void   __stdcall   SetHook(HWND,bool);  
  LRESULT   CALLBACK   HookProc(int   nCode,WPARAM   wParam,LPARAM   lParam)      
     
  //----------------------------------------------------------------------------------------------------  
  static   HINSTANCE   hInstance;         //   应用实例句柄  
  static   HWND   hWndMain;                         //   MainForm句柄  
  static   HHOOK   hKeyHook;                       //   HOOK句柄  
  static   const   myMessage=2000;       //   自定义消息号  
  static   const   SecondPar=1;                     //   自定义消息第2参数  
     
  //----------------------------------------------------------------------------------------------------  
  int   WINAPI   DllEntryPoint(HINSTANCE   hinst,   unsigned   long   reason,   void*    
  lpReserved)  
  {     hInstance=hinst;   return   1;   }  
     
  //----------------------------------------------------------------------------------------------------  
  void   __stdcall   SetHook(HWND   hMainWin,bool   nCode)      
  {            
    if(nCode)     //   安放HOOK  
        {  
          hWndMain=hMainWin;  
          hKeyHook=SetWindowsHookEx(WH_JOURNALRECORD,(HOOKPROC)HookProc,hInstance,0);  
        }    
    else                   //   卸下HOOK  
          UnhookWindowsHookEx(hKeyHook);  
  }  
     
  //----------------------------------------------------------------------------------------------------  
  LRESULT   CALLBACK   HookProc(int   nCode,WPARAM   wParam,LPARAM   lParam)      
  {                                              
    EVENTMSG   *keyMSG=(EVENTMSG   *)lParam;  
    if((nCode==HC_ACTION)&&(keyMSG->message==WM_KEYUP))  
            PostMessage(hWndMain,myMessage,(char)(keyMSG->paramL),SecondPar);  
            //   向调用窗体发消息myMessage和虚拟键码(char)(keyMSG->paramL)  
    return((int)CallNextHookEx(hKeyHook,nCode,wParam,lParam));  
  }  
     
  //----------------------------------------------------------------------------------------------------  
  应用程序代码如下:(调DLL)  
     
  //----------------------------------------------------------------------------------------------------  
  static   HINSTANCE   hDLL;     //   DLL句柄  
  typedef   void   __stdcall   (*DLLFUN)(HWND,bool);  
  DLLFUN   DLLSetHook;  
  static   const   myMessage=2000;  
  static   const   SecondPar=1;  
     
  //----------------------------------------------------------------------------------------------------  
  __fastcall   TForm1::TForm1(TComponent*   Owner):TForm(Owner)  
  {}  
     
  //----------------------------------------------------------------------------------------------------  
  void   __fastcall   TForm1::FormCreate(TObject   *Sender)  
  {  
    hDLL=LoadLibrary((LPCTSTR)"Project1.dll");   //   DLL文件名:Project1.dll  
    if(hDLL==NULL)  
        {   ShowMessage("DLL:   不能加载!程序退出。");   exit(1);   }  
    DLLSetHook   =(DLLFUN)GetProcAddress(hDLL,"SetHook");  
    if(DLLSetHook==NULL)  
        {   ShowMessage("DLL:   函数没找到!程序退出。");   FreeLibrary(hDLL);   exit(1);   }  
    DLLSetHook(this->Handle,true);  
  }  
     
  //----------------------------------------------------------------------------------------------------  
  void   __fastcall   TForm1::FormClose(TObject   *Sender,   TCloseAction   &Action)  
  {  
    DLLSetHook(NULL,false);     //   卸下HOOK  
    FreeLibrary(hDLL);                             //   卸下DLL  
  }  
     
  //----------------------------------------------------------------------------------------------------  
  void   __fastcall   TForm1::ApplicationEvents1Message(tagMSG   &Msg,bool   &Handled)  
  {                                                                                   //   BCB5.0   的ApplicationEvents元件  
    if((Msg.message==myMessage)&&(Msg.lParam==SecondPar))  
          ShowMessage("       收到HOOK按键消息!\n\n   【键虚拟码】:"+IntToStr(Msg.wParam));  
  }  
     
  //----------------------------------------------------------------------------------------------------  
  用   WH_JOURNALRECORD   类型HOOK即可简单实现全局钩子,因为它挂接系统硬件消息。  
   
   
   
  Top

6 楼NowCan(城市浪人)回复于 2002-04-07 13:21:52 得分 0

加类型转换。  
  http://www.csdn.net/Expert/TopicView1.asp?id=605136Top

相关问题

  • c++builder程序的速度
  • 什么叫钩子程序
  • 什么叫钩子程序?
  • 用C# 怎么用钩子??
  • 祝C++BUILDER程序员新年好!
  • 建议为C++BUILDER程序员加薪
  • 在C++ Builder中调用外部程序
  • 用C++Builder开发DirectX应用程序
  • 我这里要C++BUILDER程序员
  • 有关”钩子“程序的问题

关键词

  • 函数
  • 消息
  • 安装
  • 系统
  • 代码
  • 应用程序
  • 原型
  • 钩子
  • wh
  • 调用

得分解答快速导航

  • 帖主:softman_2000
  • dycdyc123
  • bigwhiteshark

相关链接

  • CSDN Blog
  • 技术文档
  • 代码下载
  • 第二书店
  • 读书频道

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo