hook again!
use wh_keyboard. 

解决方案 »

  1.   

    public
      { Public declarations }
      procedure WndProc(var msg:TMessage);override;{截获的WINDOWS :WM_KEYDOWN 消息}
    procedure Tshisu_client.WndProc(var msg:TMessage);
    begin
     if  msg.Msg= WM_KEYDOWN then
         begin
         {做你要做的事!!!}
         end;
      inherited WndProc(msg);
    end;
    {你试试看,我没试过}
      

  2.   

    主  题:钩子函数问题.下面的源代码可以跟踪鼠标和键盘,但是如何取消所有的按键?最好能给出代码(前10位来者有分,答对多加分)
    作  者:xzisgood
    所属论坛:Delphi
    问题点数:40
    回复次数:13
    发表时间:2001-2-8 8:59:00
     
    这个程序是一个窗体上有4个按钮和一个编辑框,钩子函数运行后可以跟踪鼠标和键盘的事件,但是我现在想封锁键盘,请问如何实现?最好有源代码.前10位来者有分,所有答对者都加分.小弟在此先谢过所有进来的兄弟了.
    unit fhook;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ScktComp;type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        Button3: TButton;
        Edit1: TEdit;
        Button4: TButton;
        Button5: TButton;
        ServerSocket1: TServerSocket;
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
        
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;  EventArr:array[0..1000]of EVENTMSG;
      EventLog:Integer;
      PlayLog:Integer;
      hHook,hPlay:Integer;
      recOK:Integer;
      canPlay:Integer;
      bDelay:Bool;
    implementation{$R *.DFM}
    Function PlayProc(iCode:Integer;wParam:wParam;lParam:lParam):LRESULT;stdcall;
    begin
      canPlay:=1;
      Result:=0;  if iCode < 0 then    //必须将消息传递到消息链的下一个接受单元
        Result := CallNextHookEx(hPlay,iCode,wParam,lParam)
      else if iCode = HC_SYSMODALON then
        canPlay:=0
      else if iCode = HC_SYSMODALOFF then
        canPlay:=1
      else if ((canPlay =1 )and(iCode=HC_GETNEXT)) then begin
        if bDelay then begin
          bDelay:=False;
          Result:=50;
        end;
        pEventMSG(lParam)^:=EventArr[PlayLog];
      end
      else if ((canPlay = 1)and(iCode = HC_SKIP))then begin
        bDelay := True;
        PlayLog:=PlayLog+1;
      end;
      if PlayLog>=EventLog then begin
        UNHookWindowsHookEx(hPlay);
      end;
    end;function HookProc(iCode:Integer;wParam:wParam;lParam:lParam):LRESULT;stdcall;
    begin
      recOK:=1;
      Result:=0;  if iCode < 0 then
        Result := CallNextHookEx(hHook,iCode,wParam,lParam)
      else if iCode = HC_SYSMODALON then
        recOK:=0
      else if iCode = HC_SYSMODALOFF then
        recOK:=1
      else if ((recOK>0) and (iCode = HC_ACTION)) then begin
        EventArr[EventLog]:=pEventMSG(lParam)^;
        EventLog:=EventLog+1;    if EventLog>=1000 then begin
          UnHookWindowsHookEx(hHook);
        end;
      end;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      Button1.Caption:='纪录';
      Button2.Caption:='停止';
      Button3.Caption:='回放';
      Button4.Caption:='范例';
      Button2.Enabled:=False;
      Button3.Enabled:=False;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      EventLog:=0;
      //建立键盘鼠标操作消息纪录链
      hHook:=SetwindowsHookEx(WH_JOURNALRECORD,HookProc,HInstance,0);
      //hHook:=SetwindowsHookEx(wh_debug,HookProc,HInstance,0);
      Button2.Enabled:=True;
      Button1.Enabled:=False;
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      UnHookWindowsHookEx(hHook);
      hHook:=0;  Button1.Enabled:=True;
      Button2.Enabled:=False;
      Button3.Enabled:=True;
    end;procedure TForm1.Button3Click(Sender: TObject);
    begin
      PlayLog:=0;
      //建立键盘鼠标操作消息纪录回放链
      hPlay:=SetwindowsHookEx(WH_JOURNALPLAYBACK,PlayProc,
        HInstance,0);  Button3.Enabled:=False;
    end;end. 
    回复贴子: 
     回复人:BCB([email protected]) (2001-2-8 9:13:00)  得40分 
    把原来的Return CallNextHook(....);
    改成return 1;  
     回复人:BCB([email protected]) (2001-2-8 9:16:00)  得0分 
    新钩子处理中,return (1)  表示消息不传到目标窗口;
                return (0)  继续传到窗口  
    这是关键部分  
     回复人:BCB([email protected]) (2001-2-8 9:18:00)  得0分 
    LRESULT CALLBACK KeyboardProc(    int code,            // hook code
        WPARAM wParam,    // virtual-key code
        LPARAM lParam     // keystroke-message information
      );    
    这是这个回调函数中  
      

  3.   

    主  题:键盘事件和消息?
    作  者:saxash
    所属论坛:Delphi
    问题点数:50
    回复次数:14
    发表时间:2000-12-9 12:56:00
     
      
      模拟键盘输入,遇到以下问题:
    1.  PostMessage(Form1.Handle, WM_CHAR, 65, 0);
      为什么没有作用?Focus 在 Edit1。
    2.  VOID keybd_event(
        BYTE bVk,    // virtual-key code
        BYTE bScan,    // hardware scan code
        DWORD dwFlags,    // flags specifying various function options
        DWORD dwExtraInfo     // additional data associated with keystroke
      );
      bVK, bScan 是如何定义的?是否与ASCII 码不同,virtual-key code在哪里定义?  keybd_event(ord('A'), 0, 0, 0);
      只能发小写的'a',带SHIFT 的键值如‘A$%^&*(#{}’要怎么发送?
      
     
    回复贴子: 
     回复人:WorldCreater(造化天尊) (2000-12-9 13:01:00)  得0分 
    听听  
     回复人:zkfly(KK) (2000-12-9 13:10:00)  得20分 
    1.  PostMessage(Form1.Edit1.Handle, WM_CHAR, 65, 0);
    2.  scan code : A code number transmitted to a computer whenever a key is pressed or released. Each key on the keyboard has a unique scan code. This code is not the same as the ASCII code for the letter, number, or symbol shown on the key; it is a special identifier for the key itself and is always the same for a particular key. When a key is pressed, the scan code is transmitted to the computer, where a portion of the read-only memory basic input/output system (ROM BIOS) dedicated to the keyboard translates the scan code into its ASCII equivalent. Because a single key can generate more than one character—lowercase "a" and uppercase "A," for example—the ROM BIOS also keeps track of the status of keys that change the keyboard state, such as the SHIFT key, and takes them into account when translating a scan code. 
    VK 是一个Windows的设备无关性键值,在Windows单元定义
     
     回复人:zheng(怎么办啊?) (2000-12-9 14:30:00)  得0分 
    guanzhu  
     回复人:saxash(还在想) (2000-12-9 14:48:00)  得0分 
    Thanks zkfly first.
    我的问题是:有六个编辑框,需要随时切换焦点,是否可以直接发键盘消息给窗口,哪个编辑框有焦点就在哪里显示,而不使用编辑框的句柄,这样用PostMessage 可以做到吗?
    如果用keybd_event,怎样发送大写或换档字符,谁能详细说明一下。  
     回复人:saxash(还在想) (2000-12-9 14:51:00)  得0分 
    是否要用SetKeyboardState 函数?  
     回复人:saxash(还在想) (2000-12-9 18:09:00)  得0分 
    我不管啦,谁告诉我用keybd_event 怎么发 ':'这个字符,其他不要了。  
     回复人:Anoa(寂寞小野) (2000-12-9 22:01:00)  得30分 
    用keybd_event 先把shift(16)按下,在按";"(186),在让shift弹开即可
    1 keybd_event(16,16,0,0);
    2 keybd_event(186,186,0,0);
    3(弹开略去)  
     回复人:saxash(还在想) (2000-12-10 13:24:00)  得0分 
    Anoa: Thank you ^_^.再一个问题,这些键值(16、186)是怎么得来的?我怎么找不到。  
     回复人:zkfly(KK) (2000-12-10 13:38:00)  得0分 
    最好是查一下MSDN了Virtual-Key Codes,或者查一下Delphi自带的Api帮助。
    哦,Anoa,如果Shift键不放的话会有问题吧,那今后的按键不是Shift一直按着吗?
    以小弟之见还是弹开的好,在最后加上keybd_event(16,0,KEYEVENTF_KEYUP,0)  
     回复人:saxash(还在想) (2000-12-10 14:16:00)  得0分 
    刚才我马上试了一下,按键弹起我已经搞定了。
    MSDN 里面好象只有名称没有数值,Delphi 的封装又不全,Windows.pas 里的定义缺了好多。
    Anoa 是在那里找到的?  
     回复人:Anoa(寂寞小野) (2000-12-10 14:38:00)  得0分 
    在form的onkeydown事件里面,key(:word)值就是  
     回复人:Anoa(寂寞小野) (2000-12-10 14:40:00)  得0分 
    to zkfly:
    当然弹开的好呢,不然就麻烦了:))  
     回复人:saxash(还在想) (2000-12-10 16:15:00)  得0分 
    to Anoa:
    你不觉得windows.pas 里的定义不全吗?象, . / ' ; ` - = \ 这些键值我都找不到。里面的键值从165 直接跳到229,186 在哪里呢?
    再帮忙一下。  
     回复人:saxash(还在想) (2000-12-10 18:52:00)  得0分 
    不好意思,刚才我没理解Anoa 的意思,现在明白了。多谢! 
      

  4.   

    有那么麻烦吗?不就是截获按键吗?
        procedure WMKey(var msg:TWMKey);message WM_KEYDOWN;
    写一个处理消息的过程,不就可以了?