Code:
import sys
import win32api
import win32con
import win32gui
import win32process
import psutil
import time
import threading
import tkinter as tk
from tkinter import messagebox
import darkdetect
class KeyPresser:
def __init__(self, process_id, send_space, send_4, send_y):
self.process_id = process_id
self.send_space = send_space
self.send_4 = send_4
self.send_y = send_y
self.hwnd = self.find_window()
self.running = False
self.threads = []
def find_window(self):
def enum_callback(hwnd, process_id_list):
_, pid = win32process.GetWindowThreadProcessId(hwnd)
if pid == self.process_id:
process_id_list.append(hwnd)
process_id_list = []
win32gui.EnumWindows(enum_callback, process_id_list)
if not process_id_list:
raise Exception(f"Fenster für Prozess-ID '{self.process_id}' nicht gefunden.")
return process_id_list[0]
def send_keystroke(self, key, hold=False):
if hold:
win32api.SendMessage(self.hwnd, win32con.WM_KEYDOWN, key, 0)
else:
win32api.SendMessage(self.hwnd, win32con.WM_KEYDOWN, key, 0)
win32api.SendMessage(self.hwnd, win32con.WM_KEYUP, key, 0)
def hold_key(self, key):
while self.running:
self.send_keystroke(key, hold=True)
time.sleep(0.01)
def repeat_key(self, key, interval=0.1):
while self.running:
self.send_keystroke(key)
time.sleep(interval)
def start(self):
self.running = True
if self.send_space:
self.threads.append(threading.Thread(target=self.hold_key, args=(win32con.VK_SPACE,)))
if self.send_4:
self.threads.append(threading.Thread(target=self.repeat_key, args=(ord('4'),)))
if self.send_y:
self.threads.append(threading.Thread(target=self.repeat_key, args=(ord('Y'), 0.05)))
for thread in self.threads:
thread.daemon = True
thread.start()
def stop(self):
self.running = False
for thread in self.threads:
thread.join()
class App:
def __init__(self, root, window_title):
self.key_presser = None
root.title(window_title)
if darkdetect.isDark():
self.bg_color = "#333333"
self.fg_color = "#FFFFFF"
else:
self.bg_color = "#FFFFFF"
self.fg_color = "#000000"
root.configure(bg=self.bg_color)
self.process_frame = tk.Frame(root, bg=self.bg_color)
self.process_frame.grid(row=0, column=0, columnspan=2, pady=5)
self.select_process_button = tk.Button(self.process_frame, text="Prozess auswählen", command=self.open_process_selection, bg=self.bg_color, fg=self.fg_color)
self.select_process_button.pack(pady=5)
self.selected_process_label = tk.Label(self.process_frame, text="Kein Prozess ausgewählt", bg=self.bg_color, fg=self.fg_color)
self.selected_process_label.pack(pady=5)
self.checkbox_frame = tk.Frame(root, bg=self.bg_color)
self.checkbox_frame.grid(row=1, column=0, columnspan=2, pady=5)
self.space_var = tk.BooleanVar()
self.space_checkbox = tk.Checkbutton(self.checkbox_frame, text="Leertaste", variable=self.space_var, bg=self.bg_color, fg=self.fg_color, selectcolor=self.bg_color)
self.space_checkbox.pack(side=tk.LEFT, padx=10)
self.key4_var = tk.BooleanVar()
self.key4_checkbox = tk.Checkbutton(self.checkbox_frame, text="Taste 4", variable=self.key4_var, bg=self.bg_color, fg=self.fg_color, selectcolor=self.bg_color)
self.key4_checkbox.pack(side=tk.LEFT, padx=10)
self.keyy_var = tk.BooleanVar()
self.keyy_checkbox = tk.Checkbutton(self.checkbox_frame, text="Taste Y", variable=self.keyy_var, bg=self.bg_color, fg=self.fg_color, selectcolor=self.bg_color)
self.keyy_checkbox.pack(side=tk.LEFT, padx=10)
self.button_frame = tk.Frame(root, bg=self.bg_color)
self.button_frame.grid(row=2, column=0, columnspan=2, pady=10)
self.start_button = tk.Button(self.button_frame, text="Start", command=self.start, bg=self.bg_color, fg=self.fg_color)
self.start_button.pack(side=tk.LEFT, padx=10)
self.stop_button = tk.Button(self.button_frame, text="Stop", command=self.stop, bg=self.bg_color, fg=self.fg_color)
self.stop_button.pack(side=tk.LEFT, padx=10)
def open_process_selection(self):
self.process_window = tk.Toplevel()
self.process_window.title("Prozess auswählen")
process_listbox = tk.Listbox(self.process_window, selectmode=tk.SINGLE)
process_listbox.pack(fill=tk.BOTH, expand=True)
processes = []
for p in psutil.process_iter(['pid', 'name']):
try:
for hwnd in self.get_hwnds_for_pid(p.pid):
if win32gui.IsWindowVisible(hwnd):
processes.append((p.pid, p.name()))
break
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
continue
for pid, name in processes:
process_listbox.insert(tk.END, f"{pid} - {name}")
select_button = tk.Button(self.process_window, text="Auswählen", command=lambda: self.select_process(process_listbox))
select_button.pack(pady=5)
def get_hwnds_for_pid(self, pid):
def callback(hwnd, hwnds):
if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowText(hwnd):
_, found_pid = win32process.GetWindowThreadProcessId(hwnd)
if found_pid == pid:
hwnds.append(hwnd)
return True
hwnds = []
win32gui.EnumWindows(callback, hwnds)
return hwnds
def select_process(self, listbox):
selection = listbox.curselection()
if selection:
process_info = listbox.get(selection[0])
self.selected_process_label.config(text=f"Ausgewählt: {process_info}")
self.process_id = int(process_info.split(' - ')[0])
self.process_window.destroy()
else:
messagebox.showwarning("Warnung", "Bitte wählen Sie einen Prozess aus.")
def start(self):
if hasattr(self, 'process_id'):
send_space = self.space_var.get()
send_4 = self.key4_var.get()
send_y = self.keyy_var.get()
self.key_presser = KeyPresser(self.process_id, send_space, send_4, send_y)
self.key_presser.start()
else:
messagebox.showerror("Fehler", "Bitte wählen Sie einen Prozess aus.")
def stop(self):
if self.key_presser:
self.key_presser.stop()
else:
messagebox.showwarning("Warnung", "Kein laufender Prozess zum Stoppen.")
if __name__ == "__main__":
if len(sys.argv) < 3 or sys.argv[2] != "valid_start":
tk.messagebox.showerror("Fehler", "Dieses Macro muss über StartMacro gestartet werden.")
sys.exit(1)
root = tk.Tk()
window_title = sys.argv[1] if len(sys.argv) > 1 else " "
app = App(root, window_title)
root.mainloop()