【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.pswp.cn/news/696866.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/696866.shtml
英文地址,請注明出處:http://en.pswp.cn/news/696866.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Leetcode】889. 根據前序和后序遍歷構造二叉樹

文章目錄 題目思路代碼結果 題目 題目鏈接 給定兩個整數數組&#xff0c;preorder 和 postorder &#xff0c;其中 preorder 是一個具有 無重復 值的二叉樹的前序遍歷&#xff0c;postorder 是同一棵樹的后序遍歷&#xff0c;重構并返回二叉樹。 如果存在多個答案&#xff0c;…

CSS基礎屬性

【三】基礎屬性 【1】高度和寬度 &#xff08;1&#xff09;參數 width&#xff08;寬度&#xff09;&#xff1a;用于設置元素的寬度。可以使用具體的數值&#xff08;如像素值&#xff09;或百分比來指定寬度。 height&#xff08;高度&#xff09;&#xff1a;用于設置元…

Kubernetes 卷存儲 NFS | nfs搭建配置 原理介紹 nfs作為存儲卷使用

目錄 1、NFS介紹2、NFS服務部署2.1安裝nfs服務 (服務端配置)2.2啟動NFS服務2.3 服務檢查2.4 客戶端配置 3、nfs作為存儲卷使用3.1 nfs作為volume3.2 nfs存儲的缺點3.3 nfs作為PersistentVolum 4、nfs作為動態存儲提供5、總結 1、NFS介紹 NFS&#xff08;Network File System&a…

4.pom文件介紹Maven常用命令

1.pom.xml文件介紹. 1.1project標簽和modelVersion標簽介紹. pom.xml文件是maven的核心文件&#xff0c;POM(Project Object Model&#xff0c;項目對象模型)定義了項目的基本信息&#xff0c;用于描述如何構建&#xff0c;聲明項目依賴;&#xff1b; 1.2依賴坐標介紹. 依賴的…

得物面試:Kafka消息0丟失,如何實現?

得物面試&#xff1a;Kafka消息0丟失&#xff0c;如何實現&#xff1f; 尼恩說在前面 在40歲老架構師 尼恩的讀者交流群(50)中&#xff0c;最近有小伙伴拿到了一線互聯網企業如得物、阿里、滴滴、極兔、有贊、希音、百度、網易、美團的面試資格&#xff0c;遇到很多很重要的面…

新版Java面試專題視頻教程——多線程篇②

新版Java面試專題視頻教程——多線程篇② 0. 問題匯總0.1 線程的基礎知識0.2 線程中并發安全0.3 線程池0.4 使用場景 1.線程的基礎知識2.線程中并發鎖3.線程池3.1 說一下線程池的核心參數&#xff08;線程池的執行原理知道嘛&#xff09;3.2 線程池中有哪些常見的阻塞隊列Array…

高級語言期末2014級A卷

1.編寫函數 int delarr(int a[] ,int n)&#xff0c;刪除有n個元素的正整型數組a中所有素數&#xff0c;要求&#xff1a; 1&#xff09;數組a中剩余元素保持原來次序&#xff1b; 2&#xff09;將處理后的數組輸出&#xff1b; 3&#xff09;函數值返回剩余元素個數&#xff1…

MySQL索引面試題(高頻)

文章目錄 前言什么時候需要&#xff08;不需要&#xff09;)使用索引&#xff1f;有哪些優化索引的方法前綴索引優化索引覆蓋優化索引失效場景 總結 前言 今天來講一講 MySQL 索引的高頻面試題。主要是針對前一篇文章 MySQL索引入門&#xff08;一文搞定&#xff09;進行查漏補…

虛擬機的內存結構

一、摘要 熟悉 Java 語言特性的同學都知道&#xff0c;相比 C、C 等編程語言&#xff0c;Java 無需通過手動方式回收內存&#xff0c;內存中所有的對象都可以交給 Java 虛擬機來幫助自動回收&#xff1b;而像 C、C 等編程語言&#xff0c;需要開發者通過代碼手動釋放內存資源&…

MedicalGPT 訓練醫療大模型,實現了包括增量預訓練、有監督微調、RLHF(獎勵建模、強化學習訓練)和DPO(直接偏好優化)

MedicalGPT 訓練醫療大模型&#xff0c;實現了包括增量預訓練、有監督微調、RLHF(獎勵建模、強化學習訓練)和DPO(直接偏好優化)。 MedicalGPT: Training Your Own Medical GPT Model with ChatGPT Training Pipeline. 訓練醫療大模型&#xff0c;實現了包括增量預訓練、有監督微…

