【问题标题】:How can I handle a keyboard shortcut when my program isn't active?当我的程序不活动时,如何处理键盘快捷键?
【发布时间】:2011-05-06 03:38:16
【问题描述】:

如果我这样使用它可以..用于多个事件吗?

unit Unit4;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Clipbrd;

type
  TForm4 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure WMHotkey(var Message: TWMHotKey); message WM_HOTKEY;
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

const
  MY_ID = 123;
  MY_ID1 = 123;
  MY_ID2 = 123;

{$R *.dfm}

procedure TForm4.FormCreate(Sender: TObject);
begin
  RegisterHotKey(Handle, MY_ID, MOD_CONTROL, ord('1'));
   RegisterHotKey(Handle, MY_ID1, MOD_CONTROL, ord('2'));
    RegisterHotKey(Handle, MY_ID2, MOD_CONTROL, ord('3'));
end;

procedure TForm4.FormDestroy(Sender: TObject);
begin
  UnregisterHotKey(Handle, MY_ID);
  UnregisterHotKey(Handle, MY_ID1);
  UnregisterHotKey(Handle, MY_ID2);
end;

procedure TForm4.WMHotkey(var Message: TWMHotKey);
begin
  if Message.HotKey = MY_ID then
  begin

    if not AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), true) then
      RaiseLastOSError;

    try
      Clipboard.AsText := 'text1';
      SendMessage(GetFocus, WM_PASTE, 0, 0);
    finally
      AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), false);
    end;

    if Message.HotKey = MY_ID1 then
  begin

    if not AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), true) then
      RaiseLastOSError;

    try
      Clipboard.AsText := 'text2';
      SendMessage(GetFocus, WM_PASTE, 0, 0);
    finally
      AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), false);
    end;

  if Message.HotKey = MY_ID2 then
  begin

    if not AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), true) then
      RaiseLastOSError;

    try
      Clipboard.AsText := 'text3';
      SendMessage(GetFocus, WM_PASTE, 0, 0);
    finally
      AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), false);
    end;

  end;
end;

end;
end;
end.

【问题讨论】:

标签: delphi events shortcut taction


【解决方案1】:

使用RegisterHotKey 函数。如果您希望应用程序不可见,您可能需要 my answer to a similar question 中的所有详细信息。

试试这个:

unit Unit4;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Clipbrd;

type
  TForm4 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure WMHotkey(var Message: TWMHotKey); message WM_HOTKEY;
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

const
  MY_ID = 123;

{$R *.dfm}

procedure TForm4.FormCreate(Sender: TObject);
begin
  RegisterHotKey(Handle, MY_ID, MOD_CONTROL, ord('1'));
end;

procedure TForm4.FormDestroy(Sender: TObject);
begin
  UnregisterHotKey(Handle, MY_ID);
end;

procedure TForm4.WMHotkey(var Message: TWMHotKey);
begin
  if Message.HotKey = MY_ID then
  begin

    if not AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), true) then
      RaiseLastOSError;

    try
      Clipboard.AsText := 'This is my own text!';
      SendMessage(GetFocus, WM_PASTE, 0, 0);
    finally
      AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), false);
    end;

  end;
end;

end.

当然,您需要使用这种方法并对其进行修改,使其适合您的特定情况。 (也就是说,您可能需要的不仅仅是在 Ctrl+1 上打印“这是我自己的文本!”的应用程序,但没有别的。)

【讨论】:

  • 你能举个例子吗?
  • 假设当我按 ctrl+1 时,delphi 这个词会出现在每个 Windows 应用程序上,比如 microsoft word 左右
  • @andrei:我现在举一个例子。但它似乎至少在 Word 2010 中不起作用(但记事本工作正常)。
  • 安德烈亚斯,当您使用RegisterHotKey 释放热键时,您只需使用UnregisterHotKey 函数。
  • 我知道。我只是草率地向 OP 展示了这个想法。
【解决方案2】:

为了补充 Andreas 的答案,您可以将 RegisterHotKey 函数与 WM_HOTKEY windows 消息结合使用。

试试这个代码

type
  TForm17 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    HotKey1 : Integer;
    HotKey2 : Integer;
    procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;
  public
    { Public declarations }
  end;

var
  Form17: TForm17;

implementation

{$R *.dfm}

{ TForm17 }

procedure TForm17.FormCreate(Sender: TObject);
const
  MOD_CONTROL = $0002;//0x0002
begin
  // Register Ctrl + 1 hotkey
  HotKey1 := GlobalAddAtom('Hotkey1');
  RegisterHotKey(Handle, HotKey1, MOD_CONTROL, Ord('1'));
  // Register  Ctrl + 2 hotkey
  HotKey2 := GlobalAddAtom('Hotkey2');
  RegisterHotKey(Handle, HotKey2, MOD_CONTROL, Ord('2'));
end;

procedure TForm17.FormDestroy(Sender: TObject);
begin
  //unregister the hotkeys
  UnRegisterHotKey(Handle, HotKey1);
  GlobalDeleteAtom(HotKey1);
  UnRegisterHotKey(Handle, HotKey2);
  GlobalDeleteAtom(HotKey2);
end;

procedure TForm17.WMHotKey(var Msg: TWMHotKey); 
begin
  if Msg.HotKey = HotKey1 then
  begin
    ShowMessage('Ctrl + 1 was pressed');
    //do your stuff
  end
  else
  if Msg.HotKey = HotKey2 then
  begin
    ShowMessage('Ctrl + 2 was pressed');
    //do your stuff
  end;
end;

【讨论】:

    【解决方案3】:

    正如其他人所建议的,它是 RegisterHotKey 函数。但是,要设计的应用程序的正确实现需要键盘挂钩和 DLL 注入应用程序。

    我建议你看看 TypePilot 应用程序。它允许您使用您键入的某些快捷方式键入或复制/粘贴任何文本。例如。您可以键入“thnk”,应用程序会将其替换为“thank you”。

    【讨论】:

    • 为什么?我认为获取活动窗口的句柄并发送粘贴消息就足够了?
    • 粘贴消息将粘贴剪贴板内容。如果您认为您将用文本替换剪贴板内容,粘贴文本并将数据放回剪贴板,请再想一想:剪贴板实际上没有必要包含数据。可以将数据的引用放到剪贴板中,您将无法正确保存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-15
    • 2016-02-05
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多