
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