【Python】实现一个类似于Glass2k的Windows窗口透明化软件

一 背景说明

        网上看到一款Windows下的窗口透明化工具Glass2k(Glass2k官网),可以简单地通过快捷键实现任意窗口的透明化,还挺方便的,想用Python自己实现一下类似的功能。

        软件已经开源到:窗口透明化小工具开源地址

        效果图如下:

二 设计实现

        工具包含以下几个模块:

        【1】用 tkinter 类实现工具的界面;

        【2】用 pystray 类实现工具最小化托盘的功能;

        【3】用pynput 类实现键盘快捷键的监听功能;

        【4】用ctypes 类实现Windows窗口透明化操作;

三 功能编写

        用GUI类包含设计中的几种功能:

【1】初始化中实现工具的主界面:

def __init__(self):self.root = tk.Tk()self.root.title('窗口透明化工具')self.root.geometry("400x90")# 当用户点击窗口右上角的关闭按钮时,Tkinter将自动发送WM_DELETE_WINDOW关闭事件。通过对其进行处理并调用self.hide_window()方法,可以改为将窗口隐藏到系统托盘中。# 该方法用于将程序窗口隐藏到系统托盘中而非直接退出应用程序self.root.protocol('WM_DELETE_WINDOW', self.hide_window)# 添加菜单和图标self.create_systray_icon()# 绘制界面frame1 = tk.Frame(self.root)frame1.pack(side='top')l1 = tk.Label(frame1,text='【窗口透明化操作】点击窗口,按Ctrl + Alt + [0-9]使其透明化。\nCtrl + Alt + 1:全透明\nCtrl + Alt + 5:半透明\nCtrl + Alt + 0:全填充\n')l1.pack()# 开启键盘监听t = threading.Thread(target=self.new_thread_start)# 开启守护线程,这样在GUI意外关闭时线程能正常退出t.setDaemon(True)t.start()

【2】最小化托盘包括:创建最小化托盘图标/隐藏窗口/打开窗口/退出程序 几个方法:

"""
[1]最小化托盘
"""
def create_systray_icon(self):# 使用 Pystray 创建系统托盘图标menu = (pystray.MenuItem('显示', self.show_window, default=True),pystray.Menu.SEPARATOR,  # 在系统托盘菜单中添加分隔线pystray.MenuItem('退出', self.quit_window))image = Image.open("TPWin.ico")self.icon = pystray.Icon("icon", image, "图标名称", menu)threading.Thread(target=self.icon.run, daemon=True).start()def hide_window(self):# 关闭窗口时隐藏窗口,并将 Pystray 图标放到系统托盘中self.root.withdraw()def show_window(self):# 打开主窗口self.icon.visible = Trueself.root.deiconify()def quit_window(self, icon: pystray.Icon):# 退出程序icon.stop()  # 停止 Pystray 的事件循环self.root.quit()  # 终止 Tkinter 的事件循环self.root.destroy()  # 销毁应用程序的主窗口和所有活动

【3】键盘的监听包括:监听键盘点击/监听键盘释放/启动监听线程 几个方法,其中组合键用一个无序不重复元素集来管理:

