GUI视窗 使用鼠标指标进行定位程序,获得程序的视窗句柄、视窗类名、视窗标题、执行绪ID、行程ID、行程名称、行程路径、CPU用量、执行绪数、视窗定位及鼠标坐标,并附加五项可操作控制元件,强制置顶、取消置顶、显示顶部、前置终止、打开档案所在位置,可显示定位程序的图示,
pip install 模块名
pip install -U 模块名
import tkinter
from tkinter import *
from tkinter.ttk import *
import win32api
import win32gui
import win32con
import win32ui
import time
from win32 import win32process
import psutil
import subprocess
from PIL import Image
import os
基本的GUI界面,程序的图示可要可不要,也可以自己去制作
root = Tk()
root.title('贱工坊-视窗句柄') # 程序的标题名称
root.geometry("480x320+512+288") # 视窗的大小及页面的显示位置
root.resizable(False, False) # 固定页面不可放大缩小
root.iconbitmap("picture.ico") # 程序的图示
在程序里创建画布改变颜色,添加图片,这个图片是圆形图示
canvas = tkinter.Canvas(root, bg="#ebebeb", height=400, width=700, borderwidth=-3) # 创建画布
canvas.pack(side='top') # 放置画布(为上端)
canvas_2 = tkinter.Canvas(root, bg="#ebebeb",cursor='target', height=50, width=50, borderwidth=-2) # 创建画布
canvas_2.place(x=402, y=70) # 放置画布(为上端)
image_file = tkinter.PhotoImage(file="./Key.png") # 加载图片档案
canvas_2.create_image(0, 0, anchor='nw', image=image_file) # 将图片置于画布上
在程序里添加文本框,用来放置资料
# 配置视窗句柄
var_hwnd = tkinter.StringVar()
tkinter.Entry(root, width=20,borderwidth=1,bg='#ebebeb',textvariable=var_hwnd).place(x=70,y=10)
# 配置标题名称
var_title = tkinter.StringVar()
tkinter.Entry(root, width=54, borderwidth=1,bg='#ebebeb', textvariable=var_title).place(x=70, y=40)
# 配置视窗类名
var_clsname = tkinter.StringVar()
tkinter.Entry(root, width=20, borderwidth=1, bg='#ebebeb', textvariable=var_clsname).place(x=306, y=10)
# 配置执行绪ID
var_hread_id = tkinter.StringVar()
tkinter.Entry(root, width=10, borderwidth=1, bg='#ebebeb', textvariable=var_hread_id).place(x=70, y=70)
# 配置行程ID
var_process_id = tkinter.StringVar()
tkinter.Entry(root, width=10, borderwidth=1, bg='#ebebeb', textvariable=var_process_id).place(x=204, y=70)
# 配置程序名称
var_process = tkinter.StringVar()
tkinter.Entry(root, width=29, borderwidth=1, bg='#ebebeb', textvariable=var_process).place(x=70, y=100)
# 配置程序路径
var_p_bin = tkinter.StringVar()
tkinter.Entry(root, width=54, borderwidth=1, bg='#ebebeb', textvariable=var_p_bin).place(x=70, y=130)
# 配置CPU利用率
var_mem_percent = tkinter.StringVar()
tkinter.Entry(root, width=20, borderwidth=1, bg='#ebebeb', textvariable=var_mem_percent).place(x=70, y=160)
# 配置执行绪数
var_num_threads = tkinter.StringVar()
tkinter.Entry(root, width=20, borderwidth=1, bg='#ebebeb', textvariable=var_num_threads).place(x=306, y=160)
# 配置视窗左上
var_top = tkinter.StringVar()
tkinter.Entry(root, width=6, borderwidth=1, bg='#ebebeb', textvariable=var_top).place(x=70, y=190)
# 配置视窗左下
var_left = tkinter.StringVar()
tkinter.Entry(root, width=6, borderwidth=1, bg='#ebebeb', textvariable=var_left).place(x=70, y=220)
# 配置视窗右上
var_right = tkinter.StringVar()
tkinter.Entry(root, width=6, borderwidth=1, bg='#ebebeb', textvariable=var_right).place(x=194, y=190)
# 配置视窗右下
var_bottom = tkinter.StringVar()
tkinter.Entry(root, width=6, borderwidth=1, bg='#ebebeb', textvariable=var_bottom).place(x=194, y=220)
# 配置坐标x,y
var_point = tkinter.StringVar()
tkinter.Entry(root, width=24, borderwidth=1, bg='#ebebeb', textvariable=var_point).place(x=70, y=250)
程序添加标签,用来标注
tkinter.Label(canvas, bg="#ebebeb", text='视窗句柄').place(x=10, y=8)
tkinter.Label(canvas, bg="#ebebeb", text='视窗标题').place(x=10, y=38)
tkinter.Label(canvas, bg="#ebebeb", text='视窗类名').place(x=248, y=8)
tkinter.Label(canvas, bg="#ebebeb", text='执行绪ID').place(x=10, y=68)
tkinter.Label(canvas, bg="#ebebeb", text='行程ID').place(x=154, y=68)
tkinter.Label(canvas, bg="#ebebeb", text='行程名称').place(x=10, y=98)
tkinter.Label(canvas, bg="#ebebeb", text='行程路径').place(x=10, y=128)
tkinter.Label(canvas, bg="#ebebeb", text='CPU用量').place(x=10, y=158)
tkinter.Label(canvas, bg="#ebebeb", text='执行绪数').place(x=258, y=158)
tkinter.Label(canvas, bg="#ebebeb", text='视窗左上').place(x=10, y=188)
tkinter.Label(canvas, bg="#ebebeb", text='视窗左下').place(x=10, y=218)
tkinter.Label(canvas, bg="#ebebeb", text='视窗右上').place(x=134, y=188)
tkinter.Label(canvas, bg="#ebebeb", text='视窗右下').place(x=134, y=218)
tkinter.Label(canvas, bg="#ebebeb", text='坐标x,y').place(x=10, y=248)
程序内放置一个CSDN博主二维码,直达博主主页,图片的尺寸是 200x80 ,二维码由博主制作,内置为博主的主页链接
# 放置二维码
canvas_4 = tkinter.Canvas(root, bg="red", height=80, width=200, borderwidth=-2)
canvas_4.place(x=250, y=190)
image_file_4 = tkinter.PhotoImage(file="./share.png") # 加载图片档案
canvas_4.create_image(0, 0, anchor='nw', image=image_file_4) # 将图片置于画布上
获取鼠标的坐标,通过坐标获取视窗句柄,然后通过句柄获取视窗标题、视窗类名、执行绪ID、行程ID和视窗坐标,然后通过行程ID获取程序名称、程序路径、CUP用量和执行绪数,通程序式路径获取软件图示,这里关联着鼠标的bind <B1-Motion>左键持续移动,只要鼠标左键持续移动则会执行如下代码,动一下执行一次
point = win32api.GetCursorPos() # 鼠标位置
hwnd = win32gui.WindowFromPoint(point) # 视窗句柄
title = win32gui.GetWindowText(hwnd) # 视窗标题
clsname = win32gui.GetClassName(hwnd) # 视窗类名
hread_id, process_id = win32process.GetWindowThreadProcessId(hwnd) #执行绪ID 行程ID
process = psutil.Process(process_id) # 程序名称 通过行程ID获取
p_bin = psutil.Process(process_id).exe() # 程序路径 通过行程ID获取
mem_percent = psutil.Process(process_id).memory_percent() # CPU利用率 通过行程ID获取
num_threads = psutil.Process(process_id).num_threads() # 执行绪数 通过行程ID获取
left, top, right, bottom = win32gui.GetWindowRect(hwnd) #视窗坐标 通过视窗句柄获取 四个角的坐标
picture() # 更换软件图示
ICON(p_bin) # 获取软件图示
var_hwnd.set(hwnd)
var_title.set(title)
var_clsname.set(clsname)
var_hread_id.set(hread_id)
var_process_id.set(process_id)
var_process.set(process.name())
var_p_bin.set(p_bin)
var_mem_percent.set(mem_percent)
var_num_threads.set(num_threads)
var_left.set(left)
var_top.set(top)
var_right.set(right)
var_bottom.set(bottom)
var_point.set(point)
这个代码的用处是用来获取软件的图示,通过路径获取,并持续保存替换 icon.png 图片
# 获取软件图示
def ICON(exePath2):
try:
exePath = exePath2.replace("\\", "/") # 替换
large, small = win32gui.ExtractIconEx(f'{exePath}', 0)
useIcon = large[0]
destroyIcon = small[0]
win32gui.DestroyIcon(destroyIcon)
hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
hbmp = win32ui.CreateBitmap()
hbmp.CreateCompatibleBitmap(hdc, ico_x, ico_x)
hdc = hdc.CreateCompatibleDC()
hdc.SelectObject(hbmp)
hdc.DrawIcon((0, 0), useIcon)
bmpstr = hbmp.GetBitmapBits(True)
img = Image.frombuffer(
'RGBA',
(32, 32),
bmpstr, 'raw', 'BGRA', 0, 1
)
img.save('icon.png')
except:
pass
将保存好扽图片进行加载进来,pictures.png 是软件的默认图示,而 icon.png 则是保存下来的图示进行替换,所以指标指向哪里就会替换为哪一个软件的图示,原理就是这样,只是有一部分的软件图示获取不了或使用不了,会造成软件内图示变白
image_file_3 = tkinter.PhotoImage(file="pictures.png") # 软件第一次打开时要呈现的图片
Button_2 = Button(canvas_3,image=image_file_3).place(x=0, y=0)
# 更换软件图示
def picture():
try:
image_file_3.config(file='icon.png') # 替换
except:
pass
这是能获取到图示的
这是获取不到图示或使用不了图示的,只有绝少部分获取不到或使用不了,不影响软件的使用,
下面的是按钮所对应的函式控制元件,用来置顶、取消置顶、显示顶部、终止程序和打开档案所在位置,这里要注意的是我采用的taskkill 计算机自带的终止指令,可以不会支持win7以下的计算机命令,还有就是我这个终止命令会把程序的子程序也终止掉,所以尽量不要去尝试终止档案夹和桌面之类的,如果终止掉了荧屏会全白,可以使用【ctrl+alt+delete】进入任务管理器,新建任务,explorer 回车即可恢复,但是有可能你的资料都会被强行关闭,
# 置顶 通过句柄
def set_top():
try:
win32gui.SetWindowPos(var_hwnd.get(), win32con.HWND_TOPMOST, 0, 0, 0, 0,win32con.SWP_NOMOVE | win32con.SWP_NOACTIVATE | win32con.SWP_NOOWNERZORDER | win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE)
except:
pass
# 取消置顶 通过句柄
def set_down():
try:
win32gui.SetWindowPos(var_hwnd.get(), win32con.HWND_NOTOPMOST, 0, 0, 0, 0,win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE | win32con.SWP_NOMOVE)
except:
pass
# 显示在顶部 通过句柄
def set_yop_p():
try:
win32gui.SetForegroundWindow(var_hwnd.get())
except:
pass
# 终止程序
def kill():
try:
subprocess.Popen("taskkill /F /T /PID " + var_process_id.get(), shell=True)
subprocess.Popen("taskkill /F /T /IM " + process.get(), shell=True)
except:
pass
# 打开档案夹
def bin():
pbin = var_p_bin.get().replace("\\", "/") # 替换
pbin = os.path.split(pbin)[0].replace("\\", "/")
os.startfile(str(pbin))
按钮控制元件
Button(root, text='强制置顶', command=set_top).place(x=10, y=280)
Button(root, text='取消置顶', command=set_down).place(x=100, y=280)
Button(root, text='显示顶部', command=set_yop_p).place(x=190, y=280)
Button(root, text='强制终止', command=kill).place(x=280, y=280)
Button(root, text='打开档案所在位置', command=bin).place(x=370, y=280)
这个是最关键的,只有这个控制元件才能起到指标移动是执行命令,canvas_2 指的是在 canvas_2的画布下可以使用,<B1-Motion> 指的是鼠标左键并移动 待触发控制元件,showMenu 指的是要执行的命令函式,
# 鼠标移动控制元件
canvas_2.bind("<B1-Motion>", showMenu)
废话不多说,上代码,
运行不成功的可以要注意,是不是没有图片,最上方有数据链接,里面包括图片和源档案,可以免费下载,代码都不用复制了
完整代码:
import tkinter
from tkinter import *
from tkinter.ttk import *
import win32api
import win32gui
import win32con
import win32ui
import time
from win32 import win32process
import psutil
import subprocess
from PIL import Image
import os
def main():
root = Tk()
root.title('贱工坊-视窗句柄') # 程序的标题名称
root.geometry("480x320+512+288") # 视窗的大小及页面的显示位置
root.resizable(False, False) # 固定页面不可放大缩小
root.iconbitmap("picture.ico") # 程序的图示
canvas = tkinter.Canvas(root, bg="#ebebeb", height=400, width=700, borderwidth=-3) # 创建画布
canvas.pack(side='top') # 放置画布(为上端)
canvas_2 = tkinter.Canvas(root, bg="#ebebeb",cursor='target', height=50, width=50, borderwidth=-2) # 创建画布
canvas_2.place(x=402, y=70) # 放置画布(为上端)
image_file = tkinter.PhotoImage(file="./Key.png") # 加载图片档案
canvas_2.create_image(0, 0, anchor='nw', image=image_file) # 将图片置于画布上
canvas_3 = tkinter.Canvas(root, bg="red", height=40, width=40, borderwidth=-2) # 创建画布
canvas_3.place(x=332, y=74) # 放置画布(为上端)
# 配置视窗句柄
var_hwnd = tkinter.StringVar()
tkinter.Entry(root, width=20,borderwidth=1,bg='#ebebeb',textvariable=var_hwnd).place(x=70,y=10)
# 配置标题名称
var_title = tkinter.StringVar()
tkinter.Entry(root, width=54, borderwidth=1,bg='#ebebeb', textvariable=var_title).place(x=70, y=40)
# 配置视窗类名
var_clsname = tkinter.StringVar()
tkinter.Entry(root, width=20, borderwidth=1, bg='#ebebeb', textvariable=var_clsname).place(x=306, y=10)
# 配置执行绪ID
var_hread_id = tkinter.StringVar()
tkinter.Entry(root, width=10, borderwidth=1, bg='#ebebeb', textvariable=var_hread_id).place(x=70, y=70)
# 配置行程ID
var_process_id = tkinter.StringVar()
tkinter.Entry(root, width=10, borderwidth=1, bg='#ebebeb', textvariable=var_process_id).place(x=204, y=70)
# 配置程序名称
var_process = tkinter.StringVar()
tkinter.Entry(root, width=29, borderwidth=1, bg='#ebebeb', textvariable=var_process).place(x=70, y=100)
# 配置程序路径
var_p_bin = tkinter.StringVar()
tkinter.Entry(root, width=54, borderwidth=1, bg='#ebebeb', textvariable=var_p_bin).place(x=70, y=130)
# 配置CPU利用率
var_mem_percent = tkinter.StringVar()
tkinter.Entry(root, width=20, borderwidth=1, bg='#ebebeb', textvariable=var_mem_percent).place(x=70, y=160)
# 配置执行绪数
var_num_threads = tkinter.StringVar()
tkinter.Entry(root, width=20, borderwidth=1, bg='#ebebeb', textvariable=var_num_threads).place(x=306, y=160)
# 配置视窗左上
var_top = tkinter.StringVar()
tkinter.Entry(root, width=6, borderwidth=1, bg='#ebebeb', textvariable=var_top).place(x=70, y=190)
# 配置视窗左下
var_left = tkinter.StringVar()
tkinter.Entry(root, width=6, borderwidth=1, bg='#ebebeb', textvariable=var_left).place(x=70, y=220)
# 配置视窗右上
var_right = tkinter.StringVar()
tkinter.Entry(root, width=6, borderwidth=1, bg='#ebebeb', textvariable=var_right).place(x=194, y=190)
# 配置视窗右下
var_bottom = tkinter.StringVar()
tkinter.Entry(root, width=6, borderwidth=1, bg='#ebebeb', textvariable=var_bottom).place(x=194, y=220)
# 配置坐标x,y
var_point = tkinter.StringVar()
tkinter.Entry(root, width=24, borderwidth=1, bg='#ebebeb', textvariable=var_point).place(x=70, y=250)
image_file_3 = tkinter.PhotoImage(file="pictures.png") # 软件第一次打开时要呈现的图片
Button_2 = Button(canvas_3, image=image_file_3).place(x=0, y=0)
# 更换软件图示
def picture():
try:
image_file_3.config(file='icon.png') # 替换
except:
pass
# 图示尺寸
ico_x = 32
# 获取软件图示
def ICON(exePath2):
try:
exePath = exePath2.replace("\\", "/") # 替换
large, small = win32gui.ExtractIconEx(f'{exePath}', 0)
useIcon = large[0]
destroyIcon = small[0]
win32gui.DestroyIcon(destroyIcon)
hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
hbmp = win32ui.CreateBitmap()
hbmp.CreateCompatibleBitmap(hdc, ico_x, ico_x)
hdc = hdc.CreateCompatibleDC()
hdc.SelectObject(hbmp)
hdc.DrawIcon((0, 0), useIcon)
bmpstr = hbmp.GetBitmapBits(True)
img = Image.frombuffer(
'RGBA',
(32, 32),
bmpstr, 'raw', 'BGRA', 0, 1
)
img.save('icon.png')
except:
pass
# 通过鼠标移动获取函式
def showMenu(event):
try:
point = win32api.GetCursorPos() # 鼠标位置
hwnd = win32gui.WindowFromPoint(point) # 视窗句柄
title = win32gui.GetWindowText(hwnd) # 视窗标题
clsname = win32gui.GetClassName(hwnd) # 视窗类名
hread_id, process_id = win32process.GetWindowThreadProcessId(hwnd) #执行绪ID 行程ID
process = psutil.Process(process_id) # 程序名称 通过行程ID获取
p_bin = psutil.Process(process_id).exe() # 程序路径 通过行程ID获取
mem_percent = psutil.Process(process_id).memory_percent() # CPU利用率 通过行程ID获取
num_threads = psutil.Process(process_id).num_threads() # 执行绪数 通过行程ID获取
left, top, right, bottom = win32gui.GetWindowRect(hwnd) #视窗坐标 通过视窗句柄获取 四个角的坐标
picture() # 更换软件图示
ICON(p_bin) # 获取软件图示
var_hwnd.set(hwnd)
var_title.set(title)
var_clsname.set(clsname)
var_hread_id.set(hread_id)
var_process_id.set(process_id)
var_process.set(process.name())
var_p_bin.set(p_bin)
var_mem_percent.set(mem_percent)
var_num_threads.set(num_threads)
var_left.set(left)
var_top.set(top)
var_right.set(right)
var_bottom.set(bottom)
var_point.set(point)
except:
pass
# 置顶 通过句柄
def set_top():
try:
win32gui.SetWindowPos(var_hwnd.get(), win32con.HWND_TOPMOST, 0, 0, 0, 0,win32con.SWP_NOMOVE | win32con.SWP_NOACTIVATE | win32con.SWP_NOOWNERZORDER | win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE)
except:
pass
# 取消置顶 通过句柄
def set_down():
try:
win32gui.SetWindowPos(var_hwnd.get(), win32con.HWND_NOTOPMOST, 0, 0, 0, 0,win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE | win32con.SWP_NOMOVE)
except:
pass
# 显示在顶部 通过句柄
def set_yop_p():
try:
win32gui.SetForegroundWindow(var_hwnd.get())
except:
pass
# 终止程序
def kill():
try:
subprocess.Popen("taskkill /F /T /PID " + var_process_id.get(), shell=True)
subprocess.Popen("taskkill /F /T /IM " + process.get(), shell=True)
except:
pass
# 打开档案夹
def bin():
pbin = var_p_bin.get().replace("\\", "/") # 替换
pbin = os.path.split(pbin)[0].replace("\\", "/")
os.startfile(str(pbin))
def Label():
# 标签
tkinter.Label(canvas, bg="#ebebeb", text='视窗句柄').place(x=10, y=8)
tkinter.Label(canvas, bg="#ebebeb", text='视窗标题').place(x=10, y=38)
tkinter.Label(canvas, bg="#ebebeb", text='视窗类名').place(x=248, y=8)
tkinter.Label(canvas, bg="#ebebeb", text='执行绪ID').place(x=10, y=68)
tkinter.Label(canvas, bg="#ebebeb", text='行程ID').place(x=154, y=68)
tkinter.Label(canvas, bg="#ebebeb", text='行程名称').place(x=10, y=98)
tkinter.Label(canvas, bg="#ebebeb", text='行程路径').place(x=10, y=128)
tkinter.Label(canvas, bg="#ebebeb", text='CPU用量').place(x=10, y=158)
tkinter.Label(canvas, bg="#ebebeb", text='执行绪数').place(x=258, y=158)
tkinter.Label(canvas, bg="#ebebeb", text='视窗左上').place(x=10, y=188)
tkinter.Label(canvas, bg="#ebebeb", text='视窗左下').place(x=10, y=218)
tkinter.Label(canvas, bg="#ebebeb", text='视窗右上').place(x=134, y=188)
tkinter.Label(canvas, bg="#ebebeb", text='视窗右下').place(x=134, y=218)
tkinter.Label(canvas, bg="#ebebeb", text='坐标x,y').place(x=10, y=248)
# 鼠标移动控制元件
canvas_2.bind("<B1-Motion>", showMenu)
Button(root, text='强制置顶', command=set_top).place(x=10, y=280)
Button(root, text='取消置顶', command=set_down).place(x=100, y=280)
Button(root, text='显示顶部', command=set_yop_p).place(x=190, y=280)
Button(root, text='强制终止', command=kill).place(x=280, y=280)
Button(root, text='打开档案所在位置', command=bin).place(x=370, y=280)
# 放置二维码
canvas_4 = tkinter.Canvas(root, bg="red", height=80, width=200, borderwidth=-2)
canvas_4.place(x=250, y=190)
image_file_4 = tkinter.PhotoImage(file="./share.png") # 加载图片档案
canvas_4.create_image(0, 0, anchor='nw', image=image_file_4) # 将图片置于画布上
Label()
root.mainloop() #运行
if __name__ == '__main__':
main()
0 评论