**** 作者被禁止或删除 内容自动屏蔽 ****
可以上B站哈~ 小甲鱼 发表于 2023-8-12 19:57
可以上B站哈~
嘻嘻 liuhongrun2022 发表于 2023-8-7 10:25
恭喜中标!
? 期待 陶远航 发表于 2023-10-5 07:14
期待
等csp完了的{:10_256:} Mike_python小 发表于 2023-10-15 15:46
等csp完了的
甲鱼哥要等好久{:10_250:} 陶远航 发表于 2023-10-15 12:48
甲鱼哥要等好久
{:10_256:} 本帖最后由 kbq1415 于 2025-5-4 10:35 编辑
Windows截屏程序
用的是Python
import ctypes
import sys
import time
# 定义Windows API所需的结构体和常量
class BITMAPINFOHEADER(ctypes.Structure):
_fields_ = [
('biSize', ctypes.c_ulong),
('biWidth', ctypes.c_long),
('biHeight', ctypes.c_long),
('biPlanes', ctypes.c_ushort),
('biBitCount', ctypes.c_ushort),
('biCompression', ctypes.c_ulong),
('biSizeImage', ctypes.c_ulong),
('biXPelsPerMeter', ctypes.c_long),
('biYPelsPerMeter', ctypes.c_long),
('biClrUsed', ctypes.c_ulong),
('biClrImportant', ctypes.c_ulong)
]
class BITMAPINFO(ctypes.Structure):
_fields_ = [
('bmiHeader', BITMAPINFOHEADER),
('bmiColors', ctypes.c_ulong * 3)
]
class POINT(ctypes.Structure):
_fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
# GDI常量
SRCCOPY = 0x00CC0020
DIB_RGB_COLORS = 0
WH_MOUSE_LL = 14
WM_LBUTTONDOWN = 0x0201
WM_LBUTTONUP = 0x0202
WM_MOUSEMOVE = 0x0200
# 全局变量存储选区坐标
start_point = POINT()
end_point = POINT()
dragging = False
# 鼠标钩子回调函数
def low_level_mouse_handler(nCode, wParam, lParam):
global start_point, end_point, dragging
if nCode == 0:
event = wParam
mouse_data = ctypes.cast(lParam, ctypes.POINTER(MSLLHOOKSTRUCT)).contents
if event == WM_LBUTTONDOWN:
start_point.x = mouse_data.pt.x
start_point.y = mouse_data.pt.y
end_point.x = mouse_data.pt.x
end_point.y = mouse_data.pt.y
dragging = True
elif event == WM_MOUSEMOVE and dragging:
# 实时更新选区终点
end_point.x = mouse_data.pt.x
end_point.y = mouse_data.pt.y
elif event == WM_LBUTTONUP:
end_point.x = mouse_data.pt.x
end_point.y = mouse_data.pt.y
dragging = False
return 1# 终止钩子
return ctypes.windll.user32.CallNextHookEx(None, nCode, wParam, lParam)
def select_region():
"""通过鼠标交互选择屏幕区域"""
print("请按住鼠标左键拖拽选择区域,释放左键完成选择")
# 安装鼠标钩子
hook_proc = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_void_p))(low_level_mouse_handler)
hook = ctypes.windll.user32.SetWindowsHookExA(WH_MOUSE_LL, hook_proc, None, 0)
# 消息循环
msg = ctypes.wintypes.MSG()
while ctypes.windll.user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0:
if not dragging:
break
ctypes.windll.user32.TranslateMessage(ctypes.byref(msg))
ctypes.windll.user32.DispatchMessageA(ctypes.byref(msg))
# 卸载钩子
ctypes.windll.user32.UnhookWindowsHookEx(hook)
# 规范坐标
x1 = min(start_point.x, end_point.x)
y1 = min(start_point.y, end_point.y)
x2 = max(start_point.x, end_point.x)
y2 = max(start_point.y, end_point.y)
return (x1, y1, x2, y2)
def take_screenshot(x1=0, y1=0, x2=None, y2=None, filename='screenshot.bmp'):
"""
执行屏幕截图
:param x1: 区域左上角X坐标
:param y1: 区域左上角Y坐标
:param x2: 区域右下角X坐标(None表示屏幕右边缘)
:param y2: 区域右下角Y坐标(None表示屏幕下边缘)
:param filename: 输出文件名
"""
user32 = ctypes.windll.user32
gdi32 = ctypes.windll.gdi32
# 获取屏幕尺寸
if x2 is None: x2 = user32.GetSystemMetrics(0)
if y2 is None: y2 = user32.GetSystemMetrics(1)
width = x2 - x1
height = y2 - y1
# 设备上下文操作
hdc = user32.GetDC(None)
memdc = gdi32.CreateCompatibleDC(hdc)
bmp = gdi32.CreateCompatibleBitmap(hdc, width, height)
old_bmp = gdi32.SelectObject(memdc, bmp)
# 复制屏幕区域
gdi32.BitBlt(memdc, 0, 0, width, height, hdc, x1, y1, SRCCOPY)
# 准备位图信息结构
bmi = BITMAPINFO()
bmi.bmiHeader.biSize = ctypes.sizeof(BITMAPINFOHEADER)
bmi.bmiHeader.biWidth = width
bmi.bmiHeader.biHeight = -height# 从上到下
bmi.bmiHeader.biPlanes = 1
bmi.bmiHeader.biBitCount = 24
bmi.bmiHeader.biCompression = 0
# 获取位图数据
stride = ((width * 3 + 3) // 4) * 4
buffer_size = stride * height
buffer = ctypes.create_string_buffer(buffer_size)
gdi32.GetDIBits(hdc, bmp, 0, height, buffer, ctypes.byref(bmi), DIB_RGB_COLORS)
# 构建BMP文件
file_header = bytearray(b'BM')
file_header.extend((14 + 40 + buffer_size).to_bytes(4, 'little'))
file_header.extend(bytes(4))
file_header.extend((14 + 40).to_bytes(4, 'little'))
info_header = bytearray()
info_header.extend(bmi.bmiHeader.biSize.to_bytes(4, 'little'))
info_header.extend(width.to_bytes(4, 'little', signed=True))
info_header.extend((-height).to_bytes(4, 'little', signed=True))
info_header.extend(bmi.bmiHeader.biPlanes.to_bytes(2, 'little'))
info_header.extend(bmi.bmiHeader.biBitCount.to_bytes(2, 'little'))
info_header.extend(bmi.bmiHeader.biCompression.to_bytes(4, 'little'))
info_header.extend((stride * height).to_bytes(4, 'little'))
info_header.extend(bytes(16))
with open(filename, 'wb') as f:
f.write(file_header)
f.write(info_header)
f.write(buffer)
# 清理资源
gdi32.SelectObject(memdc, old_bmp)
做了一个简单的Windows截屏程序
用Python。
import ctypes
import sys
import time
# 定义Windows API所需的结构体和常量
class BITMAPINFOHEADER(ctypes.Structure):
_fields_ = [
('biSize', ctypes.c_ulong),
('biWidth', ctypes.c_long),
('biHeight', ctypes.c_long),
('biPlanes', ctypes.c_ushort),
('biBitCount', ctypes.c_ushort),
('biCompression', ctypes.c_ulong),
('biSizeImage', ctypes.c_ulong),
('biXPelsPerMeter', ctypes.c_long),
('biYPelsPerMeter', ctypes.c_long),
('biClrUsed', ctypes.c_ulong),
('biClrImportant', ctypes.c_ulong)
]
class BITMAPINFO(ctypes.Structure):
_fields_ = [
('bmiHeader', BITMAPINFOHEADER),
('bmiColors', ctypes.c_ulong * 3)
]
class POINT(ctypes.Structure):
_fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
# GDI常量
SRCCOPY = 0x00CC0020
DIB_RGB_COLORS = 0
WH_MOUSE_LL = 14
WM_LBUTTONDOWN = 0x0201
WM_LBUTTONUP = 0x0202
WM_MOUSEMOVE = 0x0200
# 全局变量存储选区坐标
start_point = POINT()
end_point = POINT()
dragging = False
# 鼠标钩子回调函数
def low_level_mouse_handler(nCode, wParam, lParam):
global start_point, end_point, dragging
if nCode == 0:
event = wParam
mouse_data = ctypes.cast(lParam, ctypes.POINTER(MSLLHOOKSTRUCT)).contents
if event == WM_LBUTTONDOWN:
start_point.x = mouse_data.pt.x
start_point.y = mouse_data.pt.y
end_point.x = mouse_data.pt.x
end_point.y = mouse_data.pt.y
dragging = True
elif event == WM_MOUSEMOVE and dragging:
# 实时更新选区终点
end_point.x = mouse_data.pt.x
end_point.y = mouse_data.pt.y
elif event == WM_LBUTTONUP:
end_point.x = mouse_data.pt.x
end_point.y = mouse_data.pt.y
dragging = False
return 1# 终止钩子
return ctypes.windll.user32.CallNextHookEx(None, nCode, wParam, lParam)
def select_region():
"""通过鼠标交互选择屏幕区域"""
print("请按住鼠标左键拖拽选择区域,释放左键完成选择")
# 安装鼠标钩子
hook_proc = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_void_p))(low_level_mouse_handler)
hook = ctypes.windll.user32.SetWindowsHookExA(WH_MOUSE_LL, hook_proc, None, 0)
# 消息循环
msg = ctypes.wintypes.MSG()
while ctypes.windll.user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0:
if not dragging:
break
ctypes.windll.user32.TranslateMessage(ctypes.byref(msg))
ctypes.windll.user32.DispatchMessageA(ctypes.byref(msg))
# 卸载钩子
ctypes.windll.user32.UnhookWindowsHookEx(hook)
# 规范坐标
x1 = min(start_point.x, end_point.x)
y1 = min(start_point.y, end_point.y)
x2 = max(start_point.x, end_point.x)
y2 = max(start_point.y, end_point.y)
return (x1, y1, x2, y2)
def take_screenshot(x1=0, y1=0, x2=None, y2=None, filename='screenshot.bmp'):
"""
执行屏幕截图
:param x1: 区域左上角X坐标
:param y1: 区域左上角Y坐标
:param x2: 区域右下角X坐标(None表示屏幕右边缘)
:param y2: 区域右下角Y坐标(None表示屏幕下边缘)
:param filename: 输出文件名
"""
user32 = ctypes.windll.user32
gdi32 = ctypes.windll.gdi32
# 获取屏幕尺寸
if x2 is None: x2 = user32.GetSystemMetrics(0)
if y2 is None: y2 = user32.GetSystemMetrics(1)
width = x2 - x1
height = y2 - y1
# 设备上下文操作
hdc = user32.GetDC(None)
memdc = gdi32.CreateCompatibleDC(hdc)
bmp = gdi32.CreateCompatibleBitmap(hdc, width, height)
old_bmp = gdi32.SelectObject(memdc, bmp)
# 复制屏幕区域
gdi32.BitBlt(memdc, 0, 0, width, height, hdc, x1, y1, SRCCOPY)
# 准备位图信息结构
bmi = BITMAPINFO()
bmi.bmiHeader.biSize = ctypes.sizeof(BITMAPINFOHEADER)
bmi.bmiHeader.biWidth = width
bmi.bmiHeader.biHeight = -height# 从上到下
bmi.bmiHeader.biPlanes = 1
bmi.bmiHeader.biBitCount = 24
bmi.bmiHeader.biCompression = 0
# 获取位图数据
stride = ((width * 3 + 3) // 4) * 4
buffer_size = stride * height
buffer = ctypes.create_string_buffer(buffer_size)
gdi32.GetDIBits(hdc, bmp, 0, height, buffer, ctypes.byref(bmi), DIB_RGB_COLORS)
# 构建BMP文件
file_header = bytearray(b'BM')
file_header.extend((14 + 40 + buffer_size).to_bytes(4, 'little'))
file_header.extend(bytes(4))
file_header.extend((14 + 40).to_bytes(4, 'little'))
info_header = bytearray()
info_header.extend(bmi.bmiHeader.biSize.to_bytes(4, 'little'))
info_header.extend(width.to_bytes(4, 'little', signed=True))
info_header.extend((-height).to_bytes(4, 'little', signed=True))
info_header.extend(bmi.bmiHeader.biPlanes.to_bytes(2, 'little'))
info_header.extend(bmi.bmiHeader.biBitCount.to_bytes(2, 'little'))
info_header.extend(bmi.bmiHeader.biCompression.to_bytes(4, 'little'))
info_header.extend((stride * height).to_bytes(4, 'little'))
info_header.extend(bytes(16))
with open(filename, 'wb') as f:
f.write(file_header)
f.write(info_header)
f.write(buffer)
# 清理资源
gdi32.SelectObject(memdc, old_bmp)
他可以全屏、选择尺寸、滚动截屏
页:
1
[2]