Python窗口句柄截图源码

查看 104|回复 9
作者:tyler998   
是否好用大家自己测试一下,截图后图片可以放大缩小


wechat_2025-06-25_184342_378.png (98.38 KB, 下载次数: 0)
下载附件
2025-6-25 18:44 上传

[Python] 纯文本查看 复制代码import sys
import win32gui
import win32ui
import win32con
import win32api
import time
import ctypes
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                             QPushButton, QLineEdit, QLabel, QGraphicsView, QGraphicsScene,
                             QMessageBox, QGraphicsPixmapItem)
from PyQt5.QtCore import Qt, QPoint, QPointF
from PyQt5.QtGui import QPixmap, QImage, QPainter, QWheelEvent
class ZoomableGraphicsView(QGraphicsView):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setRenderHint(QPainter.Antialiasing)
        self.setRenderHint(QPainter.SmoothPixmapTransform)
        self.setDragMode(QGraphicsView.ScrollHandDrag)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
        self.scale_factor = 1.0
        self.pan_start = QPointF()
        self.panning = False
    def wheelEvent(self, event: QWheelEvent):
        # 缩放控制
        zoom_in_factor = 1.25
        zoom_out_factor = 1 / zoom_in_factor
        
        if event.angleDelta().y() > 0:
            self.scale(zoom_in_factor, zoom_in_factor)
            self.scale_factor *= zoom_in_factor
        else:
            self.scale(zoom_out_factor, zoom_out_factor)
            self.scale_factor *= zoom_out_factor
    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.pan_start = event.pos()
            self.panning = True
            self.setCursor(Qt.ClosedHandCursor)
        super().mousePressEvent(event)
    def mouseMoveEvent(self, event):
        if self.panning:
            delta = event.pos() - self.pan_start
            self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - delta.x())
            self.verticalScrollBar().setValue(self.verticalScrollBar().value() - delta.y())
            self.pan_start = event.pos()
        super().mouseMoveEvent(event)
    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.panning = False
            self.setCursor(Qt.ArrowCursor)
        super().mouseReleaseEvent(event)
class WindowCaptureApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("窗口捕获工具 - 完整功能版")
        self.setFixedSize(800, 500)
        
        # 初始化变量
        self.target_hwnd = None
        self.is_selecting = False
        self.last_hwnd = None
        self.current_pixmap_item = None
        
        # 创建UI
        self.setup_ui()
        
    def setup_ui(self):
        # 主部件和布局
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        layout = QVBoxLayout()
        main_widget.setLayout(layout)
        
        # 第一行控件
        row1 = QHBoxLayout()
        self.btn_select = QPushButton("选择窗口", self)
        self.btn_select.clicked.connect(self.begin_window_selection)  # 统一使用begin_window_selection
        
        self.edit_handle = QLineEdit(self)
        self.edit_handle.setPlaceholderText("窗口句柄")
        self.edit_handle.setReadOnly(True)
        
        self.edit_title = QLineEdit(self)
        self.edit_title.setPlaceholderText("窗口标题")
        self.edit_title.setReadOnly(True)
        
        self.btn_capture = QPushButton("截图", self)
        self.btn_capture.clicked.connect(self.capture_window)
        self.btn_capture.setEnabled(False)
        
        self.btn_reset = QPushButton("重置视图", self)
        self.btn_reset.clicked.connect(self.reset_view)
        
        row1.addWidget(self.btn_select)
        row1.addWidget(QLabel("句柄:"))
        row1.addWidget(self.edit_handle)
        row1.addWidget(QLabel("标题:"))
        row1.addWidget(self.edit_title)
        row1.addWidget(self.btn_capture)
        row1.addWidget(self.btn_reset)
        
        # 第二行画板
        self.graphics_view = ZoomableGraphicsView(self)
        self.scene = QGraphicsScene(self)
        self.graphics_view.setScene(self.scene)
        
        layout.addLayout(row1)
        layout.addWidget(self.graphics_view)
   
    def begin_window_selection(self):
        """开始窗口选择"""
        self.is_selecting = True
        self.btn_select.setText("请点击目标窗口...")
        self.btn_select.setEnabled(False)
        self.grabMouse()
        self.setCursor(Qt.CrossCursor)
   
    def mouseMoveEvent(self, event):
        if self.is_selecting:
            pos = self.mapToGlobal(event.pos())
            hwnd = win32gui.WindowFromPoint((pos.x(), pos.y()))
            if hwnd != self.last_hwnd:
                self.last_hwnd = hwnd
                self.highlight_window(hwnd)
        super().mouseMoveEvent(event)
   
    def highlight_window(self, hwnd):
        """高亮显示目标窗口"""
        if not hwnd or hwnd == self.winId():
            return
            
        try:
            hdc = win32gui.GetWindowDC(hwnd)
            rect = win32gui.GetWindowRect(hwnd)
            w, h = rect[2]-rect[0], rect[3]-rect[1]
            
            pen = win32ui.CreatePen(win32con.PS_SOLID, 3, win32api.RGB(255,0,0))
            old_pen = win32gui.SelectObject(hdc, pen)
            
            for _ in range(3):
                win32gui.Rectangle(hdc, 0, 0, w, h)
                time.sleep(0.2)
                win32gui.RedrawWindow(hwnd, None, None,
                                    win32con.RDW_INVALIDATE | win32con.RDW_UPDATENOW)
                time.sleep(0.2)
            
            win32gui.SelectObject(hdc, old_pen)
            win32gui.DeleteObject(pen)
            win32gui.ReleaseDC(hwnd, hdc)
            
        except Exception as e:
            print(f"高亮窗口失败: {e}")
   
    def mouseReleaseEvent(self, event):
        if self.is_selecting:
            self.is_selecting = False
            self.btn_select.setText("选择窗口")
            self.btn_select.setEnabled(True)
            self.releaseMouse()
            self.unsetCursor()
            
            pos = self.mapToGlobal(event.pos())
            self.target_hwnd = win32gui.WindowFromPoint((pos.x(), pos.y()))
            
            if self.target_hwnd and self.target_hwnd != self.winId():
                self.edit_handle.setText(str(self.target_hwnd))
                self.edit_title.setText(win32gui.GetWindowText(self.target_hwnd))
                self.btn_capture.setEnabled(True)
            else:
                self.edit_handle.clear()
                self.edit_title.clear()
                self.btn_capture.setEnabled(False)
                QMessageBox.warning(self, "警告", "未选择有效窗口")
        
        super().mouseReleaseEvent(event)
   
    def capture_window(self):
        """执行截图操作"""
        if not self.target_hwnd:
            return
            
        try:
            # 检查窗口状态
            if not self.is_window_visible():
                QMessageBox.warning(self, "警告", "目标窗口不可见或已最小化")
                return
               
            # 获取窗口尺寸
            left, top, right, bottom = win32gui.GetWindowRect(self.target_hwnd)
            width = right - left
            height = bottom - top
            
            if width

窗口, 截图

shojnhv   

收藏学习了,感谢分享
358059103   

感谢分享,收藏了,
flyer_2001   

感谢楼主分享!支持
cn00417984   

感谢楼主分享
wensong151   

谢谢,分享
senooo   

这么麻烦吗 我记得几行代码就可以了,可以支持窗口元素的截图吗
lazychen   

封装一下丫  有很多不懂编程的小白想用
Gan1Ser   

我直接学习
tjy0916   

太专业,看不懂
您需要登录后才可以回帖 登录 | 立即注册

返回顶部