我试图在Windows中使用Python设置非滚动文本输出窗口。
我找到了一些使用win32gui.DrawText在窗口中放置文本的代码示例,但是在初始文本到位后,它们都没有添加或更改文本。
我没有在文档中看到任何内容表明在调用DrawText后窗口文本已修复,但是在第一次绘制窗口后我无法进行任何更改。
我错过了哪些可以让我更新Windows文本?
这是Christophe Keller" Hello World"我修改为1秒后更改窗口文本的示例。 (我添加的代码不起作用。)
import win32api
import win32con
import win32gui
import time
#Code example modified from:
#Christophe Keller
#Hello World in Python using Win32
# New code: Define global
g_str_Text = 'Hello send by Python via Win32!'
def main():
#get instance handle
hInstance = win32api.GetModuleHandle()
# the class name
className = 'SimpleWin32'
# create and initialize window class
wndClass = win32gui.WNDCLASS()
wndClass.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
wndClass.lpfnWndProc = wndProc
wndClass.hInstance = hInstance
wndClass.hIcon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION)
wndClass.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW)
wndClass.hbrBackground = win32gui.GetStockObject(win32con.WHITE_BRUSH)
wndClass.lpszClassName = className
# register window class
wndClassAtom = None
try:
wndClassAtom = win32gui.RegisterClass(wndClass)
except Exception as e:
print (e)
raise e
hWindow = win32gui.CreateWindow(
wndClassAtom, #it seems message dispatching only works with the atom, not the class name
'Python Win32 Window',
win32con.WS_OVERLAPPEDWINDOW,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
0,
0,
hInstance,
None)
# Show & update the window
win32gui.ShowWindow(hWindow, win32con.SW_SHOWNORMAL)
win32gui.UpdateWindow(hWindow)
# Dispatch messages
win32gui.PumpMessages()
# New code: Attempt to change the text 1 second later
time.sleep(1.0)
g_str_Text = 'Something new'
win32gui.ShowWindow(hWindow, win32con.SW_SHOWNORMAL)
win32gui.UpdateWindow(hWindow)
win32gui.PumpMessages()
def wndProc(hWnd, message, wParam, lParam):
if message == win32con.WM_PAINT:
hDC, paintStruct = win32gui.BeginPaint(hWnd)
rect = win32gui.GetClientRect(hWnd)
win32gui.DrawText(
hDC,
g_str_Text,
-1,
rect,
win32con.DT_SINGLELINE | win32con.DT_CENTER | win32con.DT_VCENTER)
win32gui.EndPaint(hWnd, paintStruct)
return 0
elif message == win32con.WM_DESTROY:
print ('Being destroyed')
win32gui.PostQuitMessage(0)
return 0
else:
return win32gui.DefWindowProc(hWnd, message, wParam, lParam)
if __name__ == '__main__':
main()
答案 0 :(得分:0)
您的代码存在3个问题:
win32gui.PumpMessages
阻止直到窗口收到WM_QUIT
,这意味着它后面的代码(应该重绘)只会在之后执行 / strong>你关闭了窗口,并且还会生成异常,因为那时hWindow
句柄将无效。请注意,此问题还会阻止代码运行到下一个代码。win32gui.ShowWindow
,win32gui.UpdateWindow
都不会触发窗口重绘,因为从相关窗口看,没有任何变化(没有窗口区域无效)。强制失效的典型用户操作是窗口大小调整(包括最小化/最大化)。请注意,移动窗口也会不重绘它。g_str_Text = 'Something new'
- 这不符合您的想法,它是 Python gotcha 的(变体):它将创建一个新的g_str_Text
,它将是本地至main
,而不是修改wndProc
用于绘制窗口的全局。要解决这些问题,重新绘制窗口的代码应该从新的线程执行。为了做到这一点:
customDraw
)。win32gui.PumpMessages
之前开始,睡眠一秒钟,然后更改windowText
值(注意global
)。win32gui.RedrawWindow
重叠窗口(这是[MSDN] RedrawWindow
function上的包装器):
win32con.RDW_INVALIDATE
)。win32con.RDW_ERASE
),以避免将新文本绘制在旧文本上。WM_PAINT
条消息。以下是具有上述更改的脚本 - 请注意我做了一些其他小的更改(例如将g_str_Text
重命名为windowText
),只有一个命名约定 - camelCase (哪个 BTW ,不 Python 推荐一个):
import win32api
import win32con
import win32gui
import time
import threading
#Code example modified from:
#Christophe Keller
#Hello World in Python using Win32
# New code: Define global
windowText = 'Hello send by Python via Win32!'
def main():
#get instance handle
hInstance = win32api.GetModuleHandle()
# the class name
className = 'SimpleWin32'
# create and initialize window class
wndClass = win32gui.WNDCLASS()
wndClass.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
wndClass.lpfnWndProc = wndProc
wndClass.hInstance = hInstance
wndClass.hIcon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION)
wndClass.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW)
wndClass.hbrBackground = win32gui.GetStockObject(win32con.WHITE_BRUSH)
wndClass.lpszClassName = className
# register window class
wndClassAtom = None
try:
wndClassAtom = win32gui.RegisterClass(wndClass)
except Exception as e:
print (e)
raise e
hWindow = win32gui.CreateWindow(
wndClassAtom, #it seems message dispatching only works with the atom, not the class name
'Python Win32 Window',
win32con.WS_OVERLAPPEDWINDOW,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
0,
0,
hInstance,
None)
# Show & update the window
win32gui.ShowWindow(hWindow, win32con.SW_SHOWNORMAL)
win32gui.UpdateWindow(hWindow)
# New code: Create and start the thread
thr = threading.Thread(target=customDraw, args=(hWindow,))
thr.setDaemon(False)
thr.start()
# Dispatch messages
win32gui.PumpMessages()
# New code: Attempt to change the text 1 second later
def customDraw(hWindow):
global windowText
time.sleep(1.0)
windowText = 'Something new'
win32gui.RedrawWindow(hWindow, None, None, win32con.RDW_INVALIDATE | win32con.RDW_ERASE)
def wndProc(hWnd, message, wParam, lParam):
if message == win32con.WM_PAINT:
hDC, paintStruct = win32gui.BeginPaint(hWnd)
rect = win32gui.GetClientRect(hWnd)
win32gui.DrawText(
hDC,
windowText,
-1,
rect,
win32con.DT_SINGLELINE | win32con.DT_CENTER | win32con.DT_VCENTER)
win32gui.EndPaint(hWnd, paintStruct)
return 0
elif message == win32con.WM_DESTROY:
print('Being destroyed')
win32gui.PostQuitMessage(0)
return 0
else:
return win32gui.DefWindowProc(hWnd, message, wParam, lParam)
if __name__ == '__main__':
main()