赞
踩
在桌面插件例如日历,便签或桌面宠物等等应用,通常希望能够将软件的窗口钉在桌面上,同时又不影响打开的其他窗口(即不是置顶,而是常驻与桌面,即使用win+d也不会将其窗口关闭)。许多桌面美化类软件都有这个功能。
该功能在win10环境下的实现是通过将软件窗口的父窗口设为windows桌面窗口来实现的(所谓桌面实际上也是一个窗口)。平时使用软件时,软件的一些弹窗或子窗口在失焦时并不会被关闭,正是利用了父子窗口的特性。tkinter并没有预设该功能,我们可以通过win32gui来实现。
代码逻辑是:创建tkinter窗口 -> 获取tkinker窗口句柄 -> 获取windows桌面窗口句柄 -> 将tkinter窗口设置为windows桌面的子窗口。在获取windows桌面句柄时有些曲折,因为最上层桌面被藏在几层窗口内,并且底层窗口的命名并不唯一,所以需要进行遍历。
参考:
怎么在桌面上嵌入窗口(使用FindWindow(),FindWindowEx(),EnumChildWindows())_win32gui.findwindowex将窗口置于桌面层-CSDN博客
https://www.cnblogs.com/2018shawn/p/9833276.html
- # -*- coding: utf-8 -*-
-
- import tkinter as tk
- import win32gui
-
- def go():
- #找到第一个WorkerW窗口
- dwndparent=win32gui.FindWindowEx(None,None,"WorkerW","")
- dwndviem=False
-
- #遍历所有的WorkerW,直至找到具有SHELLDLL_DefView子窗口的那个
- while(dwndparent):
- dwndviem=win32gui.FindWindowEx(dwndparent,None,"SHELLDLL_DefView",None)
- if(dwndviem!=0):
- break
- dwndparent=win32gui.FindWindowEx(None,dwndparent,"WorkerW","")
-
- #经实测,有时SHELLDLL_DefView并不在WorkerW下,而是在唯一的Progman窗口下
- #这和windows是否启用了任务视图(多桌面)有关。在刚刚启动windows时,SHELLDLL_DefView在Progman下。
- #一旦进入任务视图,SHELLDLL_DefView就进入了WorkerW
- #因此如果在WorkerW中没有找到SHELLDLL_DefView的话,就再看看Progman中有没有
- if(dwndparent==0):
- print('WorkerW not found, change to Progman')
- dwndparent=win32gui.FindWindow('Progman',None)
- dwndviem=win32gui.FindWindowEx(dwndparent,None,"SHELLDLL_DefView",None)
- if(dwndparent==0):
- print('Progman not found')
- else:
- print('Desktop found, starting program')
- dwdesktopicon=win32gui.FindWindowEx(dwndviem,None,"SysListView32","FolderView");
- hwnd = win32gui.FindWindow(None,u'First Demo')
- win32gui.SetParent(hwnd,dwdesktopicon)
-
- #设置tkinter窗口属性
- root = tk.Tk()
- root.title("First Demo")
- root.geometry('500x300+100+100')
- theLabel = tk.Label(root, text="tkinter窗口!")
- theLabel.pack()
-
- #窗口启动后100ms运行go()函数
- root.after(100,go)
-
- #创建窗口
- root.mainloop()

此外,如果使用了其他美化桌面的软件,它们会遮盖住桌面的子窗口。可以将美化软件的窗口作为父窗口,也可以实现常驻的功能。要查看窗口,可以用spy++。
TIPS:发现经过SetParent之后tkinter窗口会变得怪怪的,像褪色了一样。并且如果在最开始设置属性时设置了-alpha透明度,整个窗口会直接消失。经过测试,只要把root.attributes()函数放在go()函数最后即可解决该问题,相当于先指定父窗口,再去改变窗口属性。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。