"""
[2]键盘操作
"""
def on_key_press(self, key):if key == keyboard.Key.alt_l or key == keyboard.Key.alt_gr:keys.add('Alt')elif key == keyboard.Key.ctrl_l or key == keyboard.Key.ctrl_r:keys.add('Ctrl')elif str(key) == r"<48>":   # ctrl + 0组合键keys.add('0')elif str(key) == r"<49>":   # ctrl + 1组合键keys.add('1')elif str(key) == r"<50>":   # ctrl + 2组合键keys.add('2')elif str(key) == r"<51>":   # ctrl + 3组合键keys.add('3')elif str(key) == r"<52>":   # ctrl + 4组合键keys.add('4')elif str(key) == r"<53>":   # ctrl + 5组合键keys.add('5')elif str(key) == r"<54>":   # ctrl + 6组合键keys.add('6')elif str(key) == r"<55>":   # ctrl + 7组合键keys.add('7')elif str(key) == r"<56>":   # ctrl + 8组合键keys.add('8')elif str(key) == r"<57>":   # ctrl + 9组合键keys.add('9')if all(k in keys for k in ['Alt', 'Ctrl', '0']):self.set_transparency(0)elif all(k in keys for k in ['Alt', 'Ctrl', '1']):self.set_transparency(1)elif all(k in keys for k in ['Alt', 'Ctrl', '2']):self.set_transparency(2)elif all(k in keys for k in ['Alt', 'Ctrl', '3']):self.set_transparency(3)elif all(k in keys for k in ['Alt', 'Ctrl', '4']):self.set_transparency(4)elif all(k in keys for k in ['Alt', 'Ctrl', '5']):self.set_transparency(5)elif all(k in keys for k in ['Alt', 'Ctrl', '6']):self.set_transparency(6)elif all(k in keys for k in ['Alt', 'Ctrl', '7']):self.set_transparency(7)elif all(k in keys for k in ['Alt', 'Ctrl', '8']):self.set_transparency(8)elif all(k in keys for k in ['Alt', 'Ctrl', '9']):self.set_transparency(9)def on_key_release(self, key):if key == keyboard.Key.alt_l or key == keyboard.Key.alt_gr:keys.remove('Alt')elif key == keyboard.Key.ctrl_l or key == keyboard.Key.ctrl_r:keys.remove('Ctrl')elif str(key) == r"<48>":  # ctrl + 0组合键keys.remove('0')elif str(key) == r"<49>":  # ctrl + 1组合键keys.remove('1')elif str(key) == r"<50>":  # ctrl + 2组合键keys.remove('2')elif str(key) == r"<51>":  # ctrl + 3组合键keys.remove('3')elif str(key) == r"<52>":  # ctrl + 4组合键keys.remove('4')elif str(key) == r"<53>":  # ctrl + 5组合键keys.remove('5')elif str(key) == r"<54>":  # ctrl + 6组合键keys.remove('6')elif str(key) == r"<55>":  # ctrl + 7组合键keys.remove('7')elif str(key) == r"<56>":  # ctrl + 8组合键keys.remove('8')elif str(key) == r"<57>":  # ctrl + 9组合键keys.remove('9')if key == keyboard.Key.esc:return False  # 释放了esc 键,停止监听def new_thread_start(self):key_listen_thread = keyboard.Listener(on_press=self.on_key_press, on_release=self.on_key_release)# 运行线程key_listen_thread.start()

【4】设置透明度的操作包括:设置透明度/获取当前鼠标位置(获取窗口句柄用):

"""
[3]设置透明度操作(Ctrl + Alt + [0-9])
"""
def set_transparency(self, set_tp):global hwndhwnd = ctypes.windll.user32.WindowFromPoint(self.get_mouse_position())  # 获取窗口句柄p = create_string_buffer(256)windll.user32.GetWindowTextW(hwnd, byref(p), 256)  # 获取窗口标题title = str(p.raw, encoding='utf-16').strip('\x00')exstyle = windll.user32.GetWindowLongA(hwnd, GWL_EXSTYLE)exstyle |= WS_EX_LAYERED  # 使窗口具有能设置透明度的样式windll.user32.SetWindowLongA(hwnd, GWL_EXSTYLE, exstyle)    # 获取窗口名if set_tp == 0:alpha = 255else:alpha = set_tp * 25windll.user32.SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA) # 设置透明度print('窗口 ' + title + ' 透明度设置为 ' + str(set_tp) + '\n')def get_mouse_position(self):point = ctypes.wintypes.POINT()ctypes.windll.user32.GetCursorPos(ctypes.byref(point))return point

四 程序整合

        将上述功能整合:

