热键1,效果图和全代码

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ActnList, ComCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    btn1: TButton;
    grp1: TGroupBox;
    btn2: TButton;
    grp2: TGroupBox;
    lbl1: TLabel;
    actlst1: TActionList;
    lbl2: TLabel;
    lbl3: TLabel;
    act1: TAction;
    act2: TAction;
    act3: TAction;
    grp3: TGroupBox;
    btn3: TButton;
    btn4: TButton;
    grp4: TGroupBox;
    hk1: THotKey;
    btn5: TButton;
    grp5: TGroupBox;
    lst1: TListBox;
    btn6: TButton;
    grp6: TGroupBox;
    lbl4: TLabel;
    btn7: TButton;
    grp7: TGroupBox;
    lbl5: TLabel;
    btn8: TButton;
    tmr1: TTimer;
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure act1Execute(Sender: TObject);
    procedure act2Execute(Sender: TObject);
    procedure act3Execute(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btn3Click(Sender: TObject);
    procedure btn4Click(Sender: TObject);
    procedure btn5Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btn6Click(Sender: TObject);
    procedure btn7Click(Sender: TObject);
    procedure btn8Click(Sender: TObject);
    procedure tmr1Timer(Sender: TObject);
  private
    procedure WmHotKey(var msg:TMessage); message WM_HOTKEY;//自定义快捷键响应函数
    procedure GetCombination(Modifiers: Word); //获取所有系统热键
    procedure ScanHotKeys; //获取所有系统热键
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  Hook :HHook;//钩子句柄

{键盘回调函数
LRESULT CALLBACK KeyboardProc(
    int code,
    WPARAM wParam,
    LPARAM lParam
);}
function LowLevelKeyboardProc(vNode:Integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
(*自定义消息结构体
 typedef struct tagMSG
 {
 HWND hwnd; 消息将要发送到的那个窗口的句柄,用这个参数可以决定让哪个窗口接收消息
 UINT message; 消息号,它唯一标识了一种消息类型。每种消息类型都在Windows文件进行了预定义。
 WPARAM wParam; 一个32位的消息参数,这个值的确切意义取决于消息本身。
 LPARAM lParam;同上。
 DWORD time;消息放入消息队列中的时间,在这个域中写入的并非当时日期,而是从Windows启动后所测量的时间值。
 POINT pt;消息放入消息队列时的鼠标坐标。
 } MSG, *PMSG;
 *)
type
KbDllHookStruct = record
     vkCode:DWord;
     ScanCode:DWord;
     Flags:DWord;
     Time:DWord;
     dwExtraInfo:DWord;
end;
var
P:^KbDllHookStruct;//定义消息指针
begin
  Result := 0;//如果为0则表示失败
  P := Pointer(LPARAM);//消息结构图转换为指针
  if vNode = HC_ACTION then //如果这个消息wParam和lParam包含了按键消息
  begin
    case wParam of //判断这个消息为按下键或者按下放开系统键
      WM_KEYUP,WM_SYSKEYUP:
      if (p.vkCode =  VK_HOME) {OR (p.vkCode =  VK_RWIN)}//判断按下的是不是左右Win键盘
      then begin
        Form1.Text := '您按下了Home键!';
        //ShowMessage('您按下了Home键!');
        Result := 1; //返回1
      end;
    end;
    {如果 code不为按键消息,则 必须让KeyboardProc()函数返回CallNextHookEx()}
    if vNode <> 0 then //如果这个消息
      Result := CallNextHookEx(0,vNode,wParam,lParam);
  end;
end;

{注册钩子}
procedure TForm1.btn1Click(Sender: TObject);
begin
(*HHOOK SetWindowsHookEx(
            int idHook,钩子的类型,即它处理的消息类型
            HOOKPROC lpfn,
钩子子程的地址指针。如果dwThreadId参数为0 或是一个由别的进程创建的线程的标识,
lpfn必须指向DLL中的钩子子程。除此以外,lpfn可以指向当前进程的一段钩子子程代码。
钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数。
            HINSTANCE hMod, 应用程序实例的句柄。标识包含lpfn所指的子程的DLL。
如果dwThreadId 标识当前进程创建的一个线程,而且子程代码位于当前进程,hMod必须为NULL。
可以很简单的设定其为本应用程序的实例句柄。
            DWORD dwThreadId 与安装的钩子子程相关联的线程的标识符。如果为0,钩子子程
与所有的线程关联,即为全局钩子。);*)
{WH_KEYBOARD_LL为13是键盘钩子}
 Hook := SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,hInstance,0);
end;

{卸载钩子}
procedure TForm1.btn2Click(Sender: TObject);
begin
  UnHookWindowsHookEx(Hook);//卸载钩子
end;

{锁定大小写}
procedure ToggleCapsLock;
var
  KeyState: TKeyboardState;//键盘状态
begin
  GetKeyboardState(KeyState);//获取键盘状态
  if (KeyState[VK_CAPITAL] = 0) then //如果键盘大小写没锁定
  begin //按下
  {VOID keybd_event(BYTE bVk,BYTE bScan,DWORD dwFlags,DWORD dwExtralnfo);
      bVk:定义一个虚拟键码。键码值必须在1~254之间。
      bScan:定义该键的硬件扫描码。
      dwFlags:定义函数操作的各个方面的一个标志位集。应用程序可使用如下一些预定义常数的组合设置标志位。
      KEYEVENTF_EXTENDEDKEY:若指定该值,则扫描码前一个值为OXEO(224)的前缀字节。
      KEYEVENTF_KEYUP:若指定该值,该键将被释放;若未指定该值,该键将被按下。
      dwExtralnfo:定义与击键相关的附加的32位值。}
    Keybd_Event(VK_CAPITAL, 1, KEYEVENTF_EXTENDEDKEY or 0, 0);//按下 (KEYEVENTF_EXTENDEDKEY为扩展键)
    Keybd_Event(VK_CAPITAL, 1, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);//松开
  end else
  begin //松开
    Keybd_Event(VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY or 0, 0);
    Keybd_Event(VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
  end;
end;

{锁定数字键}
procedure ToggleNumLock;
var
  KeyState: TKeyboardState;//键盘状态
begin
  GetKeyboardState(KeyState);//获取键盘状态
  if (KeyState[VK_NUMLOCK] = 0) then //如果小键盘没锁定
  begin //按下
  {VOID keybd_event(BYTE bVk,BYTE bScan,DWORD dwFlags,DWORD dwExtralnfo);
        bVk:定义一个虚拟键码。键码值必须在1~254之间。
        bScan:定义该键的硬件扫描码。键的OEM扫描码
        dwFlags:定义函数操作的各个方面的一个标志位集。应用程序可使用如下一些预定义常数的组合设置标志位。
        KEYEVENTF_EXTENDEDKEY:若指定该值,则扫描码前一个值为OXEO(224)的前缀字节。
        KEYEVENTF_KEYUP:若指定该值,该键将被释放;若未指定该值,该键将被按下。
        dwExtralnfo:定义与击键相关的附加的32位值。}
    Keybd_Event(VK_NUMLOCK, 1, KEYEVENTF_EXTENDEDKEY or 0, 0);//按下 (KEYEVENTF_EXTENDEDKEY为扩展键)
    Keybd_Event(VK_NUMLOCK, 1, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);//松开
  end else
  begin //松开
    Keybd_Event(VK_NUMLOCK, 0, KEYEVENTF_EXTENDEDKEY or 0, 0);
    Keybd_Event(VK_NUMLOCK, 0, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
  end;
end;

{锁定大小写}
procedure TForm1.btn3Click(Sender: TObject);
var
  KeyState: TKeyboardState; //键盘状态
begin
  ToggleCapsLock;//改变函数
  GetKeyboardState(KeyState);//获取按键状态
  btn3.Caption := '大小写状态:' + IntToStr(KeyState[VK_CAPITAL]);//改变按钮文本
end;

{锁定数字键盘}
procedure TForm1.btn4Click(Sender: TObject);
var
  KeyState: TKeyboardState;
begin
  ToggleNumLock;
  GetKeyboardState(KeyState);//获取按键状态
   btn4.Caption := '小键盘状态:' + IntToStr(KeyState[VK_NUMLOCK]);//改变按钮文本
end;

{注册快捷键}
var
  Id: Integer;
  Key,Shift: Word;//定义2个按键(用于快捷键的)
procedure TForm1.btn5Click(Sender: TObject);
var
{shift 是一个集合变量。type TShiftState = set of (ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble);}
  TShift: TShiftState;
begin
{使用前必须先注册热键.HotKeyId的合法取之范围是0x0000到0xBFFF之间,
GlobalAddAtom函数得到的值 在0xC000到0xFFFF之间,所以减掉0xC000来满足调用要求。}
  Id := GlobalAddAtom('MyHotKey') - $C000;
{判断用了哪些系统键}
  Key := hk1.HotKey and not (scShift + scCtrl + scAlt);
  TShift := [];
  if hk1.HotKey and scShift <> 0 then Include(TShift, ssShift);
  if hk1.HotKey and scCtrl <> 0 then Include(TShift, ssCtrl);
  if hk1.HotKey and scAlt <> 0 then Include(TShift, ssAlt);
{判断是哪个系统键}
  Shift:= 0;
  if ssShift in TShift then Shift := MOD_SHIFT;
  if ssCtrl in TShift then Shift := Shift or MOD_CONTROL;
  if ssAlt in TShift then Shift:= Shift or MOD_ALT;
{BOOL   RegisterHotKey(
            HWND   hWnd,响应该热键的窗口句柄
            Int   id,该热键的唯一标识
            UINT   fsModifiers,该热键的辅助按键
            UINT   vk该热键的键值);}
  if not RegisterHotKey(Handle, Id, Shift, Key) then //如果注册失败
  MessageDlg('注册热键失败,与系统中已注册的热键冲突,请尝试其它热键',mtError,[mbOk],0);
end;

{获取所有系统热键}
const
  // Windows 2000/XP multimedia keys (adapted from winuser.h and renamed to avoid potential conflicts)
  // See also: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
  _VK_BROWSER_BACK = $A6; // Browser Back key
  _VK_BROWSER_FORWARD = $A7; // Browser Forward key
  _VK_BROWSER_REFRESH = $A8; // Browser Refresh key
  _VK_BROWSER_STOP = $A9; // Browser Stop key
  _VK_BROWSER_SEARCH = $AA; // Browser Search key
  _VK_BROWSER_FAVORITES = $AB; // Browser Favorites key
  _VK_BROWSER_HOME = $AC; // Browser Start and Home key
  _VK_VOLUME_MUTE = $AD; // Volume Mute key
  _VK_VOLUME_DOWN = $AE; // Volume Down key
  _VK_VOLUME_UP = $AF; // Volume Up key
  _VK_MEDIA_NEXT_TRACK = $B0; // Next Track key
  _VK_MEDIA_PREV_TRACK = $B1; // Previous Track key
  _VK_MEDIA_STOP = $B2; // Stop Media key
  _VK_MEDIA_PLAY_PAUSE = $B3; // Play/Pause Media key
  _VK_LAUNCH_MAIL = $B4; // Start Mail key
  _VK_LAUNCH_MEDIA_SELECT = $B5; // Select Media key
  _VK_LAUNCH_APP1 = $B6; // Start Application 1 key
  _VK_LAUNCH_APP2 = $B7; // Start Application 2 key
  // Self-invented names for the extended keys
  NAME_VK_BROWSER_BACK = 'Browser Back';
  NAME_VK_BROWSER_FORWARD = 'Browser Forward';
  NAME_VK_BROWSER_REFRESH = 'Browser Refresh';
  NAME_VK_BROWSER_STOP = 'Browser Stop';
  NAME_VK_BROWSER_SEARCH = 'Browser Search';
  NAME_VK_BROWSER_FAVORITES = 'Browser Favorites';
  NAME_VK_BROWSER_HOME = 'Browser Start/Home';
  NAME_VK_VOLUME_MUTE = 'Volume Mute';
  NAME_VK_VOLUME_DOWN = 'Volume Down';
  NAME_VK_VOLUME_UP = 'Volume Up';
  NAME_VK_MEDIA_NEXT_TRACK = 'Next Track';
  NAME_VK_MEDIA_PREV_TRACK = 'Previous Track';
  NAME_VK_MEDIA_STOP = 'Stop Media';
  NAME_VK_MEDIA_PLAY_PAUSE = 'Play/Pause Media';
  NAME_VK_LAUNCH_MAIL = 'Start Mail';
  NAME_VK_LAUNCH_MEDIA_SELECT = 'Select Media';
  NAME_VK_LAUNCH_APP1 = 'Start Application 1';
  NAME_VK_LAUNCH_APP2 = 'Start Application 2';

const
  LOCALIZED_KEYNAMES = True;
  HotKeyAtomPrefix = 'HotKeyManagerHotKey';
  // Non-localized (!) modifier names
  ModName_Shift = 'Shift';
  ModName_Ctrl = 'Ctrl';
  ModName_Alt = 'Alt';
  ModName_Win = 'Win';

var
  EnglishKeyboardLayout: HKL;
  ShouldUnloadEnglishKeyboardLayout: Boolean;
  // Localized (!) modifier names; initialized to English names
  LocalModName_Shift: string = ModName_Shift;
  LocalModName_Ctrl: string = ModName_Ctrl;
  LocalModName_Alt: string = ModName_Alt;
  LocalModName_Win: string = ModName_Win;

{是否为扩展键}
function IsExtendedKey(Key: Word): Boolean;
begin
  Result := ((Key >= _VK_BROWSER_BACK) and (Key <= _VK_LAUNCH_APP2));
end;

{分割热键}
procedure SeparateHotKey(HotKey: Cardinal; var Modifiers, Key: Word);
// Separate key and modifiers, so they can be used with RegisterHotKey
const
  VK2_SHIFT = 32;
  VK2_CONTROL = 64;
  VK2_ALT = 128;
  VK2_WIN = 256;
var
  Virtuals: Integer;
  V: Word;
//  x: Byte;
  x: Word;
begin
  Key := Byte(HotKey);
  x := HotKey shr 8;//右移8位
  Virtuals := x;
  V := 0;
  if (Virtuals and VK2_WIN) <> 0 then
    Inc(V, MOD_WIN);
  if (Virtuals and VK2_ALT) <> 0 then
    Inc(V, MOD_ALT);
  if (Virtuals and VK2_CONTROL) <> 0 then
    Inc(V, MOD_CONTROL);
  if (Virtuals and VK2_SHIFT) <> 0 then
    Inc(V, MOD_SHIFT);
  Modifiers := V;
end;

{把热键显示在列表框里面}
function HotKeyToText(HotKey: Cardinal; Localized: Boolean): string;
    {获取扩展键}
    function GetExtendedVKName(Key: Word): string;
    begin
      case Key of
        _VK_BROWSER_BACK: Result := NAME_VK_BROWSER_BACK;
        _VK_BROWSER_FORWARD: Result := NAME_VK_BROWSER_FORWARD;
        _VK_BROWSER_REFRESH: Result := NAME_VK_BROWSER_REFRESH;
        _VK_BROWSER_STOP: Result := NAME_VK_BROWSER_STOP;
        _VK_BROWSER_SEARCH: Result := NAME_VK_BROWSER_SEARCH;
        _VK_BROWSER_FAVORITES: Result := NAME_VK_BROWSER_FAVORITES;
        _VK_BROWSER_HOME: Result := NAME_VK_BROWSER_HOME;
        _VK_VOLUME_MUTE: Result := NAME_VK_VOLUME_MUTE;
        _VK_VOLUME_DOWN: Result := NAME_VK_VOLUME_DOWN;
        _VK_VOLUME_UP: Result := NAME_VK_VOLUME_UP;
        _VK_MEDIA_NEXT_TRACK: Result := NAME_VK_MEDIA_NEXT_TRACK;
        _VK_MEDIA_PREV_TRACK: Result := NAME_VK_MEDIA_PREV_TRACK;
        _VK_MEDIA_STOP: Result := NAME_VK_MEDIA_STOP;
        _VK_MEDIA_PLAY_PAUSE: Result := NAME_VK_MEDIA_PLAY_PAUSE;
        _VK_LAUNCH_MAIL: Result := NAME_VK_LAUNCH_MAIL;
        _VK_LAUNCH_MEDIA_SELECT: Result := NAME_VK_LAUNCH_MEDIA_SELECT;
        _VK_LAUNCH_APP1: Result := NAME_VK_LAUNCH_APP1;
        _VK_LAUNCH_APP2: Result := NAME_VK_LAUNCH_APP2;
      else
        Result := '';
      end;
    end;
    {获取左右的ctrl或者alt或者shift键}
    function GetModifierNames: string;
    var
      S: string;
    begin
      S := '';
      if Localized then
      begin
        if (HotKey and $4000) <> 0 then // scCtrl
          S := S + LocalModName_Ctrl + '+';
        if (HotKey and $2000) <> 0 then // scShift
          S := S + LocalModName_Shift + '+';
        if (HotKey and $8000) <> 0 then // scAlt
          S := S + LocalModName_Alt + '+';
        if (HotKey and $10000) <> 0 then
          S := S + LocalModName_Win + '+';
      end else
      begin
        if (HotKey and $4000) <> 0 then // scCtrl
          S := S + ModName_Ctrl + '+';
        if (HotKey and $2000) <> 0 then // scShift
          S := S + ModName_Shift + '+';
        if (HotKey and $8000) <> 0 then // scAlt
          S := S + ModName_Alt + '+';
        if (HotKey and $10000) <> 0 then
          S := S + ModName_Win + '+';
      end;
      Result := S;
    end;
    {获取快捷键名字}
    function GetVKName(Special: Boolean): string;
    var
      ScanCode: Cardinal;
      KeyName: array[0..255] of Char;
      oldkl: HKL;
      Modifiers, Key: Word;
    begin
      Result := '';
      if Localized then {本地特有键}
      begin
        if Special then
          ScanCode := (MapVirtualKey(Byte(HotKey), 0) shl 16) or (1 shl 24)
        else
          ScanCode := (MapVirtualKey(Byte(HotKey), 0) shl 16);
        if ScanCode <> 0 then
        begin
          GetKeyNameText(ScanCode, KeyName, SizeOf(KeyName));
          Result := KeyName;
        end;
      end else {英文键}
      begin
        if Special then
          ScanCode := (MapVirtualKeyEx(Byte(HotKey), 0, EnglishKeyboardLayout) shl 16) or (1 shl 24)
        else
          ScanCode := (MapVirtualKeyEx(Byte(HotKey), 0, EnglishKeyboardLayout) shl 16);
        if ScanCode <> 0 then
        begin
          oldkl := GetKeyboardLayout(0);
          if oldkl <> EnglishKeyboardLayout then
            ActivateKeyboardLayout(EnglishKeyboardLayout, 0); // Set English kbd. layout
          GetKeyNameText(ScanCode, KeyName, SizeOf(KeyName));
          Result := KeyName;
          if oldkl <> EnglishKeyboardLayout then
          begin
            if ShouldUnloadEnglishKeyboardLayout then
              UnloadKeyboardLayout(EnglishKeyboardLayout); // Restore prev. kbd. layout
            ActivateKeyboardLayout(oldkl, 0);
          end;
        end;
      end;
      if Length(Result) <= 1 then
      begin
        // Try the internally defined names
        SeparateHotKey(HotKey, Modifiers, Key);
        if IsExtendedKey(Key) then
          Result := GetExtendedVKName(Key);
      end;
    end;
var
  KeyName: string;
begin
  case Byte(HotKey) of
    // PgUp, PgDn, End, Home, Left, Up, Right, Down, Ins, Del
    $21..$28, $2D, $2E: KeyName := GetVKName(True);
  else
    KeyName := GetVKName(False);
  end;
  Result := GetModifierNames + KeyName;
end;

{测试热键是否可以被注册}
function HotKeyAvailable(HotKey: Cardinal): Boolean;
var
  M, K: Word;
  Atom: Word;
begin
  Atom := GlobalAddAtom(PChar('HotKeyManagerHotKeyTest'));
  SeparateHotKey(HotKey, M, K);
  Result := RegisterHotKey(Application.Handle, Atom, M, K);
  if Result then
    UnregisterHotKey(Application.Handle, Atom);
  GlobalDeleteAtom(Atom);
end;

{获取系统热键}
function GetHotKey(Modifiers, Key: Word): Cardinal;
const
  VK2_SHIFT = 32;
  VK2_CONTROL = 64;
  VK2_ALT = 128;
  VK2_WIN = 256;
var
  hk: Cardinal;
begin
  hk := 0;
  if (Modifiers and MOD_ALT) <> 0 then
    Inc(hk, VK2_ALT);
  if (Modifiers and MOD_CONTROL) <> 0 then
    Inc(hk, VK2_CONTROL);
  if (Modifiers and MOD_SHIFT) <> 0 then
    Inc(hk, VK2_SHIFT);
  if (Modifiers and MOD_WIN) <> 0 then
    Inc(hk, VK2_WIN);
  hk := hk shl 8;
  Inc(hk, Key);
  Result := hk;
end;

{系统热键输出到列表框}
procedure TForm1.GetCombination(Modifiers: Word);
var
  I: Integer;
  HotKey: Cardinal;
begin
  for I := $08 to $E6 do
  begin
    HotKey := GetHotKey(Modifiers, I);
    if not HotKeyAvailable(HotKey) then
      lst1.Items.Add(HotKeyToText(HotKey, LOCALIZED_KEYNAMES));
  end;
end;

{取系统热键(主函数)}
procedure TForm1.ScanHotKeys;
begin
  Screen.Cursor := crHourGlass;
  lst1.Clear;
  GetCombination(MOD_WIN);
  GetCombination(MOD_WIN + MOD_SHIFT);
  GetCombination(MOD_WIN + MOD_CONTROL);
  GetCombination(MOD_WIN + MOD_ALT);
  GetCombination(MOD_WIN + MOD_SHIFT + MOD_CONTROL);
  GetCombination(MOD_WIN + MOD_SHIFT + MOD_ALT);
  GetCombination(MOD_WIN + MOD_CONTROL + MOD_ALT);
  GetCombination(MOD_WIN + MOD_SHIFT + MOD_CONTROL + MOD_ALT);
  GetCombination(MOD_SHIFT);
  GetCombination(MOD_SHIFT + MOD_CONTROL);
  GetCombination(MOD_SHIFT + MOD_ALT);
  GetCombination(MOD_SHIFT + MOD_CONTROL + MOD_ALT);
  GetCombination(MOD_CONTROL);
  GetCombination(MOD_CONTROL + MOD_ALT);
  GetCombination(MOD_ALT);
  GetCombination(0);
  Screen.Cursor := crDefault;
end;


{获取所有系统热键}
procedure TForm1.btn6Click(Sender: TObject);
begin
  ScanHotKeys;
end;

{注册个性化热键}
var
  TmpAtom:atom; //键盘标识符
  KeyUse:Boolean;
procedure TForm1.btn7Click(Sender: TObject);
begin
{向全局原子表添加一个字符串,并返回这个字符串的唯一标识符(原子ATOM)}
  TmpAtom:=globaladdatom('hot key');
{注册快捷键}
{BOOL   RegisterHotKey(
            HWND   hWnd,响应该热键的窗口句柄
            Int   id,该热键的唯一标识
            UINT   fsModifiers,该热键的辅助按键
            UINT   vk该热键的键值);}
  KeyUse:=registerhotkey(handle,TmpAtom,0,vk_f11);
end;

{个性化热键2}
procedure TForm1.tmr1Timer(Sender: TObject);
begin
    tmr1.Interval:=1;
  if (GetKeyState(Ord('P'))<0) and (GetKeyState(Ord('J'))<0) then
  Begin
    tmr1.Interval := 200; //延时,防止事件触发过快;
    ShowMessage('你按下了个性化快捷键j+p');
  End;
end;

{个性化热键2}
procedure TForm1.btn8Click(Sender: TObject);
begin
  If KeyUse Then
  Begin
    UnregisterHotKey(Handle,TmpAtom);//注册热键
    GlobalDeleteAtom(TmpAtom); //如果热键被使用,就撤销热键pjjp
  End;
  tmr1.Interval:=1;
  tmr1.Enabled:=True;
end;

{热键相应函数}
procedure TForm1.WmHotKey(var msg:TMessage);
begin
{热键对应的函数}
  if (Msg.LparamLo = Shift) AND (Msg.LParamHi = Key) then //如果按下了自定义快捷键
  ShowMessage('自定义快捷键!');
{个性化热键}
  If (Msg.LParamHi=Vk_F11) Then //判断按键是否为F11
  Begin
    if GetKeyState(Ord('T'))<0 then //判断T键是否被按下
    ShowMessage('你按下了个性化快捷键'); //输出消息
  End;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin

end;

{退出时候取消热键}
procedure TForm1.FormDestroy(Sender: TObject);
begin
  {退出时撤销已经注册的热键}
  if not UnRegisterHotKey(Self.Handle,id) then
  MessageDlg('撤销热键失败!',mtError,[mbOk],0);
  {撤销热键}
  GlobalDeleteAtom(Id);
  {退出时撤销已经注册的个性化热键}
  If KeyUse Then
  Begin
    UnregisterHotKey(Handle,TmpAtom);
    GlobalDeleteAtom(TmpAtom);
  End;
end;

{响应TActionList函数}
procedure TForm1.act1Execute(Sender: TObject);
begin
  ShowMessage('您按下了F5!');
end;
{响应TActionList函数}
procedure TForm1.act2Execute(Sender: TObject);
begin
  ShowMessage('您按下了F6!');
end;
{响应TActionList函数}
procedure TForm1.act3Execute(Sender: TObject);
begin
  ShowMessage('您按下了F7!');
end;



end.
原文地址:https://www.cnblogs.com/GodPan/p/3412120.html