delphi全局热键游戏内执行的热键,长按鼠标侧键1,执行循环按下鼠标左键,放开侧键1则跳出循环

delphi全局热键游戏内执行的热键,长按鼠标侧键1,执行循环按下鼠标左键,放开侧键1则跳出循环,怎么做

好像是个硬件问题。需要设备文件或者驱动文件配合。在事件响应上重写长安鼠标侧键1的响应代码,需要找到鼠标的缓冲区地址,向缓冲区写左键信号。需要权限,可能会被系统拒绝或者纠正成原来的服务。还是从硬件上开发比较可靠。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答来自chatgpt:

    针对该问题,可以通过以下步骤实现:

    1. 使用 Windows API函数 SetWindowsHookEx 和 UnhookWindowsHookEx 设置全局鼠标钩子来监听鼠标侧键1的按下和松开事件。

    2. 在鼠标钩子回调函数中,当监听到鼠标侧键1被按下时,启动线程来执行循环按下鼠标左键的操作,并且将线程的句柄保存到全局变量中。

    3. 在鼠标钩子回调函数中,当监听到鼠标侧键1被松开时,向保存在全局变量中的线程发送一个消息,让线程停止循环并且退出。

    4. 在线程中实现循环按下鼠标左键的操作,可以使用 Windows API函数 mouse_event 来模拟鼠标左键按下和弹起的操作。循环停止的条件就是接收到线程的退出消息。

    具体实现代码如下(注意代码中的注释和说明):

    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
    
    type
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Private declarations }
        FHookHandle: HHOOK; // 钩子句柄
        FThreadHandle: THandle; // 线程句柄
        FThreadId: DWORD; // 线程ID
        FExitEvent: THandle; // 线程退出事件
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    type
      PThreadParams = ^TThreadParams;
      TThreadParams = record
        Hwnd: HWND;
        ExitEvent: THandle;
      end;
    
    const
      LEFT_DOWN = $0002; // 鼠标左键按下
      LEFT_UP = $0004; // 鼠标左键弹起
      KEY_DOWN = $8000; // 按键按下
    
    // 钩子回调函数
    function HookCallback(nCode: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    var
      ExitEvent: THandle;
      ThreadParams: PThreadParams;
    begin
      // 监听鼠标事件
      if nCode = HC_ACTION then
      begin
        ThreadParams := PThreadParams(lParam);
        ExitEvent := ThreadParams^.ExitEvent;
    
        // 鼠标侧键1按下
        if (wParam = WM_MOUSEWHEEL) and (LOWORD(GetKeyState(VK_RBUTTON)) <> 0) then
        begin
          // 启动线程,执行循环按下鼠标左键的操作
          Form1.FThreadHandle := CreateThread(nil, 0, @ThreadProc, ThreadParams, 0, Form1.FThreadId);
        end;
        // 鼠标侧键1松开
        else if (wParam = WM_MOUSEWHEEL) and (LOWORD(GetKeyState(VK_RBUTTON)) = 0) and (Form1.FThreadHandle <> 0) then
        begin
          // 发送退出消息,让线程停止循环并且退出
          SetEvent(ExitEvent);
    
          // 等待线程结束
          WaitForSingleObject(Form1.FThreadHandle, INFINITE);
    
          // 关闭线程句柄
          CloseHandle(Form1.FThreadHandle);
          Form1.FThreadHandle := 0;
        end;
      end;
    
      // 调用下一个钩子
      Result := CallNextHookEx(Form1.FHookHandle, nCode, wParam, lParam);
    end;
    
    // 线程函数
    function ThreadProc(lpParameter: Pointer): DWORD; stdcall;
    var
      Params: PThreadParams;
    begin
      Params := PThreadParams(lpParameter);
    
      // 循环按下鼠标左键,直到接收到退出消息
      while WaitForSingleObject(Params^.ExitEvent, 0) <> WAIT_OBJECT_0 do
      begin
        // 模拟鼠标左键按下和弹起
        mouse_event(LEFT_DOWN, 0, 0, 0, 0);
        mouse_event(LEFT_UP, 0, 0, 0, 0);
    
        // 休眠一定时间,以便操作系统能够处理消息
        Sleep(50);
      end;
    
      // 返回线程退出代码
      Result := 0;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      ThreadParams: TThreadParams;
    begin
      // 注册鼠标钩子
      ThreadParams.Hwnd := Handle;
      ThreadParams.ExitEvent := FExitEvent;
      FHookHandle := SetWindowsHookEx(WH_MOUSE_LL, @HookCallback, HInstance, 0);
    
      // 创建线程退出事件
      FExitEvent := CreateEvent(nil, True, False, nil);
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      // 注销鼠标钩子
      UnhookWindowsHookEx(FHookHandle);
    
      // 关闭线程退出事件句柄
      CloseHandle(FExitEvent);
    end;
    
    end.
    

    需要注意的是,由于 SetWindowsHookEx 函数不能直接在 Delphi 中使用,因此我在代码中使用了 HINSTANCE 和 WH_MOUSE_LL 的值来调用该函数。如果你想了解如何在 Delphi 中使用 SetWindowsHookEx 函数,可以参考这篇博客:Delphi中如何设置全局热键。 另外,代码中我使用了一个线程来执行循环按下鼠标左键的操作,这可以保证程序不会因为按下鼠标左键而阻塞。线程在收到退出消息后会停止循环并且退出。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^