Python GUI窗口保持在顶部而没有焦点

时间:2017-06-27 23:30:42

标签: python user-interface tkinter

我正在尝试在messagease keyboard之后的python中编写我自己的屏幕键盘,它将滑动和点击结合到输入字符。 我计划在Windows上使用它,但如果可能的话,我想尽量保持跨平台。

目前我正在尝试找到一种方法将窗口保持在顶部并将光标/焦点保持在上一个窗口中,这样当我模拟按键时(使用pyautogui)它们将出现在正确的窗口中。

使用tkinter,我可以使用这行代码保持窗口顶部,但我不知道如何保持前一个窗口的焦点。

root.wm_attributes("-topmost", 1)

要发送按键,我正在使用pyautogui:

pyautogui.typewrite("characters to write")

我在python中编写gui的经验不多,所以如果在不同的框架中更容易实现,我愿意转换。

所以问题的基础是:

如何创建一个可以与之交互的gui窗口(触摸,滑动等),但这不会使键盘焦点远离另一个窗口/应用程序?

1 个答案:

答案 0 :(得分:0)

这只是windows,但要设置python窗口的样式以不获得焦点,你可以使用ctypes:

CheckBox chkBtn = new CheckBox();
boxes.Add(chkBtn);

您需要根据应用程序环境使用正确的Get / Set功能。对于32位窗口,似乎你需要使用:
foreach(CheckBox box in boxes) box.Checked = true; import tkinter as tk from ctypes import windll, wintypes GWL_STYLE = -16 GWL_EXSTYLE = -20 WS_CHILD = 0x40000000 WS_EX_APPWINDOW = 0x00040000 WS_EX_TOOLWINDOW = 0x00000080 WS_EX_NOACTIVATE = 0x08000000 SWP_FRAMECHANGED = 0x0020 SWP_NOACTIVATE = 0x0010 SWP_NOMOVE = 0x0002 SWP_NOSIZE = 0x0001 # write short names for functions and specify argument and return types GetWindowLong = windll.user32.GetWindowLongW GetWindowLong.restype = wintypes.ULONG GetWindowLong.argtpes = (wintypes.HWND, wintypes.INT) SetWindowLong = windll.user32.SetWindowLongW SetWindowLong.restype = wintypes.ULONG SetWindowLong.argtpes = (wintypes.HWND, wintypes.INT, wintypes.ULONG) SetWindowPos = windll.user32.SetWindowPos def find_root_window(win): # takes tkinter window ref w_id = win.winfo_id() # gets handle style = GetWindowLong(w_id, GWL_STYLE) # get existing style newstyle = style & ~WS_CHILD # remove child style res = SetWindowLong(w_id, GWL_STYLE, newstyle) # set new style res = SetWindowPos(w_id, 0, 0,0,0,0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE) hwnd = int(root.wm_frame(), 16) # find handle of parent res = SetWindowLong(w_id, GWL_STYLE, style) # set back to old style res = SetWindowPos(w_id, 0, 0,0,0,0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE) return hwnd # return parents handle def set_no_focus(hwnd): style = GetWindowLong(hwnd, GWL_EXSTYLE) # get existing style style = style & ~WS_EX_TOOLWINDOW # remove toolwindow style style = style | WS_EX_NOACTIVATE | WS_EX_APPWINDOW res = SetWindowLong(hwnd, GWL_EXSTYLE, style) res = SetWindowPos(hwnd, 0, 0,0,0,0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE) def push_me(): print('you pushed me!') def focus_me(event): root.focus_force() root = tk.Tk() root.wm_attributes("-topmost", 1) tk.Button(root, text="Push me", command=push_me).pack() e = tk.Entry(root) e.pack() e.bind('<Button-1>', focus_me) # if we have a widget that must have focus it needs to be bound root.update() # for some reason, window style is messed with after window creation, update to get past this hwnd = find_root_window(root) if hwnd: set_no_focus(hwnd) root.mainloop()

GetWindowLongWSetWindowLongW

但需要64位:
GetWindowLongASetWindowLongA

GetWindowLongPtrWSetWindowLongPtrW
this