import ctypes.wintypes
import threading
import tkinter as tk
import pystray
from PIL import Image
from pynput import keyboard
from ctypes import *WM_CLOSE = 0x10
WM_SETTEXT = 0x0c
GWL_STYLE = -16
GWL_EXSTYLE = -20
SW_MINIMIZE = 6
SW_MAXIMIZE = 3
SW_RESTORE = 9
WS_BORDER = 0x800000
WS_CAPTION = 0xC00000 # WS_BORDER Or WS_DLGFRAME
WS_CHILD = 0x40000000
WS_CLIPCHILDREN = 0x2000000
WS_CLIPSIBLINGS = 0x4000000
WS_POPUP = 0x80000000
WS_DLGFRAME = 0x400000
WS_DISABLED = 0x8000000
WS_OVERLAPPEDWINDOW = 0xcf0000
WS_THICKFRAME = 0x40000
WS_VISIBLE = 0x10000000
WS_EX_APPWINDOW = 0x40000
WS_EX_DLGMODALFRAME = 0x1
WS_EX_ACCEPTFILES = 0x10
WS_EX_CLIENTEDGE= 0x200
WS_EX_TOOLWINDOW = 0x80
WS_EX_WINDOWEDGE = 0x100
LWA_ALPHA = 0x2;LWA_COLORKEY=0x1
WS_EX_LAYERED = 0x80000keys = set()
hwnd = 0    # 窗口句柄class GUI:def __init__(self):#初始化窗口"""[1]最小化托盘""""""[2]键盘操作""""""[3]设置透明度操作(Ctrl + Alt + [0-9])"""if __name__ == '__main__':# 主界面TKDemo = GUI()TKDemo.root.mainloop()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/261889.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 面向对象进阶 14 抽象类和抽象方法(黑马)

抽象类不能实例化&#xff08;创建对象&#xff09;&#xff1a; 抽象类中不一定有抽象方法&#xff1a; 有抽象方法的类一定是抽象类&#xff1a; 可以有构造方法&#xff1a;&#xff08;作用&#xff1a;在创建子类对象时&#xff0c;给属性进行赋值的&#xff09; Perso…

RabbitMQ保证消息的可靠性

1. 问题引入 消息从发送&#xff0c;到消费者接收&#xff0c;会经理多个过程&#xff1a; 其中的每一步都可能导致消息丢失&#xff0c;常见的丢失原因包括&#xff1a; 发送时丢失&#xff1a; 生产者发送的消息未送达exchange消息到达exchange后未到达queue MQ宕机&…

C++ Webserver从零开始:配置环境(九)——下载github的项目进行测试

前言 大家好&#xff0c;我又来更新Webserver的博客了。上一次更新这个专栏时2024.2.5号&#xff0c;离现在已经13天了。非常抱歉&#xff0c;中间隔了那么久。一方面是基础知识学完之后&#xff0c;就要开始自己写代码了。看基础知识和写代码是两回事&#xff0c;理论和实践的…

Git常用命令整理

在介绍安装和简单使用前&#xff0c;先看一下百度百科中的简介吧&#xff1a; ———————————————————————————————————————— Git --- The stupid content tracker, 傻瓜内容跟踪器。 Linux 是这样给我们介绍 Git 的&#xff1a; Git 是用…

Kafka进阶

文章目录 概要应用场景消息队列两种模式kafka的基础架构分区常见问题小结 概要 kafka的传统定义&#xff1a;kafka是一个分布式的基于发布\订阅模式的消息队列&#xff0c;主要用于大数据实时处理领域。 kafka的最新概念&#xff1a;kafka是一个开源的分布式事件流平台&#x…

UIKit 在 UICollectionView 中拖放交换 Cell 视图的极简实现

概览 UIKit 中的 UICollectionView 视图是我们显示多列集合数据的不二选择&#xff0c;而丰富多彩的交互操作更是我们选择 UICollectionView 视图的另一个重要原因。 如上图所示&#xff1a;我们实现了在 UICollectionView 中拖放交换任意两个 Cell 子视图的功能&#xff0c;这…

不要抱怨,不如抱 Java 运算符吧 (1)

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

学习鸿蒙基础(5)

一、honmonyos的page路由界面的路径 新建了一个page,然后删除了。运行模拟器的时候报错了。提示找不到这个界面。原来是在路由界面没有删除这个page。新手刚接触找了半天才找到这个路由。在resources/base/profile/main_pages.json 这个和微信小程序好类似呀。 吐槽&#xf…

普中51单片机学习(串口通信)

串口通信 原理 计算机通信是将计算机技术和通信技术的相结合&#xff0c;完成计算机与外部设备或计算机与计算机之间的信息交换 。可以分为两大类&#xff1a;并行通信与串行通信。并行通信通常是将数据字节的各位用多条数据线同时进行传送 。控制简单、传输速度快&#xff1…

