MouseKeyHook 应用程序在启动时滞后并且无法关闭

Posted

技术标签:

【中文标题】MouseKeyHook 应用程序在启动时滞后并且无法关闭【英文标题】:MouseKeyHook application lags on boot and can't be closed 【发布时间】:2015-11-21 17:51:41 【问题描述】:

我使用 MouseKeyHook 编写了一个简单的自动点击器。

我使用 MouseKeyHook 的原因是为了检测整个 Windows 操作系统中的全局左键单击。

虽然,当我运行 .exe 时,该软件在单击时出现延迟,一段时间后我似乎无法再点击“X”按钮,并且该应用程序使我的窗口崩溃或减慢了一切速度。

我正在制作这个软件来测试我们的游戏,但这并没有真正的帮助:P

软件代码如下:

using Gma.System.MouseKeyHook;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Rapid_Fire

public partial class Form1 : Form

    #region structs
    /// <summary>
    /// Structure for SendInput function holding relevant mouse coordinates and information
    /// </summary>
    public struct INPUT
    
        public uint type;
        public MOUSEINPUT mi;
    ;

    /// <summary>
    /// Structure for SendInput function holding coordinates of the click and other information
    /// </summary>
    public struct MOUSEINPUT
    
        public int dx;
        public int dy;
        public int mouseData;
        public int dwFlags;
        public int time;
        public IntPtr dwExtraInfo;
    ;
    #endregion

    // Constants for use in SendInput and mouse_event
    public const int INPUT_MOUSE = 0x0000;
    public const int MOUSEEVENTF_LEFTDOWN = 0x0002;
    public const int MOUSEEVENTF_LEFTUP = 0x0004;

    private const int INTERVAL = 10;

    private bool m_fire = false;
    private bool m_close = false;
    private int m_counter = INTERVAL;
    private INPUT m_input = new INPUT();
    private IKeyboardMouseEvents m_GlobalHook;

    public Form1()
    
        InitializeComponent();
        Subscribe();
        InitAutoClick();

        this.FormClosed += new FormClosedEventHandler(formClosed);
    

    private void Subscribe()
    
        m_GlobalHook = Hook.GlobalEvents();
        m_GlobalHook.KeyPress += GlobalHookKeyPress;
        m_GlobalHook.MouseDownExt += GlobalHookMouseDownExt;
    

    private void GlobalHookKeyPress(object sender, KeyPressEventArgs e)
    
        if (e.KeyChar == 'q') m_fire = false;
    

    private void GlobalHookMouseDownExt(object sender, MouseEventExtArgs e)
    
        m_fire = true;
        RapidFire();
    

    private void InitAutoClick()
    
        m_input.type = INPUT_MOUSE;
        m_input.mi.dx = 0;
        m_input.mi.dy = 0;
        m_input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
        m_input.mi.dwExtraInfo = IntPtr.Zero;
        m_input.mi.mouseData = 0;
        m_input.mi.time = 0;
    

    private void RapidFire()
    
        while (m_fire && !m_close)
        
            if (m_counter <= 0)
            
                // ClickLeftMouseButtonSendInput();
                m_counter = INTERVAL;
            
            m_counter--;
        
    

    private void ClickLeftMouseButtonSendInput()
    
        // Send a left click down followed by a left click up to simulate a full left click
        SendInput(1, ref m_input, Marshal.SizeOf(m_input));
        m_input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
        SendInput(1, ref m_input, Marshal.SizeOf(m_input));
    

    private void formClosed(object sender, FormClosedEventArgs e)
    
        m_fire = false;
        m_close = true;
        Unsubscribe();
    

    public void Unsubscribe()
    
        m_GlobalHook.MouseDownExt -= GlobalHookMouseDownExt;
        m_GlobalHook.KeyPress -= GlobalHookKeyPress;
        m_GlobalHook.Dispose();
    


【问题讨论】:

一旦它进入 RapidFire() 然后节目就结束了,你的 UI 线程开始 100% 燃烧并且不会有更多的 UI 事件。所以 m_fire 和 m_close 变量不能改变。永远不要挂起 UI 线程。 所以我要在新线程上运行它? :) 编写合理的代码是首先要考虑的事情。除了 Random.Next() Once the q button is hit ... 该消息将永远不会被处理,因为 UI 线程正忙于循环。所有 UI 消息(按键、鼠标点击)都将暂停,直到 RapidFire 完成。您可能想为BackgroundWorker 使用BackgroundWorker 或单独的线程。 用一个新线程修复了它,谢谢大家 :D 由于我没有得到真正的答案,我不能将其标记为好的解决方案 :( 评论不能标记为已解决的答案.. 【参考方案1】:

通过另一种方式修复了脚本。原来我必须将它附加到鼠标左键按下事件:D

这里的脚本是:

using Gma.System.MouseKeyHook;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Rapid_Fire

public partial class Form1 : Form

    [DllImport("user32.dll", SetLastError = true)]
    public static extern int SendInput(int nInputs, ref INPUT pInputs, int cbSize);

    #region structs
    /// <summary>
    /// Structure for SendInput function holding relevant mouse coordinates and information
    /// </summary>
    public struct INPUT
    
        public uint type;
        public MOUSEINPUT mi;
    ;

    /// <summary>
    /// Structure for SendInput function holding coordinates of the click and other information
    /// </summary>
    public struct MOUSEINPUT
    
        public int dx;
        public int dy;
        public int mouseData;
        public int dwFlags;
        public int time;
        public IntPtr dwExtraInfo;
    ;
    #endregion

    public const int INPUT_MOUSE = 0x0000;
    public const int MOUSEEVENTF_LEFTDOWN = 0x0002;
    public const int MOUSEEVENTF_LEFTUP = 0x0004;

    private const int TIMES_CLICK_FIRE = 25;

    private bool m_fire = false;
    private INPUT m_input = new INPUT();
    private IKeyboardMouseEvents m_Events;

    public Form1()
    
        InitializeComponent();
        SubscribeGlobal();
        InitAutoClick();

        this.FormClosed += new FormClosedEventHandler(formClosed);
    

    private void SubscribeGlobal()
    
        Unsubscribe();
        Subscribe(Hook.GlobalEvents());
    

    private void Subscribe(IKeyboardMouseEvents events)
    
        m_Events = events;
        m_Events.MouseUp += OnMouseUp;
        m_Events.MouseDown += OnMouseDown;
       

    private void InitAutoClick()
    
        m_input.type = INPUT_MOUSE;
        m_input.mi.dx = 0;
        m_input.mi.dy = 0;
        m_input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
        m_input.mi.dwExtraInfo = IntPtr.Zero;
        m_input.mi.mouseData = 0;
        m_input.mi.time = 0;
    

    private void Log(string text)
    
        if (IsDisposed) return;
        Console.WriteLine(text);
    

    private void OnMouseDown(object sender, MouseEventArgs e)
    
        m_fire = true;

        Thread thread = new Thread(RapidFire);
        thread.Start();
    

    private void RapidFire()
    
        while (m_fire)
        
            for (; ; )
            
                ClickLeftMouseButtonSendInput();
            
        
    

    private void OnMouseUp(object sender, MouseEventArgs e)
    
        m_fire = false;
    

    private void ClickLeftMouseButtonSendInput()
    
        SendInput(1, ref m_input, Marshal.SizeOf(m_input));
        m_input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
        SendInput(1, ref m_input, Marshal.SizeOf(m_input));
    

    private void formClosed(object sender, FormClosedEventArgs e)
    
        Unsubscribe();
    

    private void Unsubscribe()
    
        if (m_Events == null) return;
        m_Events.MouseUp -= OnMouseUp;
        m_Events.MouseDown -= OnMouseDown;

        m_Events.Dispose();
        m_Events = null;
    


【讨论】:

以上是关于MouseKeyHook 应用程序在启动时滞后并且无法关闭的主要内容,如果未能解决你的问题,请参考以下文章

重复使用的单元格在刷新图像时滞后

在滚动视图中动态隐藏状态栏时滞后/屏幕冻结(Swift 3)

RecyclerView 滚动时滞后

当 win.blit() 后台 pygame 时滞后

当 win.blit() 后台 pygame 时滞后

我的 MainActivity 在使用 android 旧版本(例如 oreo)时滞后,但在最新版本中运行良好,如何解决?