好像只有通过hook或注册表才能达到目的
转载一注册表的
用到3个API函数BOOL RegisterHotKey(
HWND hWnd,    //响应该热键的窗口句柄
Int id,           //该热键的唯一标识
UINT fsModifiers, //该热键的辅助按键
UINT vk        //该热键的键值
); 为了得到唯一标识,我们还将用到另一个API函数 ATOM GlobalAddAtom(LPCTSTR lpString //自己设定的一个字符串);因为我们还要在程序退出的时候,消除这个热键, 所以需要声明一个全局变量: HotKeyId: Integer;   第一步: 在窗口的create事件中,加入以下代码 HotKeyId := GlobalAddAtom(‘MyHotKey’) - $C000;
注: HotKeyId的合法取之范围是0x0000到0xBFFF之间, GlobalAddAtom函数得到的值
在0xC000到0xFFFF之间,所以减掉0xC000来满足调用要求。第二步: 在上面的代码下面加入: RegisterHotKey(Handle, hotkeyid, MOD_ALT, VK_F8);  热键的辅助按键包括Mod_Ctrl 、Mod_Alt、Mod_Shift,对于Windows兼容键盘还支持Windows
键,即其键面上有Windows标志的那个键,其值为Mod_win。上面 的代码注册了一个热键:ALT+F8。当然如果你希望象TAKEIT那样,只用F8, 就这么写:RegisterHotKey(Handle, hotkeyid, 0, VK_F8);  注:handle是一个特殊的变量,它表示当前窗口的句柄。这个函数你应该能句举一反三了吧。原理:一旦热键设置成功,在程序应用过程中如果有相应的键被按下,Windows系统都会给你的应
用程序发送一个消息WM_HOTKEY,不管你的应用程序是否为当前活动的。其中WM_HOTKEY消
息的格式为:  idHotKey = (int) wParam; // 该参数在设置系统级的热键有用,一般不予使用
fuModifiers = (UINT) LOWORD(lParam);  //热键的辅助按键
uVirtKey = (UINT) HIWORD(lParam); //热键的键值   第三步: 注册了热键,就该写下响应代码了。 首先,在程序头部分的private段中加入声明 (作用是声明这个过程,和声明变量类似。
关于如何声明函数、过程,请请参考各自的帮助文件或其它资料): procedure HotKeyDown(var Msg: Tmessage); message WM_HOTKEY;   然后在程序中加入如下代码: procedure Tfmain.HotKeyDown(var Msg: Tmessage); begin if (Msg.LparamLo = MOD_ALT) AND Msg.LParamHi = VK_F8 then // 假设热键为ALT+F8 begin end; 最后一步: 在窗口的close事件中加入 UnRegisterHotKey(handle, HotKeyId); //注销HotKey, 释放资源。 