Linux第63步_為新創建的虛擬機添加必要的目錄和安裝支持linux系統移植的軟件

1、創建必要的目錄 1)、創建“/home/zgq/linux/”目錄 打開終端&#xff0c;進入“/home/zgq/”目錄 輸入“mkdir linux回車”&#xff0c;創建“/home/zgq/linux/”目錄 輸入“ls回車”&#xff0c;列舉“/home/zgq/”目錄的所有文件和文件夾 創建好“/home/zgq/linux/”…

EIS(防抖):meshflow算法 C++實現

視頻防抖的應用 對視頻防抖的需求在許多領域都有。 這在消費者和專業攝像中是極其重要的。因此&#xff0c;存在許多不同的機械、光學和算法解決方案。即使在靜態圖像拍攝中&#xff0c;防抖技術也可以幫助拍攝長時間曝光的手持照片。 在內窺鏡和結腸鏡等醫療診斷應用中&…

Go 中的 init 如何用?它的常見應用場景有哪些呢?

嗨&#xff0c;大家好&#xff01;我是波羅學。本文是系列文章 Go 技巧第十六篇&#xff0c;系列文章查看&#xff1a;Go 語言技巧。 Go 中有一個特別的 init() 函數&#xff0c;它主要用于包的初始化。init() 函數在包被引入后會被自動執行。如果在 main 包中&#xff0c;它也…

QT基本組件

四、基本組件 Designer 設計師&#xff08;重點&#xff09; Qt包含了一個Designer程序&#xff0c;用于通過可視化界面設計開發界面&#xff0c;保存文件格式為.ui&#xff08;界面文件&#xff09;。界面文件內部使用xml語法的標簽式語言。 在Qt Creator中創建文件時&#xf…

滾雪球學Java(67):深入理解 TreeMap:Java 中的有序鍵值映射表

咦咦咦&#xff0c;各位小可愛&#xff0c;我是你們的好伙伴——bug菌&#xff0c;今天又來給大家普及Java SE相關知識點了&#xff0c;別躲起來啊&#xff0c;聽我講干貨還不快點贊&#xff0c;贊多了我就有動力講得更嗨啦&#xff01;所以呀&#xff0c;養成先點贊后閱讀的好…

機器人內部傳感器閱讀筆記及心得-位置傳感器-旋轉變壓器、激光干涉式編碼器

旋轉變壓器 旋轉變壓器是一種輸出電壓隨轉角變化的檢測裝置&#xff0c;是用來檢測角位移的&#xff0c;其基本結構與交流繞線式異步電動機相似&#xff0c;由定子和轉子組成。 旋轉變壓器的原理如圖1所示&#xff0c;定子相當于變壓器的一次側&#xff0c;有兩組在空間位置上…

MyBatis-Plus 優雅實現數據加密存儲

文章目錄 前言一、數據庫字段加解密實現1. 定義加密類型枚舉2. 定義AES密鑰和偏移量3. 配置定義使用的加密類型4. 加密解密接口5. 解密解密異常類6. 加密解密實現類6.1 AES加密解密實現類6.2 Base64加密解密實現類 7. 實現數據庫的字段保存加密與查詢解密處理類8. MybatisPlus配…

使用python進行量化交易

yfinance yfinance國內不能使用&#xff0c;可以使用tushare、akshare代替 import yfinance as yf# 輸入股票代碼 stock_symbol AAPL # 替換為你想要查詢的股票代碼# 獲取股票數據 data yf.download(stock_symbol)# 打印實時數據 print(data)pip install akshare import …

Selenium安裝與配置

文章目錄 一、selenium安裝1. Python環境準備&#xff1a;2. 安裝Selenium&#xff1a;3. 瀏覽器驅動安裝&#xff1a;4. 驗證安裝&#xff1a; 二、常見問題1. Selenium版本與瀏覽器驅動程序不兼容&#xff1a;2. 瀏覽器驅動程序路徑未正確設置&#xff1a; Selenium是一個用于…

2024年1月手機市場行業分析:蘋果手機份額驟降,國產高端手機成功逆襲!

小米Ultra發布。 一方面&#xff0c;我們有望看到國產手機再一次超越自己的決心&#xff0c;繼續創新追逐高端&#xff1b;另一方面&#xff0c;我們也不得不正視目前手機市場所面臨的危機狀態。 2024年1月的線上手機市場遠不如去年。根據鯨參謀數據顯示&#xff0c;今年1月京…