刚刚学习钩子,可是在调用的时候总会报错,请帮我看一下那里有错.
*****钩子的功能为:当接收到系统打印对列中有任务后,发送WM_SPOOLERSTATUS消息给调用程序,以实现对打印任务实时监控.
________________________________________________________________
library PrinterHook;
uses
  SysUtils,
  Classes,
  Windows,
  Messages;var fHHook:HHook;
    Apphandle:HWND;
{$R *.res}
//钩子处理过程
function ProcessHook(Code: Integer;WP:WParam;LP:LParam): LRESULT;stdcall;
begin
  Result:=0;
  if PMSG(lP).message=WM_SPOOLERSTATUS then
    SendMessage(AppHandle,WM_SPOOLERSTATUS,WP,LP);
  Result := CallNextHookEx(fHHook, Code, WP, LP);
end;
//注册钩子
function RegsiterHook(handle:HWND):boolean;stdcall;export;
begin
  AppHandle:=handle;
  fHHOOK:=SetWindowsHookEx(WH_GETMESSAGE,@ProcessHook,hInstance,0);
  result:=true;
  MessageBox(handle,'ok!','information',mb_ok);//Test...
end;
//撤消钩子
function UnRegsiterHook:boolean;stdcall;export;
begin
  result:=UnhookWindowsHookEx(FHHOOK);
end;exports
  RegsiterHook,
  UnRegsiterHook;
begin
end.
____________________________________________

解决方案 »

  1.   

    SendMessage
    改為 PostMessage 試下
      

  2.   

    谢谢,经调试不会提示出错了,但是新的问题又有了, 在
    if PMSG(lP).message=WM_SPOOLERSTATUS then
          SendMessage(AppHandle,WM_SPOOLERSTATUS,WP,LP);
    这一步,无法拦截到WM_SPOOLERSTATUS 消息?或者不知道那位能给我讲一WM_SPOOLERSTATUS 这个消息在系统中的运作流程?谢谢.
      

  3.   

    关于这个问题有两个方面我有疑问,先说第二个疑问,那就是AppHandle这个全局变量的问题。设想一下,你的钩子是一个全局勾子(DLL方式),在设置的时候,由你的程序(称之为程序A吧)来加载DLL,调用RegisterHook函数,并传递一个HANDLE给它,我想,这个HANDLE应该是程序B的主窗口句柄吧?它肯定是不为零的。
    现在HOOK成功了,当每个进程(包括程序B)取得消息时,都会加载DLL并进入ProcessHook函数,注意,这时DLL在不同的进程空间里,它被加载进来的时候,全局变量AppHandle的值为零!!!
    这是钩子应用过程中的常见BUG,解决方法之一是利用内存映射来产生一个真正意义上的全局变量-----跨进程访问的!
      

  4.   

    内存映射文件:
    const
      BUFFER_SIZE  = 16 * 1024;
      HOOK_MEM_FILENAME = 'MEM_FILE';type
      TShared = record
        MainWnd  :THandle;
      end;
      PShared = ^TShared;var
      MemFile: THandle;
      Shared: PShared;procedure DllEntry(dwReason : integer);
    begin
      case dwReason Of
        DLL_PROCESS_ATTACH:
          begin
            MemFile := OpenFileMapping(FILE_MAP_WRITE,False,HOOK_MEM_FILENAME);
            if MemFile = 0 then
              MemFile := CreateFileMapping($FFFFFFFF,nil,
                PAGE_READWRITE,
                0,
                SizeOf(TShared),
                HOOK_MEM_FILENAME);
            Shared := MapViewOfFile(MemFile,
              File_MAP_WRITE,
              0,
              0,
              0);
          end;
        DLL_PROCESS_DETACH:
          begin
            //你的处理
         UnmapViewOfFile(Shared);
         CloseHandle(memFile);
          end;
        else;
      end;
    end;Shared^.MainWnd := Handle;
      

  5.   

    内存映射已经搞定了.
    现在的问题是当系统中打印任务有变化时钩子无法检测到?而使用其它程序采用PostMessage 
    WM_SPOOLERSTATUS 消息就可以钩到.怀疑是不是windows在打印队列发生变化时不广播这个消息????欢迎继续讨论!