(C++/Python) 捕获 window 不带插入符指示符的屏幕截图
(C++/Python) Capture window screenshot without caret indicator
我想通过Python.
捕获现有运行ning window的屏幕截图
以下是我捕获记事本的示例代码 window:
import time
import win32gui
import win32ui
import win32con
import pyautogui
def getWindowScreenshot(hwnd, output_file):
r = win32gui.GetWindowRect(hwnd)
width = r[2] - r[0]
height = r[3] - r[1]
wDC = win32gui.GetWindowDC(hwnd)
dcObj = win32ui.CreateDCFromHandle(wDC)
cDC = dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, width, height)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0, 0), (width, height), dcObj, (0, 0), win32con.SRCCOPY)
# save the bitmap to a file
dataBitMap.SaveBitmapFile(cDC, output_file)
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
window_title = "Untitled - Notepad"
winHandle = win32gui.FindWindow(None, window_title)
if winHandle == 0:
raise RuntimeError(f"Window '{window_title}' is not opening!")
# Bring the window to foreground in case it is overlap by other windows
win32gui.SetForegroundWindow(winHandle)
# Do something with Notepad
time.sleep(3)
# Capture the window
getWindowScreenshot(winHandle, "output.bmp")
但是,有时捕获的图像会在输入文本框上有闪烁的插入符号指示符。
我的问题是,如何在没有插入符号指示器的情况下捕获屏幕截图?
我已经尝试了一些解决方案,但不适合:
方案一:
# Bring the window to foreground in case it is overlap by other windows
win32gui.SetForegroundWindow(winHandle)
# Do something with Notepad
time.sleep(3)
# Make the "Desktop window" focus
win32gui.SetForegroundWindow(win32gui.GetDesktopWindow())
# Capture the window
getWindowScreenshot(winHandle, "output.bmp")
截屏前,尝试将“桌面”设置为前景window。
但是,命令 win32gui.SetForegroundWindow(win32gui.GetDesktopWindow())
会引发错误:
pywintypes.error: (0, 'SetForegroundWindow', 'No error message is available')
方案二:
将 win32gui.SetForegroundWindow(win32gui.GetDesktopWindow())
替换为 win32gui.ShowWindow(winHandle, 4)
,其中 4
为 SW_SHOWNOACTIVATE
。
代码运行 OK,但是记事本window执行后没有失去焦点
方案三:
# Bring the window to foreground in case it is overlap by other windows
win32gui.SetForegroundWindow(winHandle)
# Do something with Notepad
time.sleep(3)
# Click outside of window
r = win32gui.GetWindowRect(winHandle)
pyautogui.click(r[2]+1, r[3]+1)
# Capture the window
getWindowScreenshot(winHandle, "output.bmp")
使用此解决方案,我尝试在记事本外部单击 window(单击桌面)。这段代码似乎有效,但如果另一个 window 在记事本 window 后面,则无法正常工作,如下所示:
代码执行时,会点击Windows资源管理器window。因此,代码可以执行意外点击(例如:意外删除系统文件?)。
解决方案 4
(来自@SongZhu-MSFT)
if __name__ == '__main__':
window_title = "Untitled - Notepad"
winHandle = win32gui.FindWindow(None, window_title)
if winHandle == 0:
raise RuntimeError(f"Window '{window_title}' is not opening!")
# Bring the window to foreground in case it is overlap by other windows
win32gui.SetForegroundWindow(winHandle)
# Do something with Notepad
time.sleep(3)
win32gui.EnableWindow(winHandle,False)
# Capture the window
getWindowScreenshot(winHandle, "output.bmp")
time.sleep(0.5)
getWindowScreenshot(winHandle, "output1.bmp")
time.sleep(5)
win32gui.EnableWindow(winHandle,True)
当我 运行 代码时,我仍然看到插入符号始终显示。
output.bmp
+ output1.bmp
仍然存在一张带有插入符号的图像。
系统信息:
- Windows 10 1909
- Python 3.7.9
经过我的测试,我可以使用 SendMessageW
发送 WM_KILLFOCUS
让插入符号消失。
这是对我有用的代码:
import time
import win32gui
import win32ui
import win32con
import pyautogui
from ctypes import windll
def getWindowScreenshot(hwnd, output_file):
r = win32gui.GetWindowRect(hwnd)
width = r[2] - r[0]
height = r[3] - r[1]
wDC = win32gui.GetWindowDC(hwnd)
dcObj = win32ui.CreateDCFromHandle(wDC)
cDC = dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, width, height)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0, 0), (width, height), dcObj, (0, 0), win32con.SRCCOPY)
# save the bitmap to a file
dataBitMap.SaveBitmapFile(cDC, output_file)
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())
if __name__ == '__main__':
window_title = "Untitled - Notepad"
winHandle = win32gui.FindWindow(None, window_title)
if winHandle == 0:
raise RuntimeError(f"Window '{window_title}' is not opening!")
# Bring the window to foreground in case it is overlap by other windows
win32gui.SetForegroundWindow(winHandle)
# Do something with Notepad
windll.user32.SendMessageW(winHandle, win32con.WM_KILLFOCUS, None, None)
# Capture the window
getWindowScreenshot(winHandle, "output.bmp")
time.sleep(0.5)
getWindowScreenshot(winHandle, "output1.bmp")
我想通过Python.
捕获现有运行ning window的屏幕截图
以下是我捕获记事本的示例代码 window:
import time
import win32gui
import win32ui
import win32con
import pyautogui
def getWindowScreenshot(hwnd, output_file):
r = win32gui.GetWindowRect(hwnd)
width = r[2] - r[0]
height = r[3] - r[1]
wDC = win32gui.GetWindowDC(hwnd)
dcObj = win32ui.CreateDCFromHandle(wDC)
cDC = dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, width, height)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0, 0), (width, height), dcObj, (0, 0), win32con.SRCCOPY)
# save the bitmap to a file
dataBitMap.SaveBitmapFile(cDC, output_file)
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
window_title = "Untitled - Notepad"
winHandle = win32gui.FindWindow(None, window_title)
if winHandle == 0:
raise RuntimeError(f"Window '{window_title}' is not opening!")
# Bring the window to foreground in case it is overlap by other windows
win32gui.SetForegroundWindow(winHandle)
# Do something with Notepad
time.sleep(3)
# Capture the window
getWindowScreenshot(winHandle, "output.bmp")
但是,有时捕获的图像会在输入文本框上有闪烁的插入符号指示符。
我的问题是,如何在没有插入符号指示器的情况下捕获屏幕截图?
我已经尝试了一些解决方案,但不适合:
方案一:
# Bring the window to foreground in case it is overlap by other windows
win32gui.SetForegroundWindow(winHandle)
# Do something with Notepad
time.sleep(3)
# Make the "Desktop window" focus
win32gui.SetForegroundWindow(win32gui.GetDesktopWindow())
# Capture the window
getWindowScreenshot(winHandle, "output.bmp")
截屏前,尝试将“桌面”设置为前景window。
但是,命令 win32gui.SetForegroundWindow(win32gui.GetDesktopWindow())
会引发错误:
pywintypes.error: (0, 'SetForegroundWindow', 'No error message is available')
方案二:
将 win32gui.SetForegroundWindow(win32gui.GetDesktopWindow())
替换为 win32gui.ShowWindow(winHandle, 4)
,其中 4
为 SW_SHOWNOACTIVATE
。
代码运行 OK,但是记事本window执行后没有失去焦点
方案三:
# Bring the window to foreground in case it is overlap by other windows
win32gui.SetForegroundWindow(winHandle)
# Do something with Notepad
time.sleep(3)
# Click outside of window
r = win32gui.GetWindowRect(winHandle)
pyautogui.click(r[2]+1, r[3]+1)
# Capture the window
getWindowScreenshot(winHandle, "output.bmp")
使用此解决方案,我尝试在记事本外部单击 window(单击桌面)。这段代码似乎有效,但如果另一个 window 在记事本 window 后面,则无法正常工作,如下所示:
代码执行时,会点击Windows资源管理器window。因此,代码可以执行意外点击(例如:意外删除系统文件?)。
解决方案 4 (来自@SongZhu-MSFT)
if __name__ == '__main__':
window_title = "Untitled - Notepad"
winHandle = win32gui.FindWindow(None, window_title)
if winHandle == 0:
raise RuntimeError(f"Window '{window_title}' is not opening!")
# Bring the window to foreground in case it is overlap by other windows
win32gui.SetForegroundWindow(winHandle)
# Do something with Notepad
time.sleep(3)
win32gui.EnableWindow(winHandle,False)
# Capture the window
getWindowScreenshot(winHandle, "output.bmp")
time.sleep(0.5)
getWindowScreenshot(winHandle, "output1.bmp")
time.sleep(5)
win32gui.EnableWindow(winHandle,True)
当我 运行 代码时,我仍然看到插入符号始终显示。
output.bmp
+ output1.bmp
仍然存在一张带有插入符号的图像。
系统信息:
- Windows 10 1909
- Python 3.7.9
经过我的测试,我可以使用 SendMessageW
发送 WM_KILLFOCUS
让插入符号消失。
这是对我有用的代码:
import time
import win32gui
import win32ui
import win32con
import pyautogui
from ctypes import windll
def getWindowScreenshot(hwnd, output_file):
r = win32gui.GetWindowRect(hwnd)
width = r[2] - r[0]
height = r[3] - r[1]
wDC = win32gui.GetWindowDC(hwnd)
dcObj = win32ui.CreateDCFromHandle(wDC)
cDC = dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, width, height)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0, 0), (width, height), dcObj, (0, 0), win32con.SRCCOPY)
# save the bitmap to a file
dataBitMap.SaveBitmapFile(cDC, output_file)
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())
if __name__ == '__main__':
window_title = "Untitled - Notepad"
winHandle = win32gui.FindWindow(None, window_title)
if winHandle == 0:
raise RuntimeError(f"Window '{window_title}' is not opening!")
# Bring the window to foreground in case it is overlap by other windows
win32gui.SetForegroundWindow(winHandle)
# Do something with Notepad
windll.user32.SendMessageW(winHandle, win32con.WM_KILLFOCUS, None, None)
# Capture the window
getWindowScreenshot(winHandle, "output.bmp")
time.sleep(0.5)
getWindowScreenshot(winHandle, "output1.bmp")