使用python实现程序最小化截图
简单介绍一下这个功能,像程序最小化之后,用鼠标移动到下面的图表会出现一个缩略图,就是通过这样方式来实现最小化截图。但是测试后发现最小化后缩略图不会发生变化,所以有点鸡肋。然后放到后台测试了一下延迟,发现还是蛮快的,所以就发出来供大家参考学习,开发出更多用法。
import ctypesimport time
import win32api
import win32con
import win32gui
from ctypes import wintypes
# Windows API 常量
DWM_TNP_RECTDESTINATION = 0x00000001
DWM_TNP_VISIBLE = 0x00000008
DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010
# 定义 RECT 结构体
class RECT(ctypes.Structure):
_fields_ = [("left", wintypes.LONG),
("top", wintypes.LONG),
("right", wintypes.LONG),
("bottom", wintypes.LONG)]
# DWM_THUMBNAIL_PROPERTIES 结构体
class DWM_THUMBNAIL_PROPERTIES(ctypes.Structure):
_fields_ = [("dwFlags", wintypes.DWORD),
("rcDestination", RECT),
("fVisible", wintypes.BOOL),
("fSourceClientAreaOnly", wintypes.BOOL),
("opacity", wintypes.UINT)]
# 定义 HRESULT 类型
HRESULT = ctypes.c_int
# DWM API 函数声明
DWM_API = ctypes.windll.dwmapi
# DwmRegisterThumbnail 函数声明
DWM_API.DwmRegisterThumbnail.argtypes =
DWM_API.DwmRegisterThumbnail.restype = HRESULT# 使用 c_int 来表示 HRESULT
# DwmUpdateThumbnailProperties 函数声明
DWM_API.DwmUpdateThumbnailProperties.argtypes =
DWM_API.DwmUpdateThumbnailProperties.restype = HRESULT
# 定义窗口回调函数
def wnd_proc(hwnd, msg, w_param, l_param):
if msg == win32con.WM_CLOSE:
win32gui.DestroyWindow(hwnd)
# DWM_API.DwmUnregisterThumbnail(hwnd)
return win32gui.DefWindowProc(hwnd, msg, w_param, l_param)
# 创建窗口函数
def create_window(window_title, w, h):
wc = win32gui.WNDCLASS()
wc.lpfnWndProc = wnd_proc
wc.lpszClassName = window_title
wc.hInstance = win32api.GetModuleHandle(None)
class_atom = win32gui.RegisterClass(wc)
hwnd = win32gui.CreateWindow(
class_atom,# 窗口类的标识符
window_title,# 窗口标题
win32con.WS_OVERLAPPEDWINDOW,# 窗口样式
0, 0,# 窗口位置
w + 50, h + 50,# 窗口大小
0,# 父窗口句柄
0,# 菜单句柄
wc.hInstance,# 实例句柄
None# 额外的参数
)
return hwnd
def mapping_window(target_hwnd, source_hwnd, draw_position):
thumbnail = wintypes.HANDLE()
# 注册缩略图
result = DWM_API.DwmRegisterThumbnail(target_hwnd, source_hwnd, ctypes.byref(thumbnail))
if result != 0:# 如果 DwmRegisterThumbnail 返回非 0,表示失败
print("未获取到缩略图")
return
# 设置缩略图属性
thumb_props = DWM_THUMBNAIL_PROPERTIES()
thumb_props.dwFlags = DWM_TNP_RECTDESTINATION
thumb_props.rcDestination = draw_position
thumb_props.fVisible = True
thumb_props.fSourceClientAreaOnly = False
thumb_props.opacity = (255 * 70) // 100# 设置透明度为 70%
# 更新缩略图属性
DWM_API.DwmUpdateThumbnailProperties(thumbnail, ctypes.byref(thumb_props))
print("缩略图已映射到目标窗口")
def get_window_normal_size(hwnd):
# 获取窗口的位置信息和状态
placement = win32gui.GetWindowPlacement(hwnd)
print(placement)
# 获取窗口正常状态下的尺寸
rect = placement# rcNormalPosition: (left, top, right, bottom)
# 计算宽度和高度
width = rect - rect
height = rect - rect
return width, height
# 获取源窗口的句柄
source_hwnd = 198072# 这里填写需要截图的窗口的句柄
width, height = get_window_normal_size(source_hwnd)
print(width, height)
# 创建目标窗口
target_window_title = "Target Window"# 目标窗口的标题
target_hwnd = create_window(target_window_title, width, height)
# 显示目标窗口
win32gui.ShowWindow(target_hwnd, win32con.SW_SHOWNORMAL)
win32gui.UpdateWindow(target_hwnd)
# 定义绘制位置(你可以根据需要调整)
draw_position = RECT()
draw_position.left = 0
draw_position.top = 0
draw_position.right = draw_position.left + width
draw_position.bottom = draw_position.top + height
# 调用映射窗口函数
mapping_window(target_hwnd, source_hwnd, draw_position)
# 运行消息循环以保持窗口显示
while True:
win32gui.PumpMessages()
time.sleep(0.1)
本帖最后由 52zct 于 2024-11-14 09:40 编辑
52zct 发表于 2024-11-14 09:11
测试了一下,像是实时投屏
import ctypes
import win32gui
def enum_windows_callback(hwnd, windows):
if win32gui.IsWindowVisible(hwnd):
windows.append((hwnd, win32gui.GetWindowText(hwnd)))
def get_all_window_titles():
windows = []
win32gui.EnumWindows(enum_windows_callback, windows)
return windows
def write_window_info_to_file(windows, filename="窗口信息.txt"):
with open(filename, 'w', encoding='utf-8') as file:
for hwnd, title in windows:
file.write(f"HWND: {hwnd}, Title: {title}\n")
def main():
# 获取所有窗口的标题
all_windows = get_all_window_titles()
# 定义文件名
filename = "窗口信息.txt"
# 将窗口信息写入文件
write_window_info_to_file(all_windows, filename)
# 打印消息
print(f"窗口信息已写入到 {filename}")
if __name__ == "__main__":
main()
上面是检测窗口的代码
下面这个是读取config.ini进行窗口映射的代码
import ctypes
import time
import win32api
import win32con
import win32gui
from ctypes import wintypes
# Windows API 常量
DWM_TNP_RECTDESTINATION = 0x00000001
DWM_TNP_VISIBLE = 0x00000008
DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010
# 定义 RECT 结构体
class RECT(ctypes.Structure):
_fields_ = [("left", wintypes.LONG),
("top", wintypes.LONG),
("right", wintypes.LONG),
("bottom", wintypes.LONG)]
# DWM_THUMBNAIL_PROPERTIES 结构体
class DWM_THUMBNAIL_PROPERTIES(ctypes.Structure):
_fields_ = [("dwFlags", wintypes.DWORD),
("rcDestination", RECT),
("fVisible", wintypes.BOOL),
("fSourceClientAreaOnly", wintypes.BOOL),
("opacity", wintypes.UINT)]
# 定义 HRESULT 类型
HRESULT = ctypes.c_int
# DWM API 函数声明
DWM_API = ctypes.windll.dwmapi
# DwmRegisterThumbnail 函数声明
DWM_API.DwmRegisterThumbnail.argtypes =
DWM_API.DwmRegisterThumbnail.restype = HRESULT# 使用 c_int 来表示 HRESULT
# DwmUpdateThumbnailProperties 函数声明
DWM_API.DwmUpdateThumbnailProperties.argtypes =
DWM_API.DwmUpdateThumbnailProperties.restype = HRESULT
# 定义窗口回调函数
def wnd_proc(hwnd, msg, w_param, l_param):
if msg == win32con.WM_CLOSE:
win32gui.DestroyWindow(hwnd)
# DWM_API.DwmUnregisterThumbnail(hwnd)
return win32gui.DefWindowProc(hwnd, msg, w_param, l_param)
# 创建窗口函数
def create_window(window_title, w, h):
wc = win32gui.WNDCLASS()
wc.lpfnWndProc = wnd_proc
wc.lpszClassName = window_title
wc.hInstance = win32api.GetModuleHandle(None)
class_atom = win32gui.RegisterClass(wc)
hwnd = win32gui.CreateWindow(
class_atom,# 窗口类的标识符
window_title,# 窗口标题
win32con.WS_OVERLAPPEDWINDOW,# 窗口样式
0, 0,# 窗口位置
w + 50, h + 50,# 窗口大小
0,# 父窗口句柄
0,# 菜单句柄
wc.hInstance,# 实例句柄
None# 额外的参数
)
return hwnd
def mapping_window(target_hwnd, source_hwnd, draw_position):
thumbnail = wintypes.HANDLE()
# 注册缩略图
result = DWM_API.DwmRegisterThumbnail(target_hwnd, source_hwnd, ctypes.byref(thumbnail))
if result != 0:# 如果 DwmRegisterThumbnail 返回非 0,表示失败
print("未获取到缩略图")
return
# 设置缩略图属性
thumb_props = DWM_THUMBNAIL_PROPERTIES()
thumb_props.dwFlags = DWM_TNP_RECTDESTINATION
thumb_props.rcDestination = draw_position
thumb_props.fVisible = True
thumb_props.fSourceClientAreaOnly = False
thumb_props.opacity = (255 * 70) // 100# 设置透明度为 70%
# 更新缩略图属性
DWM_API.DwmUpdateThumbnailProperties(thumbnail, ctypes.byref(thumb_props))
print("缩略图已映射到目标窗口")
def get_window_normal_size(hwnd):
if not win32gui.IsWindow(hwnd):
print("窗口已关闭或不存在")
return None, None
# 获取窗口的位置信息和状态
placement = win32gui.GetWindowPlacement(hwnd)
print(f"Placement: {placement}")
# 获取窗口正常状态下的尺寸
rect = placement# rcNormalPosition: (left, top, right, bottom)
# 计算宽度和高度
width = rect - rect
height = rect - rect
return width, height
# 从 config.txt 文件中读取窗口标题
def read_config():
try:
with open('config.ini', 'r') as file:
window_title = file.readline().strip()
return window_title
except FileNotFoundError:
print("config.ini 文件未找到")
return None
# 主程序逻辑
window_title = read_config()
if window_title:
source_hwnd = win32gui.FindWindow(None, window_title)# 替换为实际的窗口标题
if not win32gui.IsWindow(source_hwnd):
print("未找到指定的窗口")
else:
width, height = get_window_normal_size(source_hwnd)
if width is not None and height is not None:
print(f"窗口尺寸: {width} x {height}")
# 创建目标窗口
target_window_title = "Target Window"# 目标窗口的标题
target_hwnd = create_window(target_window_title, width, height)
# 显示目标窗口
win32gui.ShowWindow(target_hwnd, win32con.SW_SHOWNORMAL)
win32gui.UpdateWindow(target_hwnd)
# 定义绘制位置(你可以根据需要调整)
draw_position = RECT()
draw_position.left = 0
draw_position.top = 0
draw_position.right = draw_position.left + width
draw_position.bottom = draw_position.top + height
# 调用映射窗口函数
mapping_window(target_hwnd, source_hwnd, draw_position)
# 运行消息循环以保持窗口显示
while True:
win32gui.PumpMessages()
time.sleep(0.1)
else:
print("未从 config.txt 中读取到窗口标题")
最后只需要自己创建一个config,ini存放提取出来的窗口标题即可 测试了一下,像是实时投屏
import ctypes
import time
import win32api
import win32con
import win32gui
from ctypes import wintypes
# Windows API 常量
DWM_TNP_RECTDESTINATION = 0x00000001
DWM_TNP_VISIBLE = 0x00000008
DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010
# 定义 RECT 结构体
class RECT(ctypes.Structure):
_fields_ = [("left", wintypes.LONG),
("top", wintypes.LONG),
("right", wintypes.LONG),
("bottom", wintypes.LONG)]
# DWM_THUMBNAIL_PROPERTIES 结构体
class DWM_THUMBNAIL_PROPERTIES(ctypes.Structure):
_fields_ = [("dwFlags", wintypes.DWORD),
("rcDestination", RECT),
("fVisible", wintypes.BOOL),
("fSourceClientAreaOnly", wintypes.BOOL),
("opacity", wintypes.UINT)]
# 定义 HRESULT 类型
HRESULT = ctypes.c_int
# DWM API 函数声明
DWM_API = ctypes.windll.dwmapi
# DwmRegisterThumbnail 函数声明
DWM_API.DwmRegisterThumbnail.argtypes =
DWM_API.DwmRegisterThumbnail.restype = HRESULT# 使用 c_int 来表示 HRESULT
# DwmUpdateThumbnailProperties 函数声明
DWM_API.DwmUpdateThumbnailProperties.argtypes =
DWM_API.DwmUpdateThumbnailProperties.restype = HRESULT
# 定义窗口回调函数
def wnd_proc(hwnd, msg, w_param, l_param):
if msg == win32con.WM_CLOSE:
win32gui.DestroyWindow(hwnd)
# DWM_API.DwmUnregisterThumbnail(hwnd)
return win32gui.DefWindowProc(hwnd, msg, w_param, l_param)
# 创建窗口函数
def create_window(window_title, w, h):
wc = win32gui.WNDCLASS()
wc.lpfnWndProc = wnd_proc
wc.lpszClassName = window_title
wc.hInstance = win32api.GetModuleHandle(None)
class_atom = win32gui.RegisterClass(wc)
hwnd = win32gui.CreateWindow(
class_atom,# 窗口类的标识符
window_title,# 窗口标题
win32con.WS_OVERLAPPEDWINDOW,# 窗口样式
0, 0,# 窗口位置
w + 50, h + 50,# 窗口大小
0,# 父窗口句柄
0,# 菜单句柄
wc.hInstance,# 实例句柄
None# 额外的参数
)
return hwnd
def mapping_window(target_hwnd, source_hwnd, draw_position):
thumbnail = wintypes.HANDLE()
# 注册缩略图
result = DWM_API.DwmRegisterThumbnail(target_hwnd, source_hwnd, ctypes.byref(thumbnail))
if result != 0:# 如果 DwmRegisterThumbnail 返回非 0,表示失败
print("未获取到缩略图")
return
# 设置缩略图属性
thumb_props = DWM_THUMBNAIL_PROPERTIES()
thumb_props.dwFlags = DWM_TNP_RECTDESTINATION
thumb_props.rcDestination = draw_position
thumb_props.fVisible = True
thumb_props.fSourceClientAreaOnly = False
thumb_props.opacity = (255 * 70) // 100# 设置透明度为 70%
# 更新缩略图属性
DWM_API.DwmUpdateThumbnailProperties(thumbnail, ctypes.byref(thumb_props))
print("缩略图已映射到目标窗口")
def get_window_normal_size(hwnd):
# 获取窗口的位置信息和状态
placement = win32gui.GetWindowPlacement(hwnd)
print(placement)
# 获取窗口正常状态下的尺寸
rect = placement# rcNormalPosition: (left, top, right, bottom)
# 计算宽度和高度
width = rect - rect
height = rect - rect
return width, height
# 获取源窗口的句柄
source_hwnd = 198072# 这里填写需要截图的窗口的句柄
width, height = get_window_normal_size(source_hwnd)
print(width, height)
# 创建目标窗口
target_window_title = "Target Window"# 目标窗口的标题
target_hwnd = create_window(target_window_title, width, height)
# 显示目标窗口
win32gui.ShowWindow(target_hwnd, win32con.SW_SHOWNORMAL)
win32gui.UpdateWindow(target_hwnd)
# 定义绘制位置(你可以根据需要调整)
draw_position = RECT()
draw_position.left = 0
draw_position.top = 0
draw_position.right = draw_position.left + width
draw_position.bottom = draw_position.top + height
# 调用映射窗口函数
mapping_window(target_hwnd, source_hwnd, draw_position)
# 运行消息循环以保持窗口显示
while True:
win32gui.PumpMessages()
time.sleep(0.1) 有用!有用! 好用好用 不错,有意思 感谢分亨,学习了 有点意思,学习了~~ 感谢分享 谢分享,测试下,确实如楼主所说,截取播放器 会和播放器一起播放,但最小化播放 就是静止的。
看来需要先激活窗口再截图不可 支持一下 最小化后截取程序界面吗?描述看不出具体用途,可以加个演示