Windows 原生风格的鼠标自动操作工具

AI摘要
Deepseek提供支持

平时办公、测试或者玩游戏时,总有一些重复的鼠标点击动作让人厌烦:比如每隔几分钟就要点一下“刷新”、在固定位置进行一系列右键操作,或者为了测试某个软件要反复模拟用户点击。市面上虽然有不少“按键精灵”类工具,但要么体积臃肿,要么需要付费,要么界面不符合我的审美。于是,我决定用 Python 自己写一个——既满足原生 Windows 风格,又能录制、保存、循环回放鼠标操作,而且打包后只有一个 exe 文件,不依赖任何外部环境。

二、技术选型与环境

我用的是 Python 3.8+,依赖库:

  • pyautogui:模拟鼠标移动和点击
  • pynput:监听鼠标事件(按下/释放)
  • tkinter + ttk:GUI 框架,借助 vista 主题呈现原生风格

安装命令:

pip install pyautogui pynput

(打包时再加 pyinstaller


三、项目骨架与数据持久化(防丢数据的核心)

首先解决一个关键问题:打包成 exe 后,配置文件该存哪?

如果直接用 __file__,打包后它指向临时解压目录,退出即销毁,你的宏就全没了。所以我们需要一个函数,返回 exe 真正所在的目录

def get_app_dir():
    if getattr(sys, "frozen", False):
        return os.path.dirname(os.path.abspath(sys.executable))
    return os.path.dirname(os.path.abspath(__file__))

APP_DIR = get_app_dir()
MACROS_FILE = os.path.join(APP_DIR, "macros.json")

同时,为了避免旧版单文件 macro.json 被遗忘,我做了自动迁移:

if os.path.exists(OLD_MACRO_FILE):
    with open(OLD_MACRO_FILE) as f:
        old_steps = json.load(f)
    self.macros = {"默认操作": old_steps}
    self._save_macros_to_disk()

这样用户升级时数据无缝过渡。

另外,打包时加了 -w(无控制台),sys.stdout 可能为 None,一调 print 就崩。所以我做了保护:

if sys.stdout is None:
    sys.stdout = open(os.devnull, "w")
if sys.stderr is None:
    sys.stderr = open(os.devnull, "w")

四、界面布局:原生主题 + 置顶 + 左右分栏

GUI 我用 ttk 并强制加载 vista 主题(Win10/11 原生风格):

style = ttk.Style(self.root)
available = style.theme_names()
for theme in ("vista", "xpnative", "winnative", "clam"):
    if theme in available:
        style.theme_use(theme)
        break

窗口左上角是标题,右上角是“窗口置顶”复选框,通过 attributes("-topmost", ...) 控制。

主体采用左右两栏(grid 布局):

  • 左栏LabelFrame 包裹 Listbox + 三个按钮(加载/重命名/删除)
  • 右栏LabelFrame 包裹录制控制、当前步骤 Listbox、编辑按钮和“保存操作…”

底部是循环控制区,包含间隔输入、开始/停止、倒计时标签、循环次数、红色运行警告。

所有控件都使用系统字体 Segoe UI,并定义了多种 style 来美化标题和倒计时。

关键代码片段(构建右侧录制控制):

rec_frame = ttk.Frame(frame)
rec_frame.pack(fill="x", pady=(0, 8))
self.btn_start_rec = ttk.Button(rec_frame, text="开始录制", command=self.start_recording)
self.btn_start_rec.pack(side="left", padx=(0, 6))
self.btn_stop_rec = ttk.Button(rec_frame, text="停止录制", command=self.stop_recording, state="disabled")
self.btn_stop_rec.pack(side="left")

步骤列表用 Listbox 配合 Consolas 字体显示坐标和间隔,整齐对齐。


五、录制功能:监听、过滤、双击合并

点击“开始录制”后,会清空步骤列表,启动 pynput 监听器:

self.listener = mouse.Listener(on_click=self._on_click)
self.listener.start()

_on_click 回调中,只处理 pressed=True(按下瞬间),并判断坐标是否在面板窗口内,是则忽略:

def _is_click_on_panel(self, x, y):
    rx = self.root.winfo_rootx()
    ry = self.root.winfo_rooty()
    rw = self.root.winfo_width()
    rh = self.root.winfo_height()
    return rx <= x <= rx + rw and ry <= y <= ry + rh

有效点击后,计算与上次点击的时间差 delay,并检查是否符合双击条件(坐标距离 ≤ 6 像素,时间差 ≤ 0.35 秒,同一按键,且上一步是单次点击)。如果满足,就把上一步的 click_type 改为 "double",本次不新增步骤;否则新建一个步骤:

if same_pos and same_btn and fast_enough and last.get("click_type", "single") == "single":
    last["click_type"] = "double"
    self._last_click_time = now
    self.root.after(0, self._update_last_step_in_listbox)
    return

step = {"x": x, "y": y, "button": btn_name, "delay": delay, "click_type": "single"}
self.steps.append(step)
self.root.after(0, self._append_step_to_listbox, step, len(self.steps))

注意这里用 root.after(0, ...) 把 UI 更新放回主线程,避免界面卡顿。


六、多组操作管理:保存、加载、重命名、删除

macros 是一个字典,键为操作名,值为步骤列表(深拷贝后存储)。

保存:调用 save_current_as,弹出输入框,如果重名则询问覆盖,然后写入 JSON:

self.macros[name] = json.loads(json.dumps(self.steps))
self._save_macros_to_disk()

加载:从字典中深拷贝步骤到当前编辑区:

self.steps = json.loads(json.dumps(self.macros[name]))
self.current_macro_name = name
self._refresh_listbox()

重命名:删除旧键,插入新键,刷新列表。

删除:确认后 del self.macros[name]

每个操作后都调用 _save_macros_to_disk() 持久化。


七、循环回放:多线程、倒计时、安全停止

回放不能阻塞 UI,所以我用 threading.Thread 执行循环。开始前先检查步骤是否存在,并读取间隔分钟数转为秒。

核心循环:

def _play_loop(self, interval_seconds):
    while not self._stop_play_flag.is_set():
        self.root.after(0, self.countdown_var.set, "执行中...")
        self._run_once()          # 执行一次所有步骤
        if self._stop_play_flag.is_set():
            return
        self.loop_count += 1
        self.root.after(0, self.loop_count_var.set, f"{self.loop_count} 次")

        # 倒计时(每秒更新一次)
        waited = 0.0
        while waited < interval_seconds:
            if self._stop_play_flag.is_set():
                self.root.after(0, self.countdown_var.set, "--:--")
                return
            remaining = interval_seconds - waited
            mm = int(remaining) // 60
            ss = int(remaining) % 60
            self.root.after(0, self.countdown_var.set, f"{mm:02d}:{ss:02d}")
            time.sleep(0.2)
            waited += 0.2

执行单次操作 _run_once 会遍历所有步骤,移动鼠标(pyautogui.moveTo)、根据 click_type 单击或双击(pyautogui.click(clicks=2)),并在状态栏更新进度。

停止时设置 _stop_play_flag,线程检测到立即退出,并重置 UI 状态。

安全细节:我把 pyautogui.FAILSAFE = False,因为默认的“左上角中断”在倒计时等待时容易被误触,影响用户体验。


八、打包成单 exe(带图标)

使用 PyInstaller,命令如下:

pyinstaller -F -w --icon=mouse_icon.ico --add-data "mouse_icon.ico;." auto_click_panel.py
  • -F:单文件
  • -w:无控制台
  • --icon:指定 exe 图标
  • --add-data:将图标文件打包进 exe,运行时通过 sys._MEIPASS 访问

在代码中,我这样加载图标(兼顾开发环境和打包环境):

meipass = getattr(sys, "_MEIPASS", None)
candidates = []
if meipass:
    candidates.append(os.path.join(meipass, "mouse_icon.ico"))
candidates.append(os.path.join(APP_DIR, "mouse_icon.ico"))
for c in candidates:
    if os.path.exists(c):
        icon_path = c
        break
if icon_path:
    self.root.iconbitmap(icon_path)

这样不管你是直接跑 .py 还是运行打包后的 exe,图标都能正常显示。


九、最终效果与使用心得

最终程序运行起来就是一个清爽的 Windows 风格窗口。录制时面板内点击被自动忽略,回放时红色大字警告防止误操作,倒计时清晰可见。所有宏保存在 exe 同目录的 macros.json 中,拷贝到其他电脑也能直接用。

我平时用它来定时刷新网页、重复测试 UI、挂机采集游戏资源,稳定可靠。代码总共不到 500 行,注释详尽,易于扩展(比如加入键盘录制、条件判断等)。


十、完整代码

由于篇幅,这里不再全文粘贴(你可在原问题中找到完整源码),但上面的代码片段已经覆盖了所有核心逻辑。你只需将它们组合起来,并参考开头的完整文件结构,就能跑起来。

Click_Mouse

手把手打造一个原生 Windows 风格的鼠标自动操作工具

最后的话

通过这篇文章,希望你不仅学会了怎么用,更明白了它是如何一步步实现的。如果你有任何改进想法(比如增加快捷键、热键启动、多语言支持),欢迎在评论区交流。动手实践,你也能写出属于自己的生产力工具!


本文所有代码均在 Windows 10/11 上测试通过,Python 3.8+ 环境。

广告
广告图片
温馨提示 : 非特殊注明,否则均为©李联华的博客网原创文章,本站文章未经授权禁止任何形式转载;来自:俄亥俄州·哥伦布 ,欢迎您的访问!
文章链接:https://www.lilianhua.com/windows-native-style-mouse-automatic-operation-tool.html
请先登录才能参与答题
距本场结束剩 00 00 00 00
轻量应用服务器 2核2G
200M峰值带宽,适用于网站搭建、Web应用、容器环境、电商独立站等
立即前往
扫码进入
扫描二维码购买
文澜千文

文澜千文

请登录以使用此功能。

按住 Ctrl+K 可以调出本站向量搜索
弹窗图片

Linux AI

记不住繁琐的Linux参数?让AI为你精准检索!输入你的需求,一秒锁定标准命令,彻底告别搜索引擎的冗长翻找。

Loading...

请您留言

如有任何关于本站的任何问题,欢迎联系我们,我们会第一时间为您解答。

客服
联系客服咨询

Hi,如果对于本站的任何问题你都可以在此联系到我们,我们会第一时间为您解。

关注微信公众号
QQ联系
立即联系客服
1546482882
lee@8i5.net