小甲鱼 发表于 2023-8-12 19:57:48

编程追风梦 发表于 2023-8-10 06:04
**** 作者被禁止或删除 内容自动屏蔽 ****

可以上B站哈~

编程追风梦小号 发表于 2023-8-13 05:49:19

小甲鱼 发表于 2023-8-12 19:57
可以上B站哈~

嘻嘻

sfqxx 发表于 2023-8-16 11:47:14

liuhongrun2022 发表于 2023-8-7 10:25
恭喜中标!

陶远航 发表于 2023-10-5 10:14:22

期待

Mike_python小 发表于 2023-10-15 15:46:56

陶远航 发表于 2023-10-5 07:14
期待

等csp完了的{:10_256:}

陶远航 发表于 2023-10-15 15:48:03

Mike_python小 发表于 2023-10-15 15:46
等csp完了的

甲鱼哥要等好久{:10_250:}

Mike_python小 发表于 2023-10-15 15:49:52

陶远航 发表于 2023-10-15 12:48
甲鱼哥要等好久

{:10_256:}

kbq1415 发表于 4 小时前

本帖最后由 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)
   

kbq1415 发表于 4 小时前

做了一个简单的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]
查看完整版本: 【开发中】求贤令000:开发一个截图程序