百度智能云分布式数据库 GaiaDB-X 与龙芯平台完成兼容认证

近日&#xff0c;百度智能云的分布式关系型数据库软件 V3.0 与龙芯中科技术股份有限公司的龙芯 3C5000L/3C5000 处理器平台完成兼容性测试&#xff0c;功能与稳定性良好&#xff0c;获得了龙架构兼容互认证证书。 龙芯系列处理器 通用 CPU 处理器是信息产业的基础部件&#xf…

LINUX读取RTC实时时钟时间

linux 读写RTC时间_linux rtc 读写-CSDN博客

《游戏引擎架构》--学习3

内存管理 优化动态内存分配 维持最低限度的堆分配&#xff0c;并且永不在紧凑循环中使用堆分配 容器 迭代器 Unicode

LeetCode 0590. N 叉树的后序遍历:深度优先搜索(DFS)

【LetMeFly】590.N 叉树的后序遍历&#xff1a;深度优先搜索(DFS) 力扣题目链接&#xff1a;https://leetcode.cn/problems/n-ary-tree-postorder-traversal/ 给定一个 n 叉树的根节点 root &#xff0c;返回 其节点值的 后序遍历 。 n 叉树 在输入中按层序遍历进行序列化表…

【Linux】自主WEB服务器实现

自主web服务器实现 1️⃣构建TcpServer2️⃣构建HttpServer3️⃣构建HttpRequest和HttpResponseHttp请求报文格式Http相应报文读取、处理请求&构建响应读取请求中的一行读取请求中需要注意的点 4️⃣CGI模式判断是否需要用CGI处理请求构建任务&线程池管理 5️⃣实验结果…

解决pycharm中PIL安装失败

问题&#xff1a;在调用pil时显示pil标红 我在设置中下载每次失败&#xff0c;显示 ERROR: Could not find a version that satisfies the requirement PIL (from versions: none) ERROR: No matching distribution found for PIL我尝试了很久&#xff0c;查看了一些博客 &a…

odoo16-API(Controller)带有验证访问的接口

odoo16-API&#xff08;Controller&#xff09;带有验证访问的接口 目前我使用odoo原生的登录token来验证登陆的有效性 废话不多说直接上代码 # 测试获取session_id import requests class GetOdooData(http.Controller):def getOdooToken(self):# http://localhost:8123访问…

OpenAI 的 GPTs 提示词泄露攻击与防护实战:防御卷(一)

前面的OpenAI DevDay活动上&#xff0c;GPTs技术的亮相引起了广泛关注。随着GPTs的创建权限开放给Plus用户&#xff0c;社区里迅速涌现了各种有趣的GPT应用&#xff0c;这些都是利用了Prompt提示词的灵活性。这不仅展示了技术的创新潜力&#xff0c;也让人们开始思考如何获取他…

AI新工具(20240222)SDXL-Lightning-节跳动开发一个快速的文本到图像生成模型;GoEnhance - 视频风格转换等

SDXL-Lightning - 节跳动开发一个快速的文本到图像生成模型 SDXL-Lightning是字节跳动开发一个快速的文本到图像生成模型&#xff0c;能够在几个步骤内生成高质量的1024像素图像。该模型发布用于研究目的&#xff0c;可以从stabilityai/stable-diffusion-xl-base-1.0中提取模型…

nginx之web性能location优先级

4.2 event事件 events {worker_connections 65536; #设置单个工作进程的最大并发连接数use epoll;#使用epoll事件驱动&#xff0c;Nginx支持众多的事件驱动&#xff0c;比如:select、poll、epoll&#xff0c;只能设置在events模块中设置。accept_mutex on; #on为同一时刻一个…

【OpenFeign常用配置】

OpenFeign常用配置 快速入门&#xff1a;1、引入依赖2、启用OpenFeign 实践1、引入依赖2、开启连接池功能3、模块划分4、日志5、重试 快速入门&#xff1a; OpenFeign是一个声明式的http客户端&#xff0c;是spring cloud在eureka公司开源的feign基础上改造而来。其作用及时基于…