解决方案 »

  1.   


    一、Hook(钩子)的实现:
    Hook是应用程序在Microsoft Windows 消息处理过程中设置的用来监控消息流并且处理系统中尚未到达目的窗口的某一类型消息过程的机制。如果Hook过程在应用程序中实现,若应用程序不是当前窗口时,该Hook就不起作用;如果Hook在DLL中实现,程序在运行中动态调用它,它能实时对系统进行监控。根据需要,我们采用的是在DLL中实现Hook的方式。1.新建一个导出两个函数的DLL文件,在hookproc.pas中定义了钩子具体实现过
    程。代码如下:
    library keyspy;
    uses
    windows, messages, hookproc in 'hookproc.pas';
    exports
    setkeyhook,
    endkeyhook;
    begin
    nexthookproc:=0;
    procsaveexit:=exitproc;
    exitproc:=@keyhookexit;
    end.2.在Hookproc.pas中实现了钩子具体过程:
    unit hookproc;
    interface
    uses
    Windows, Messages, SysUtils, Controls, StdCtrls;
    var
    nexthookproc:hhook;
    procsaveexit:pointer;
    function keyboardhook(icode:integer;wparam:wparam;
    lparam:lparam):lresult;stdcall;export;
    function setkeyhook:bool;export;//加载钩子
    function endkeyhook:bool;export;//卸载钩子
    procedure keyhookexit;far;
    const
    afilename='c:\debug.txt';//将键盘输入动作写入文件中
    var
    debugfile:textfile;
    implementation
    function keyboardhookhandler(icode:integer;wparam:wparam;
    lparam:lparam):lresult;stdcall;export;
    begin
    if icode<0 then
    begin
    result:=callnexthookex(hnexthookproc,icode,wparam,lparam);
    exit;
    end;
    assignfile(debugfile,afilename);
    append(debugfile);
    if getkeystate(vk_return)<0 then
    begin
    writeln(debugfile,'');
    write(debugfile,char(wparam));
    end
    else
    write(debugfile,char(wparam));
    closefile(debugfile);
    result:=0;
    end;
    function endkeyhook:bool;export;
    begin
    if nexthookproc<>0 then begin
    unhookwindowshookex(nexthookproc);
    nexthookproc:=0;
    messagebeep(0); end;
    result:=hnexthookproc=0;
    end;
    procedure keyhookexit;far;
    begin
    if nexthookproc<>0 then endkeyhook;
    exitproc:=procsaveexit; end;
    end.二、Win95/98使用任务栏右方指示区来显示应用程序或工具图标对指示区图标的操作涉及了一个API函数Shell_NotifyIcon,它有两个参数,一个是指向TnotifyIconData结构的指针,另一个是要添加、删除、改动图标的标志。通过该函函数将应用程序的图标添加到指示区中,使其作为图标运行,增加专业特色。当程序起动后,用鼠标右键点击图标,则弹出一个菜单,可选择sethook或endhook。unit kb;
    interface
    uses
    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms,
    Dialogs,
    StdCtrls, Menus,shellapi;
    const
    icon_id=1;
    MI_iconevent=wm_user+1;//定义一个用户消息
    type
    TForm1 = class(TForm)
    PopupMenu1: TPopupMenu;
    sethook1: TMenuItem;
    endhook1: TMenuItem;
    N1: TMenuItem;
    About1: TMenuItem;
    Close1: TMenuItem;
    Gettext1: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure sethook1Click(Sender: TObject);
    procedure endhook1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Close1Click(Sender: TObject);
    private
    { Private declarations }
    nid:tnotifyicondata;
    normalicon:ticon;
    public
    { Public declarations }
    procedure icontray(var msg:tmessage); 
    message mi_iconevent;
    end;
    var
    Form1: TForm1;
    implementation
    {$R *.DFM}
    function setkeyhook:bool;external 'keyspy.dll';
    function endkeyhook:bool;external 'keyspy.dll';procedure tform1.icontray(var msg:tmessage);
    var
    pt:tpoint;
    begin
    if msg.lparam=wm_lbuttondown then
    sethook1click(self);
    if msg.LParam=wm_rbuttondown then
    begin
    getcursorpos(pt);
    setforegroundwindow(handle);
    popupmenu1.popup(pt.x,pt.y);
    end;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
    normalicon:=ticon.create;
    application.title:=caption;
    nid.cbsize:=sizeof(nid);
    nid.wnd:=handle;
    nid.uid:=icon_id;
    nid.uflags:=nif_icon or nif_message or nif_tip;
    nid.ucallbackmessage:=mi_iconevent;
    nid.hIcon :=normalicon.handle;
    strcopy(nid.sztip,pchar(caption));
    nid.uFlags:=nif_message or nif_icon or nif_tip;
    shell_notifyicon(nim_add,@nid);
    SetWindowLong(Application.Handle,
    GWL_EXSTYLE,WS_EX_TOOLWINDOW);
    end;procedure TForm1.sethook1Click(Sender: TObject);
    begin
    setkeyhook;
    end;procedure TForm1.endhook1Click(Sender: TObject);
    begin
    endkeyhook;
    end;procedure TForm1.FormDestroy(Sender: TObject);
    begin
    nid.uFlags :=0;
    shell_notifyicon(nim_delete,@nid);
    end;procedure TForm1.Close1Click(Sender: TObject);
    begin
    application.terminate;
    end;
    以下是一个按键地勾子:
    Intercepting The TAB and ENTER Keys{the prototype for the new keyboard hook function}
      function KeyboardHook(nCode: Integer; wParam: WPARAM;
                            lParam: LPARAM): LResult; stdcall;var
      Form1: TForm1;
      WinHook: HHOOK;    // a handle to the keyboard hook functionimplementation{$R *.DFM}procedure TForm1.FormCreate(Sender: TObject);
    begin  {install the keyboard hook function into the keyboard hook chain}
      WinHook:=SetWindowsHookEx(WH_KEYBOARD, @KeyboardHook, 0, GetCurrentThreadID);
    end;procedure TForm1.FormDestroy(Sender: TObject);
    begin
      {remove the keyboard hook function from the keyboard hook chain}
      UnhookWindowsHookEx(WinHook);
    end;function KeyboardHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LResult;begin
      {if we can process the hook information...}
      if (nCode>-1) then
        {...was the TAB key pressed?}
        if (wParam=VK_TAB) then
        begin
          {if so, output a beep sound}
          MessageBeep(0);      {indicate that the message was processed}
          Result := 1;
        end
        else
        {...was the RETURN key pressed?}    if (wParam=VK_RETURN) then
        begin
          {if so, and if the key is on the up stroke, cause
          the focus to move to the next control}
          if ((lParam shr 31)=1) then
            Form1.Perform(WM_NEXTDLGCTL, 0, 0);      {indicate that the message was processed}
          Result := 1;
        end
        else
          {otherwise, indicate that the message was not processed.}      Result := 0
      else
        {we must pass the hook information to the next hook in the chain}
        Result := CallNextHookEx(WinHook, nCode, wParam, lParam);
    end;Hook Win32 API 是一项有趣而实用的WINDOWS系统编程技术,应用领域十分广泛。虽然已经有不少的文章介绍过 Hook Win32 API 的方法了,我还是来作些简单的介绍,以便大家了解其工作原理。    Hook Win32 API 是什么意思?就是钩住Win32 API;那又何谓“钩”呢?就是绕弯的意思,让Win32 API函数的调用先绕一个弯路,在它执行实际功能之前,我们可以先做一些“预处理”,这样我们可以监视或定制某个Win32 API的调用,以实现一些特殊的功能。至于具体可以实现些什么样的功能,那就取决于程序设计者的想象力了。    为什么要Hook Win32 API呢?因为在很多情况下,我们想监视或改变某个应用程序的一些特定的行为,但是那个应用程序却没有提供相应的接口,而我们又几乎不可能得到其源代码,怎么办呢?因为大多数WINDOWS引用程序的行为很大程度上依赖于Win32 API,所以我们可以采用Hook Win32 API的方式来试图监视和改变应用程序的行为。    如何Hook Win32 API呢?实际上Win32 API是由一组动态链接库实现的,使用动态链接库是为了尽可能的共享内存。由于动态链接库是动态装入的,所以Win32 API函数的入口点也是动态确定的。当WINDOWS应用程序在调用Win32 API的时候,并不是直接调用某个函数地址,而是调用某处所存储的一个动态确定的函数地址来实现间接调用地,该处被命名为Import Address Table(简称IAT)。知道了这一点,接下来要做的就是想办法找到这个存储单元的位置,然后将其内容替换为接管函数的入口地址,不过得事先保存原函数的入口地址,以便执行了接管函数的代码后,可以在适当的地方以适当的方式再调用原函数。最后退出的时
      

  2.   

    没这么麻烦吧!
    我认为这个功能没必要用热键。无非是实现程序运行期按ctrl+l键响应事件。
    procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
       form1.KeyPreview:=true;
       if (shift=[ssctrl])and(key=108)OR(key=76) then
            showmessage('aaaaa');
    end;
    这样就行了。
      

  3.   

    同一楼上,我觉得使用FormKeyDown这个最简单!!
      

  4.   

    可是当程序运行时,Form是隐藏的....所以我无法使用FormKeyDown
      

  5.   

    这样的程序有很多,给你一个
     
    定义全局热键(本例中定义热键Ctrl+Del+R),步骤:   1、定义捕获Windows消息WM_HOTKEY的钩子函数,即:procedure WMHotKey(var Msg : TWMHotKey); message WM_HOTKEY;   2、向Windows加入一个全局原子 Myhotkey: GlobalAddAtom(’MyHotkey’), 并保留其句柄。   3、向Windows登记热键:调用API函数RegisterHotKey实现。   三、源程序: unit Unit1; 
    interface 
    uses 
    Windows, Messages, Forms, Dialogs, Classes, Controls, StdCtrls; 
    type 
    TForm1 = class(TForm) 
    procedure FormCreate(Sender: TObject); 
    procedure FormClose(Sender: TObject; var Action: TCloseAction); 
    private 
    {热键标识ID} 
    id: Integer; 
    procedure WMHotKey(var Msg : TWMHotKey); message WM_HOTKEY; 
    { Privat-Declarations} 
    public 
    { Public-Declarations} 
    end; 
    var 
    Form1 : TForm1; 
    implementation 
    const RSP_SIMPLE_SERVICE=1; 
    function RegisterServiceProcess (dwProcessID, dwType: DWord) : DWord; stdcall; external ’KERNEL32.DLL’; 
    {$R *.DFM} {捕获热键消息} 
    procedure TForm1.WMHotKey (var Msg : TWMHotKey); 
    begin 
    if msg.HotKey = id then 
    ShowMessage(’Ctrl+Alt+R键被按下!’); 
    form1.Visible :=true; 
    end; procedure TForm1.FormCreate(Sender: TObject); 
    Const 
    {ALT、CTRL和R键的虚拟键值} 
    MOD_ALT = 1; 
    MOD_CONTROL = 2; 
    VK_R = 82; 
    begin 
    {首先判断程序是否已经运行} 
    if GlobalFindAtom(’MyHotkey’) = 0 then 
    begin 
    {注册全局热键Ctrl + Alt + R} 
      id:=GlobalAddAtom(’MyHotkey’); 
      RegisterHotKey(handle,id,MOD_CONTROL+MOD_Alt,VK_R); 
    end 
    else 
      halt; 
    end;
     
    {退出时释放全局热键} 
    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); 
    begin 
    UnRegisterHotKey(handle,id); 
    GlobalDeleteAtom(id); 
    end; 
    end. 
     
      

  6.   

    看一下我做的一个小东西http://www.skycn.com/soft/4199.html
    有问题可以来信
      

  7.   

    谢谢上面各位朋友的回答!
    我想问一下:用户在我的程序中使用Hotkey控件设定了自定义的热键,那么我怎么知道他设定的是什么呢?比如用户设置的是Ctrl+L,我怎么能知道他设置的是这个呢?有什么属性可以得到吗?Hotkey有个属性叫hotkey1.hotkey,是TShortCut类的,怎么用?
      

  8.   

    我用ShutcuttoText(hotkey1.hotkey),获得用户在hotkey1中设置的热键,比如ALT+F8,(是String类型的)我怎么使用RegisterHotKey(Handle, hotkeyid,辅助按键, 按键);呢?因为用户定义的是动态的,所以不能写成 RegisterHotKey(Handle, hotkeyid, MOD_ALT, VK_F8); 那要怎么写呢?
      

  9.   

    RegisterHotKey函数原型及说明:
    BOOL RegisterHotKey(
      HWND hWnd,         // window to receive hot-key notification
      int id,            // identifier of hot key
      UINT fsModifiers,  // key-modifier flags
      UINT vk            // virtual-key code);
    参数 id为你自己定义的一个ID值,对一个线程来讲其值必需在0x0000 - 0xBFFF范围之内,对DLL来讲其值必需在0xC000 - 0xFFFF 范围之内,在同一进程内该值必须唯一
    参数 fsModifiers指明与热键联合使用按键,可取值为:MOD_ALT MOD_CONTROL MOD_WIN MOD_SHIFT
    参数 vk指明热键的虚拟键码 
    首先(举个例子):  
      RegisterHotKey(handle,globaladdatom('hot key'),MOD_ALT,vk_f12);
    然后在form中声明一个函数(过程):
      procedure hotkey(var msg:tmessage);message wm_hotkey;
    过程如下:
    procedure TForm1.hotkey(var msg:tmessage);
    begin
      if (msg.LParamHi=VK_F12) and (msg.LParamLo=MOD_ALT) then
      begin
       form1.show;
       SetForegroundWindow(handle);
      end;
    end;
    这样,不管你在什么地方,窗口就会显示出来。
    当然,你要GlobalDeleteAtom;unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;type
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Private declarations }
        aatom:atom;
        procedure hotkey(var msg:tmessage);message wm_hotkey;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.DFM}procedure TForm1.FormCreate(Sender: TObject);
    begin
      aatom:=globaladdatom('hot key');
      RegisterHotKey(handle,aatom,MOD_ALT,vk_f12);
    end;procedure TForm1.hotkey(var msg:tmessage);
    begin
      if (msg.LParamHi=VK_F12) and (msg.LParamLo=MOD_ALT) then
        SetForegroundWindow(handle);
    end;    procedure TForm1.FormDestroy(Sender: TObject);
    begin
     globalDeleteatom(aatom);
    end;end.
      

  10.   

    你们看这样行不??
    type
        Box : TComboBox;
        Ctrl        : TRadioButton;
        Alt         : TRadioButton;
        Shift       : TRadioButton;
        Win         : TRadioButton;var
      RightLabel:Cardinal;
      LeftLabel:Cardinal;procedure TForm1.BoxChange(Sender: TObject);
    begin
      if Box.Text='0'   then RightLabel:=$30;
      if Box.Text='1'   then RightLabel:=$31;
      if Box.Text='2'   then RightLabel:=$32;
      if Box.Text='3'   then RightLabel:=$33;
      if Box.Text='4'   then RightLabel:=$34;
      if Box.Text='5'   then RightLabel:=$35;
      if Box.Text='6'   then RightLabel:=$36;
      if Box.Text='7'   then RightLabel:=$37;
      if Box.Text='8'   then RightLabel:=$38;
      if Box.Text='9'   then RightLabel:=$39;
      if Box.Text='Insert' then RightLabel:=$2D;
      if Box.Text='Delete' then RightLabel:=$2E;
      RegHotkey;
    end;procedure TForm1.CtrlClick(Sender: TObject);
    begin
      LeftLabel:=MOD_CONTROL;
      RegHotkey;
    end;procedure TForm1.AltClick(Sender: TObject);
    begin
      LeftLabel:=MOD_ALT;
      RegHotkey;
    end;procedure TForm1.ShiftClick(Sender: TObject);
    begin
      LeftLabel:=MOD_SHIFT;
      RegHotkey;
    end;procedure TForm1.WinClick(Sender: TObject);
    begin
      LeftLabel:=MOD_WIN;
      RegHotkey;
    end;procedure TForm1.ComboSelect(Sender: TObject);
    begin
      if Combo.Text =Combo.Items.Strings[0]
      then
        begin
          Ctrl.Checked:=True;
          XP.Caption := 'Ctrl';
          LeftLabel:=MOD_CONTROL;
        end;  if Combo.Text =Combo.Items.Strings[1]
      then
        begin
           Alt.Checked:=True;
           XP.Caption := 'Alt';
           LeftLabel:=MOD_Alt;
        end;  if Combo.Text =Combo.Items.Strings[2]
      then
        begin
          Win.Checked:=True;
          xp.Caption := 'Win';
          LeftLabel:=MOD_Win;
        end;
      if Combo.Text =Combo.Items.Strings[3]
      then
        begin
          Shift.Checked:=True;
          xp.Caption := 'Shift';
          LeftLabel:=MOD_Shift;
        end;  RegHotkey;
    end;procedure TForm1.RegHotkey;
    begin //注册快捷键
      Short:= GlobalAddAtom('short');
      RegisterHotKey(handle,short,LeftLabel,RightLabel);
    end;
      

  11.   

    最后别忘了 globalDeleteatom('short');
    这样,用户就可以自己选折快捷键了!!