依赖:
pip install pynput
pip install pywin32
代码:
import tkinter as tk
import time
import json
from pynput.keyboard import Controller, Key, Listener
import win32gui
import threading
class KeyPressSimulator:
def __init__(self, root, output_text):
self.root = root
self.output_text = output_text
self.title = "按键模拟器"
self.root.title(self.title)
self.root.attributes("-topmost", True)
self.root.geometry("600x400+640+360")
self.name = ""
self.name0_label = tk.Label(self.root, text="当前窗口:")
self.name0_label.pack(pady=4)
self.name_label = tk.Label(self.root, bg="lightgray")
self.name_label.pack(pady=4)
self.target0_label = tk.Label(self.root, text="目标窗口:")
self.target0_label.pack(pady=4)
self.target_label = tk.Label(self.root, bg="lightgray")
self.target_label.pack(pady=4)
self.delay_label = tk.Label(self.root, text=f"{'-' * 100}\n模拟延迟 (秒):")
self.delay_label.pack(pady=4)
self.delay_entry = tk.Entry(self.root)
self.delay_entry.insert(tk.END, "1")
self.delay_entry.pack(pady=5)
self.key_label = tk.Label(self.root, text="模拟按键 (用英文逗号分隔):")
self.key_label.pack(pady=4)
self.key_entry = tk.Entry(self.root)
self.key_entry.insert(tk.END, "a,b,c")
self.key_entry.pack(pady=4)
self.fr = tk.Frame(self.root)
self.fr.pack(pady=5)
self.confirm_button = tk.Button(self.fr, text="目标窗口(F6)", command=self.confirm)
self.confirm_button.grid(row=0, column=0, padx=5, pady=5)
self.start_button = tk.Button(self.fr, text="启动按键(F7)", command=self.start_simulation, state=tk.DISABLED)
self.start_button.grid(row=1, column=0, padx=5, pady=5)
self.stop_button = tk.Button(self.fr, text="停止按键(F8)", command=self.stop_simulation, state=tk.DISABLED)
self.stop_button.grid(row=2, column=0, padx=5, pady=5)
self.save_button = tk.Button(self.fr, text="保存设置", command=self.save_settings)
self.save_button.grid(row=0, column=1, padx=5, pady=5)
self.load_button = tk.Button(self.fr, text="读取设置", command=self.load_settings)
self.load_button.grid(row=1, column=1, padx=5, pady=5)
self.clear_button = tk.Button(self.fr, text="清除输出", command=self.clear_output)
self.clear_button.grid(row=2, column=1, padx=5, pady=5)
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
self.keyboard = Controller()
self.simulating = False
self.keys_to_press = []
self.current_key_index = 0
self.rep_name()
self.print_to_output("首先确定目标窗口,然后点击启动。\n活动窗口非目标窗口不工作。")
def confirm(self):
name = self.name
if name:
if name != self.title:
self.print_to_output(f"锁定窗口: {name}")
self.start_button.config(state=tk.NORMAL)
self.stop_button.config(state=tk.DISABLED)
self.confirm_button.config(state=tk.DISABLED)
self.target_label.config(text=name)
else:
self.print_to_output("不能锁定本程序窗口")
else:
self.print_to_output("未能获取到窗口句柄")
def rep_name(self):
title = win32gui.GetWindowText(win32gui.GetForegroundWindow())
if title:
if title != self.title:
self.name = title
self.name_label.config(text=title)
self.root.after(200, self.rep_name)
def start_simulation(self):
try:
delay = float(self.delay_entry.get())
if delay <= 0:
raise ValueError("延迟必须大于0")
except ValueError:
self.print_to_output("无效的延迟值,请输入正数")
return
keys = self.key_entry.get()
if not keys:
self.print_to_output("请输入需要模拟的按键")
return
self.clear_output()
self.simulating = True
self.keys_to_press = [key.strip() for key in keys.split(',')]
self.current_key_index = 0
self.start_button.config(state=tk.DISABLED)
self.stop_button.config(state=tk.NORMAL)
self.confirm_button.config(state=tk.DISABLED)
self.simulate_key_press()
def stop_simulation(self):
self.simulating = False
self.start_button.config(state=tk.NORMAL)
self.stop_button.config(state=tk.DISABLED)
self.confirm_button.config(state=tk.NORMAL)
def simulate_key_press(self):
if self.simulating:
delay = float(self.delay_entry.get())
if self.target_label.cget("text") == self.name_label.cget("text"):
if self.keys_to_press:
key_to_press = self.keys_to_press[self.current_key_index]
self.keyboard.press(key_to_press)
time.sleep(0.1)
self.keyboard.release(key_to_press)
self.print_to_output(f"模拟按键: {key_to_press},延迟: {delay}秒")
self.current_key_index = (self.current_key_index + 1) % len(self.keys_to_press)
self.root.after(int(delay * 1000), self.simulate_key_press)
def save_settings(self):
settings = {"keys": self.key_entry.get(), "delay": self.delay_entry.get()}
try:
with open("按键机设置.json", "w") as json_file:
json.dump(settings, json_file)
self.print_to_output("设置已保存")
except Exception as e:
self.print_to_output(f"保存设置失败:{e}")
def load_settings(self):
try:
with open("按键机设置.json", "r") as json_file:
settings = json.load(json_file)
self.key_entry.delete(0, tk.END)
self.key_entry.insert(tk.END, settings["keys"])
self.delay_entry.delete(0, tk.END)
self.delay_entry.insert(tk.END, settings["delay"])
self.print_to_output("设置已加载")
except FileNotFoundError:
self.print_to_output("没有找到保存的设置文件")
except json.JSONDecodeError:
self.print_to_output("配置文件格式错误")
except Exception as e:
self.print_to_output(f"加载设置失败:{e}")
def print_to_output(self, text):
self.output_text.insert(tk.END, text + "\n")
self.output_text.yview(tk.END)
def on_closing(self):
self.stop_simulation()
self.root.destroy()
def clear_output(self):
self.output_text.delete(1.0, tk.END)
def start_key_listener():
def on_press(key):
if key == Key.f6:
app.confirm()
elif key == Key.f7:
app.start_simulation()
elif key == Key.f8:
app.stop_simulation()
with Listener(on_press=on_press) as listener:
listener.join()
if __name__ == "__main__":
rt = tk.Tk()
out_text = tk.Text(rt, width=50, height=30)
out_text.pack(side=tk.RIGHT, padx=10, pady=10)
app = KeyPressSimulator(rt, out_text)
listener_thread = threading.Thread(target=start_key_listener, daemon=True)
listener_thread.start()
rt.mainloop()