强制 tkinter window 使用原生 Python 在其他所有内容下方渲染
Forcing tkinter window to render below everything else with native Python
我想创建一个 tkinter window,它位于所有其他 windows 之下,并且无法使用 Window 的 SetWindowPos()
功能进行交互。我希望下面的代码可以解决问题,但出现的 window 是可调整大小的,可以接受焦点,接收鼠标点击,并且不低于其他所有内容。
import time
import ctypes.wintypes
from ctypes import c_bool, c_int
from ctypes.wintypes import HWND, UINT
import tkinter
# Create a window and get its HWND
root = tkinter.Tk()
hwnd = root.winfo_id()
# Flags to move the window to the bottom and keep it from being touched
SWP_NOSIZE = 0x0001
SWP_NOMOVE = 0x0002
SWP_NOACTIVATE = 0x0010
SWP_NOOWNERZORDER = 0x0200
SWP_NOSENDCHANGING = 0x0400
swpFlags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING
SetWindowPos = ctypes.windll.user32.SetWindowPos
SetWindowPos.argtypes = [HWND, HWND, c_int, c_int, c_int, c_int, UINT]
SetWindowPos.restype = c_bool
HWND_BOTTOM = 1
root.update()
SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 400, 600, swpFlags)
while True:
time.sleep(0.1)
root.update_idletasks()
root.update()
横向思考,grab_*
是您用例的解决方案吗?您可以创建一个 window,将其设置为在背景中并设置合适的大小,然后在其上创建一个新的 window 并执行 grab_set
,强制应用程序中的交互以仅发生在新 window 及其子项上。这种模式通常用于对话框 windows 和弹出框,以强制用户与特定的 window 进行交互,但它也可能在这里起作用,具体取决于您真正想要做什么。
根据您的意见,我相信您对 SetWindowPos 的用法有误解。您想使 window 不可调整大小,并将 zorder 设置为底部加上其他一些东西。
这个 api 调用做了 3 件事,设置 zorder、大小和位置。但是,如果您只想设置其中的 1 或 2 个,则可以使用标志来表示“不要执行该项目”。它不会使 window 不再做那些事情。我相信您需要使用不同的 api 调用。
在上面的代码中,您实际上是在说不要执行调用要执行的 3 项操作中的任何一项,这会使调用变成 NOP。将所有 3 个一起使用似乎是一个编程错误。
我想 windows api 没有任何其他方式来获得可选参数。他们可能应该将该调用分成 3 个独立的调用。
对于你想要的,我认为你正在寻找一个不同的 api 调用,可能 SetWindowLongPtr 就是你正在寻找的。
在tcl twapi代码中,有2个小程序用来设置额外的样式位。您可以在
下载 twapi 的 zip 源代码
``https://sourceforge.net/projects/twapi/files/Development%20Releases/
然后在文件 ui.tcl 中有一些用于设置样式的代码。
# Update the frame - needs to be called after setting certain style bits
proc twapi::redraw_window_frame {hwin} {
# 0x4037 -> SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE |
# SWP_NOMOVE | SWP_NOSIZE |
# SWP_NOZORDER | SWP_FRAMECHANGED
SetWindowPos $hwin 0 0 0 0 0 0x4037
}
proc twapi::set_window_style {hwin style exstyle} {
# GWL_STYLE -> -16, GWL_EXSTYLE -20
set style [SetWindowLongPtr $hwin -16 $style]
set exstyle [SetWindowLongPtr $hwin -20 $exstyle]
redraw_window_frame $hwin
return
}
我想创建一个 tkinter window,它位于所有其他 windows 之下,并且无法使用 Window 的 SetWindowPos()
功能进行交互。我希望下面的代码可以解决问题,但出现的 window 是可调整大小的,可以接受焦点,接收鼠标点击,并且不低于其他所有内容。
import time
import ctypes.wintypes
from ctypes import c_bool, c_int
from ctypes.wintypes import HWND, UINT
import tkinter
# Create a window and get its HWND
root = tkinter.Tk()
hwnd = root.winfo_id()
# Flags to move the window to the bottom and keep it from being touched
SWP_NOSIZE = 0x0001
SWP_NOMOVE = 0x0002
SWP_NOACTIVATE = 0x0010
SWP_NOOWNERZORDER = 0x0200
SWP_NOSENDCHANGING = 0x0400
swpFlags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING
SetWindowPos = ctypes.windll.user32.SetWindowPos
SetWindowPos.argtypes = [HWND, HWND, c_int, c_int, c_int, c_int, UINT]
SetWindowPos.restype = c_bool
HWND_BOTTOM = 1
root.update()
SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 400, 600, swpFlags)
while True:
time.sleep(0.1)
root.update_idletasks()
root.update()
横向思考,grab_*
是您用例的解决方案吗?您可以创建一个 window,将其设置为在背景中并设置合适的大小,然后在其上创建一个新的 window 并执行 grab_set
,强制应用程序中的交互以仅发生在新 window 及其子项上。这种模式通常用于对话框 windows 和弹出框,以强制用户与特定的 window 进行交互,但它也可能在这里起作用,具体取决于您真正想要做什么。
根据您的意见,我相信您对 SetWindowPos 的用法有误解。您想使 window 不可调整大小,并将 zorder 设置为底部加上其他一些东西。
这个 api 调用做了 3 件事,设置 zorder、大小和位置。但是,如果您只想设置其中的 1 或 2 个,则可以使用标志来表示“不要执行该项目”。它不会使 window 不再做那些事情。我相信您需要使用不同的 api 调用。
在上面的代码中,您实际上是在说不要执行调用要执行的 3 项操作中的任何一项,这会使调用变成 NOP。将所有 3 个一起使用似乎是一个编程错误。
我想 windows api 没有任何其他方式来获得可选参数。他们可能应该将该调用分成 3 个独立的调用。
对于你想要的,我认为你正在寻找一个不同的 api 调用,可能 SetWindowLongPtr 就是你正在寻找的。
在tcl twapi代码中,有2个小程序用来设置额外的样式位。您可以在
下载 twapi 的 zip 源代码``https://sourceforge.net/projects/twapi/files/Development%20Releases/
然后在文件 ui.tcl 中有一些用于设置样式的代码。
# Update the frame - needs to be called after setting certain style bits
proc twapi::redraw_window_frame {hwin} {
# 0x4037 -> SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE |
# SWP_NOMOVE | SWP_NOSIZE |
# SWP_NOZORDER | SWP_FRAMECHANGED
SetWindowPos $hwin 0 0 0 0 0 0x4037
}
proc twapi::set_window_style {hwin style exstyle} {
# GWL_STYLE -> -16, GWL_EXSTYLE -20
set style [SetWindowLongPtr $hwin -16 $style]
set exstyle [SetWindowLongPtr $hwin -20 $exstyle]
redraw_window_frame $hwin
return
}