I used python3 to make game automation scripts before, and I used many things, and finally I had a complete solution. Feel free to elaborate on the core ideas here:
Game-assisted form design:
There is no need for large software like pyqt, just use the built-in tkinter to write small tools. Of course, it is not purely by hand to type the code, it is achieved through drag and drop. Why, don’t you know that tkinter can generate code by dragging the interface, just like VB?
Haha, PAGE find out.
Game-assisted application release:
Naturally, it was released as a 32-bit version of exe packaged with pyinstaller, with the program icon and version information.
The core simulation aspects of the game:
Of course, it is not achieved by hand-knocking code, but by calling powerful dll plug-ins on the market. For example, com components such as Damo plug-in and Lewan plug-in. In other words, some modules of easy language can be compiled into windll to call.
Auxiliary form hotkey registration:
These need to use the low-level things, realized with win32 things, you can register global hotkeys. The principle is that a single thread is used to detect the hot key press, and then a separate thread is opened to perform the required functions after the hot key is pressed. In view of the fact that the native one is too difficult to write, I encapsulated and wrote a demo by myself. Registering global key combinations and individual hot keys is no problem.
The benevolent in the first three aspects differ. I'll post a core source code for the latter, so that it won't be found later.
Post a new piece of code below:
#! /usr/bin/env python3
# - *- coding: utf-8-*-
# File :Simple hotkey.py
# Author: DaShenHan&Taoist-----First bitter then sweet, let the evening breeze blow the willow face------
# Date :2020/3/4import win32con
import ctypes
import ctypes.wintypes
from threading import Thread,activeCount, enumerate
from time import sleep,time
classHotkey(Thread):
user32 = ctypes.windll.user32
hkey_list ={}
hkey_flags ={} #Press down
hkey_running ={} #Start and stop
_ reg_list ={} #Hotkey information to be registered
def regiskey(self, hwnd=None, flagid=0, fnkey=win32con.MOD_ALT, vkey=win32con.VK_F9): #Register hotkey, default one alt+F9
return self.user32.RegisterHotKey(hwnd, flagid, fnkey, vkey)
def get_reginfo(self):return self._reg_list
def get_id(self,func):
self_id = None
for id in self.get_reginfo():if self.get_reginfo()[id]["func"]== func:
self_id = id
breakif self_id:
self.hkey_running[self_id]= True
return self_id
def get_running_state(self,self_id):if self.hkey_running.get(self_id):return self.hkey_running[self_id]else:return False
def reg(self,key,func,args=None):
id =int(str(round(time()*10))[-6:])
fnkey = key[0]
vkey = key[1]
info ={"fnkey":fnkey,"vkey":vkey,"func":func,"args":args
}
self._reg_list[id]= info
# print(info) #Information to be registered here
sleep(0.1)return id
def fast_reg(self,id,key =(0,win32con.VK_HOME),func = lambda:print('Hotkey registration starts')):if not self.regiskey(None, id, key[0], key[1]):print("Hotkey registration failed")return None
self.hkey_list[id]= func
self.hkey_flags[id]= False
return id
def callback(self):
def inner(self = self):for flag in self.hkey_flags:
self.hkey_flags[flag]= False
while True:for id, func in self.hkey_list.items():if self.hkey_flags[id]:
args = self._reg_list[id]["args"]if args:
# print(args) #Here print the parameters passed to the registration function
thread_it(func,*args)else:thread_it(func)
self.hkey_flags[id]= False
return inner
def run(self):for id in self._reg_list:
reg_info = self._reg_list[id]
fnkey = reg_info["fnkey"]
vkey = reg_info["vkey"]
func = reg_info["func"]
self.fast_reg(id,(fnkey, vkey), func)
fn = self.callback()thread_it(fn) #Start monitoring hotkey press thread
try:
msg = ctypes.wintypes.MSG()while True:if self.user32.GetMessageA(ctypes.byref(msg), None,0,0)!=0:if msg.message == win32con.WM_HOTKEY:if msg.wParam in self.hkey_list:
self.hkey_flags[msg.wParam]= True
self.user32.TranslateMessage(ctypes.byref(msg))
self.user32.DispatchMessageA(ctypes.byref(msg))finally:for id in self.hkey_list:
self.user32.UnregisterHotKey(None, id)
def thread_it(func,*args):
t =Thread(target=func, args=args)
t.setDaemon(True)
t.start()
def jump(func,hotkey):
self_id = hotkey.get_id(func)while hotkey.get_running_state(self_id):print(f"{self_id : }You are beating once a second")sleep(1)
def stop_jump(start_id,hotkey):
hotkey.hkey_running[start_id]= False
print(f"{start_id}About to stop")sleep(1)print(f'Current thread list:{activeCount()}',enumerate())
def main():
hotkey =Hotkey()
start_id = hotkey.reg(key =(win32con.MOD_ALT,win32con.VK_HOME),func=jump,args=(jump,hotkey)) #alt home button to start
hotkey.reg(key =(0,win32con.VK_END),func=stop_jump,args=(start_id,hotkey)) #alt end key end
hotkey.start() #Start the hotkey main thread
print(f"Current total number of threads:{activeCount()}")print('Current thread list:',enumerate())print('After the hot key registration is initialized, try to press the key combination alt+Home or single key END to see the effect')if __name__ =='__main__':main()
The following is the old code, which is troublesome to use.
#! /usr/bin/env python3
# _*_ coding: utf-8 _*_
# File : demo.py
# Author: DaShenHan&Taoist-----First bitter then sweet, let the evening breeze blow the willow face------
# Date :2019/6/28import win32con
import ctypes
import ctypes.wintypes
from threading import Thread, Timer, activeCount, enumerate
from time import sleep
h_ids =[i for i inrange(2)] #Create two hotkey sequences
h_keys ={i: False for i in h_ids} #Initialize all hotkey sequences to False
h_dict ={} #Initialize an empty dictionary, record id and func
classHotkey(Thread): #Create an extended class of Thread
user32 = ctypes.windll.user32 #Load user32.dll
# global h_ids, h_keys,h_dict
def regiskey(self, hwnd=None, flagid=0, fnkey=win32con.MOD_ALT, vkey=win32con.VK_F9): #Register hotkey, default one alt+F9
return self.user32.RegisterHotKey(hwnd, flagid, fnkey, vkey)
def callback(self, id, func):
h_dict[id]= func #This id corresponds to this func, if it is not, it is added, if it is, it is modified
def inner():for key, value in h_dict.items():print(f'Total hotkey pool:{h_ids},Current hotkey number:{key},Current hotkey function:{value}, The current hotkey state:{h_keys[h_ids[key]]}')while True:for key, value in h_dict.items():if h_keys[h_ids[key]]:thread_it(value) #In addition, open a thread to execute value
h_keys[h_ids[key]]= False
return inner
def run(self):
# print(self.user32)if not self.regiskey(None,h_ids[0],win32con.MOD_ALT,win32con.VK_F9): #Register shortcut alt+F9 and judge whether it is successful. This hotkey is used to execute the content that needs to be executed once.
print(f"Hotkey registration failed! id{h_ids[0]}") #Return an error message
if not self.regiskey(None,h_ids[1],0,win32con.VK_F10): #Register the shortcut key F10 and judge whether it is successful. The hot key is used to end the program, and it is best to end this way, otherwise it will affect the next hot key registration.
print(f"Hotkey registration failed! id{h_ids[1]}")
# The following is to detect whether the hotkey is pressed, and release the shortcut at the end
try:
msg = ctypes.wintypes.MSG()while True:if self.user32.GetMessageA(ctypes.byref(msg), None,0,0)!=0:if msg.message == win32con.WM_HOTKEY:if msg.wParam in h_ids:
h_keys[msg.wParam]= True
self.user32.TranslateMessage(ctypes.byref(msg))
self.user32.DispatchMessageA(ctypes.byref(msg))finally:for i in h_ids:
self.user32.UnregisterHotKey(None, i)
# The hot key must be released, otherwise the registration will fail next time, so when the program exits abnormally, the hot key is not released.
# Then next time there is probably no way to register successfully, then you can change to a hotkey test
def thread_it(func,*args):
t =Thread(target=func, args=args)
t.setDaemon(True)
t.start()
def settimeout(func, sec):
def inner():func()Timer(sec, inner).start()thread_it(inner)
def setinterval(func, sec, tmrname, flag=True):
global timer_dict
timer_dict[tmrname]= flag
print("The enabled state of tqtimer has been set to:{}".format(flag))
def inner():
global timer_dict
if timer_dict[tmrname]:func()Timer(sec, inner).start()thread_it(inner)
def clearinterval(timername):
global timer_dict
timer_dict[timername]= False
flag = timer_dict[timername]print("The enabled state of tqtimer has been set to:{}".format(flag))
def test_start():print("Start button pressed...the programe is running")
def test_stop():print("Stop button pressed...the programe is stopped")
def run_ok():
hotkey =Hotkey()
hotkey.start()
fn = hotkey.callback(0, test_start)
fn = hotkey.callback(1, test_stop)thread_it(fn)sleep(0.5)
count =activeCount()print(f"Current total number of threads:{count}")print('Current thread list:',enumerate())print('After the hot key registration is initialized, try to press the key combination alt+F9 or single key F10 to see the effect')while True:
pass
if __name__ =='__main__':run_ok()
Here is the source code without the interface, so I blocked the main thread infinite loop. After running, pressing alt+F9 will print the start button, and pressing F10 will print the stop button.
If you run in tkinter, just delete the while True:pass behind the run_ok function, and then add run_ok() to the init function. This refers to the tkinter program designed with PAGE!
Then the main thread will be automatically blocked when the form is created, and other threads that monitor hotkeys will end with the main thread. During the start-up period, it runs independently without interference.
So far, this article on the implementation of python3 registration global hotkeys is introduced. For more related python3 registration global hotkeys, please search for ZaLou.Cn's previous articles or continue to browse related articles below. Hope you will support ZaLou more in the future .Cn!
Recommended Posts